diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0cfb762 --- /dev/null +++ b/.gitignore @@ -0,0 +1,130 @@ +# Byte-compiled / optimized / DLL files +.idea/* +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ diff --git a/calculator.py b/calculator.py index a46affd..87d3e03 100644 --- a/calculator.py +++ b/calculator.py @@ -1,3 +1,5 @@ +from wsgiref.simple_server import make_server +import traceback """ For your homework this week, you'll be creating a wsgi application of your own. @@ -41,17 +43,73 @@ """ +def index(): + """ Returns a STRING with the sum of the arguments """ + example_list = [ + '/add/400/23/10', + '/subtract/23', + '/multiply/21/43', + '/divide/2000/50' + ] + + body = [ + '

WSGI CALCULATOR

', + '

Here\'s how to use this tool:

', + '

You will use the path in the url browser to calculate values. Your path will have a format of:

', + '

/{function}/{arg1}/{arg2}/{arg3}/...

', + '

The calculator will then use the function and apply it to the list of ', + 'arguments in the path. Please see below for examples on how to formulate urls. ', + 'Each link will provide the result from the calculation.

' + '

Examples:

', + '') + return '\n'.join(body) + def add(*args): """ Returns a STRING with the sum of the arguments """ - # TODO: Fill sum with the correct value, based on the - # args provided. - sum = "0" + summation = 0 + for number in args: + summation += int(number) + + return str(summation) + + +def subtract(*args): + """ Returns a STRING with the result of the arguments """ + + base_num = int(args[0]) + for index in range(1, len(args)): + base_num -= int(args[index]) + + return str(base_num) + - return sum +def multiply(*args): + """ Returns a STRING with the product of the arguments """ + + product = int(args[0]) + for number in range(1, len(args)): + product *= int(args[number]) + + return str(product) + + +def divide(*args): + """ Returns a STRING with the quotient of the arguments """ + + quotient = int(args[0]) + for number in range(1, len(args)): + quotient /= int(args[number]) + + return str(quotient) -# TODO: Add functions for handling more arithmetic operations. def resolve_path(path): """ @@ -59,26 +117,61 @@ def resolve_path(path): arguments. """ - # TODO: Provide correct values for func and args. The + # Provide correct values for func and args. The # examples provide the correct *syntax*, but you should # determine the actual values of func and args using the # path. - func = add - args = ['25', '32'] + funcs = { + '/': index, + 'add': add, + 'subtract': subtract, + 'multiply': multiply, + 'divide': divide + } + if path == '/': + func_name = path + else: + path = path.strip('/').split('/') + func_name = path[0] + args = path[1:] + + try: + func = funcs[func_name] + except KeyError: + raise NameError return func, args + def application(environ, start_response): - # TODO: Your application code from the book database + # Your application code from the book database # work here as well! Remember that your application must # invoke start_response(status, headers) and also return # the body of the response in BYTE encoding. # # TODO (bonus): Add error handling for a user attempting # to divide by zero. - pass + headers = [("Content-type", "text/html")] + try: + path = environ.get('PATH_INFO', None) + if path is None: + raise NameError + func, args = resolve_path(path) + body = func(*args) + status = "200 OK" + except NameError: + status = "404 Not Found" + body = "

Not Found

" + except Exception: + status = "500 Internal Server Error" + body = "

Internal Server Error

" + print(traceback.format_exc()) + finally: + headers.append(('Content-length', str(len(body)))) + start_response(status, headers) + return [body.encode('utf8')] + if __name__ == '__main__': - # TODO: Insert the same boilerplate wsgiref simple - # server creation that you used in the book database. - pass + srv = make_server('localhost', 8080, application) + srv.serve_forever() diff --git a/tests.py b/tests.py index c2a8dcb..80cbb4d 100644 --- a/tests.py +++ b/tests.py @@ -30,6 +30,7 @@ def get_response(self, url): conn.request('GET', url) response = conn.getresponse() + self.assertEqual(200, response.getcode()) conn.close()