diff --git a/dist/app-1.0.0-py3-none-any.whl b/dist/app-1.0.0-py3-none-any.whl index 4fafb46..48bab7c 100644 Binary files a/dist/app-1.0.0-py3-none-any.whl and b/dist/app-1.0.0-py3-none-any.whl differ diff --git a/dist/app-1.0.0.tar.gz b/dist/app-1.0.0.tar.gz index a91d9da..c74ea22 100644 Binary files a/dist/app-1.0.0.tar.gz and b/dist/app-1.0.0.tar.gz differ diff --git a/src/app/__init__.py b/src/app/__init__.py index 7e315cc..45ab4ae 100644 --- a/src/app/__init__.py +++ b/src/app/__init__.py @@ -1,9 +1,9 @@ -import logging +import logging logging.basicConfig( level=logging.DEBUG, - format='%(asctime)s - %(levelname)s - %(message)s', - datefmt='%Y-%m-%d %H:%M:%S' + format="%(asctime)s - %(levelname)s - %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", ) log = logging.getLogger(__name__) diff --git a/src/app/__main__.py b/src/app/__main__.py index e7713f8..2c9f57e 100644 --- a/src/app/__main__.py +++ b/src/app/__main__.py @@ -1,13 +1,11 @@ -from aiohttp import web -from .app import create_app from .args import parse_args from .server import serve + def main(): args = parse_args() serve(args.host, args.port) -if __name__ == '__main__': +if __name__ == "__main__": main() - diff --git a/src/app/app.py b/src/app/app.py index 25277e2..40b8e21 100644 --- a/src/app/app.py +++ b/src/app/app.py @@ -1,29 +1,41 @@ -from aiohttp import web +import json import time -from . import log -import json import uuid + import dataset +from aiohttp import web + +from . import log + def get_timestamp(): from datetime import datetime + now = datetime.now() formatted_datetime = now.strftime("%Y-%m-%d %H:%M:%S") return formatted_datetime + class BaseApplication(web.Application): - def __init__(self, username = None, password=None, cookie_name=None,session=None, *args, **kwargs): + def __init__( + self, + username=None, + password=None, + cookie_name=None, + session=None, + *args, + **kwargs, + ): self.cookie_name = cookie_name or str(uuid.uuid4()) - self.username = username - self.password = password + self.username = username + self.password = password self.session = session or {} - middlewares = kwargs.pop("middlewares",[]) + middlewares = kwargs.pop("middlewares", []) middlewares.append(self.request_middleware) middlewares.append(self.base64_auth_middleware) middlewares.append(self.session_middleware) super().__init__(*args, **kwargs) - async def authenticate(self, username, password): return self.username == username and self.password == password @@ -37,58 +49,60 @@ class BaseApplication(web.Application): return web.Response( status=401, text="Unauthorized", - headers={"WWW-Authenticate": 'Basic realm="Restricted"'} + headers={"WWW-Authenticate": 'Basic realm="Restricted"'}, ) - + try: encoded_credentials = auth_header.split(" ", 1)[1] decoded_credentials = base64.b64decode(encoded_credentials).decode("utf-8") username, password = decoded_credentials.split(":", 1) except (ValueError, base64.binascii.Error): return web.Response(status=400, text="Invalid Authorization Header") - + if not await self.authenticate(username, password): return web.Response( status=401, text="Invalid Credentials", - headers={"WWW-Authenticate": 'Basic realm="Restricted"'} + headers={"WWW-Authenticate": 'Basic realm="Restricted"'}, ) - + return await handler(request) + @web.middleware async def request_middleware(self, request, handler): time_start = time.time() created = get_timestamp() request = await handler(request) time_end = time.time() - await self.insert("http_access",dict( - created=created, - path=request.path, - duration=time_end - time_start, - )) + await self.insert( + "http_access", + { + "created": created, + "path": request.path, + "duration": time_end - time_start, + }, + ) return request @web.middleware - async def session_middleware(self,request, handler): + async def session_middleware(self, request, handler): # Process the request and get the response cookies = request.cookies session_id = cookies.get(self.cookie_name, None) - setattr(request,"session", self.session.get(session_id,{})) + setattr(request, "session", self.session.get(session_id, {})) response = await handler(request) - + if not session_id: session_id = str(uuid.uuid4()) - response.set_cookie( - self.cookie_name, - session_id, - max_age=3600, - httponly=True - ) + response.set_cookie(self.cookie_name, session_id, max_age=3600, httponly=True) return response + class WebDbApplication(BaseApplication): - def __init__(self, db=None, db_web=False,db_path="sqlite:///:memory:",*args, **kwargs): + def __init__( + self, db=None, db_web=False, db_path="sqlite:///:memory:", *args, **kwargs + ): super().__init__(*args, **kwargs) self.db_web = db_web self.db_path = db_path @@ -103,53 +117,57 @@ class WebDbApplication(BaseApplication): self.router.add_post("/delete", self.delete_handler) async def insert_handler(self, request): - obj = await request.json() + await request.json() response = await self.insert(request.get("table"), request.get("data")) return web.json_response(response) async def update_handler(self, request): - obj = await request.json() - response = await self.update(request.get('table'), request.get('data'), request.get('where',{})) + await request.json() + response = await self.update( + request.get("table"), request.get("data"), request.get("where", {}) + ) return web.json_response(response) - + async def upsert_handler(self, request): - obj = await request.json() - response = await self.upsert(request.get('table'), request.get('data'), request.get('keys',[])) + await request.json() + response = await self.upsert( + request.get("table"), request.get("data"), request.get("keys", []) + ) return web.json_response(response) async def find_handler(self, request): - obj = await request.json() - response = await self.find(request.get('table'), requesst.get('where',{})) + await request.json() + response = await self.find(request.get("table"), requesst.get("where", {})) return web.json_response(response) async def find_one_handler(self, request): - obj = await request.json() - response = await self.find_one(request.get('table'), requesst.get('where',{})) + await request.json() + response = await self.find_one(request.get("table"), requesst.get("where", {})) return web.json_response(response) async def delete_handler(self, request): - obj = await request.json() - response = await self.delete(request.get('table'), requesst.get('where',{})) + await request.json() + response = await self.delete(request.get("table"), requesst.get("where", {})) return web.json_response(response) async def set(self, key, value): value = json.dumps(value, default=str) - self.db['kv'].upsert(dict(key=key,value=value),['key']) + self.db["kv"].upsert({"key": key, "value": value}, ["key"]) async def get(self, key, default=None): - record = self.db['kv'].find_one(key=key) + record = self.db["kv"].find_one(key=key) if record: - return json.loads(record.get('value','null')) + return json.loads(record.get("value", "null")) return default async def insert(self, table_name, data): return self.db[table_name].insert(data) async def update(self, table_name, data, where): - return self.db[table_name].update(data,where) + return self.db[table_name].update(data, where) async def upsert(self, table_name, data, keys): - return self.db[table_name].upsert(data,keys or []) + return self.db[table_name].upsert(data, keys or []) async def find(self, table_name, filters): if not filters: @@ -162,17 +180,15 @@ class WebDbApplication(BaseApplication): try: return dict(self.db[table_name].find_one(**filters)) except ValueError: - return None + return None async def delete(self, table_name, where): return self.db[table_name].delete(**where) - - class Application(WebDbApplication): - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.on_startup.append(self.on_startup_task) self.router.add_get("/", self.index_handler) @@ -189,19 +205,22 @@ class Application(WebDbApplication): self.running_since = get_timestamp() async def inc_request_count(self): - request_count = await self.get("root_request_count",0) + request_count = await self.get("root_request_count", 0) request_count += 1 await self.set("root_request_count", request_count) - return request_count + return request_count - async def index_handler(self,request): - - return web.json_response(dict( - request_count=await self.inc_request_count(), - timestamp=get_timestamp(), - uptime=self.uptime, - running_since=self.running_since - ),content_type="application/json") + async def index_handler(self, request): + + return web.json_response( + { + "request_count": await self.inc_request_count(), + "timestamp": get_timestamp(), + "uptime": self.uptime, + "running_since": self.running_since, + }, + content_type="application/json", + ) def create_app(*args, **kwargs): diff --git a/src/app/args.py b/src/app/args.py index 57cb6f0..dff7717 100644 --- a/src/app/args.py +++ b/src/app/args.py @@ -1,36 +1,31 @@ -import argparse +import argparse + def parse_args(): - parser = argparse.ArgumentParser( - description="Async web service" - ) + parser = argparse.ArgumentParser(description="Async web service") parser.add_argument( - '--host', + "--host", type=str, required=False, default="0.0.0.0", - help='Host to serve on. Default: 0.0.0.0.' + help="Host to serve on. Default: 0.0.0.0.", ) parser.add_argument( - '--port', + "--port", type=int, required=False, default=8888, - help='Port to serve on Default: 8888.' + help="Port to serve on Default: 8888.", ) - - parser.add_argument( - '--url', + "--url", type=str, default="http://localhost:8888", required=False, - help='Base URL.' + help="Base URL.", ) return parser.parse_args() - - diff --git a/src/app/cli.py b/src/app/cli.py index d5980af..81179d5 100644 --- a/src/app/cli.py +++ b/src/app/cli.py @@ -1,23 +1,24 @@ import asyncio +import time + from aiohttp import ClientSession + +from . import log from .args import parse_args -import time -from . import log - - async def cli_client(url): while True: sentence = input("> ") async with ClientSession() as session: - async with session.post("http://localhost:8080",json=sentence) as response: + async with session.post("http://localhost:8080", json=sentence) as response: try: print(await response.json()) except Exception as ex: print(ex) print(await response.text()) + async def bench(url): index = 0 while True: @@ -28,13 +29,14 @@ async def bench(url): async with ClientSession() as session: async with session.get(url) as response: print(await response.text()) - #print(await response.json()) + # print(await response.json()) time_end = time.time() - print("Request {}. Duration: {}".format(index,time_end-time_start)) + print(f"Request {index}. Duration: {time_end - time_start}") except Exception as ex: log.exception(ex) await asyncio.sleep(1) + def cli_bench(): args = parse_args() asyncio.run(bench(args.url)) @@ -44,9 +46,6 @@ def main(): args = parse_args() asyncio.run(cli_client(args.url)) -if __name__ == '__main__': + +if __name__ == "__main__": main() - - - - diff --git a/src/app/kim.py b/src/app/kim.py index df61755..2b55ef3 100644 --- a/src/app/kim.py +++ b/src/app/kim.py @@ -1,17 +1,18 @@ #!/usr/bin/python3 -import sys import shutil +import sys + from readchar import readkey -def text_editor(init='', prompt=''): - ''' +def text_editor(init="", prompt=""): + """ Allow user to edit a line of text complete with support for line wraps and a cursor | you can move back and forth with the arrow keys. init = initial text supplied to edit prompt = Decoration presented before the text (not editable and not returned) - ''' + """ term_width = shutil.get_terminal_size()[0] ptr = len(init) @@ -25,26 +26,24 @@ def text_editor(init='', prompt=''): copy = prompt + text.copy() if ptr < len(text): - copy.insert(ptr + len(prompt), '|') + copy.insert(ptr + len(prompt), "|") # Line wraps support: if len(copy) > term_width: cut = len(copy) + 3 - term_width if ptr > len(copy) / 2: - copy = ['<'] * 3 + copy[cut:] + copy = ["<"] * 3 + copy[cut:] else: - copy = copy[:-cut] + ['>'] * 3 - + copy = copy[:-cut] + [">"] * 3 # Display current line - print('\r' * term_width + ''.join(copy), end=' ' * (term_width - len(copy))) - + print("\r" * term_width + "".join(copy), end=" " * (term_width - len(copy))) # Read new character into c if c in (53, 54): # Page up/down bug c = readkey() - if c == '~': + if c == "~": continue else: c = readkey() @@ -52,17 +51,17 @@ def text_editor(init='', prompt=''): if len(c) > 1: # Control Character c = ord(c[-1]) - if c == 68: # Left + if c == 68: # Left ptr -= 1 - elif c == 67: # Right + elif c == 67: # Right ptr += 1 - elif c == 53: # PgDn + elif c == 53: # PgDn ptr -= term_width // 2 - elif c == 54: # PgUp + elif c == 54: # PgUp ptr += term_width // 2 - elif c == 70: # End + elif c == 70: # End ptr = len(text) - elif c == 72: # Home + elif c == 72: # Home ptr = 0 else: print("\nUnknown control character:", c) @@ -77,17 +76,18 @@ def text_editor(init='', prompt=''): num = ord(c) if num in (13, 10): # Enter print() - return ''.join(text) - elif num == 127: # Backspace + return "".join(text) + elif num == 127: # Backspace if text: text.pop(ptr - 1) ptr -= 1 - elif num == 3: # Ctrl-C + elif num == 3: # Ctrl-C sys.exit(1) else: # Insert normal character into text. text.insert(ptr, c) ptr += 1 + if __name__ == "__main__": - print("Result =", text_editor('Edit this text', prompt="Prompt: ")) + print("Result =", text_editor("Edit this text", prompt="Prompt: ")) diff --git a/src/app/repl.py b/src/app/repl.py index 468d723..6ea516d 100644 --- a/src/app/repl.py +++ b/src/app/repl.py @@ -1,4 +1,4 @@ -import code +import code def repl(**kwargs): @@ -8,6 +8,7 @@ def repl(**kwargs): variables.update(kwargs) code.interact(local=variables) + if __name__ == "__main__": repl() diff --git a/src/app/server.py b/src/app/server.py index 647f214..6a7bd90 100644 --- a/src/app/server.py +++ b/src/app/server.py @@ -1,14 +1,17 @@ -from aiohttp import web -from .app import create_app -from . import log -import time +import time -def serve(host="0.0.0.0",port=8888): +from aiohttp import web + +from . import log +from .app import create_app + + +def serve(host="0.0.0.0", port=8888): app = create_app() - log.info("Serving on {}:{}".format(host,port)) + log.info(f"Serving on {host}:{port}") while True: try: - web.run_app(app,host=host,port=port) + web.run_app(app, host=host, port=port) except KeyboardInterrupt: break except Exception as ex: diff --git a/src/app/tests.py b/src/app/tests.py index 914c583..098f1ab 100644 --- a/src/app/tests.py +++ b/src/app/tests.py @@ -1,20 +1,19 @@ -from .app import WebDbApplication import unittest -import asyncio +from .app import WebDbApplication class WebDbApplicationTestCase(unittest.IsolatedAsyncioTestCase): - def setUp(self): self.db = WebDbApplication() async def test_insert(self): - self.assertEqual(await self.db.insert("test",dict(test=True)), 1) - self.assertEqual(len(await self.db.find("test",dict(test=True, id=1))), 1) - + self.assertEqual(await self.db.insert("test", {"test": True}), 1) + self.assertEqual(len(await self.db.find("test", {"test": True, "id": 1})), 1) + async def test_find(self): - print(await self.db.find("test",None)) + print(await self.db.find("test", None)) + # self.assertEqual(len(await self.db.find("test",dict(test=True, id=1))), 1)