From 72f482d8bc1593176557b8a67c382c1e9611f113 Mon Sep 17 00:00:00 2001 From: PAND-or Date: Fri, 15 Mar 2019 02:48:43 +0300 Subject: [PATCH 1/2] hw04 --- lesson04/client/__main__.py | 81 +++++++++++++++++++ lesson04/server/__init__.py | 3 + lesson04/server/__main__.py | 79 ++++++++++++++++++ lesson04/server/routes.py | 20 +++++ lesson04/server/test_module/controllers.py | 5 ++ lesson04/server/test_module/routes.py | 6 ++ lesson04/server/text/controllers.py | 6 ++ lesson04/server/text/routes.py | 9 +++ lesson04/server/text/tests/__init__.py | 0 .../server/text/tests/test_controllers.py | 9 +++ 10 files changed, 218 insertions(+) create mode 100644 lesson04/client/__main__.py create mode 100644 lesson04/server/__init__.py create mode 100644 lesson04/server/__main__.py create mode 100644 lesson04/server/routes.py create mode 100644 lesson04/server/test_module/controllers.py create mode 100644 lesson04/server/test_module/routes.py create mode 100644 lesson04/server/text/controllers.py create mode 100644 lesson04/server/text/routes.py create mode 100644 lesson04/server/text/tests/__init__.py create mode 100644 lesson04/server/text/tests/test_controllers.py diff --git a/lesson04/client/__main__.py b/lesson04/client/__main__.py new file mode 100644 index 0000000..713d571 --- /dev/null +++ b/lesson04/client/__main__.py @@ -0,0 +1,81 @@ +#!/usr/bin/python3 +__author__ = "Андрей Петров" + +""" +клиент отправляет запрос серверу; +сервер отвечает соответствующим кодом результата. Клиент и сервер должны быть реализованы в виде отдельных скриптов, +содержащих соответствующие функции. + +Функции клиента: +сформировать presence-сообщение; +отправить сообщение серверу; +получить ответ сервера; +разобрать сообщение сервера; +параметры командной строки скрипта client.py []: addr — ip-адрес сервера; +port — tcp-порт на сервере, +по умолчанию 7777. + +""" +import re +import sys +import argparse +import socket +import json +from datetime import datetime + + +def createParser(): + parser = argparse.ArgumentParser() + parser.add_argument('host', nargs='?', default='localhost') + parser.add_argument('port', nargs='?', default='7777') + return parser + + +parser = createParser() +args = parser.parse_args(sys.argv[1:]) + +port = int(re.search('[0-9]{2,}', args.port).group(0)) + +sock = socket.socket() +sock.connect((args.host, port)) + +# сформировать presence-сообщение; +# В формате JIM +msg_presence = json.dumps( + { + "action": "presence", + "time": datetime.now().timestamp(), + "type": "status", + "user": { + "account_name": "User Name", + "status": "Yep, I am here!" + } + } +) + +msg_lower = json.dumps( + { + "action": "lower_text", + "data": 'GGGGG' + } +) + +# отправить сообщение серверу; +sock.send(msg_presence.encode()) +#sock.send(msg_lower.encode()) + +# получить ответ сервера; +data = sock.recv(1024) +response = json.loads( + data.decode('utf-8') +) +# разобрать сообщение сервера; +if response.get('response') == 200: + print( + f"Response Message: {response.get('msg')}" + ) +else: + print( + f"Error: {response.get('error')}" + ) +sock.close() diff --git a/lesson04/server/__init__.py b/lesson04/server/__init__.py new file mode 100644 index 0000000..da70eca --- /dev/null +++ b/lesson04/server/__init__.py @@ -0,0 +1,3 @@ +from .controllers import * +from .routes import * + diff --git a/lesson04/server/__main__.py b/lesson04/server/__main__.py new file mode 100644 index 0000000..f7a47e6 --- /dev/null +++ b/lesson04/server/__main__.py @@ -0,0 +1,79 @@ +#!/usr/bin/python3 +__author__ = "Андрей Петров" + +""" +клиент отправляет запрос серверу; +сервер отвечает соответствующим кодом результата. Клиент и сервер должны быть реализованы в виде отдельных скриптов, +содержащих соответствующие функции. + +Функции сервера: +принимает сообщение клиента; +формирует ответ клиенту; +отправляет ответ клиенту; +имеет параметры командной строки: -p — TCP-порт для работы (по умолчанию использует 7777); +-a — IP-адрес для прослушивания (по умолчанию слушает все доступные адреса). +""" + +import sys +import os +import json +import socket +import argparse +from routes import get_server_routes + + +def createParser(): + parser = argparse.ArgumentParser() + parser.add_argument('-a', '--addr', nargs='?', default='') + parser.add_argument('-p', '--port', nargs='?', default='7777') + return parser + + +parser = createParser() +args = parser.parse_args(sys.argv[1:]) + + +sock = socket.socket() +sock.bind((args.addr, int(args.port))) +sock.listen(5) + + +## Без этого не работал код из урока +os.chdir('server') +sys.path.append(os.getcwd()) +## + +while True: + # принимает сообщение клиента; + client, address = sock.accept() + + data = client.recv(1024) + request = json.loads( + data.decode('utf-8') + ) + + # формирует ответ клиенту; + + client_action = request.get('action') + + resolved_routes = list( + filter( + lambda itm: itm.get('action') == client_action, + get_server_routes() + ) + ) + + route = resolved_routes[0] if resolved_routes else None + if route: + controller = route.get('controller') + response = controller(request.get('data'), request) + + else: + response = { + "response": 400, + "error": "Wrong action, try again" + } + + # отправляет ответ клиенту; + client.send(json.dumps(response).encode('utf-8')) + client.close() diff --git a/lesson04/server/routes.py b/lesson04/server/routes.py new file mode 100644 index 0000000..9d5b03a --- /dev/null +++ b/lesson04/server/routes.py @@ -0,0 +1,20 @@ +import os +from importlib import import_module +from functools import reduce + + +def get_server_routes(): + return reduce( + lambda routes, module: routes + getattr(module, 'routes', []), + reduce( + lambda modules, dir: modules + [import_module(f'{dir}.routes')], + filter( + lambda itm: os.path.isdir(itm) and itm != '__pycache__', + os.listdir() + ), + [] + ), + [] + ) + + diff --git a/lesson04/server/test_module/controllers.py b/lesson04/server/test_module/controllers.py new file mode 100644 index 0000000..036ec40 --- /dev/null +++ b/lesson04/server/test_module/controllers.py @@ -0,0 +1,5 @@ +def send_presence(data, request): + return { + "response": 200, + "msg": f"Hi {request.get('user')['account_name']}" + } diff --git a/lesson04/server/test_module/routes.py b/lesson04/server/test_module/routes.py new file mode 100644 index 0000000..1eb5c4c --- /dev/null +++ b/lesson04/server/test_module/routes.py @@ -0,0 +1,6 @@ +from .controllers import send_presence + + +routes = [ + {'action': 'presence', 'controller': send_presence} +] \ No newline at end of file diff --git a/lesson04/server/text/controllers.py b/lesson04/server/text/controllers.py new file mode 100644 index 0000000..f320424 --- /dev/null +++ b/lesson04/server/text/controllers.py @@ -0,0 +1,6 @@ +def get_lower_text(data): + return data.lower() + + +def get_upper_text(data): + return data.upper() diff --git a/lesson04/server/text/routes.py b/lesson04/server/text/routes.py new file mode 100644 index 0000000..290e162 --- /dev/null +++ b/lesson04/server/text/routes.py @@ -0,0 +1,9 @@ +from .controllers import get_lower_text +from .controllers import get_upper_text + + + +routes = [ + {'action': 'lower_text', 'controller': get_lower_text}, + {'action': 'upper_text', 'controller': get_upper_text} +] \ No newline at end of file diff --git a/lesson04/server/text/tests/__init__.py b/lesson04/server/text/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lesson04/server/text/tests/test_controllers.py b/lesson04/server/text/tests/test_controllers.py new file mode 100644 index 0000000..ee83895 --- /dev/null +++ b/lesson04/server/text/tests/test_controllers.py @@ -0,0 +1,9 @@ +from text.controllers import ( + get_lower_text, get_upper_text +) + +TEXT_TEST = 'SOME TEXT' +ASSERT_TEXT = 'some text' + +def test_get_lower_text_is_lower(): + assert get_lower_text(TEXT_TEST) == ASSERT_TEXT From 0f2a73a19d4bc2f2dfce86504d6e95dddd135f5c Mon Sep 17 00:00:00 2001 From: PAND-or Date: Fri, 15 Mar 2019 03:39:00 +0300 Subject: [PATCH 2/2] test --- lesson04/server/__init__.py | 3 --- lesson04/server/__main__.py | 2 +- lesson04/server/routes.py | 2 +- lesson04/server/test_module/controllers.py | 2 +- lesson04/server/text/controllers.py | 6 ----- lesson04/server/text/routes.py | 9 -------- lesson04/server/text/tests/__init__.py | 0 .../server/text/tests/test_controllers.py | 9 -------- lesson04/tests/test_server.py | 22 +++++++++++++++++++ 9 files changed, 25 insertions(+), 30 deletions(-) delete mode 100644 lesson04/server/__init__.py delete mode 100644 lesson04/server/text/controllers.py delete mode 100644 lesson04/server/text/routes.py delete mode 100644 lesson04/server/text/tests/__init__.py delete mode 100644 lesson04/server/text/tests/test_controllers.py create mode 100644 lesson04/tests/test_server.py diff --git a/lesson04/server/__init__.py b/lesson04/server/__init__.py deleted file mode 100644 index da70eca..0000000 --- a/lesson04/server/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .controllers import * -from .routes import * - diff --git a/lesson04/server/__main__.py b/lesson04/server/__main__.py index f7a47e6..c72ea45 100644 --- a/lesson04/server/__main__.py +++ b/lesson04/server/__main__.py @@ -66,7 +66,7 @@ def createParser(): route = resolved_routes[0] if resolved_routes else None if route: controller = route.get('controller') - response = controller(request.get('data'), request) + response = controller(request) else: response = { diff --git a/lesson04/server/routes.py b/lesson04/server/routes.py index 9d5b03a..3451d82 100644 --- a/lesson04/server/routes.py +++ b/lesson04/server/routes.py @@ -9,7 +9,7 @@ def get_server_routes(): reduce( lambda modules, dir: modules + [import_module(f'{dir}.routes')], filter( - lambda itm: os.path.isdir(itm) and itm != '__pycache__', + lambda itm: os.path.isdir(itm) and itm != '__pycache__' and itm != '.pytest_cache', os.listdir() ), [] diff --git a/lesson04/server/test_module/controllers.py b/lesson04/server/test_module/controllers.py index 036ec40..4b1996d 100644 --- a/lesson04/server/test_module/controllers.py +++ b/lesson04/server/test_module/controllers.py @@ -1,4 +1,4 @@ -def send_presence(data, request): +def send_presence(request): return { "response": 200, "msg": f"Hi {request.get('user')['account_name']}" diff --git a/lesson04/server/text/controllers.py b/lesson04/server/text/controllers.py deleted file mode 100644 index f320424..0000000 --- a/lesson04/server/text/controllers.py +++ /dev/null @@ -1,6 +0,0 @@ -def get_lower_text(data): - return data.lower() - - -def get_upper_text(data): - return data.upper() diff --git a/lesson04/server/text/routes.py b/lesson04/server/text/routes.py deleted file mode 100644 index 290e162..0000000 --- a/lesson04/server/text/routes.py +++ /dev/null @@ -1,9 +0,0 @@ -from .controllers import get_lower_text -from .controllers import get_upper_text - - - -routes = [ - {'action': 'lower_text', 'controller': get_lower_text}, - {'action': 'upper_text', 'controller': get_upper_text} -] \ No newline at end of file diff --git a/lesson04/server/text/tests/__init__.py b/lesson04/server/text/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/lesson04/server/text/tests/test_controllers.py b/lesson04/server/text/tests/test_controllers.py deleted file mode 100644 index ee83895..0000000 --- a/lesson04/server/text/tests/test_controllers.py +++ /dev/null @@ -1,9 +0,0 @@ -from text.controllers import ( - get_lower_text, get_upper_text -) - -TEXT_TEST = 'SOME TEXT' -ASSERT_TEXT = 'some text' - -def test_get_lower_text_is_lower(): - assert get_lower_text(TEXT_TEST) == ASSERT_TEXT diff --git a/lesson04/tests/test_server.py b/lesson04/tests/test_server.py new file mode 100644 index 0000000..46ed84b --- /dev/null +++ b/lesson04/tests/test_server.py @@ -0,0 +1,22 @@ +import sys +sys.path.append('../') + +from server.test_module.controllers import send_presence + +REQUEST = { + "action": "presence", + "type": "status", + "user": { + "account_name": "User Name", + "status": "Yep, I am here!" + } + } + +RESPONSE = { + "response": 200, + "msg": "Hi User Name" + } + + +def presence_msg_request_to_response(): + assert send_presence(REQUEST) == RESPONSE