Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.idea
.vscode
.DS_Store
__pycache__
6 changes: 5 additions & 1 deletion client-server-app/messenger/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# README
Все файлы должны выполняться в директории messenger,
поскольку внутри скриптов есть добавление sys path
для поиска библиотек './'.
для поиска библиотек ".".

Для тестирования файлы аналогично надо запускать в
директории messenger, не test, например:
```python tests/test_logger.py```
18 changes: 13 additions & 5 deletions client-server-app/messenger/client.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
#!/usr/bin/env python

from logging import getLogger
from socket import socket, AF_INET, SOCK_STREAM

import sys

sys.path.append('.')
sys.path.append(".")

from jim.config import BUFSIZE
from jim.utils import parse_arguments, make_raw_json, \
parse_raw_json, is_valid_response, raise_invalid_username
from jim.utils import (
parse_arguments,
make_raw_json,
parse_raw_json,
is_valid_response,
raise_invalid_username,
)
from jim.messages import presence
import jim.logger

if __name__ == "__main__":
logger = getLogger("messenger.client")
opts = parse_arguments()
raise_invalid_username(opts.username)

Expand All @@ -25,6 +33,6 @@
data = parse_raw_json(raw_data)

if is_valid_response(data):
print(f"Получено корректное сообщение от сервера: {data}")
logger.debug(f"Получено корректное сообщение от сервера: {data}")
else:
print(f"Получено некорректное сообщение от сервера: {data}")
logger.error(f"Получено некорректное сообщение от сервера: {data}")
10 changes: 8 additions & 2 deletions client-server-app/messenger/jim/config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import logging

BACKLOG = 1024
BUFSIZE = 4096

SERVER_ADDRESS = ''
SERVER_ADDRESS = "127.0.0.1"
SERVER_PORT = 7777

ENCODING = 'utf-8'
ENCODING = "utf-8"

SERVER_LOGFILE = "log/server.log"
CLIENT_LOGFILE = "log/client.log"
LOGLEVEL = logging.DEBUG
40 changes: 40 additions & 0 deletions client-server-app/messenger/jim/decorators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import sys

from logging import getLogger
from . import logger


def log(func):
program_name = sys.argv[0]
role = "server" if "server" in program_name else "client"
logger = getLogger(f"messenger.{role}")

def wrapper(*args, **kwargs):
logger.debug(
f"Вызвана функция {func.__name__} с аргументами {args}, "
f"{kwargs} в модуле {func.__module__}"
)
return func(*args, **kwargs)

return wrapper


class Log:
"""
Class works like a @log decorator,
only as example.
"""

def __init__(self, function):
self.function = function

program_name = sys.argv[0]
role = "server" if "server" in program_name else "client"
self.logger = getLogger(f"messenger.{role}")

def __call__(self, *args, **kwargs):
self.logger.info(
f"Вызвана функция {self.function.__name__} с аргументами {args}, "
f"{kwargs} в модуле {self.function.__module__}"
)
return self.function(*args, **kwargs)
40 changes: 40 additions & 0 deletions client-server-app/messenger/jim/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import logging
import logging.handlers
import sys

from .config import SERVER_LOGFILE, CLIENT_LOGFILE, LOGLEVEL, ENCODING


formatter = logging.Formatter("%(asctime)s %(filename)s > %(module)s:%(levelname)s %(message)s")


# Server logger object
server_logger = logging.getLogger("messenger.server")
server_logger.setLevel(LOGLEVEL)

server_timed_fh = logging.handlers.TimedRotatingFileHandler(
SERVER_LOGFILE, when="D", interval=1, backupCount=3, encoding=ENCODING
)
server_timed_fh.setLevel(logging.DEBUG)
server_timed_fh.setFormatter(formatter)
server_logger.addHandler(server_timed_fh)

err_stream = logging.StreamHandler(sys.stderr)
err_stream.setFormatter(formatter)
err_stream.setLevel(logging.ERROR)
server_logger.addHandler(err_stream)


# Client logger object
client_logger = logging.getLogger("messenger.client")
client_logger.setLevel(LOGLEVEL)

client_fh = logging.FileHandler(CLIENT_LOGFILE, encoding=ENCODING, mode="a")
client_fh.setFormatter(formatter)
client_fh.setLevel(logging.ERROR)
client_logger.addHandler(client_fh)

out_stream = logging.StreamHandler(sys.stdout)
out_stream.setFormatter(formatter)
out_stream.setLevel(logging.INFO)
client_logger.addHandler(out_stream)
47 changes: 17 additions & 30 deletions client-server-app/messenger/jim/messages.py
Original file line number Diff line number Diff line change
@@ -1,76 +1,63 @@
import datetime

from .config import ENCODING
from .decorators import log


@log
def authenticate(account_name=None, password=None):
return {
"action": "authenticate",
"time": datetime.datetime.now().timestamp(),
"user": {
"account_name": account_name,
"password": password
}
"user": {"account_name": account_name, "password": password},
}


@log
def presence(account_name=None, status=None):
return {
"action": "presence",
"time": datetime.datetime.now().timestamp(),
"type": "status",
"user": {
"account_name": account_name,
"status": status
}
"user": {"account_name": account_name, "status": status},
}


@log
def probe():
return {
"action": "probe",
"time": datetime.datetime.now().timestamp()
}
return {"action": "probe", "time": datetime.datetime.now().timestamp()}


@log
def msg(message=None, source=None, destination=None):
return {
"action": "msg",
"time": datetime.datetime.now().timestamp(),
"from": source,
"to": destination,
"encoding": ENCODING,
"message": message
"message": message,
}


@log
def join(room=None):
return {
"action": "join",
"time": datetime.datetime.now().timestamp(),
"room": room
}
return {"action": "join", "time": datetime.datetime.now().timestamp(), "room": room}


@log
def leave(room=None):
return {
"action": "leave",
"time": datetime.datetime.now().timestamp(),
"room": room
}
return {"action": "leave", "time": datetime.datetime.now().timestamp(), "room": room}


@log
def quit():
return {
"action": "quit"
}
return {"action": "quit"}


@log
def response(status, message="", is_success=True):
body = {
"response": status,
"time": datetime.datetime.now().timestamp()
}
body = {"response": status, "time": datetime.datetime.now().timestamp()}

message_desc = {"alert": message} if is_success else {"error": message}
body.update(message_desc)
Expand Down
19 changes: 8 additions & 11 deletions client-server-app/messenger/jim/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,10 @@


def parse_arguments():
parser = argparse.ArgumentParser(description='Messenger application.')
parser.add_argument('-a', '--address', dest='address',
type=str, default=SERVER_ADDRESS)
parser.add_argument('-p', '--port', dest='port',
type=int, default=SERVER_PORT)
parser.add_argument('-u', '--username', dest='username',
type=str, default='Guest')
parser = argparse.ArgumentParser(description="Messenger application.")
parser.add_argument("-a", "--address", dest="address", type=str, default=SERVER_ADDRESS)
parser.add_argument("-p", "--port", dest="port", type=int, default=SERVER_PORT)
parser.add_argument("-u", "--username", dest="username", type=str, default="Guest")
args = parser.parse_args()

return args
Expand All @@ -38,7 +35,7 @@ def make_raw_json(python_object):

def is_valid_message(msg):
try:
action = msg.get('action', None)
action = msg.get("action", None)
# A bit magic: call function from messages with name as action
msg_template = getattr(messages, action)()
except Exception as err:
Expand All @@ -52,15 +49,15 @@ def is_valid_message(msg):

def raise_invalid_username(username):
if len(username) > 25:
raise exceptions.UsernameError('максимальная длина имени пользователя 25 символов')
raise exceptions.UsernameError("максимальная длина имени пользователя 25 символов")

if not re.match(r"^[\w ]+$", username):
raise exceptions.UsernameError('допустимые символы - буквы, цифры, подчеркивания и пробелы')
raise exceptions.UsernameError("допустимые символы - буквы, цифры, подчеркивания и пробелы")

return True


def is_valid_response(msg):
if 'response' not in msg or 'time' not in msg:
if "response" not in msg or "time" not in msg:
return False
return True
1 change: 1 addition & 0 deletions client-server-app/messenger/log/client.log
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2019-09-22 14:00:18,137 client.py > client:ERROR Получено некорректное сообщение от сервера: {'responses': 202, 'time': 1569150018.137507, 'alert': 'Accepted'}
24 changes: 24 additions & 0 deletions client-server-app/messenger/log/server.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
2019-09-22 13:58:36,300 server.py > server:DEBUG Получено сообщение от клиента ('127.0.0.1', 59791): {'action': 'presence', 'time': 1569149916.300413, 'type': 'status', 'user': {'account_name': 'Guest', 'status': None}}
2019-09-22 13:58:36,300 decorators.py > decorators:DEBUG Вызвана функция response с аргументами (400, 'Incorrect JSON', False), {} в модуле jim.messages
2019-09-22 13:58:36,300 decorators.py > decorators:DEBUG Вызвана функция presence с аргументами (), {} в модуле jim.messages
2019-09-22 13:58:36,300 decorators.py > decorators:DEBUG Вызвана функция response с аргументами (202, 'Accepted', True), {} в модуле jim.messages
2019-09-22 13:59:16,357 server.py > server:DEBUG Получено сообщение от клиента ('127.0.0.1', 59800): {'action': 'presences', 'time': 1569149956.356914, 'type': 'status', 'user': {'account_name': 'Guest', 'status': None}}
2019-09-22 13:59:16,357 decorators.py > decorators:DEBUG Вызвана функция response с аргументами (400, 'Incorrect JSON', False), {} в модуле jim.messages
2019-09-22 13:59:16,357 server.py > server:ERROR Ошибка валидации сообщения от ('127.0.0.1', 59800), ошибка в сообщении, module 'jim.messages' has no attribute 'presences'
2019-09-22 14:00:18,136 server.py > server:DEBUG Получено сообщение от клиента ('127.0.0.1', 59811): {'action': 'presence', 'time': 1569150018.13673, 'type': 'status', 'user': {'account_name': 'Guest', 'status': None}}
2019-09-22 14:00:18,137 decorators.py > decorators:INFO Вызвана функция response с аргументами (400, 'Incorrect JSON', False), {} в модуле jim.messages
2019-09-22 14:00:18,137 decorators.py > decorators:INFO Вызвана функция presence с аргументами (), {} в модуле jim.messages
2019-09-22 14:00:18,137 decorators.py > decorators:INFO Вызвана функция response с аргументами (202, 'Accepted', True), {} в модуле jim.messages
2019-09-22 14:05:23,453 server.py > server:DEBUG Получено сообщение от клиента ('127.0.0.1', 59929): {}
2019-09-22 14:05:23,454 decorators.py > decorators:INFO Вызвана функция response с аргументами (400, 'Incorrect JSON', False), {} в модуле jim.messages
2019-09-22 14:05:23,454 server.py > server:ERROR Ошибка валидации сообщения от ('127.0.0.1', 59929), ошибка в сообщении, getattr(): attribute name must be string
2019-09-22 14:05:55,095 server.py > server:DEBUG Получено сообщение от клиента ('127.0.0.1', 59934): {'action': 'presence', 'time': 1569150355.094712, 'type': 'status', 'user': {'account_name': 'Guest', 'status': None}}
2019-09-22 14:05:55,095 decorators.py > decorators:INFO Вызвана функция response с аргументами (400, 'Incorrect JSON', False), {} в модуле jim.messages
2019-09-22 14:05:55,095 server.py > server:ERROR Ошибка валидации сообщения от ('127.0.0.1', 59934), ошибка в сообщении, name 'func' is not defined
2019-09-22 14:06:07,632 server.py > server:DEBUG Получено сообщение от клиента ('127.0.0.1', 59936): {'action': 'presence', 'time': 1569150367.632411, 'type': 'status', 'user': {'account_name': 'Guest', 'status': None}}
2019-09-22 14:06:07,632 decorators.py > decorators:INFO Вызвана функция response с аргументами (400, 'Incorrect JSON', False), {} в модуле jim.messages
2019-09-22 14:06:07,632 server.py > server:ERROR Ошибка валидации сообщения от ('127.0.0.1', 59936), ошибка в сообщении, name 'func' is not defined
2019-09-22 14:06:47,225 server.py > server:DEBUG Получено сообщение от клиента ('127.0.0.1', 59940): {'action': 'presence', 'time': 1569150407.225189, 'type': 'status', 'user': {'account_name': 'Guest', 'status': None}}
2019-09-22 14:06:47,226 decorators.py > decorators:INFO Вызвана функция response с аргументами (400, 'Incorrect JSON', False), {} в модуле jim.messages
2019-09-22 14:06:47,226 decorators.py > decorators:INFO Вызвана функция presence с аргументами (), {} в модуле jim.messages
2019-09-22 14:06:47,226 decorators.py > decorators:INFO Вызвана функция response с аргументами (202, 'Accepted', True), {} в модуле jim.messages
27 changes: 17 additions & 10 deletions client-server-app/messenger/server.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
#!/usr/bin/env python
#!/usr/bin/env python3

from logging import getLogger
from socket import socket, AF_INET, SOCK_STREAM

import sys

sys.path.append('.')
sys.path.append(".")

from jim.config import BACKLOG, BUFSIZE
from jim.utils import parse_arguments, parse_raw_json, \
is_valid_message, make_raw_json
from jim.exceptions import MessageError
from jim.messages import response
from jim.utils import parse_arguments, parse_raw_json, is_valid_message, make_raw_json
from jim.config import BACKLOG, BUFSIZE
import jim.logger


if __name__ == "__main__":
logger = getLogger("messenger.server")
opts = parse_arguments()

s = socket(family=AF_INET, type=SOCK_STREAM)
Expand All @@ -23,10 +26,14 @@
raw_data = sock.recv(BUFSIZE)
data = parse_raw_json(raw_data)

print(f"Получено сообщение от клиента: {data}")
message = response(400, 'Incorrect JSON', False)
if is_valid_message(data):
message = response(202, 'Accepted', True)
logger.debug(f"Получено сообщение от клиента {addr}: {data}")

message = response(400, "Incorrect JSON", False)
try:
if is_valid_message(data):
message = response(202, "Accepted", True)
except MessageError as err:
logger.error(f"Ошибка валидации сообщения от {addr}, {err}")

sock.send(make_raw_json(message))
sock.close()
Expand Down
22 changes: 22 additions & 0 deletions client-server-app/messenger/tests/test_decorators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import sys
import unittest

sys.path.append(".")
sys.path.append("..")

from jim.decorators import log


class TestUtils(unittest.TestCase):
def _testing_function(self):
return 42

def test_unchanged(self):
"""
Our decorator should not change init funcion behaviour.
"""
self.assertEqual(log(self._testing_function)(), self._testing_function())


if __name__ == "__main__":
unittest.main()
Loading