diff --git a/calculator.py b/calculator.py
index a46affd..30c2107 100644
--- a/calculator.py
+++ b/calculator.py
@@ -40,45 +40,111 @@
"""
+import traceback
+from numpy import prod
def add(*args):
""" Returns a STRING with the sum of the arguments """
+ return sum(map(int, args))
+
+
+def subtract(*args):
+ """ Returns a STRING, in which the first number retains its value, the remaining numbers
+ take their negative value, and all numbers are summed."""
+ args_mut = []
+ for i in range(len(args)):
+ args_mut.append('')
+ if i == 0:
+ args_mut[i] = int(args[i])
+ else:
+ args_mut[i] = int(args[i]) * -1
+ return sum(map(int, args_mut))
+
+
+def multiply(*args):
+ """ Returns a STRING, in which all numbers are multiplied in sequence."""
+ return prod(list(map(int, args)))
+
+
+def divide(*args):
+ """ Returns a STRING, in which the numbers are divided in sequence.
+ ZeroDivisionError included."""
+ if '0' in args[1:]:
+ raise ZeroDivisionError
+
+ args_mut = []
+ for arg in args:
+ args_mut.append(int(arg))
+ quotient = args_mut[0]
+ for i in range(1, len(args_mut)):
+ quotient /= args_mut[i]
+
+ return quotient
+
+
+def instructions():
+ """Return an html string of instructions."""
+ page = """
+
Instructions
+
+- add, subtract, multiply, or divide goes after root
+- any sequence of integers separated by / goes next
+- example: http://127.0.0.1:8080/divide/2/5/9/10
+
+"""
- # TODO: Fill sum with the correct value, based on the
- # args provided.
- sum = "0"
-
- return sum
+ return page
-# TODO: Add functions for handling more arithmetic operations.
def resolve_path(path):
"""
Should return two values: a callable and an iterable of
arguments.
"""
+ funcs = {'': instructions, 'add': add, 'subtract': subtract, 'multiply': multiply,
+ 'divide': divide}
+
+ path = path.strip('/').split('/')
- # TODO: 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']
+ 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
- # 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
+ """Provide the response, including for raised ZeroDivisionError."""
+ 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 ZeroDivisionError:
+ status = "403 Forbidden"
+ body = "Division by Zero Not Permitted
"
+ except Exception:
+ status = "500 Internal Server Error"
+ body = "Internal Server Error
"
+ print(traceback.format_exc())
+ finally:
+ headers.append(('Content-length', str(len(str(body)))))
+ start_response(status, headers)
+ return [str(body).encode('utf8')]
+
if __name__ == '__main__':
- # TODO: Insert the same boilerplate wsgiref simple
- # server creation that you used in the book database.
- pass
+ from wsgiref.simple_server import make_server
+ srv = make_server('127.0.0.1', 8080, application)
+ srv.serve_forever()
diff --git a/tests.py b/tests.py
index c2a8dcb..7a91ed5 100644
--- a/tests.py
+++ b/tests.py
@@ -26,7 +26,7 @@ def get_response(self, url):
Helper function to get a response from a given url, using http.client
"""
- conn = http.client.HTTPConnection('localhost:8080')
+ conn = http.client.HTTPConnection('127.0.0.1:8080')
conn.request('GET', url)
response = conn.getresponse()