diff --git a/submissions/eoneoff/data-structures-http/data_structures/__init__.py b/submissions/eoneoff/data-structures-http/data_structures/__init__.py new file mode 100644 index 0000000..420621f --- /dev/null +++ b/submissions/eoneoff/data-structures-http/data_structures/__init__.py @@ -0,0 +1,2 @@ +from .stack import Stack +from .linked_list import LinkedList diff --git a/submissions/eoneoff/data-structures-http/data_structures/linked_list.py b/submissions/eoneoff/data-structures-http/data_structures/linked_list.py new file mode 100644 index 0000000..6487ad4 --- /dev/null +++ b/submissions/eoneoff/data-structures-http/data_structures/linked_list.py @@ -0,0 +1,44 @@ +from .node import Node + +class LinkedList: + def __init__(self): + self._root = None + self._length = 0 + + def __iter__(self): + current = self._root + while current: + yield current + current = current.next + + def insert(self, value, successor = None): + if(successor and self._root.value != successor): + for node in self: + if node.next and node.next.value == successor: + node.next = Node(value, node.next) + self._length+=1 + return + error_message = f'Value {successor} is not in the list' + raise ValueError(error_message) + else: + self._root = Node(value, self._root) + self._length+=1 + + def remove(self, value): + if self._root.value == value: + self._root = self._root.next + self._length-=1 + return + for node in self: + if node.next and node.next.value == value: + node.next = node.next.next + self._length-=1 + return + error_message = f'Value {value} is not in the list' + raise ValueError(error_message) + + def show_list(self): + return [node.value for node in self] + + def __len__(self): + return self._length diff --git a/submissions/eoneoff/data-structures-http/data_structures/node.py b/submissions/eoneoff/data-structures-http/data_structures/node.py new file mode 100644 index 0000000..564e864 --- /dev/null +++ b/submissions/eoneoff/data-structures-http/data_structures/node.py @@ -0,0 +1,20 @@ +class Node: + def __init__(self, value = None, next = None): + self._value = value + self._next = next + + @property + def value(self): + return self._value + + @value.setter + def value(self, value): + self._value = value + + @property + def next(self): + return self._next + + @next.setter + def next(self, value): + self._next = value diff --git a/submissions/eoneoff/data-structures-http/data_structures/stack.py b/submissions/eoneoff/data-structures-http/data_structures/stack.py new file mode 100644 index 0000000..7a0c27d --- /dev/null +++ b/submissions/eoneoff/data-structures-http/data_structures/stack.py @@ -0,0 +1,21 @@ +from .node import Node + +class Stack: + def __init__ (self): + self._root = None + self._length = 0 + + def push(self, value): + self._root = Node(value, self._root) + self._length+=1 + + def pop(self): + if self._length: + out = self._root.value + self._root = (self._root or None) and self._root.next + self._length-=1 + return out + else: return None + + def __len__(self): + return self._length diff --git a/submissions/eoneoff/data-structures-http/main.py b/submissions/eoneoff/data-structures-http/main.py new file mode 100644 index 0000000..74e290a --- /dev/null +++ b/submissions/eoneoff/data-structures-http/main.py @@ -0,0 +1,35 @@ +"""Data structues with html assess + + The assess to data structues is provided through html requests + + stack + /stack + + POST request with json object of format {"data":} pushes vaule to stack + + DELETE request pops a value from a stack and returns in in json object of format + {"data": /list + + GET request returns the contents of list in a json object + + POST request with json object of format + { + "data": [, + "sucessor": ] + } + inserts value into list + + DELETE request with json object of format {"data":} removes + the value from the list + + If data is not presented in json format, if it is not string or number or if a successor + or an item to remove is not in the list a Bad Reques code is returned +""" + +from data_structures import * +from server import * + +DataServer(Stack, LinkedList).run() \ No newline at end of file diff --git a/submissions/eoneoff/data-structures-http/server/__init__.py b/submissions/eoneoff/data-structures-http/server/__init__.py new file mode 100644 index 0000000..100d0fc --- /dev/null +++ b/submissions/eoneoff/data-structures-http/server/__init__.py @@ -0,0 +1 @@ +from .server import DataServer \ No newline at end of file diff --git a/submissions/eoneoff/data-structures-http/server/handler.py b/submissions/eoneoff/data-structures-http/server/handler.py new file mode 100644 index 0000000..0624f21 --- /dev/null +++ b/submissions/eoneoff/data-structures-http/server/handler.py @@ -0,0 +1,84 @@ +from http.server import BaseHTTPRequestHandler +import json +import cgi + +class DataHandler(BaseHTTPRequestHandler): + def __init__(self, stack, linked_list, *args): + self._stack = stack + self._list = linked_list + super().__init__(*args) + + def _set_headers(self): + self.send_response(200) + self.send_header('Content-type', 'application/json') + self.end_headers() + + def do_HEAD(self): + self._set_headers() + + @staticmethod + def _value_is_valid(value): + return type(value) == str \ + or type(value) == int \ + or type(value) == float + + def _request_is_json(self): + ctype,_ = cgi.parse_header(self.headers.get('content-type')) + if ctype!='application/json': + self.send_error(400, 'Wrong content type') + return False + else: return True + + def _get_request_data(self): + length = int(self.headers.get('content-length')) + return json.loads(self.rfile.read(length)) + + def _get_structure_type(self): + structure_type = self.path.split('/')[1] + return structure_type if structure_type in ['stack', 'list'] else None + + + def do_GET(self): + if(self._get_structure_type() == 'list'): + self._set_headers() + self.wfile.write(str.encode(json.dumps({'data':self._list.show_list()}))) + + def do_POST(self): + if(self._request_is_json()): + data = self._get_request_data() + if DataHandler._value_is_valid(data['data']): + structure_type = self._get_structure_type() + if structure_type == 'stack': + self._stack.push(data['data']) + self.send_response(200) + self.end_headers() + elif structure_type == 'list': + successor = data.setdefault('successor') + if not successor or DataHandler._value_is_valid(successor): + try: + self._list.insert(data['data'], successor) + self.send_response(200) + self.end_headers() + except ValueError as err: + self.send_error(400, str(err)) + else: self.send_error(400, 'Wrong successor format') + else: self.send_error(400, 'Wrong value type') + else: self.send_error(400, 'Wrong content type') + + def do_DELETE(self): + structure_type = self._get_structure_type() + if structure_type == 'stack': + self._set_headers() + self.wfile.write(str.encode(json.dumps({'data': self._stack.pop()}))) + elif structure_type == 'list': + if self._request_is_json(): + data = self._get_request_data() + if DataHandler._value_is_valid(data['data']): + try: + self._list.remove(data['data']) + self.send_response(200) + self.end_headers() + except ValueError as err: + self.send_error(400, str(err)) + else: self.send_error(400, 'Wrong data type') + else: self.send_error(400, 'Wrong content type') diff --git a/submissions/eoneoff/data-structures-http/server/server.py b/submissions/eoneoff/data-structures-http/server/server.py new file mode 100644 index 0000000..3b396e9 --- /dev/null +++ b/submissions/eoneoff/data-structures-http/server/server.py @@ -0,0 +1,12 @@ +from http.server import HTTPServer +from .handler import DataHandler + +class DataServer(HTTPServer): + def __init__(self, queue, linked_list, host='localhost', port=8000): + self._queue = queue() + self._list = linked_list() + super().__init__((host, port), + lambda *args: DataHandler(self._queue, self._list, *args)) + + def run(self): + self.serve_forever() \ No newline at end of file