Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

This Codio project is the workspace for the final course project. While you are welcome to completeproject on your own computer, this project has several

This Codio project is the workspace for the final course project. While you are welcome to completeproject on your own computer, this project has several tools to allow you to check your work along the way.

We have not provided you with any files for this project. You will create the files as directed. When you are done, you will have three files: currency.py, the module with the project functions; testcurrency.py, the unit tests for the currency functions, and exchangeit.py, an interactive script that allows a non-programmer to convert between two currencies.

You should also take a chance to familiarize yourself with this guide. To access the table of contents, click the upper-right button.

You will see several sections, breaking up each step into smaller tasks. In this project, you will work in the top-level directory. You should not make any new folders, and you should not store your files anywhere else.

2. Project Rules

This project is designed for a student who has learned about functions, specifications, and testing but has not yet learned any advanced control structures (if-statements, for-loops, etc.). It is also designed to be used in tandem with the introcs module, which simplifies a lot of advanced Python concepts.

To maintain the spirit of the assignment (and help with the grading process), certain Python commands are restricted in this assignment:

No advanced control structures (conditionals, loops, try-except blocks)

No Python or 3rd party modules other than introcs and the ones you make

No method calls, including string methods

Strings should use the functions in introcs instead of methods.

In addition, this project has the following style requirements:

Every function must have a complete specification.

Every module must start with a docstring with your name and date.

There must be two blank lines between any two function definitions.

Function bodies should be indented with 4 spaces.

No non-docstring line may be longer than 80 characters.

3. Project Workflow

Throughout this project, you will stick to the following workflow, one function at a time.

Add a stub for a function to currency.py.

Add a complete set of test cases for the function to testcurrency.py.

Implement the function in currency.py, using the tests as a guide.

With few exceptions, we will not give you any hints on the functions. The specifications should be sufficient. We also will not tell you the number of test cases that we are looking for (though you will get feedback from the "Check It!" buttons). We expect you to figure these out on your own.

Remember, to run the test script, you just run it as a normal Python script.

codio@mike-panther:~/workspace/exercise1$ python3 testcurrency.py

Testing before_space

Testing after_space

Testing first_inside_quotes

Testing get_src

Testing get_dst

Testing has_error

Testing service_response

Testing iscurrency

Testing exchange

All tests completed successfully

4. A Word of Warning

This Codio project provides a lot of buttons to allow you to test your code for correctness. It might be tempting to rely on these buttons all the time, instead of testing your code on your own. This is a mistake, particularly when you are implementing functions and test cases.

Connecting to the web service takes time. It is not horribly slow, but the time is measured in seconds, not milliseconds (as many programs are). If there are many test cases, the function will have to connect to the web service many times, increasing the time to a minute or even more. Because the grading tools in this project are thorough, they are not fast.

You should use your own test script testcurrency.py to test the function before pressing the Check It button. Your test script will give you better feedback anyway. The "Check It!" button is only for when you believe you have completed the step and should move on. Remember that a new terminal session in Codio can be opened at any time through the top menu via Tools > Terminal.

5. Create the Module

The first file to create is the file currency.py, as this will be the main module for the project. You will not add any function stubs yet. Instead, we want you to add only the following three items right now (in order):

The module docstring with name and date.

A single import statement, importing introcs.

An assignment statement creating the global variable APIKEY.

You should assign APIKEY to the passkey (as a string) that you got from the course Canvas page.

The docstring of this module should be as follows:

"""

Module for currency exchange

This module provides several string parsing functions to implement a simple

currency exchange routine using an online currency service. The primary function

in this module is exchange().

Author: NAME

Date:TODAY

"""

Replace NAME and TODAY with the correct values.

The next file to create is the file exchangeit.py, which provides the text-driven user interface. You will not return to this file until the end of the project, but it is helpful to set it up now. Right now, this file should only contain two things:

The module docstring with name and date.

A single import statement, importing currency.

The docstring of this script should be as follows:

"""

User interface for module currency

When run as a script, this module prompts the user for two currencies and amount.

It prints out the result of converting the first currency to the second.

Author: NAME

Date:TODAY

"""

Replace NAME and TODAY with the correct values.

Check the Script

You may run this test multiple times.

7. Create the Test Script

The final file to create is the file testcurrency.py, which is the test script for this project. We do not want you to add test procedures yet. Right now, we just want you to create the file with the following four items (in order):

The module docstring with name and date.

An import statement for the module introcs.

An import statement for the module currency.

A print statement displaying "All tests completed successfully."

The docstring of this script should be as follows:

"""

Unit tests for module currency

When run as a script, this module invokes several procedures that test

the various functions in the module currency.

Author: NAME

Date:TODAY

"""

Replace NAME and TODAY with the correct values.

Check the Script

You may run this test multiple times.

8. Expand the Test Script

You should now add a test procedure stub to testcurrency.py for every function that you are going to implement in the project. Each stub will have a specification and a print statement. For example, for the function before_space, you should make a test procedure called test_before_space (which takes no arguments). It should have the docstring:

"""Test procedure for before_space"""

and should print out the message "Testing before_space".

Do the same for every other function in the project. The project functions are as follows: before_space, after_space, first_inside_quotes, get_src, get_dst, has_error, service_response, iscurrency and exchange.

In addition, remember to call the test procedures at the bottom of the script, but above the final print statement. When you are done, the script should display the following:

codio@mike-panther:~/workspace/exercise1$ python3 testcurrency.py

Testing before_space

Testing after_space

Testing first_inside_quotes

Testing get_src

Testing get_dst

Testing has_error

Testing service_response

Testing iscurrency

Testing exchange

All tests completed successfully

Check the Procedures

You may run this script multiple times.

9. Stub the Function before_space

A large part of this project is breaking up a JSON string. Conceptually, you want to separate the currency amount from the currency name. For example, if you are given the string:

"0.863569 Euros"

Then you want to break it up into "0.863569" and "Euros". This is the motivation for the functions in this section.

The function before_space has the following specification:

"""

Returns the substring of s up to, but not including, the first space.

Example: before_space('Hello World') returns 'Hello'

Parameter s: the string to slice

Precondition: s is a string with at least one space in it

"""

Add a stub for this function (including the specification) to the file currency.py.

Check the Stub

You may run this test multiple times

10. Add Test Cases for before_space

Reread the specification for before_space, paying close attention to the precondition. Create test cases for this function and add them to the test procedure test_before_space in testcurrency.py. Remember, to implement a test case:

Call the function on a sample input of your choice.

Store the returned result as a variable.

Compare the result with the expected output using assert_equals in introcs.

See the Unit Test Functions in the IntroCS API for more information.

When designing test cases for before_space, think about how spaces may occur in the string - both position and frequency - and how that can affect the result.

Check the Test Cases

You may call this function multiple times.

11. Implement the Function before_space

Implement the function according to the specification. Use the test script testcurrency.py to aid your development before checking your answer below.

Check the Function

You may run this test multiple times.

12. Stub the Function after_space

The function after_space is the dual to before_space. One will allow us to get the currency amount, and the other will allow us to get the currency name.

The function after_space has the following specification:

"""

Returns the substring of s after the first space

Example: after_space('Hello World') returns 'World'

Parameter s: the string to slice

Precondition: s is a string with at least one space in it

"""

Add a stub for this function (including the specification) to the file currency.py.

Check the Stub

You may run this test multiple times.

13. Add Test Cases for after_space

When designing test cases for after_space, think about how spaces may occur in the string - both position and frequency - and how that can effect the result. Because after_space processes spaces differently than before_space, there are certain tests that are important for after_space that were not necessarily important for before_space (and vice versa).

Check the Test Cases

You may run this test multiple times.

14. Implement the Function after_space

Implement the function according to the specification. Use the test script testcurrency.py to aid your development before checking your answer below.

Check the Function

You may run this test multiple times.

15. Enforce the Preconditions

Both before_space and after_space have the same preconditions. Add assert statements to both of these functions enforcing the preconditions. Error messages are not necessary.

Remember that test scripts are not designed to check assert statements. If you want to check your assert statements, you will need to check them manually:

codio@mike-panther:~/workspace$ python3

Python 3.6.6 (default, Jul 31 2018, 22:09:10)

[GCC 4.8.4] on linux

Type "help", "copyright", "credits" or "license" for more information.

>>> import currency

>>> currency.before_space(3)

Check the Asserts

You may run this test multiple times.

16. Stub the Function first_inside_quotes

Note that JSON strings have a lot of elements inside quotes:

'{"success": true, "src": "2 United States Dollars", "dst": "1.772814 Euros", "error": ""}'

We need a function that can extract the parts of the string that are inside quotes. That is the purpose of the function first_inside_quotes, which has the following specification:

"""

Returns the first substring of s between two (double) quote characters

Note that the double quotes must be part of the string.So "Hello World" is a

precondition violation, since there are no double quotes inside the string.

Example: first_inside_quotes('A "B C" D') returns 'B C'

Example: first_inside_quotes('A "B C" D "E F" G') returns 'B C', because it only

picks the first such substring.

Parameter s: a string to search

Precondition: s is a string with at least two (double) quote characters inside

"""

Add a stub for this function (including the specification) to the file currency.py.

Check the Stub

You may run this test multiple times.

17. Add Test Cases for first_inside_quotes

When designing test cases for first_inside_quotes, think about how quotes may occur in the string - both position and frequency - and how that can affect the result.

Your test cases will have to contain double quotes. Remember that "Hello" is not a valid input. Those double quotes are not part of the string. To ensure that the double quotes are part of the string, you may need to use escape characters.

Check the Test Cases

You may run this test multiple times.

18. Implement the Function first_inside_quotes

Implement the function according to the specification. Use the test script testcurrency.py to aid your development before checking your answer below.

Check the Function

You may run this test multiple times.

19. Enforce the Precondition

Review the precondition for first_inside_quotes. Add assert statements to this function enforcing the precondition. Error messages are not necessary.

Remember that test scripts are not designed to check assert statements. If you want to check your assert statements, you will need to check them manually:

codio@mike-panther:~/workspace$ python3

Python 3.6.6 (default, Jul 31 2018, 22:09:10)

[GCC 4.8.4] on linux

Type "help", "copyright", "credits" or "license" for more information.

>>> import currency

>>> currency.first_inside_quotes("Hello")

Check the Asserts

You may run this test multiple times.

20. Stub the Function get_src

The function first_inside_quotes will only access the first set of data inside quotes. To process our JSON strings, we need more targeted extraction functions, which is the purpose of the three functions in this section. Most (if not all) of the functions in this section will use first_inside_quotes as a helper.

The function get_src has the following specification:

"""

Returns the src value in the response to a currency query.

Given a JSON string provided by the web service, this function returns the string

inside string quotes (") immediately following the substring '"src"'. For example,

if the json is

'{"success": true, "src": "2 United States Dollars", "dst": "1.772814 Euros", "error": ""}'

then this function returns '2 United States Dollars' (not '"2 United States Dollars"').

On the other hand if the json is

'{"success":false,"src":"","dst":"","error":"Source currency code is invalid."}'

then this function returns the empty string.

The web server does NOT specify the number of spaces after the colons. The JSON

'{"success":true, "src":"2 United States Dollars", "dst":"1.772814 Euros", "error":""}'

is also valid (in addition to the examples above).

Parameter json: a json string to parse

Precondition: json a string provided by the web service (ONLY enforce the type)

"""

Add a stub for this function (including the specification) to the file currency.py.

Check the Stub

You may run this test multiple times.

21. Add Test Cases for get_src

When designing test cases for get_src, look very closely at the precondition. It says that the string must be a valid response from the web service. This is an extremely restrictive precondition, so it limits the possible test cases significantly. However, notice the comment about colons in the specification. That will be important for your test cases.

Check the Test Cases

You may run this test multiple times.

22. Implement the Function get_src

Implement the function according to the specification. An ideal solution will use first_inside_quotes as a helper. Use the test script testcurrency.py to aid your development before checking your answer below.

Check the Function

You may run this test multiple times.

23. Stub the Function get_dst

The function get_dst is very similar to get_src. It has the following specification:

"""

Returns the dst value in the response to a currency query.

Given a JSON string provided by the web service, this function returns the string

inside string quotes (") immediately following the substring '"dst"'. For example,

if the json is

'{"success": true, "src": "2 United States Dollars", "dst": "1.772814 Euros", "error": ""}'

then this function returns '1.772814 Euros' (not '"1.772814 Euros"'). On the other

hand if the json is

'{"success":false,"src":"","dst":"","error":"Source currency code is invalid."}'

then this function returns the empty string.

The web server does NOT specify the number of spaces after the colons. The JSON

'{"success":true, "src":"2 United States Dollars", "dst":"1.772814 Euros", "error":""}'

is also valid (in addition to the examples above).

Parameter json: a json string to parse

Precondition: json a string provided by the web service (ONLY enforce the type)

"""

Add a stub for this function (including the specification) to the file currency.py.

Check the Stub

You may run this test multiple times.

24. Add Test Cases for get_dst

When designing test cases for get_src, look very closely at the precondition. Note that whenever the "src" value is empty, the "dst" value must be as well. This means that the test cases for the two are very similar.

Check the Test Cases

You may run this test multiple times.

25. Implement the Function get_dst

Implement the function according to the specification. The solution will be very similar to get_src. Use the test script testcurrency.py to aid your development before checking your answer below.

Check the Function

You may run this test multiple times.

26. Stub the Function has_error

The function has_error is similar to get_src and get_dst except that it returns a boolean instead of a string. It has the following specification:

"""

Returns True if the response to a currency query encountered an error.

Given a JSON string provided by the web service, this function returns True if the

query failed and there is an error message. For example, if the json is

'{"success":false,"src":"","dst":"","error":"Source currency code is invalid."}'

then this function returns True (It does NOT return the error message

'Source currency code is invalid'). On the other hand if the json is

'{"success": true, "src": "2 United States Dollars", "dst": "1.772814 Euros", "error": ""}'

then this function returns False.

The web server does NOT specify the number of spaces after the colons. The JSON

'{"success":true, "src":"2 United States Dollars", "dst":"1.772814 Euros", "error":""}'

is also valid (in addition to the examples above).

Parameter json: a json string to parse

Precondition: json a string provided by the web service (ONLY enforce the type)

"""

Add a stub for this function (including the specification) to the file currency.py.

Check the Stub

You may run this test multiple times.

27. Add Test Cases for has_error

Once again, the precondition for has_error is very similar to get_src and get_dst. This suggests that the test cases are similar. Because this function returns a boolean, you are free to use assert_true and assert_false instead of assert_equals when creating your test cases.

Check the Test Cases

You may run this test multiple times.

28. Implement the Function has_error

Implement the function according to the specification. Remember that you may not use conditionals (if-statements). Instead, you should use what you know about boolean expressions. Use the test script testcurrency.py to aid your development before checking your answer below.

Check the Function

You may run this test multiple times.

29. Enforce the Preconditions

All of the functions get_src, get_dst, and has_error have the same preconditions. The precondition is quite complex and effectively impossible to enforce (without significantly more knowledge of Python). But that is okay. Enforcing preconditions is a good idea, but it is not mandatory. You are allowed to enforce all, none, or even part of a specification. So reread the specification and only enforce what you are directed to enforce.

Remember that test scripts are not designed to check assert statements. If you want to check your assert statements, you will need to check them manually:

codio@mike-panther:~/workspace$ python3

Python 3.6.6 (default, Jul 31 2018, 22:09:10)

[GCC 4.8.4] on linux

Type "help", "copyright", "credits" or "license" for more information.

>>> import currency

>>> currency.get_src(3)

Check the Asserts

You may run this test multiple times.

30. Stub the Function service_response

The function service_response is the heart of this project. It is the function that connects to the web service and returns a JSON string. It has the following specification:

"""

Returns a JSON string that is a response to a currency query.

A currency query converts amt money in currency src to the currency dst. The response

should be a string of the form

'{"success": true, "src": "", dst: "", error: ""}'

where the values src-amount and dst-amount contain the value and name for the src

and dst currencies, respectively. If the query is invalid, both src-amount and

dst-amount will be empty, and the error message will not be empty.

There may or may not be spaces after the colon.To test this function, you should

chose specific examples from your web browser.

Parameter src: the currency on hand

Precondition src is a nonempty string with only letters

Parameter dst: the currency to convert to

Precondition dst is a nonempty string with only letters

Parameter amt: amount of currency to convert

Precondition amt is a float or int

"""

Add a stub for this function (including the specification) to the file currency.py.

Check the Stub

You may run this test multiple times.

31. Add Test Cases for service_response

Creating test cases for service_response is a bit of a challenge. A test case requires both an input and an expected output. You need to know what the web service will respond with in order to get the expected output. Fortunately, we have shown you how to play with the web service in your web browser. Look at the following URL:

https://ecpyfac.ecornell.com/python/currency/fixed?src=USD&dst=EUR&amt=2.5&key=a1b2c3d4

a1b2c3d4 is a demonstration passkey that only works on this query. To try other queries, you will need to use your own passkey.

Looking at this link you see that service_response('USD','EUR',2.5) should return

'{"success": true, "src": "2.5 United States Dollars", "dst": "2.2160175 Euros", "error": ""}'

Note that we had to add additional single quotes to turn the answer into a string. Use this process to come up with more test cases for your function.

Warning: The verification process below is potentially slow since it has to connect to the web service.

Check the Test Cases

You may run this test multiple times.

32. Implement the Function service_response

Implement the function according to the specification. To, you will need a function that connects to a web page/service. Fortunately, there is such a function. Look at the Web Access Functions in the IntroCS API and find the function urlread. The purpose of this function is to generate the corresponding URL query string with the provided currency values and return a JSON string as a response to the query.

Try this function out in the interactive shell using the query from the following step:

codio@mike-panther:~/workspace$ python3

Python 3.6.6 (default, Jul 31 2018, 22:09:10)

[GCC 4.8.4] on linux

Type "help", "copyright", "credits" or "license" for more information.

>>> import introcs

>>> q = 'https://ecpyfac.ecornell.com/python/currency/fixed?src=USD&dst=EUR&amt=2.5&key=a1b2c3d4'

>>> introcs.urlread(q)

'{"success": true, "src": "2.5 United States Dollars", "dst": "2.2160175 Euros", "error": ""}'

See how this works? In this example, the source currency is USD (for US Dollars) and the destination is EUR (for Euros), and the amount of dollars to convert to Euros is the value of amt, 2.5. In the returned JSON string, the value of 2.4 Dollars in Euros is shown as "2.2160175". For other amounts or currencies, you would change the value of src, dst, or amt.

Use this function to implement service_response. Use the test script testcurrency.py to aid your development before checking your answer below.

Warning: The verification process below is potentially slow since it has to connect to the web service.

33. Enforce the Preconditions

The preconditions for service_response are straight-forward. However, notice that there are three parameters. You will need assert statements to cover the preconditions for each parameter. Error messages are not necessary.

Remember that test scripts are not designed to check assert statements. If you want to check your assert statements, you will need to check them manually:

codio@mike-panther:~/workspace$ python3

Python 3.6.6 (default, Jul 31 2018, 22:09:10)

[GCC 4.8.4] on linux

Type "help", "copyright", "credits" or "license" for more information.

>>> import currency

>>> currency.service_response('A B','C',2)

Check the Asserts

You may run this test multiple times.

34. Stub the Function iscurrency

The last two functions are the goal of the assignment: a function to check if a currency code is valid, and a function to compute the exchange rate given two currency codes. The first of these, iscurrency has the following specification:

"""

Returns True if currency is a valid (3 letter code for a) currency.

It returns False otherwise.

Parameter currency: the currency code to verify

Precondition: currency is a nonempty string with only letters

"""

Add a stub for this function (including the specification) to the file currency.py.

Check the Stub

You may run this test multiple times.

35. Add Test Cases for iscurrency

The test cases for iscurrency are limited by the precondition. Remember, you should never implement a test case that violates the precondition. Because the precondition is so strong, there are really only two significantly different tests here. Can you figure them out?

Warning: The verification process below is potentially slow, since it has to connect to the web service.

Check the Test Cases

You may run this test multiple times.

36. Implement the Function iscurrency

Many students find iscurrency to be the trickiest function in the project. We will give you a hint. The only way to figure out if a currency is valid is to ask the web service. That means this function should use service_response as a helper. But you only have one currency, not two. So think about how you could call this function with only one currency variable.

In addition, you may find some of the other functions that you developed earlier useful as helpers. As always use the test script testcurrency.py to aid your development before checking your answer below.

Warning: The verification process below is potentially slow, since it has to connect to the web service.

Check the Function

You may run this test multiple times.

37. Stub the Function exchange

The function exchange is the end goal of this assignment. It is the function that you will call in the application script exchangeit.py. It has the following specification:

"""

Returns the amount of currency received in the given exchange.

In this exchange, the user is changing amt money in currency src to the currency

dst. The value returned represents the amount in currency currency_to.

The value returned has type float.

Parameter src: the currency on hand

Precondition src is a string for a valid currency code

Parameter dst: the currency to convert to

Precondition dst is a string for a valid currency code

Parameter amt: amount of currency to convert

Precondition amt is a float or int

"""

Add a stub for this function (including the specification) to the file currency.py.

Check the Stub

You may run this test multiple times.

38. Add Test Cases for exchange

Once again, exchange has very strong preconditions that heavily restrict the allowable inputs. Once again, there are really only two significantly different tests here. Can you figure them out?

Warning: The verification process below is potentially slow, since it has to connect to the web service.

Check the Test Cases

You may run this test multiple times.

39. Implement the Function exchange

The implementation of exchange will require many (but not all) of the functions that you have implemented so far as helpers. Think about the functions you have implemented as "building blocks" and how they can help you implement this function.

As always use the test script testcurrency.py to aid your development before checking your answer below.

Warning: The verification process below is potentially slow, since it has to connect to the web service.

Check the Function

You may run this test multiple times.

40. Enforce the Preconditions

The functions iscurrency and exchange have very different preconditions. But at this point you should understand enforcing preconditions enough to add the appropriate assert statements.

The one challenging function is exchange. Note that it requires that the arguments src and dst be valid currency codes. Is there a function that could help you with this?

Check the Asserts

You may run this test multiple times.

41. Implement the Application Script

Now that you have completed the module currency.py, you are ready to work on the script exchangeit.py. This script is just that - a script. It should not contain any function definitions. It should just contain a sequence of Python statements that

Ask the the user for a first currency code

Ask the the user for a second currency code

Ask the the user for an amount (of the first currency)

Prints the conversion to the second currency

The following example shows you what the script should do when you run it.

codio@mike-panther:~/workspace$ python3 exchangeit.py

3-letter code for original currency: USD

3-letter code for the new currency: EUR

Amount of the original currency: 2.5

You can exchange 2.5 USD for 2.216 EUR.

Notice the wording, spacing, and punctuation. In addition, the final print statement rounds the exchange amount to three decimal places. Your implementation must match this.

42. Review the Style Guidelines

Before submitting the project, make sure you have obeyed the style guidelines. Remember

Every function must have a complete specification.

Every module must start with a docstring with your name and date.

There must be two blank lines between any two function definitions.

Function bodies should be indented with 4 spaces.

No non-docstring line may be longer than 80 characters.

Many of the specifications we gave you violate that last rule (because we did not want to break up the JSON strings). But it is okay for a specification to run overlong in some cases.

Check the Style

You may run this test multiple times.

43. Reflect and Submit

Congratulations. You have now completed a real Python application. Of course a lot of the hard-work was done for you. We provided the specifications and you coded to spec. But this is not uncommon for an entry-level developer. Now that you have seen how the application fits together, you may start to see why we made the choices that we did.

If you were to design the specifications yourself, what would you have changed?

Lines inside of a docstring may be longer than 80 characters.

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image_2

Step: 3

blur-text-image_3

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Modern Dental Assisting

Authors: Doni Bird, Debbie Robinson

13th Edition

978-0323624855, 0323624855

Students also viewed these Programming questions