From 64694607917c54cb12ade17e89af3acd2dd8d363 Mon Sep 17 00:00:00 2001 From: AkiRusProd Date: Wed, 24 Sep 2025 00:46:55 +0300 Subject: [PATCH 1/4] hw1 --- hw1/app.py | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 2 deletions(-) diff --git a/hw1/app.py b/hw1/app.py index 6107b870..244fa73e 100644 --- a/hw1/app.py +++ b/hw1/app.py @@ -1,5 +1,7 @@ from typing import Any, Awaitable, Callable - +from urllib.parse import parse_qs +import math +import json async def application( scope: dict[str, Any], @@ -12,7 +14,129 @@ async def application( receive: Корутина для получения сообщений от клиента send: Корутина для отправки сообщений клиенту """ - # TODO: Ваша реализация здесь + if scope["type"] != "http": + return + + path = scope["path"] + method = scope["method"] + + if path == "/factorial" and method == "GET": + await handle_factorial(scope, send) + elif path.startswith("/fibonacci/") and method == "GET": + await handle_fibonacci(scope, send) + elif path == "/mean" and method == "POST": + await handle_mean(receive, send) + else: + await send_error(send, 404, "404 Not Found") + +async def handle_factorial(scope, send): + qs = parse_qs(scope["query_string"].decode("utf-8")) + + if "n" not in qs: + await send_error(send, 422, "Missing parameter 'n'") + return + + n_str = qs["n"][0] + + try: + n = int(n_str) + except ValueError: + await send_error(send, 422, "Parameter must 'n' be an integer") + return + + if n < 0: + await send_error(send, 400, "Factorial is not defined for negative numbers") + return + + + result = math.factorial(n) + await send_json_response(send, 200, {"result": result}) + + +async def handle_fibonacci(scope, send): + path_parts = scope["path"].strip("/").split("/") + + if len(path_parts) != 2: + await send_error(send, 422, "Invalid path format. Use /fibonacci/") + return + + n_str = path_parts[1] + + try: + n = int(n_str) + except ValueError: + await send_error(send, 422, "Parameter must be an integer") + return + + if n < 0: + await send_error(send, 400, "Fibonacci is not defined for negative numbers") + return + + a, b = 0, 1 + for _ in range(2, n): + a, b = b, a + b + + await send_json_response(send, 200, {"result": b}) + +async def handle_mean(receive, send): + body = await get_request_body(receive) + + if not body: + await send_error(send, 422, "Request body is missing") + return + + try: + data = json.loads(body) + except json.JSONDecodeError: + await send_error(send, 422, "Invalid JSON in request body") + return + + if not isinstance(data, list): + await send_error(send, 422, "Request body must be a JSON array") + return + + if not data: + await send_error(send, 400, "Cannot calculate mean of an empty list") + return + + if not all(isinstance(x, (int, float)) for x in data): + await send_error(send, 422, "All elements in the array must be numbers") + return + + result = sum(data) / len(data) + await send_json_response(send, 200, {"result": result}) + + +async def get_request_body(receive: Callable[[], Awaitable[dict[str, Any]]]) -> bytes: + body = b'' + more_body = True + while more_body: + message = await receive() + body += message.get('body', b'') + more_body = message.get('more_body', False) + return body + +async def send_json_response(send, status_code, data): + body = json.dumps(data).encode("utf-8") + await send_response(send, status_code, body, "application/json") + +async def send_error(send, status_code, message): + await send_json_response(send, status_code, {"error": message}) + +async def send_response(send, status_code, body, content_type): + await send({ + "type": "http.response.start", + "status": status_code, + "headers": [ + [b"content-type", content_type.encode("utf-8")], + [b"content-length", str(len(body)).encode("utf-8")], + ], + }) + await send({ + "type": "http.response.body", + "body": body, + }) + if __name__ == "__main__": import uvicorn From f17c51b2bad12d70c135530647675ce35f6d7e7f Mon Sep 17 00:00:00 2001 From: AkiRusProd Date: Wed, 24 Sep 2025 00:50:44 +0300 Subject: [PATCH 2/4] . --- hw1/app.py | 1 - 1 file changed, 1 deletion(-) diff --git a/hw1/app.py b/hw1/app.py index 244fa73e..5d671b67 100644 --- a/hw1/app.py +++ b/hw1/app.py @@ -52,7 +52,6 @@ async def handle_factorial(scope, send): result = math.factorial(n) await send_json_response(send, 200, {"result": result}) - async def handle_fibonacci(scope, send): path_parts = scope["path"].strip("/").split("/") From 5eb76c24d48b2e811938b50444d8347b3f267410 Mon Sep 17 00:00:00 2001 From: AkiRusProd Date: Wed, 24 Sep 2025 01:04:10 +0300 Subject: [PATCH 3/4] minor fixes --- hw1/app.py | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/hw1/app.py b/hw1/app.py index 5d671b67..1d2a205f 100644 --- a/hw1/app.py +++ b/hw1/app.py @@ -8,26 +8,27 @@ async def application( receive: Callable[[], Awaitable[dict[str, Any]]], send: Callable[[dict[str, Any]], Awaitable[None]], ): - """ - Args: - scope: Словарь с информацией о запросе - receive: Корутина для получения сообщений от клиента - send: Корутина для отправки сообщений клиенту - """ - if scope["type"] != "http": - return - - path = scope["path"] - method = scope["method"] - - if path == "/factorial" and method == "GET": - await handle_factorial(scope, send) - elif path.startswith("/fibonacci/") and method == "GET": - await handle_fibonacci(scope, send) - elif path == "/mean" and method == "POST": - await handle_mean(receive, send) - else: - await send_error(send, 404, "404 Not Found") + if scope["type"] == "lifespan": + while True: + message = await receive() + if message["type"] == "lifespan.startup": + await send({"type": "lifespan.startup.complete"}) + elif message["type"] == "lifespan.shutdown": + await send({"type": "lifespan.shutdown.complete"}) + return + + elif scope["type"] == "http": + path = scope["path"] + method = scope["method"] + + if path == "/factorial" and method == "GET": + await handle_factorial(scope, send) + elif path.startswith("/fibonacci/") and method == "GET": + await handle_fibonacci(scope, send) + elif path == "/mean" and method == "POST": + await handle_mean(receive, send) + else: + await send_error(send, 404, "Not Found") async def handle_factorial(scope, send): qs = parse_qs(scope["query_string"].decode("utf-8")) @@ -40,8 +41,8 @@ async def handle_factorial(scope, send): try: n = int(n_str) - except ValueError: - await send_error(send, 422, "Parameter must 'n' be an integer") + except (ValueError, TypeError): + await send_error(send, 422, "Parameter 'n' must be an integer") return if n < 0: @@ -71,6 +72,10 @@ async def handle_fibonacci(scope, send): await send_error(send, 400, "Fibonacci is not defined for negative numbers") return + if n <= 1: + await send_json_response(send, 200, {"result": n}) + return + a, b = 0, 1 for _ in range(2, n): a, b = b, a + b From f2c9c789dd9be60bd2d9d9bc688e299241719ecb Mon Sep 17 00:00:00 2001 From: AkiRusProd Date: Wed, 24 Sep 2025 01:10:25 +0300 Subject: [PATCH 4/4] bug fix --- hw1/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw1/app.py b/hw1/app.py index 1d2a205f..38545aa7 100644 --- a/hw1/app.py +++ b/hw1/app.py @@ -25,7 +25,7 @@ async def application( await handle_factorial(scope, send) elif path.startswith("/fibonacci/") and method == "GET": await handle_fibonacci(scope, send) - elif path == "/mean" and method == "POST": + elif path == "/mean" and method == "GET": await handle_mean(receive, send) else: await send_error(send, 404, "Not Found")