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:
',
+ '',
+ ]
+
+ item_template = '- http://localhost:8080{}
'
+ for path in example_list:
+ body.append(item_template.format(path, path))
+ body.append('
')
+ 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()