From c0e287b7db1f79f524dab2b2aad23d92c5834eb7 Mon Sep 17 00:00:00 2001 From: gus <0x67757300@gmail.com> Date: Thu, 14 Dec 2023 14:48:49 -0300 Subject: [PATCH] remove type hints --- README.md | 6 ++-- uhttp.py | 97 ++++++++++++++++++++++++------------------------------- 2 files changed, 46 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index c6704c5..09ae1de 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,19 @@ # µHTTP - Pythonic web development -µHTTP emerged from the need of a **simple** web framework. It's great for micro-services, single page applications, AND monolithic monsters. +µHTTP emerged from the need of a **simple** web framework. It's great for micro-services, small applications, AND monolithic monsters. _In µHTTP there is no hidden logic. Everything is what it seems._ ### Why -- Stupid simple, seriously there are maybe 15 lines of "real" code in it. _No external dependencies._ +- Stupid simple, seriously, there are maybe 15 lines of "real" code in it. _No external dependencies._ - Extremely modular, entire extensions can just follow the simple App pattern. - Very flexible, because of decisions like being able to raise Responses. - Quite fast, because it doesn't do much. - Great learning device. +[The rant.](https://lobste.rs/s/ukh5id/uhttp_pythonic_web_development#c_9jln1d) + ### Installation µHTTP is on [PyPI](https://pypi.org/project/uhttp/). diff --git a/uhttp.py b/uhttp.py index 13479d8..9322e4e 100644 --- a/uhttp.py +++ b/uhttp.py @@ -7,7 +7,6 @@ from urllib.parse import parse_qs, unquote from asyncio import to_thread from inspect import iscoroutinefunction -from typing import Any, Callable, Iterable, Optional, Union class App: @@ -19,17 +18,20 @@ class App: def __init__( self, *, - routes: Optional[ - dict[str, dict[str, Callable[['Request'], Any]]] - ] = None, - startup: Optional[list[Callable[[dict], Any]]] = None, - shutdown: Optional[list[Callable[[dict], Any]]] = None, - before: Optional[list[Callable[['Request'], Any]]] = None, - after: Optional[list[Callable[['Request', 'Response'], Any]]] = None, - max_content: int = 1048576 + routes=None, + startup=None, + shutdown=None, + before=None, + after=None, + max_content=1048576 ): """Initializes an App. + - routes must follow: `{'PATH': {'METHOD': FUNC}}`. + - startup, shutdown, before and after must be a list of funcs. + - max_content is the maximum size allowed, in bytes, of a + request body. Defaults to 1 MB. + E.g.: ```python @@ -58,7 +60,7 @@ def __init__( self._after = after or [] self._max_content = max_content - def mount(self, app: 'App', prefix: str = ''): + def mount(self, app, prefix=''): """Mounts another app.""" self._startup += app._startup self._shutdown += app._shutdown @@ -67,7 +69,7 @@ def mount(self, app: 'App', prefix: str = ''): self._routes.update({prefix + k: v for k, v in app._routes.items()}) self._max_content = max(self._max_content, app._max_content) - def startup(self, func: Callable[[dict], Any]): + def startup(self, func): """A startup decorator. Appends the decorated function to the list of startup functions. @@ -86,7 +88,7 @@ def open_db(state): self._startup.append(func) return func - def shutdown(self, func: Callable[[dict], Any]): + def shutdown(self, func): """A shutdown decorator. Appends the decorated function to the list of shutdown @@ -104,7 +106,7 @@ def close_db(state): self._shutdown.append(func) return func - def before(self, func: Callable[['Request'], Any]): + def before(self, func): """A before decorator. Appends the decorated function to the list of before functions. @@ -124,7 +126,7 @@ def auth(request): self._before.append(func) return func - def after(self, func: Callable[['Request', 'Response'], Any]): + def after(self, func): """An after decorator. Appends the decorated function to the list of after functions. @@ -142,7 +144,7 @@ def logger(request, response): self._after.append(func) return func - def route(self, path: str, methods: Iterable[str] = ('GET',)): + def route(self, path, methods=('GET',)): """A route decorator. Adds the decorated function to the routing table. @@ -172,43 +174,43 @@ def decorator(func): return func return decorator - def get(self, path: str): + def get(self, path): """A `GET` route.""" return self.route(path, methods=('GET',)) - def head(self, path: str): + def head(self, path): """A `HEAD` route.""" return self.route(path, methods=('HEAD',)) - def post(self, path: str): + def post(self, path): """A `POST` route.""" return self.route(path, methods=('POST',)) - def put(self, path: str): + def put(self, path): """A `PUT` route.""" return self.route(path, methods=('PUT',)) - def delete(self, path: str): + def delete(self, path): """A `DELETE` route.""" return self.route(path, methods=('DELETE',)) - def connect(self, path: str): + def connect(self, path): """A `CONNECT` route.""" return self.route(path, methods=('CONNECT',)) - def options(self, path: str): + def options(self, path): """An `OPTIONS` route.""" return self.route(path, methods=('OPTIONS',)) - def trace(self, path: str): + def trace(self, path): """A `TRACE` route.""" return self.route(path, methods=('TRACE',)) - def patch(self, path: str): + def patch(self, path): """A `PATCH` route.""" return self.route(path, methods=('PATCH',)) - async def __call__(self, scope: dict, receive: Callable, send: Callable): + async def __call__(self, scope, receive, send): state = scope.get('state', {}) if scope['type'] == 'lifespan': @@ -340,30 +342,20 @@ async def __call__(self, scope: dict, receive: Callable, send: Callable): class Request: """An HTTP request.""" - method: str - path: str - params: dict[str, str] - args: 'MultiDict' - headers: 'MultiDict' - cookies: SimpleCookie - body: bytes - json: Any - form: 'MultiDict' - state: dict def __init__( self, - method: str, - path: str, + method, + path, *, - params: Optional[dict] = None, - args: Optional[Union['MultiDict', dict, list]] = None, - headers: Optional[Union['MultiDict', dict, list]] = None, - cookies: Optional[dict] = None, - body: bytes = b'', - json: Optional[Any] = None, - form: Optional[Union['MultiDict', dict, list]] = None, - state: Optional[dict] = None + params=None, + args=None, + headers=None, + cookies=None, + body=b'', + json=None, + form=None, + state=None ): self.method = method self.path = path @@ -399,19 +391,14 @@ def account(request): user = user(request.state['db'], 'john') ``` """ - status: int - description: str - headers: 'MultiDict' - cookies: SimpleCookie - body: bytes def __init__( self, - status: int, + status, *, - headers: Optional[Union['MultiDict', dict, list]] = None, - cookies: Optional[dict] = None, - body: bytes = b'' + headers=None, + cookies=None, + body=b'' ): self.status = status try: @@ -430,7 +417,7 @@ def __repr__(self): return f'{self.status} {self.description}' @classmethod - def from_any(cls, any: Any) -> 'Response': + def from_any(cls, any): if isinstance(any, int): return cls(status=any, body=HTTPStatus(any).phrase.encode()) elif isinstance(any, str):