diff --git a/hw1/app.py b/hw1/app.py index 6107b870..74e4ed0c 100644 --- a/hw1/app.py +++ b/hw1/app.py @@ -1,4 +1,8 @@ from typing import Any, Awaitable, Callable +from http import HTTPStatus +from urllib.parse import parse_qs +from funcs import NotOK, fibonacci, factorial, mean +import json async def application( @@ -12,7 +16,57 @@ async def application( receive: Корутина для получения сообщений от клиента send: Корутина для отправки сообщений клиенту """ - # TODO: Ваша реализация здесь + if 'path' not in scope: + await NotOK(send, HTTPStatus.NOT_FOUND, 'Not found') + return + + if scope['path'].startswith('/fibonacci/'): + try: + n = int(scope['path'][11:]) + except ValueError: + await NotOK(send, HTTPStatus.UNPROCESSABLE_ENTITY, 'Unprocessable Entity') + return + if n < 0: + await NotOK(send, HTTPStatus.BAD_REQUEST, 'Bad request') + return + await fibonacci(n, send) + return + + elif scope['path'].startswith('/factorial'): + params = parse_qs(scope.get('query_string', b'').decode()) + try: + n_str = params['n'][0] + except (KeyError, IndexError): + await NotOK(send, HTTPStatus.UNPROCESSABLE_ENTITY, 'Unprocessable Entity') + return + try: + n = int(n_str) + except ValueError: + await NotOK(send, HTTPStatus.UNPROCESSABLE_ENTITY, 'Unprocessable Entity') + return + if n < 0: + await NotOK(send, HTTPStatus.BAD_REQUEST, 'Bad request') + return + await factorial(n, send) + return + + elif scope['path'].startswith('/mean'): + message = await receive() + body = message.get('body').decode() + data = json.loads(body) + if not isinstance(data, list): + await NotOK(send, HTTPStatus.UNPROCESSABLE_ENTITY, 'Unprocessable Entity') + return + if not data: + await NotOK(send, HTTPStatus.BAD_REQUEST, 'Bad request') + return + nums = list(map(float, data)) + await mean(nums, send) + return + + else: + await NotOK(send, HTTPStatus.NOT_FOUND, 'Not found') + if __name__ == "__main__": import uvicorn diff --git a/hw1/funcs.py b/hw1/funcs.py new file mode 100644 index 00000000..d3a122ba --- /dev/null +++ b/hw1/funcs.py @@ -0,0 +1,48 @@ +from typing import Any, Awaitable, Callable +from http import HTTPStatus +import json + +async def NotOK(send: Callable[[dict[str, Any]], Awaitable[None]], status: HTTPStatus, message: str): + await send({ + 'type': 'http.response.start', + 'status': status, + 'headers': [[b'content-type', b'text/plain']] + }) + await send({'type': 'http.response.body', 'body': message.encode()}) + +def app(func): + async def wrapper(arg, send): + await send({ + 'type': 'http.response.start', + 'status': HTTPStatus.OK, + 'headers': [ + [b'content-type', b'text/plain'], + ], + }) + await send({ + 'type': 'http.response.body', + 'body': json.dumps({'result': func(arg)}).encode(), + }) + return wrapper + +@app +def fibonacci(n: int) -> int: + def helper(n: int) -> int: + if n < 0: + raise ValueError("n must be non-negative") + return n if n <= 1 else helper(n - 1) + helper(n - 2) + return helper(n) + +@app +def factorial(n: int) -> int: + def helper(n: int) -> int: + if n < 0: + raise ValueError("n must be non-negative") + return 1 if n == 0 else n * helper(n - 1) + return helper(n) + +@app +def mean(numbers: list[int]) -> float: + if not numbers: + raise ValueError("empty list") + return sum(numbers) / len(numbers)