From 1e111b3e358439654fc792eb6275283c8cf383e1 Mon Sep 17 00:00:00 2001 From: At0mn1yIvan Date: Tue, 27 Sep 2022 23:14:44 +0300 Subject: [PATCH 1/9] Solution --- homeworks/At0mn1yIvan/2/main.py | 72 +++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 homeworks/At0mn1yIvan/2/main.py diff --git a/homeworks/At0mn1yIvan/2/main.py b/homeworks/At0mn1yIvan/2/main.py new file mode 100644 index 0000000..5c9fe60 --- /dev/null +++ b/homeworks/At0mn1yIvan/2/main.py @@ -0,0 +1,72 @@ +class Array(object): + + def __init__(self, *args): + self._data = tuple(args) + + def append(self, obj): + self._data = (*self._data, obj) + + def __add__(self, other): + return Array(*(self._data + other._data)) + + def __radd__(self, other): + return Array(*(other._data + self._data)) + + def __len__(self): + return len(self._data) + + def index(self, obj): + + if obj in self._data: + return self._data.index(obj) + else: + return -1 + + def __getitem__(self, index): + return self._data[index] + + def printArr(self): + print(self._data) + + +#test + +#1 +print("_______№1_______") +a = Array() +b = Array(1) +c = Array(1, 2, 3) +a.printArr() +b.printArr() +c.printArr() + +#2 +print("_______№2_______") +a.append(2) +a.printArr() + +#3 +print("_______№3_______") +a = b + c +a.printArr() +a += c +a.printArr() + +#4 +print("_______№4_______") +print(len(a)) + +#5 +print("_______№5_______") +print(c.index(2)) +print(c.index(5)) + +#6 +print("_______№6_______") +for element in c: + print(element) + +#7 +print("_______№7_______") +print(Array('a', 'b', 'c', 'd')[0]) +print(c[2]) \ No newline at end of file From 05a0fe5030e303d0899be6317b1e81cb2163deff Mon Sep 17 00:00:00 2001 From: At0mn1yIvan Date: Wed, 28 Sep 2022 21:05:04 +0300 Subject: [PATCH 2/9] Solution --- practice/At0mn1yIvan/1/game.py | 83 ++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 practice/At0mn1yIvan/1/game.py diff --git a/practice/At0mn1yIvan/1/game.py b/practice/At0mn1yIvan/1/game.py new file mode 100644 index 0000000..9b3de4f --- /dev/null +++ b/practice/At0mn1yIvan/1/game.py @@ -0,0 +1,83 @@ +# `random` module is used to shuffle field, see: +# https://docs.python.org/3/library/random.html#random.shuffle +import random +# Empty tile, there's only one empty cell on a field: +EMPTY_MARK = 'x' + +# Dictionary of possible moves if a form of: +# key -> delta to move the empty tile on a field. +MOVES = { + 'w': -4, + 's': 4, + 'a': -1, + 'd': 1, +} + +def shuffle_field(): + + my_field = list() + for i in range(1, 16): + my_field.append(i) + my_field.append(EMPTY_MARK) + for move in range(100): + random.shuffle(my_field) + return my_field + + +def print_field(field): + + for i in range(len(field)): + if field[i] == EMPTY_MARK or field[i] < 10: + print(' ', end='') + print(field[i], end=' | ') + if i in [3, 7, 11]: + print() + print() + + +def is_game_finished(field): + + for i in range(len(field) - 1): + if (i + 1) != field[i]: + return False + return True + + +def perform_move(field, key): + emp_ind = 0 + for i in field: + if i == EMPTY_MARK: + emp_ind = field.index(i) + break + if emp_ind % 4 == 0 and key == 'a': + return None + if emp_ind % 4 == 3 and key == 'd': + return None + if emp_ind + MOVES[key] < 0: + return None + if emp_ind + MOVES[key] > 15: + return None + + field[emp_ind], field[emp_ind + MOVES[key]] = field[emp_ind + MOVES[key]], field[emp_ind] + return field + +def handle_user_input(): + + my_key = input() + if my_key not in ['w', 'a', 's', 'd']: + return None + return my_key + + +def main(): + game_field = shuffle_field() + while not is_game_finished(game_field): + print_field(game_field) + perform_move(game_field, handle_user_input()) + print("YOU WIN") + + +if __name__ == '__main__': + # See what this means: + # http://stackoverflow.com/questions/419163/what-does-if-name-main-do + main() From a913ad6180ea71b5323a713e5d686fd8bd8cdd3c Mon Sep 17 00:00:00 2001 From: At0mn1yIvan Date: Mon, 3 Oct 2022 22:19:49 +0300 Subject: [PATCH 3/9] Solution --- homeworks/At0mn1yIvan/2/main.py | 72 ------------------------- homeworks/At0mn1yIvan/3/contract.py | 37 +++++++++++++ practice/At0mn1yIvan/1/game.py | 83 ----------------------------- 3 files changed, 37 insertions(+), 155 deletions(-) delete mode 100644 homeworks/At0mn1yIvan/2/main.py create mode 100644 homeworks/At0mn1yIvan/3/contract.py delete mode 100644 practice/At0mn1yIvan/1/game.py diff --git a/homeworks/At0mn1yIvan/2/main.py b/homeworks/At0mn1yIvan/2/main.py deleted file mode 100644 index 5c9fe60..0000000 --- a/homeworks/At0mn1yIvan/2/main.py +++ /dev/null @@ -1,72 +0,0 @@ -class Array(object): - - def __init__(self, *args): - self._data = tuple(args) - - def append(self, obj): - self._data = (*self._data, obj) - - def __add__(self, other): - return Array(*(self._data + other._data)) - - def __radd__(self, other): - return Array(*(other._data + self._data)) - - def __len__(self): - return len(self._data) - - def index(self, obj): - - if obj in self._data: - return self._data.index(obj) - else: - return -1 - - def __getitem__(self, index): - return self._data[index] - - def printArr(self): - print(self._data) - - -#test - -#1 -print("_______№1_______") -a = Array() -b = Array(1) -c = Array(1, 2, 3) -a.printArr() -b.printArr() -c.printArr() - -#2 -print("_______№2_______") -a.append(2) -a.printArr() - -#3 -print("_______№3_______") -a = b + c -a.printArr() -a += c -a.printArr() - -#4 -print("_______№4_______") -print(len(a)) - -#5 -print("_______№5_______") -print(c.index(2)) -print(c.index(5)) - -#6 -print("_______№6_______") -for element in c: - print(element) - -#7 -print("_______№7_______") -print(Array('a', 'b', 'c', 'd')[0]) -print(c[2]) \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/3/contract.py b/homeworks/At0mn1yIvan/3/contract.py new file mode 100644 index 0000000..b7b6851 --- /dev/null +++ b/homeworks/At0mn1yIvan/3/contract.py @@ -0,0 +1,37 @@ +class ContractError(Exception): + """We use this error when someone breaks our contract.""" + + +#: Special value, that indicates that validation for this type is not required. +Any = object() + + +def contract(arg_types=None, return_type=None, raises=None): + def contract_decorator(func): + def wrapped(*args, **kwargs): + all_args = tuple(args + tuple(kwargs.values())) + if arg_types is not None: + for elem in range(len(arg_types)): + if arg_types[elem] != Any: + if not isinstance(all_args[elem], arg_types[elem]): + raise ContractError("Invalid ArgType Error") + try: + result = func(*args, **kwargs) + except (Exception if raises is None or Any in raises else raises) as exc: + raise exc + except Exception as ex: + raise ContractError from ex + if return_type is not None: + if not isinstance(result, return_type): + raise ContractError("Invalid ReturnType Error") + return result + return wrapped + return contract_decorator + + +@contract(arg_types=(Any, int), return_type=None, raises=(ZeroDivisionError,)) +def add_two_numbers(first, second): + return first + second + + +print(add_two_numbers(15, 7.5)) \ No newline at end of file diff --git a/practice/At0mn1yIvan/1/game.py b/practice/At0mn1yIvan/1/game.py deleted file mode 100644 index 9b3de4f..0000000 --- a/practice/At0mn1yIvan/1/game.py +++ /dev/null @@ -1,83 +0,0 @@ -# `random` module is used to shuffle field, see: -# https://docs.python.org/3/library/random.html#random.shuffle -import random -# Empty tile, there's only one empty cell on a field: -EMPTY_MARK = 'x' - -# Dictionary of possible moves if a form of: -# key -> delta to move the empty tile on a field. -MOVES = { - 'w': -4, - 's': 4, - 'a': -1, - 'd': 1, -} - -def shuffle_field(): - - my_field = list() - for i in range(1, 16): - my_field.append(i) - my_field.append(EMPTY_MARK) - for move in range(100): - random.shuffle(my_field) - return my_field - - -def print_field(field): - - for i in range(len(field)): - if field[i] == EMPTY_MARK or field[i] < 10: - print(' ', end='') - print(field[i], end=' | ') - if i in [3, 7, 11]: - print() - print() - - -def is_game_finished(field): - - for i in range(len(field) - 1): - if (i + 1) != field[i]: - return False - return True - - -def perform_move(field, key): - emp_ind = 0 - for i in field: - if i == EMPTY_MARK: - emp_ind = field.index(i) - break - if emp_ind % 4 == 0 and key == 'a': - return None - if emp_ind % 4 == 3 and key == 'd': - return None - if emp_ind + MOVES[key] < 0: - return None - if emp_ind + MOVES[key] > 15: - return None - - field[emp_ind], field[emp_ind + MOVES[key]] = field[emp_ind + MOVES[key]], field[emp_ind] - return field - -def handle_user_input(): - - my_key = input() - if my_key not in ['w', 'a', 's', 'd']: - return None - return my_key - - -def main(): - game_field = shuffle_field() - while not is_game_finished(game_field): - print_field(game_field) - perform_move(game_field, handle_user_input()) - print("YOU WIN") - - -if __name__ == '__main__': - # See what this means: - # http://stackoverflow.com/questions/419163/what-does-if-name-main-do - main() From 09b9e9d50f49ed92a3e68c2397c4f4ae79b7460e Mon Sep 17 00:00:00 2001 From: At0mn1yIvan Date: Wed, 12 Oct 2022 20:49:55 +0300 Subject: [PATCH 4/9] Solution --- homeworks/At0mn1yIvan/3/contract.py | 37 ----- homeworks/At0mn1yIvan/4/.idea/.gitignore | 3 + homeworks/At0mn1yIvan/4/.idea/HW4.iml | 10 ++ .../inspectionProfiles/profiles_settings.xml | 6 + homeworks/At0mn1yIvan/4/.idea/misc.xml | 4 + homeworks/At0mn1yIvan/4/.idea/modules.xml | 8 ++ homeworks/At0mn1yIvan/4/tests/__init__.py | 0 homeworks/At0mn1yIvan/4/tests/conftest.py | 5 + .../At0mn1yIvan/4/tests/test_done_command.py | 30 ++++ .../4/tests/test_representations.py | 18 +++ .../At0mn1yIvan/4/tests/test_to_read_item.py | 43 ++++++ .../4/tests/test_undone_command.py | 30 ++++ homeworks/At0mn1yIvan/4/todo/__init__.py | 0 homeworks/At0mn1yIvan/4/todo/__main__.py | 28 ++++ homeworks/At0mn1yIvan/4/todo/commands.py | 131 ++++++++++++++++++ .../At0mn1yIvan/4/todo/custom_exceptions.py | 2 + homeworks/At0mn1yIvan/4/todo/models.py | 52 +++++++ homeworks/At0mn1yIvan/4/todo/reflection.py | 35 +++++ homeworks/At0mn1yIvan/4/todo/runtime.py | 52 +++++++ homeworks/At0mn1yIvan/4/todo/storage.py | 21 +++ 20 files changed, 478 insertions(+), 37 deletions(-) delete mode 100644 homeworks/At0mn1yIvan/3/contract.py create mode 100644 homeworks/At0mn1yIvan/4/.idea/.gitignore create mode 100644 homeworks/At0mn1yIvan/4/.idea/HW4.iml create mode 100644 homeworks/At0mn1yIvan/4/.idea/inspectionProfiles/profiles_settings.xml create mode 100644 homeworks/At0mn1yIvan/4/.idea/misc.xml create mode 100644 homeworks/At0mn1yIvan/4/.idea/modules.xml create mode 100644 homeworks/At0mn1yIvan/4/tests/__init__.py create mode 100644 homeworks/At0mn1yIvan/4/tests/conftest.py create mode 100644 homeworks/At0mn1yIvan/4/tests/test_done_command.py create mode 100644 homeworks/At0mn1yIvan/4/tests/test_representations.py create mode 100644 homeworks/At0mn1yIvan/4/tests/test_to_read_item.py create mode 100644 homeworks/At0mn1yIvan/4/tests/test_undone_command.py create mode 100644 homeworks/At0mn1yIvan/4/todo/__init__.py create mode 100644 homeworks/At0mn1yIvan/4/todo/__main__.py create mode 100644 homeworks/At0mn1yIvan/4/todo/commands.py create mode 100644 homeworks/At0mn1yIvan/4/todo/custom_exceptions.py create mode 100644 homeworks/At0mn1yIvan/4/todo/models.py create mode 100644 homeworks/At0mn1yIvan/4/todo/reflection.py create mode 100644 homeworks/At0mn1yIvan/4/todo/runtime.py create mode 100644 homeworks/At0mn1yIvan/4/todo/storage.py diff --git a/homeworks/At0mn1yIvan/3/contract.py b/homeworks/At0mn1yIvan/3/contract.py deleted file mode 100644 index b7b6851..0000000 --- a/homeworks/At0mn1yIvan/3/contract.py +++ /dev/null @@ -1,37 +0,0 @@ -class ContractError(Exception): - """We use this error when someone breaks our contract.""" - - -#: Special value, that indicates that validation for this type is not required. -Any = object() - - -def contract(arg_types=None, return_type=None, raises=None): - def contract_decorator(func): - def wrapped(*args, **kwargs): - all_args = tuple(args + tuple(kwargs.values())) - if arg_types is not None: - for elem in range(len(arg_types)): - if arg_types[elem] != Any: - if not isinstance(all_args[elem], arg_types[elem]): - raise ContractError("Invalid ArgType Error") - try: - result = func(*args, **kwargs) - except (Exception if raises is None or Any in raises else raises) as exc: - raise exc - except Exception as ex: - raise ContractError from ex - if return_type is not None: - if not isinstance(result, return_type): - raise ContractError("Invalid ReturnType Error") - return result - return wrapped - return contract_decorator - - -@contract(arg_types=(Any, int), return_type=None, raises=(ZeroDivisionError,)) -def add_two_numbers(first, second): - return first + second - - -print(add_two_numbers(15, 7.5)) \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/4/.idea/.gitignore b/homeworks/At0mn1yIvan/4/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/homeworks/At0mn1yIvan/4/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/homeworks/At0mn1yIvan/4/.idea/HW4.iml b/homeworks/At0mn1yIvan/4/.idea/HW4.iml new file mode 100644 index 0000000..74d515a --- /dev/null +++ b/homeworks/At0mn1yIvan/4/.idea/HW4.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/4/.idea/inspectionProfiles/profiles_settings.xml b/homeworks/At0mn1yIvan/4/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/homeworks/At0mn1yIvan/4/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/4/.idea/misc.xml b/homeworks/At0mn1yIvan/4/.idea/misc.xml new file mode 100644 index 0000000..d5637fc --- /dev/null +++ b/homeworks/At0mn1yIvan/4/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/4/.idea/modules.xml b/homeworks/At0mn1yIvan/4/.idea/modules.xml new file mode 100644 index 0000000..37e6459 --- /dev/null +++ b/homeworks/At0mn1yIvan/4/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/4/tests/__init__.py b/homeworks/At0mn1yIvan/4/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/homeworks/At0mn1yIvan/4/tests/conftest.py b/homeworks/At0mn1yIvan/4/tests/conftest.py new file mode 100644 index 0000000..e846edf --- /dev/null +++ b/homeworks/At0mn1yIvan/4/tests/conftest.py @@ -0,0 +1,5 @@ +import os +import sys + +BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) +sys.path.append(BASE_DIR) diff --git a/homeworks/At0mn1yIvan/4/tests/test_done_command.py b/homeworks/At0mn1yIvan/4/tests/test_done_command.py new file mode 100644 index 0000000..83a6927 --- /dev/null +++ b/homeworks/At0mn1yIvan/4/tests/test_done_command.py @@ -0,0 +1,30 @@ +def test_class_exists(): + from todo.commands import DoneCommand + + assert isinstance(DoneCommand, type) + + +def test_command_label_in_list(): + from todo.commands import DoneCommand + from todo.runtime import get_routes + + assert DoneCommand().label in get_routes() + + +def test_command_execution(monkeypatch): + from todo.commands import DoneCommand + from todo.runtime import perform_command + from todo.models import Storage, ToDoItem + + monkeypatch.setitem(__builtins__, 'input', lambda _: 0) + + item = ToDoItem('test') + item.done = False + + s = Storage() + s.items.clear() + s.items.append(item) + + perform_command(DoneCommand().label) + + assert item.done is True diff --git a/homeworks/At0mn1yIvan/4/tests/test_representations.py b/homeworks/At0mn1yIvan/4/tests/test_representations.py new file mode 100644 index 0000000..07043c8 --- /dev/null +++ b/homeworks/At0mn1yIvan/4/tests/test_representations.py @@ -0,0 +1,18 @@ +def test_to_buy_item(): + from todo.models import ToBuyItem + + item = ToBuyItem('header', 'price') + assert str(item).startswith('- ToBuy: ') + + item.done = True + assert str(item).startswith('+ ToBuy: ') + + +def test_to_do_item(): + from todo.models import ToDoItem + + item = ToDoItem('subject') + assert str(item).startswith('- ToDo: ') + + item.done = True + assert str(item).startswith('+ ToDo: ') diff --git a/homeworks/At0mn1yIvan/4/tests/test_to_read_item.py b/homeworks/At0mn1yIvan/4/tests/test_to_read_item.py new file mode 100644 index 0000000..b1ea1e3 --- /dev/null +++ b/homeworks/At0mn1yIvan/4/tests/test_to_read_item.py @@ -0,0 +1,43 @@ +def test_class_exists(): + from todo.models import ToReadItem + + assert isinstance(ToReadItem, type) + + +def test_there_are_attributes(): + from todo.models import ToReadItem + + heading = 'test' + url = 'http://ya.ru' + item = ToReadItem(heading, url) + + assert item.heading == heading + assert item.url == url + assert item.done is False + + +def test_fabric_method(monkeypatch): + from todo.models import ToReadItem + + value = 'some input' + + monkeypatch.setitem(__builtins__, 'input', lambda _: value) + item = ToReadItem.construct() + + assert item.heading == value + assert item.url == value + assert item.done is False + + +def test_representation(): + from todo.models import ToReadItem + + heading = 'test' + url = 'http://ya.ru' + item = ToReadItem(heading, url) + + assert str(item) == '- ToRead: {} {}'.format(heading, url) + + item.done = True + + assert str(item) == '+ ToRead: {} {}'.format(heading, url) diff --git a/homeworks/At0mn1yIvan/4/tests/test_undone_command.py b/homeworks/At0mn1yIvan/4/tests/test_undone_command.py new file mode 100644 index 0000000..b25bedf --- /dev/null +++ b/homeworks/At0mn1yIvan/4/tests/test_undone_command.py @@ -0,0 +1,30 @@ +def test_class_exists(): + from todo.commands import UndoneCommand + + assert isinstance(UndoneCommand, type) + + +def test_command_label_in_list(): + from todo.commands import UndoneCommand + from todo.runtime import get_routes + + assert UndoneCommand().label in get_routes() + + +def test_command_execution(monkeypatch): + from todo.commands import UndoneCommand + from todo.runtime import perform_command + from todo.models import Storage, ToDoItem + + monkeypatch.setitem(__builtins__, 'input', lambda _: 0) + + item = ToDoItem('test') + item.done = True + + s = Storage() + s.items.clear() + s.items.append(item) + + perform_command(UndoneCommand().label) + + assert item.done is False diff --git a/homeworks/At0mn1yIvan/4/todo/__init__.py b/homeworks/At0mn1yIvan/4/todo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/homeworks/At0mn1yIvan/4/todo/__main__.py b/homeworks/At0mn1yIvan/4/todo/__main__.py new file mode 100644 index 0000000..55f9f2c --- /dev/null +++ b/homeworks/At0mn1yIvan/4/todo/__main__.py @@ -0,0 +1,28 @@ +""" +Main file. Contains program execution logic. +""" + +from todo.custom_exceptions import UserExitException +from todo.runtime import parse_user_input, perform_command + + +def main(): + """ + Main method, works infinitely until user runs `exit` command. + Or hits `Ctrl+C` in the console. + """ + while True: + try: + perform_command(parse_user_input()) + except UserExitException: + break + except Exception as ex: + print('You have done something wrong!', ex) + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + print() + print('Shutting down, bye!') diff --git a/homeworks/At0mn1yIvan/4/todo/commands.py b/homeworks/At0mn1yIvan/4/todo/commands.py new file mode 100644 index 0000000..330af74 --- /dev/null +++ b/homeworks/At0mn1yIvan/4/todo/commands.py @@ -0,0 +1,131 @@ + +from todo.custom_exceptions import UserExitException +from todo.models import BaseItem +from todo.reflection import find_classes + + +class BaseCommand(object): + label: str + + def perform(self, store): + raise NotImplementedError() + + +class ListCommand(BaseCommand): + label = 'list' + + def perform(self, store): + if len(store.items) == 0: + print('There are no items in the storage.') + return + + for index, obj in enumerate(store.items): + print('{0}: {1}'.format(index, str(obj))) + + +class NewCommand(BaseCommand): + label = 'new' + + def perform(self, store): + classes = self._load_item_classes() + + print('Select item type:') + for index, name in enumerate(classes.keys()): + print('{0}: {1}'.format(index, name)) + + selection = None + selected_key = None + + while True: + try: + selected_key = self._select_item(classes) + except ValueError: + print('Bad input, try again.') + except IndexError: + print('Wrong index, try again.') + else: + break + + selected_class = classes[selected_key] + print('Selected: {0}'.format(selected_class.__name__)) + print() + + new_object = selected_class.construct() + + store.items.append(new_object) + + print('Added {0}'.format(str(new_object))) + print() + return new_object + + + def _load_item_classes(self) -> dict: + # Dynamic load: + return dict(find_classes(BaseItem)) + + + def _select_item(self, classes): + selection = int(input('Input number: ')) + if selection < 0: + raise IndexError('Index needs to be >0') + return list(classes.keys())[selection] + + +class MarkCommand(object): + + def perform(self, store): + k = 0 + + for obj in store.items: + if str(obj)[0] == self.char_command: + k += 1 + if k == 0: + print("There are no {0} items in the storage.".format(self.char_command)) + return + + for index, obj in enumerate(store.items): + if str(obj)[0] == self.char_command: + print('{0}: {1}'.format(index, str(obj))) + + selected_item = self.select_item(store) + + print("{0} has been {1}\n".format(selected_item, self.operation)) + + operation = getattr(selected_item, str(self.operation), None) + assert operation is not None + operation() + + def select_item(self, store): + while True: + try: + user_selection = int(input("Input number of item: ")) + if user_selection < 0 or str(store.items[user_selection])[0] != self.char_command: + raise IndexError() + except ValueError: + print("Bad input, try again") + except IndexError: + print("Bad index, try again") + else: + break + if store.items is None: + print("There are no items in storage") + return store.items[user_selection] + + +class DoneCommand(MarkCommand, BaseCommand): + label = "done" + char_command = '-' + operation = "mark_done" + + +class UndoneCommand(MarkCommand, BaseCommand): + label = "undone" + char_command = '+' + operation = "mark_undone" + + +class ExitCommand(BaseCommand): + label = 'exit' + + def perform(self, _store): + raise UserExitException('See you next time!') diff --git a/homeworks/At0mn1yIvan/4/todo/custom_exceptions.py b/homeworks/At0mn1yIvan/4/todo/custom_exceptions.py new file mode 100644 index 0000000..5e8963c --- /dev/null +++ b/homeworks/At0mn1yIvan/4/todo/custom_exceptions.py @@ -0,0 +1,2 @@ +class UserExitException(Exception): + """We use this exception when user wants to exit.""" diff --git a/homeworks/At0mn1yIvan/4/todo/models.py b/homeworks/At0mn1yIvan/4/todo/models.py new file mode 100644 index 0000000..cac7010 --- /dev/null +++ b/homeworks/At0mn1yIvan/4/todo/models.py @@ -0,0 +1,52 @@ +class BaseItem(object): + def __init__(self, heading): + self.heading = heading + self.done = False #TODO: make sure we can use it... + + def __repr__(self): + return self.__class__.__name__ + + def mark_done(self): + self.done = True + + def mark_undone(self): + self.done = False + + def __str__(self): + return "{0} {1}".format('+' if self.done else '-', self.__repr__()) + + @classmethod + def construct(cls): + raise NotImplementedError() + + +class ToDoItem(BaseItem): + def __str__(self): + return '{0}: {1}'.format( + super().__str__(), + self.heading, + ) + + @classmethod + def construct(cls): + heading = input('Input heading: ') + return cls(heading) + + +class ToBuyItem(BaseItem): + def __init__(self, heading, price): + super().__init__(heading) + self.price = price + + def __str__(self): + return '{0}: {1} for {2}'.format( + super().__str__(), + self.heading, + self.price, + ) + + @classmethod + def construct(cls): + heading = input('Input heading: ') + price = input('Input price: ') + return cls(heading, price) diff --git a/homeworks/At0mn1yIvan/4/todo/reflection.py b/homeworks/At0mn1yIvan/4/todo/reflection.py new file mode 100644 index 0000000..40dcfbf --- /dev/null +++ b/homeworks/At0mn1yIvan/4/todo/reflection.py @@ -0,0 +1,35 @@ +import inspect +import sys + + +def find_classes(base_class) -> tuple: + """ + Finds all subclasses of a class inside module. + + :param base_class: Base class to search children. + :return: tuple of subclasses + """ + return inspect.getmembers( + sys.modules[base_class.__module__], + _reflect_filter(base_class), + ) + + +def _reflect_filter(base_class): + """ + Reflection is used to load modules dynamically. + + This method is complex. It does some dark magic. + How is it even possible to understand it? + + :param base_class: Target base class + :return: function to filter only subclasses of `base_class` + """ + + def class_filter(klass): + return inspect.isclass( + klass, + ) and klass.__module__ == base_class.__module__ and issubclass( + klass, base_class, + ) and klass is not base_class + return class_filter diff --git a/homeworks/At0mn1yIvan/4/todo/runtime.py b/homeworks/At0mn1yIvan/4/todo/runtime.py new file mode 100644 index 0000000..c955fa3 --- /dev/null +++ b/homeworks/At0mn1yIvan/4/todo/runtime.py @@ -0,0 +1,52 @@ +from todo.commands import BaseCommand +from todo.custom_exceptions import UserExitException +from todo.reflection import find_classes +from todo.storage import Storage + + +def get_routes() -> dict: + """ + This function contains the dictionary of possible commands. + :return: `dict` of possible commands, with the format: `name -> class` + """ + routes = find_classes(BaseCommand) + return { + route().label: route + for _, route in routes + } + + +def perform_command(command: str) -> None: + """ + Performs the command by name. + Stores the result in `Storage()`. + :param command: command name, selected by user. + """ + command = command.lower() + routes = get_routes() + + try: + command_class = routes[command] + except KeyError: + print('Bad command, try again.') + return + + command_inst = command_class() + storage = Storage() + + try: + command_inst.perform(storage) + except UserExitException as ex: + # Handling `exit` command. + print(ex) + raise + + +def parse_user_input(): + """ + Gets the user input. + :return: `str` with the user input. + """ + commands = get_routes().keys() + message = 'Input your command: ({0}): '.format('|'.join(commands)) + return input(message) diff --git a/homeworks/At0mn1yIvan/4/todo/storage.py b/homeworks/At0mn1yIvan/4/todo/storage.py new file mode 100644 index 0000000..b60a81d --- /dev/null +++ b/homeworks/At0mn1yIvan/4/todo/storage.py @@ -0,0 +1,21 @@ +class Storage(object): # storage = Storage() + """ + Singleton storage. + + Read more about singleton design pattern: + https://stackoverflow.com/questions/6760685/creating-a-singleton-in-python + https://en.wikipedia.org/wiki/Singleton_pattern + + It is used to emulate in-memory storage. + It should be replaced with a database in a real application. + """ + + obj = None + items = None + + @classmethod + def __new__(cls, *args): + if cls.obj is None: + cls.obj = object.__new__(cls) + cls.items = [] + return cls.obj From c3f4f200727bb70522f1f8b03d769e228ed63468 Mon Sep 17 00:00:00 2001 From: At0mn1yIvan Date: Wed, 19 Oct 2022 20:21:53 +0300 Subject: [PATCH 5/9] Solution --- homeworks/At0mn1yIvan/4/.idea/.gitignore | 3 - homeworks/At0mn1yIvan/4/tests/conftest.py | 5 - .../At0mn1yIvan/4/tests/test_done_command.py | 30 ---- .../4/tests/test_representations.py | 18 --- .../At0mn1yIvan/4/tests/test_to_read_item.py | 43 ------ .../4/tests/test_undone_command.py | 30 ---- homeworks/At0mn1yIvan/4/todo/__init__.py | 0 homeworks/At0mn1yIvan/4/todo/__main__.py | 28 ---- homeworks/At0mn1yIvan/4/todo/commands.py | 131 ------------------ .../At0mn1yIvan/4/todo/custom_exceptions.py | 2 - homeworks/At0mn1yIvan/4/todo/models.py | 52 ------- homeworks/At0mn1yIvan/4/todo/reflection.py | 35 ----- homeworks/At0mn1yIvan/4/todo/runtime.py | 52 ------- homeworks/At0mn1yIvan/4/todo/storage.py | 21 --- .../inspectionProfiles/profiles_settings.xml | 0 .../{4 => 5/my_awesome_script}/.idea/misc.xml | 2 +- .../my_awesome_script}/.idea/modules.xml | 2 +- .../.idea/my_awesome_script.iml} | 4 +- .../5/my_awesome_script/.idea/workspace.xml | 30 ++++ .../tests => 5/my_awesome_script}/__init__.py | 0 .../5/my_awesome_script/__main__.py | 16 +++ .../At0mn1yIvan/5/my_awesome_script/cmnds.py | 37 +++++ .../5/my_awesome_script/tskInput.py | 15 ++ 23 files changed, 101 insertions(+), 455 deletions(-) delete mode 100644 homeworks/At0mn1yIvan/4/.idea/.gitignore delete mode 100644 homeworks/At0mn1yIvan/4/tests/conftest.py delete mode 100644 homeworks/At0mn1yIvan/4/tests/test_done_command.py delete mode 100644 homeworks/At0mn1yIvan/4/tests/test_representations.py delete mode 100644 homeworks/At0mn1yIvan/4/tests/test_to_read_item.py delete mode 100644 homeworks/At0mn1yIvan/4/tests/test_undone_command.py delete mode 100644 homeworks/At0mn1yIvan/4/todo/__init__.py delete mode 100644 homeworks/At0mn1yIvan/4/todo/__main__.py delete mode 100644 homeworks/At0mn1yIvan/4/todo/commands.py delete mode 100644 homeworks/At0mn1yIvan/4/todo/custom_exceptions.py delete mode 100644 homeworks/At0mn1yIvan/4/todo/models.py delete mode 100644 homeworks/At0mn1yIvan/4/todo/reflection.py delete mode 100644 homeworks/At0mn1yIvan/4/todo/runtime.py delete mode 100644 homeworks/At0mn1yIvan/4/todo/storage.py rename homeworks/At0mn1yIvan/{4 => 5/my_awesome_script}/.idea/inspectionProfiles/profiles_settings.xml (100%) rename homeworks/At0mn1yIvan/{4 => 5/my_awesome_script}/.idea/misc.xml (69%) rename homeworks/At0mn1yIvan/{4 => 5/my_awesome_script}/.idea/modules.xml (54%) rename homeworks/At0mn1yIvan/{4/.idea/HW4.iml => 5/my_awesome_script/.idea/my_awesome_script.iml} (68%) create mode 100644 homeworks/At0mn1yIvan/5/my_awesome_script/.idea/workspace.xml rename homeworks/At0mn1yIvan/{4/tests => 5/my_awesome_script}/__init__.py (100%) create mode 100644 homeworks/At0mn1yIvan/5/my_awesome_script/__main__.py create mode 100644 homeworks/At0mn1yIvan/5/my_awesome_script/cmnds.py create mode 100644 homeworks/At0mn1yIvan/5/my_awesome_script/tskInput.py diff --git a/homeworks/At0mn1yIvan/4/.idea/.gitignore b/homeworks/At0mn1yIvan/4/.idea/.gitignore deleted file mode 100644 index 26d3352..0000000 --- a/homeworks/At0mn1yIvan/4/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/homeworks/At0mn1yIvan/4/tests/conftest.py b/homeworks/At0mn1yIvan/4/tests/conftest.py deleted file mode 100644 index e846edf..0000000 --- a/homeworks/At0mn1yIvan/4/tests/conftest.py +++ /dev/null @@ -1,5 +0,0 @@ -import os -import sys - -BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) -sys.path.append(BASE_DIR) diff --git a/homeworks/At0mn1yIvan/4/tests/test_done_command.py b/homeworks/At0mn1yIvan/4/tests/test_done_command.py deleted file mode 100644 index 83a6927..0000000 --- a/homeworks/At0mn1yIvan/4/tests/test_done_command.py +++ /dev/null @@ -1,30 +0,0 @@ -def test_class_exists(): - from todo.commands import DoneCommand - - assert isinstance(DoneCommand, type) - - -def test_command_label_in_list(): - from todo.commands import DoneCommand - from todo.runtime import get_routes - - assert DoneCommand().label in get_routes() - - -def test_command_execution(monkeypatch): - from todo.commands import DoneCommand - from todo.runtime import perform_command - from todo.models import Storage, ToDoItem - - monkeypatch.setitem(__builtins__, 'input', lambda _: 0) - - item = ToDoItem('test') - item.done = False - - s = Storage() - s.items.clear() - s.items.append(item) - - perform_command(DoneCommand().label) - - assert item.done is True diff --git a/homeworks/At0mn1yIvan/4/tests/test_representations.py b/homeworks/At0mn1yIvan/4/tests/test_representations.py deleted file mode 100644 index 07043c8..0000000 --- a/homeworks/At0mn1yIvan/4/tests/test_representations.py +++ /dev/null @@ -1,18 +0,0 @@ -def test_to_buy_item(): - from todo.models import ToBuyItem - - item = ToBuyItem('header', 'price') - assert str(item).startswith('- ToBuy: ') - - item.done = True - assert str(item).startswith('+ ToBuy: ') - - -def test_to_do_item(): - from todo.models import ToDoItem - - item = ToDoItem('subject') - assert str(item).startswith('- ToDo: ') - - item.done = True - assert str(item).startswith('+ ToDo: ') diff --git a/homeworks/At0mn1yIvan/4/tests/test_to_read_item.py b/homeworks/At0mn1yIvan/4/tests/test_to_read_item.py deleted file mode 100644 index b1ea1e3..0000000 --- a/homeworks/At0mn1yIvan/4/tests/test_to_read_item.py +++ /dev/null @@ -1,43 +0,0 @@ -def test_class_exists(): - from todo.models import ToReadItem - - assert isinstance(ToReadItem, type) - - -def test_there_are_attributes(): - from todo.models import ToReadItem - - heading = 'test' - url = 'http://ya.ru' - item = ToReadItem(heading, url) - - assert item.heading == heading - assert item.url == url - assert item.done is False - - -def test_fabric_method(monkeypatch): - from todo.models import ToReadItem - - value = 'some input' - - monkeypatch.setitem(__builtins__, 'input', lambda _: value) - item = ToReadItem.construct() - - assert item.heading == value - assert item.url == value - assert item.done is False - - -def test_representation(): - from todo.models import ToReadItem - - heading = 'test' - url = 'http://ya.ru' - item = ToReadItem(heading, url) - - assert str(item) == '- ToRead: {} {}'.format(heading, url) - - item.done = True - - assert str(item) == '+ ToRead: {} {}'.format(heading, url) diff --git a/homeworks/At0mn1yIvan/4/tests/test_undone_command.py b/homeworks/At0mn1yIvan/4/tests/test_undone_command.py deleted file mode 100644 index b25bedf..0000000 --- a/homeworks/At0mn1yIvan/4/tests/test_undone_command.py +++ /dev/null @@ -1,30 +0,0 @@ -def test_class_exists(): - from todo.commands import UndoneCommand - - assert isinstance(UndoneCommand, type) - - -def test_command_label_in_list(): - from todo.commands import UndoneCommand - from todo.runtime import get_routes - - assert UndoneCommand().label in get_routes() - - -def test_command_execution(monkeypatch): - from todo.commands import UndoneCommand - from todo.runtime import perform_command - from todo.models import Storage, ToDoItem - - monkeypatch.setitem(__builtins__, 'input', lambda _: 0) - - item = ToDoItem('test') - item.done = True - - s = Storage() - s.items.clear() - s.items.append(item) - - perform_command(UndoneCommand().label) - - assert item.done is False diff --git a/homeworks/At0mn1yIvan/4/todo/__init__.py b/homeworks/At0mn1yIvan/4/todo/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/homeworks/At0mn1yIvan/4/todo/__main__.py b/homeworks/At0mn1yIvan/4/todo/__main__.py deleted file mode 100644 index 55f9f2c..0000000 --- a/homeworks/At0mn1yIvan/4/todo/__main__.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -Main file. Contains program execution logic. -""" - -from todo.custom_exceptions import UserExitException -from todo.runtime import parse_user_input, perform_command - - -def main(): - """ - Main method, works infinitely until user runs `exit` command. - Or hits `Ctrl+C` in the console. - """ - while True: - try: - perform_command(parse_user_input()) - except UserExitException: - break - except Exception as ex: - print('You have done something wrong!', ex) - - -if __name__ == '__main__': - try: - main() - except KeyboardInterrupt: - print() - print('Shutting down, bye!') diff --git a/homeworks/At0mn1yIvan/4/todo/commands.py b/homeworks/At0mn1yIvan/4/todo/commands.py deleted file mode 100644 index 330af74..0000000 --- a/homeworks/At0mn1yIvan/4/todo/commands.py +++ /dev/null @@ -1,131 +0,0 @@ - -from todo.custom_exceptions import UserExitException -from todo.models import BaseItem -from todo.reflection import find_classes - - -class BaseCommand(object): - label: str - - def perform(self, store): - raise NotImplementedError() - - -class ListCommand(BaseCommand): - label = 'list' - - def perform(self, store): - if len(store.items) == 0: - print('There are no items in the storage.') - return - - for index, obj in enumerate(store.items): - print('{0}: {1}'.format(index, str(obj))) - - -class NewCommand(BaseCommand): - label = 'new' - - def perform(self, store): - classes = self._load_item_classes() - - print('Select item type:') - for index, name in enumerate(classes.keys()): - print('{0}: {1}'.format(index, name)) - - selection = None - selected_key = None - - while True: - try: - selected_key = self._select_item(classes) - except ValueError: - print('Bad input, try again.') - except IndexError: - print('Wrong index, try again.') - else: - break - - selected_class = classes[selected_key] - print('Selected: {0}'.format(selected_class.__name__)) - print() - - new_object = selected_class.construct() - - store.items.append(new_object) - - print('Added {0}'.format(str(new_object))) - print() - return new_object - - - def _load_item_classes(self) -> dict: - # Dynamic load: - return dict(find_classes(BaseItem)) - - - def _select_item(self, classes): - selection = int(input('Input number: ')) - if selection < 0: - raise IndexError('Index needs to be >0') - return list(classes.keys())[selection] - - -class MarkCommand(object): - - def perform(self, store): - k = 0 - - for obj in store.items: - if str(obj)[0] == self.char_command: - k += 1 - if k == 0: - print("There are no {0} items in the storage.".format(self.char_command)) - return - - for index, obj in enumerate(store.items): - if str(obj)[0] == self.char_command: - print('{0}: {1}'.format(index, str(obj))) - - selected_item = self.select_item(store) - - print("{0} has been {1}\n".format(selected_item, self.operation)) - - operation = getattr(selected_item, str(self.operation), None) - assert operation is not None - operation() - - def select_item(self, store): - while True: - try: - user_selection = int(input("Input number of item: ")) - if user_selection < 0 or str(store.items[user_selection])[0] != self.char_command: - raise IndexError() - except ValueError: - print("Bad input, try again") - except IndexError: - print("Bad index, try again") - else: - break - if store.items is None: - print("There are no items in storage") - return store.items[user_selection] - - -class DoneCommand(MarkCommand, BaseCommand): - label = "done" - char_command = '-' - operation = "mark_done" - - -class UndoneCommand(MarkCommand, BaseCommand): - label = "undone" - char_command = '+' - operation = "mark_undone" - - -class ExitCommand(BaseCommand): - label = 'exit' - - def perform(self, _store): - raise UserExitException('See you next time!') diff --git a/homeworks/At0mn1yIvan/4/todo/custom_exceptions.py b/homeworks/At0mn1yIvan/4/todo/custom_exceptions.py deleted file mode 100644 index 5e8963c..0000000 --- a/homeworks/At0mn1yIvan/4/todo/custom_exceptions.py +++ /dev/null @@ -1,2 +0,0 @@ -class UserExitException(Exception): - """We use this exception when user wants to exit.""" diff --git a/homeworks/At0mn1yIvan/4/todo/models.py b/homeworks/At0mn1yIvan/4/todo/models.py deleted file mode 100644 index cac7010..0000000 --- a/homeworks/At0mn1yIvan/4/todo/models.py +++ /dev/null @@ -1,52 +0,0 @@ -class BaseItem(object): - def __init__(self, heading): - self.heading = heading - self.done = False #TODO: make sure we can use it... - - def __repr__(self): - return self.__class__.__name__ - - def mark_done(self): - self.done = True - - def mark_undone(self): - self.done = False - - def __str__(self): - return "{0} {1}".format('+' if self.done else '-', self.__repr__()) - - @classmethod - def construct(cls): - raise NotImplementedError() - - -class ToDoItem(BaseItem): - def __str__(self): - return '{0}: {1}'.format( - super().__str__(), - self.heading, - ) - - @classmethod - def construct(cls): - heading = input('Input heading: ') - return cls(heading) - - -class ToBuyItem(BaseItem): - def __init__(self, heading, price): - super().__init__(heading) - self.price = price - - def __str__(self): - return '{0}: {1} for {2}'.format( - super().__str__(), - self.heading, - self.price, - ) - - @classmethod - def construct(cls): - heading = input('Input heading: ') - price = input('Input price: ') - return cls(heading, price) diff --git a/homeworks/At0mn1yIvan/4/todo/reflection.py b/homeworks/At0mn1yIvan/4/todo/reflection.py deleted file mode 100644 index 40dcfbf..0000000 --- a/homeworks/At0mn1yIvan/4/todo/reflection.py +++ /dev/null @@ -1,35 +0,0 @@ -import inspect -import sys - - -def find_classes(base_class) -> tuple: - """ - Finds all subclasses of a class inside module. - - :param base_class: Base class to search children. - :return: tuple of subclasses - """ - return inspect.getmembers( - sys.modules[base_class.__module__], - _reflect_filter(base_class), - ) - - -def _reflect_filter(base_class): - """ - Reflection is used to load modules dynamically. - - This method is complex. It does some dark magic. - How is it even possible to understand it? - - :param base_class: Target base class - :return: function to filter only subclasses of `base_class` - """ - - def class_filter(klass): - return inspect.isclass( - klass, - ) and klass.__module__ == base_class.__module__ and issubclass( - klass, base_class, - ) and klass is not base_class - return class_filter diff --git a/homeworks/At0mn1yIvan/4/todo/runtime.py b/homeworks/At0mn1yIvan/4/todo/runtime.py deleted file mode 100644 index c955fa3..0000000 --- a/homeworks/At0mn1yIvan/4/todo/runtime.py +++ /dev/null @@ -1,52 +0,0 @@ -from todo.commands import BaseCommand -from todo.custom_exceptions import UserExitException -from todo.reflection import find_classes -from todo.storage import Storage - - -def get_routes() -> dict: - """ - This function contains the dictionary of possible commands. - :return: `dict` of possible commands, with the format: `name -> class` - """ - routes = find_classes(BaseCommand) - return { - route().label: route - for _, route in routes - } - - -def perform_command(command: str) -> None: - """ - Performs the command by name. - Stores the result in `Storage()`. - :param command: command name, selected by user. - """ - command = command.lower() - routes = get_routes() - - try: - command_class = routes[command] - except KeyError: - print('Bad command, try again.') - return - - command_inst = command_class() - storage = Storage() - - try: - command_inst.perform(storage) - except UserExitException as ex: - # Handling `exit` command. - print(ex) - raise - - -def parse_user_input(): - """ - Gets the user input. - :return: `str` with the user input. - """ - commands = get_routes().keys() - message = 'Input your command: ({0}): '.format('|'.join(commands)) - return input(message) diff --git a/homeworks/At0mn1yIvan/4/todo/storage.py b/homeworks/At0mn1yIvan/4/todo/storage.py deleted file mode 100644 index b60a81d..0000000 --- a/homeworks/At0mn1yIvan/4/todo/storage.py +++ /dev/null @@ -1,21 +0,0 @@ -class Storage(object): # storage = Storage() - """ - Singleton storage. - - Read more about singleton design pattern: - https://stackoverflow.com/questions/6760685/creating-a-singleton-in-python - https://en.wikipedia.org/wiki/Singleton_pattern - - It is used to emulate in-memory storage. - It should be replaced with a database in a real application. - """ - - obj = None - items = None - - @classmethod - def __new__(cls, *args): - if cls.obj is None: - cls.obj = object.__new__(cls) - cls.items = [] - return cls.obj diff --git a/homeworks/At0mn1yIvan/4/.idea/inspectionProfiles/profiles_settings.xml b/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/inspectionProfiles/profiles_settings.xml similarity index 100% rename from homeworks/At0mn1yIvan/4/.idea/inspectionProfiles/profiles_settings.xml rename to homeworks/At0mn1yIvan/5/my_awesome_script/.idea/inspectionProfiles/profiles_settings.xml diff --git a/homeworks/At0mn1yIvan/4/.idea/misc.xml b/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/misc.xml similarity index 69% rename from homeworks/At0mn1yIvan/4/.idea/misc.xml rename to homeworks/At0mn1yIvan/5/my_awesome_script/.idea/misc.xml index d5637fc..d56657a 100644 --- a/homeworks/At0mn1yIvan/4/.idea/misc.xml +++ b/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/4/.idea/modules.xml b/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/modules.xml similarity index 54% rename from homeworks/At0mn1yIvan/4/.idea/modules.xml rename to homeworks/At0mn1yIvan/5/my_awesome_script/.idea/modules.xml index 37e6459..8f193b9 100644 --- a/homeworks/At0mn1yIvan/4/.idea/modules.xml +++ b/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/modules.xml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/4/.idea/HW4.iml b/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/my_awesome_script.iml similarity index 68% rename from homeworks/At0mn1yIvan/4/.idea/HW4.iml rename to homeworks/At0mn1yIvan/5/my_awesome_script/.idea/my_awesome_script.iml index 74d515a..d0876a7 100644 --- a/homeworks/At0mn1yIvan/4/.idea/HW4.iml +++ b/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/my_awesome_script.iml @@ -1,9 +1,7 @@ - - - + diff --git a/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/workspace.xml b/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/workspace.xml new file mode 100644 index 0000000..1a1339e --- /dev/null +++ b/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/workspace.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + 1666188150890 + + + + \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/4/tests/__init__.py b/homeworks/At0mn1yIvan/5/my_awesome_script/__init__.py similarity index 100% rename from homeworks/At0mn1yIvan/4/tests/__init__.py rename to homeworks/At0mn1yIvan/5/my_awesome_script/__init__.py diff --git a/homeworks/At0mn1yIvan/5/my_awesome_script/__main__.py b/homeworks/At0mn1yIvan/5/my_awesome_script/__main__.py new file mode 100644 index 0000000..3995515 --- /dev/null +++ b/homeworks/At0mn1yIvan/5/my_awesome_script/__main__.py @@ -0,0 +1,16 @@ +from tskInput import com_input + + +def main(): + try: + com_input() + except Exception as ex: + print("Something went wrong.", ex) + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + print() + print('Shutting down, bye!') diff --git a/homeworks/At0mn1yIvan/5/my_awesome_script/cmnds.py b/homeworks/At0mn1yIvan/5/my_awesome_script/cmnds.py new file mode 100644 index 0000000..9d636bf --- /dev/null +++ b/homeworks/At0mn1yIvan/5/my_awesome_script/cmnds.py @@ -0,0 +1,37 @@ +import pytz +from pygments import highlight +from pygments.formatters import TerminalFormatter +from pygments.lexers import PythonLexer +from cowpy import cow +from datetime import datetime + + + +def task(action: str, text: str = None) -> None: + if action == 'help': + functions[action]() + else: + functions[action](text) + + +def highlight_(code: str) -> None: + print(highlight(code, PythonLexer(), TerminalFormatter())) + + +def cowsay_(text: str) -> None: + print(cow.milk_random_cow(text)) + + +def time_(timezone: str) -> None: + local_date = datetime.now(pytz.timezone(timezone)) + print("{0} {1}".format(local_date.date(), local_date.time())) + + +def help_() -> None: + print("EXAMPLE COMMAND:") + print(" highlight 'any text'") + print(" cowsay 'any text'") + print(" time 'Region/City'") + + +functions = {'highlight': highlight_, 'cowsay': cowsay_, 'time': time_, 'help': help_} \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/5/my_awesome_script/tskInput.py b/homeworks/At0mn1yIvan/5/my_awesome_script/tskInput.py new file mode 100644 index 0000000..2a67b7d --- /dev/null +++ b/homeworks/At0mn1yIvan/5/my_awesome_script/tskInput.py @@ -0,0 +1,15 @@ +import argparse +from cmnds import task, functions + + +def com_input(): + parser = argparse.ArgumentParser() + parser.add_argument("action", help="Input action.", choices=functions) + parser.add_argument("text", help="highlight 'any text' or cowsay 'any text' or time 'Region/City'.") + args = parser.parse_args() + + try: + task(args.action, args.text) + except Exception as ex: + task("help") + raise ex \ No newline at end of file From 0fdf67519dc22839d455e7a5affc0a1cefd44917 Mon Sep 17 00:00:00 2001 From: At0mn1yIvan Date: Mon, 24 Oct 2022 22:14:00 +0300 Subject: [PATCH 6/9] Solution --- .../inspectionProfiles/profiles_settings.xml | 6 ---- .../5/my_awesome_script/.idea/misc.xml | 4 --- .../5/my_awesome_script/.idea/modules.xml | 8 ----- .../.idea/my_awesome_script.iml | 8 ----- .../5/my_awesome_script/.idea/workspace.xml | 30 ------------------- 5 files changed, 56 deletions(-) delete mode 100644 homeworks/At0mn1yIvan/5/my_awesome_script/.idea/inspectionProfiles/profiles_settings.xml delete mode 100644 homeworks/At0mn1yIvan/5/my_awesome_script/.idea/misc.xml delete mode 100644 homeworks/At0mn1yIvan/5/my_awesome_script/.idea/modules.xml delete mode 100644 homeworks/At0mn1yIvan/5/my_awesome_script/.idea/my_awesome_script.iml delete mode 100644 homeworks/At0mn1yIvan/5/my_awesome_script/.idea/workspace.xml diff --git a/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/inspectionProfiles/profiles_settings.xml b/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/misc.xml b/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/misc.xml deleted file mode 100644 index d56657a..0000000 --- a/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/modules.xml b/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/modules.xml deleted file mode 100644 index 8f193b9..0000000 --- a/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/my_awesome_script.iml b/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/my_awesome_script.iml deleted file mode 100644 index d0876a7..0000000 --- a/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/my_awesome_script.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/workspace.xml b/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/workspace.xml deleted file mode 100644 index 1a1339e..0000000 --- a/homeworks/At0mn1yIvan/5/my_awesome_script/.idea/workspace.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - 1666188150890 - - - - \ No newline at end of file From 5c713a4c6c665272f23a41855e6cdf2f746e90df Mon Sep 17 00:00:00 2001 From: At0mn1yIvan Date: Wed, 26 Oct 2022 22:57:56 +0300 Subject: [PATCH 7/9] Solution --- .../5/my_awesome_script/__init__.py | 0 .../5/my_awesome_script/__main__.py | 16 - .../At0mn1yIvan/5/my_awesome_script/cmnds.py | 37 - .../5/my_awesome_script/tskInput.py | 15 - homeworks/At0mn1yIvan/6/code/Main.py | 21 + homeworks/At0mn1yIvan/6/code/ParsingJSON.py | 37 + homeworks/At0mn1yIvan/6/code/ReadCSV.py | 14 + homeworks/At0mn1yIvan/6/code/ToStart.py | 43 + homeworks/At0mn1yIvan/6/code/Writer.py | 59 ++ .../At0mn1yIvan/6/files/emails/email.csv | 1 + homeworks/At0mn1yIvan/6/files/users/1.xml | 201 +++++ homeworks/At0mn1yIvan/6/files/users/2.xml | 201 +++++ homeworks/At0mn1yIvan/6/hw7.md | 100 +++ homeworks/At0mn1yIvan/6/poetry.lock | 739 ++++++++++++++++++ homeworks/At0mn1yIvan/6/pyproject.toml | 17 + homeworks/At0mn1yIvan/6/setup.cfg | 104 +++ 16 files changed, 1537 insertions(+), 68 deletions(-) delete mode 100644 homeworks/At0mn1yIvan/5/my_awesome_script/__init__.py delete mode 100644 homeworks/At0mn1yIvan/5/my_awesome_script/__main__.py delete mode 100644 homeworks/At0mn1yIvan/5/my_awesome_script/cmnds.py delete mode 100644 homeworks/At0mn1yIvan/5/my_awesome_script/tskInput.py create mode 100644 homeworks/At0mn1yIvan/6/code/Main.py create mode 100644 homeworks/At0mn1yIvan/6/code/ParsingJSON.py create mode 100644 homeworks/At0mn1yIvan/6/code/ReadCSV.py create mode 100644 homeworks/At0mn1yIvan/6/code/ToStart.py create mode 100644 homeworks/At0mn1yIvan/6/code/Writer.py create mode 100644 homeworks/At0mn1yIvan/6/files/emails/email.csv create mode 100644 homeworks/At0mn1yIvan/6/files/users/1.xml create mode 100644 homeworks/At0mn1yIvan/6/files/users/2.xml create mode 100644 homeworks/At0mn1yIvan/6/hw7.md create mode 100644 homeworks/At0mn1yIvan/6/poetry.lock create mode 100644 homeworks/At0mn1yIvan/6/pyproject.toml create mode 100644 homeworks/At0mn1yIvan/6/setup.cfg diff --git a/homeworks/At0mn1yIvan/5/my_awesome_script/__init__.py b/homeworks/At0mn1yIvan/5/my_awesome_script/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/homeworks/At0mn1yIvan/5/my_awesome_script/__main__.py b/homeworks/At0mn1yIvan/5/my_awesome_script/__main__.py deleted file mode 100644 index 3995515..0000000 --- a/homeworks/At0mn1yIvan/5/my_awesome_script/__main__.py +++ /dev/null @@ -1,16 +0,0 @@ -from tskInput import com_input - - -def main(): - try: - com_input() - except Exception as ex: - print("Something went wrong.", ex) - - -if __name__ == '__main__': - try: - main() - except KeyboardInterrupt: - print() - print('Shutting down, bye!') diff --git a/homeworks/At0mn1yIvan/5/my_awesome_script/cmnds.py b/homeworks/At0mn1yIvan/5/my_awesome_script/cmnds.py deleted file mode 100644 index 9d636bf..0000000 --- a/homeworks/At0mn1yIvan/5/my_awesome_script/cmnds.py +++ /dev/null @@ -1,37 +0,0 @@ -import pytz -from pygments import highlight -from pygments.formatters import TerminalFormatter -from pygments.lexers import PythonLexer -from cowpy import cow -from datetime import datetime - - - -def task(action: str, text: str = None) -> None: - if action == 'help': - functions[action]() - else: - functions[action](text) - - -def highlight_(code: str) -> None: - print(highlight(code, PythonLexer(), TerminalFormatter())) - - -def cowsay_(text: str) -> None: - print(cow.milk_random_cow(text)) - - -def time_(timezone: str) -> None: - local_date = datetime.now(pytz.timezone(timezone)) - print("{0} {1}".format(local_date.date(), local_date.time())) - - -def help_() -> None: - print("EXAMPLE COMMAND:") - print(" highlight 'any text'") - print(" cowsay 'any text'") - print(" time 'Region/City'") - - -functions = {'highlight': highlight_, 'cowsay': cowsay_, 'time': time_, 'help': help_} \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/5/my_awesome_script/tskInput.py b/homeworks/At0mn1yIvan/5/my_awesome_script/tskInput.py deleted file mode 100644 index 2a67b7d..0000000 --- a/homeworks/At0mn1yIvan/5/my_awesome_script/tskInput.py +++ /dev/null @@ -1,15 +0,0 @@ -import argparse -from cmnds import task, functions - - -def com_input(): - parser = argparse.ArgumentParser() - parser.add_argument("action", help="Input action.", choices=functions) - parser.add_argument("text", help="highlight 'any text' or cowsay 'any text' or time 'Region/City'.") - args = parser.parse_args() - - try: - task(args.action, args.text) - except Exception as ex: - task("help") - raise ex \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/6/code/Main.py b/homeworks/At0mn1yIvan/6/code/Main.py new file mode 100644 index 0000000..f9162da --- /dev/null +++ b/homeworks/At0mn1yIvan/6/code/Main.py @@ -0,0 +1,21 @@ +from typing import Final + +from ToStart import start +from loguru import logger + + +def main(): + """The Main method - starting point of our program""" + try: + start(EMAILS_PATH, JSON_PATH) + except Exception as ex: + logger.exception("Something went wrong.", ex) + + +if __name__ == '__main__': + EMAILS_PATH: Final = '../files/emails/email.csv' + JSON_PATH: Final = 'https://jsonplaceholder.typicode.com/users/' + try: + main() + except KeyboardInterrupt: + logger.critical("Something went wrong.") diff --git a/homeworks/At0mn1yIvan/6/code/ParsingJSON.py b/homeworks/At0mn1yIvan/6/code/ParsingJSON.py new file mode 100644 index 0000000..e27c009 --- /dev/null +++ b/homeworks/At0mn1yIvan/6/code/ParsingJSON.py @@ -0,0 +1,37 @@ +import requests +from loguru import logger + + +def get_user_info(path: str, user_id: str, info_types: list) -> dict: + """Receives the user information + ('posts', 'albums', 'todos') + by the id from the website.""" + user_info: dict[str:list] = {} + logger.info('Parsing for ID: {0} : Start.'.format(user_id)) + for info_type in info_types: + response = requests.get(path + '{0}/{1}'.format(user_id, info_type)) + user_info[info_type] = response.json() + logger.info('Request for ID {0} to get {1} took {2}'.format( + user_id, + info_types, + response.elapsed, + )) + logger.info('Parsing for ID: {0} : Finish.'.format(user_id)) + return user_info + + +def get_email_id(path: str) -> dict: + """Receives the user ID by the email from the website.""" + user_email_id: dict[str:int] = {} + user = 1 + logger.info('Requests from the website: Begin.') + while True: + response = requests.get(path + '/{0}'.format(user)) + user_info = response.json() + if not user_info: + break + user_email_id[user_info.get('email')] = user_info.get('id') + user += 1 + logger.info('Requests from the website: Finish.') + + return user_email_id diff --git a/homeworks/At0mn1yIvan/6/code/ReadCSV.py b/homeworks/At0mn1yIvan/6/code/ReadCSV.py new file mode 100644 index 0000000..0118ec8 --- /dev/null +++ b/homeworks/At0mn1yIvan/6/code/ReadCSV.py @@ -0,0 +1,14 @@ +import csv +from loguru import logger + + +def read(path: str = None) -> tuple: + """Read the csv file.""" + with open(path) as file: + emails: list[str] = [] + reader = csv.reader(file, delimiter=',', quotechar='"') + for line in reader: + emails.extend(line) + logger.info('{0} users were read from csv file'.format(len(emails))) + + return tuple(emails) diff --git a/homeworks/At0mn1yIvan/6/code/ToStart.py b/homeworks/At0mn1yIvan/6/code/ToStart.py new file mode 100644 index 0000000..eb6d97a --- /dev/null +++ b/homeworks/At0mn1yIvan/6/code/ToStart.py @@ -0,0 +1,43 @@ +import re + +from ReadCSV import read +from ParsingJSON import get_email_id, get_user_info +from Writer import write +from loguru import logger + + +def start(emails_path: str, json_path: str): + """This method calls other methods to make the program work.""" + types_info = ['posts', 'albums', 'todos'] + _user_xml_write(emails_path, json_path, types_info) + + +def _user_xml_write(emails_path: str, json_path: str, types_info: list): + emails_id = _get_emails_id(emails_path, json_path) + for key in emails_id: + user_info = get_user_info(json_path, str(emails_id.get(key)), types_info) # noqa: E501 + path = '../files/users/{0}.xml'.format(str(emails_id.get(key))) + user_id = str(emails_id.get(key)) + write(user_id, str(key), user_info, types_info, path) + + +def _get_emails_id(emails_path: str, json_path: str) -> dict: + emails = read(str(emails_path)) + all_emails_id = get_email_id(str(json_path)) + emails_id = dict() + for key in emails: + if _is_email(key): + user_id = all_emails_id.get(key) + if user_id is None: + logger.warning('{0} is missing from the website'.format(key)) + else: + emails_id[key] = user_id + else: + logger.warning('{0} is not valid email address'.format(key)) + logger.info('{0} users were found on the website.'.format(len(emails_id))) + return emails_id + + +def _is_email(email: str) -> bool: + regex = re.compile(r'([A-Za-z0-9]+[.-_])*[A-Za-z0-9]+@[A-Za-z0-9-]+(\.[A-Z|a-z]{2,})+') # noqa: E501 + return re.fullmatch(regex, email) is not None diff --git a/homeworks/At0mn1yIvan/6/code/Writer.py b/homeworks/At0mn1yIvan/6/code/Writer.py new file mode 100644 index 0000000..f6738d6 --- /dev/null +++ b/homeworks/At0mn1yIvan/6/code/Writer.py @@ -0,0 +1,59 @@ +from xml.etree import ElementTree as Et # noqa: S405 + +from loguru import logger + + +def _remove_enter(string: str) -> str: + return string.replace('\n', '') + + +def _append_elem(root, name_new_root: str, text: str = None): + name = Et.Element(name_new_root) + if text is not None: + name.text = text + root.append(name) + + +def _append_type_info(root, name_new_root: str, user_all_info: dict): + names = Et.Element(name_new_root) + + for user_info in user_all_info.get(name_new_root): + name = Et.Element(name_new_root[:-1]) + names.append(name) + _append_elem(name, 'id', str(user_info.get('id'))) + _append_elem(name, 'title', _remove_enter(str(user_info.get('title')))) + + if name_new_root == 'posts': + body = _remove_enter(str(user_info.get('body'))) + _append_elem(name, 'body', body) + elif name_new_root == 'todos': + completed = _remove_enter(str(user_info.get('completed'))) + _append_elem(name, 'completed', completed) + root.append(names) + + +def write(user_id: str, user_email: str, user_info: dict, types_info: list, path: str): # noqa: E501 + """ + Creates ET.Element tree and writes the user info to xml file. + :param user_id + :param user_email + :param user_info : user information from the website (PATH_JSON) + :param types_info : 'posts', 'albums', 'todos' + :param path : the path to the recording file + """ + root = Et.Element('user') + _append_elem(root, 'id', user_id) + _append_elem(root, 'email', user_email) + for type_info in types_info: + _append_type_info(root, type_info, user_info) + + etree = Et.ElementTree(root) + Et.indent(etree) + with open(path, 'wb') as xml_file: + etree.write(xml_file, encoding='utf-8', xml_declaration=True) + + logger.info('Saved {0}/{1}.xml for user with email `{2}`'.format( + path, + user_id, + user_email, + )) diff --git a/homeworks/At0mn1yIvan/6/files/emails/email.csv b/homeworks/At0mn1yIvan/6/files/emails/email.csv new file mode 100644 index 0000000..a963658 --- /dev/null +++ b/homeworks/At0mn1yIvan/6/files/emails/email.csv @@ -0,0 +1 @@ +"Sincere@april.biz","Shanna@melissa.tv","anastasia.net" \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/6/files/users/1.xml b/homeworks/At0mn1yIvan/6/files/users/1.xml new file mode 100644 index 0000000..1e0c5ed --- /dev/null +++ b/homeworks/At0mn1yIvan/6/files/users/1.xml @@ -0,0 +1,201 @@ + + + 1 + Sincere@april.biz + + + 1 + sunt aut facere repellat provident occaecati excepturi optio reprehenderit + quia et suscipitsuscipit recusandae consequuntur expedita et cumreprehenderit molestiae ut ut quas totamnostrum rerum est autem sunt rem eveniet architecto + + + 2 + qui est esse + est rerum tempore vitaesequi sint nihil reprehenderit dolor beatae ea dolores nequefugiat blanditiis voluptate porro vel nihil molestiae ut reiciendisqui aperiam non debitis possimus qui neque nisi nulla + + + 3 + ea molestias quasi exercitationem repellat qui ipsa sit aut + et iusto sed quo iurevoluptatem occaecati omnis eligendi aut advoluptatem doloribus vel accusantium quis pariaturmolestiae porro eius odio et labore et velit aut + + + 4 + eum et est occaecati + ullam et saepe reiciendis voluptatem adipiscisit amet autem assumenda provident rerum culpaquis hic commodi nesciunt rem tenetur doloremque ipsam iurequis sunt voluptatem rerum illo velit + + + 5 + nesciunt quas odio + repudiandae veniam quaerat sunt sedalias aut fugiat sit autem sed estvoluptatem omnis possimus esse voluptatibus quisest aut tenetur dolor neque + + + 6 + dolorem eum magni eos aperiam quia + ut aspernatur corporis harum nihil quis provident sequimollitia nobis aliquid molestiaeperspiciatis et ea nemo ab reprehenderit accusantium quasvoluptate dolores velit et doloremque molestiae + + + 7 + magnam facilis autem + dolore placeat quibusdam ea quo vitaemagni quis enim qui quis quo nemo aut saepequidem repellat excepturi ut quiasunt ut sequi eos ea sed quas + + + 8 + dolorem dolore est ipsam + dignissimos aperiam dolorem qui eumfacilis quibusdam animi sint suscipit qui sint possimus cumquaerat magni maiores excepturiipsam ut commodi dolor voluptatum modi aut vitae + + + 9 + nesciunt iure omnis dolorem tempora et accusantium + consectetur animi nesciunt iure doloreenim quia adveniam autem ut quam aut nobiset est aut quod aut provident voluptas autem voluptas + + + 10 + optio molestias id quia eum + quo et expedita modi cum officia vel magnidoloribus qui repudiandaevero nisi sitquos veniam quod sed accusamus veritatis error + + + + + 1 + quidem molestiae enim + + + 2 + sunt qui excepturi placeat culpa + + + 3 + omnis laborum odio + + + 4 + non esse culpa molestiae omnis sed optio + + + 5 + eaque aut omnis a + + + 6 + natus impedit quibusdam illo est + + + 7 + quibusdam autem aliquid et et quia + + + 8 + qui fuga est a eum + + + 9 + saepe unde necessitatibus rem + + + 10 + distinctio laborum qui + + + + + 1 + delectus aut autem + False + + + 2 + quis ut nam facilis et officia qui + False + + + 3 + fugiat veniam minus + False + + + 4 + et porro tempora + True + + + 5 + laboriosam mollitia et enim quasi adipisci quia provident illum + False + + + 6 + qui ullam ratione quibusdam voluptatem quia omnis + False + + + 7 + illo expedita consequatur quia in + False + + + 8 + quo adipisci enim quam ut ab + True + + + 9 + molestiae perspiciatis ipsa + False + + + 10 + illo est ratione doloremque quia maiores aut + True + + + 11 + vero rerum temporibus dolor + True + + + 12 + ipsa repellendus fugit nisi + True + + + 13 + et doloremque nulla + False + + + 14 + repellendus sunt dolores architecto voluptatum + True + + + 15 + ab voluptatum amet voluptas + True + + + 16 + accusamus eos facilis sint et aut voluptatem + True + + + 17 + quo laboriosam deleniti aut qui + True + + + 18 + dolorum est consequatur ea mollitia in culpa + False + + + 19 + molestiae ipsa aut voluptatibus pariatur dolor nihil + True + + + 20 + ullam nobis libero sapiente ad optio sint + True + + + \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/6/files/users/2.xml b/homeworks/At0mn1yIvan/6/files/users/2.xml new file mode 100644 index 0000000..964471e --- /dev/null +++ b/homeworks/At0mn1yIvan/6/files/users/2.xml @@ -0,0 +1,201 @@ + + + 2 + Shanna@melissa.tv + + + 11 + et ea vero quia laudantium autem + delectus reiciendis molestiae occaecati non minima eveniet qui voluptatibusaccusamus in eum beatae sitvel qui neque voluptates ut commodi qui inciduntut animi commodi + + + 12 + in quibusdam tempore odit est dolorem + itaque id aut magnampraesentium quia et ea odit et ea voluptas etsapiente quia nihil amet occaecati quia id voluptatemincidunt ea est distinctio odio + + + 13 + dolorum ut in voluptas mollitia et saepe quo animi + aut dicta possimus sint mollitia voluptas commodi quo doloremqueiste corrupti reiciendis voluptatem eius rerumsit cumque quod eligendi laborum minimaperferendis recusandae assumenda consectetur porro architecto ipsum ipsam + + + 14 + voluptatem eligendi optio + fuga et accusamus dolorum perferendis illo voluptasnon doloremque neque faceread qui dolorum molestiae beataesed aut voluptas totam sit illum + + + 15 + eveniet quod temporibus + reprehenderit quos placeatvelit minima officia dolores impedit repudiandae molestiae namvoluptas recusandae quis delectusofficiis harum fugiat vitae + + + 16 + sint suscipit perspiciatis velit dolorum rerum ipsa laboriosam odio + suscipit nam nisi quo aperiam autasperiores eos fugit maiores voluptatibus quiavoluptatem quis ullam qui in alias quia estconsequatur magni mollitia accusamus ea nisi voluptate dicta + + + 17 + fugit voluptas sed molestias voluptatem provident + eos voluptas et aut odit natus earumaspernatur fuga molestiae ullamdeserunt ratione qui eosqui nihil ratione nemo velit ut aut id quo + + + 18 + voluptate et itaque vero tempora molestiae + eveniet quo quislaborum totam consequatur non dolorut et est repudiandaeest voluptatem vel debitis et magnam + + + 19 + adipisci placeat illum aut reiciendis qui + illum quis cupiditate provident sit magnamea sed aut omnisveniam maiores ullam consequatur atqueadipisci quo iste expedita sit quos voluptas + + + 20 + doloribus ad provident suscipit at + qui consequuntur ducimus possimus quisquam amet similiquesuscipit porro ipsam ameteos veritatis officiis exercitationem vel fugit aut necessitatibus totamomnis rerum consequatur expedita quidem cumque explicabo + + + + + 11 + quam nostrum impedit mollitia quod et dolor + + + 12 + consequatur autem doloribus natus consectetur + + + 13 + ab rerum non rerum consequatur ut ea unde + + + 14 + ducimus molestias eos animi atque nihil + + + 15 + ut pariatur rerum ipsum natus repellendus praesentium + + + 16 + voluptatem aut maxime inventore autem magnam atque repellat + + + 17 + aut minima voluptatem ut velit + + + 18 + nesciunt quia et doloremque + + + 19 + velit pariatur quaerat similique libero omnis quia + + + 20 + voluptas rerum iure ut enim + + + + + 21 + suscipit repellat esse quibusdam voluptatem incidunt + False + + + 22 + distinctio vitae autem nihil ut molestias quo + True + + + 23 + et itaque necessitatibus maxime molestiae qui quas velit + False + + + 24 + adipisci non ad dicta qui amet quaerat doloribus ea + False + + + 25 + voluptas quo tenetur perspiciatis explicabo natus + True + + + 26 + aliquam aut quasi + True + + + 27 + veritatis pariatur delectus + True + + + 28 + nesciunt totam sit blanditiis sit + False + + + 29 + laborum aut in quam + False + + + 30 + nemo perspiciatis repellat ut dolor libero commodi blanditiis omnis + True + + + 31 + repudiandae totam in est sint facere fuga + False + + + 32 + earum doloribus ea doloremque quis + False + + + 33 + sint sit aut vero + False + + + 34 + porro aut necessitatibus eaque distinctio + False + + + 35 + repellendus veritatis molestias dicta incidunt + True + + + 36 + excepturi deleniti adipisci voluptatem et neque optio illum ad + True + + + 37 + sunt cum tempora + False + + + 38 + totam quia non + False + + + 39 + doloremque quibusdam asperiores libero corrupti illum qui omnis + False + + + 40 + totam atque quo nesciunt + True + + + \ No newline at end of file diff --git a/homeworks/At0mn1yIvan/6/hw7.md b/homeworks/At0mn1yIvan/6/hw7.md new file mode 100644 index 0000000..d0bc078 --- /dev/null +++ b/homeworks/At0mn1yIvan/6/hw7.md @@ -0,0 +1,100 @@ +## Теория + +### Чистота функций + +- https://devman.org/encyclopedia/clean_code/decomposition_pure_functions/ + +### Форматы файлов + +- `csv`: https://pyneng.readthedocs.io/ru/latest/book/17_serialization/1_csv.html и https://docs.python.org/3/library/csv.html +- Что такое `json`? http://www.json.org/json-ru.html +- Как работать с `json`? https://pyneng.readthedocs.io/ru/latest/book/17_serialization/2_json.html и http://docs.python-guide.org/en/latest/scenarios/json/ и https://docs.python.org/3/library/json.html + +### tcp/ip + +- Стек `TCP/IP`: https://ru.wikipedia.org/wiki/TCP/IP +- Протокол `HTTP`: https://ru.wikipedia.org/wiki/HTTP +- Протокол `TCP`: https://ru.wikipedia.org/wiki/TCP +- Протокол `UDP`: https://ru.wikipedia.org/wiki/UDP +- Протокол `IP`: https://ru.wikipedia.org/wiki/IP + +### urllib / requests + +- Модуль `urllib`: https://docs.python.org/3/library/urllib.html +- `requests` http://docs.python-requests.org/en/master/ +- `requests` vs `urllib` https://stackoverflow.com/questions/2018026/what-are-the-differences-between-the-urllib-urllib2-and-requests-module + +### loguru + +- `loguru`: https://github.com/Delgan/loguru + + +## Практика + +Необходимо реализовать простой парсер данных. + +1. На вход подается `csv` список email адресов, вида: + +```csv +"Sincere@april.biz","Shanna@melissa.tv","anastasia.net" +``` + +2. Получаем по переданным почтам `id` пользователей с сайта: https://jsonplaceholder.typicode.com/users/ + +3. Для каждого пользователя необходимо скачать всю информацию по его `posts`, `albums` и `todos`, пример: + +- https://jsonplaceholder.typicode.com/users/1/posts +- https://jsonplaceholder.typicode.com/users/1/albums +- https://jsonplaceholder.typicode.com/users/1/todos + +4. В качестве результата необходимо сохранить всю информацию о каждом пользователе в виде `xml` файла вида: + +```xml + + + 1 + Sincere@april.biz + + + + 1 + sunt aut optio repfacere repellat provident occaecati excepturirehenderit + quia et suscipit suscipit recusandae consequuntur expedita et cum reprehenderit molestiae ut ut quas totam nostrum rerum est autem sunt rem eveniet architecto + + + + + + 1 + omnis laborum odio + + + + + + 1 + delectus aut autem + false + + + +``` + +Если у пользователя нет какой-то части данных, например `posts`, то записываем просто `` + +5. Все файлы мы сохраняем в папку `users/${userId}/`, где `${userId}` заменяем на `id` пользователя + +6. Необходимо логировать: + +- количество пользователей для запуска +- переход к парсингу каждого конкретного `email`, пример: `Starts parsing for Sincere@april.biz` +- время выполнения каждого запроса к внешнему источнику данных +- логируем ошибки, если они случаются + +Технические требования: + +- используем встроенный модуль `csv` для работы с `csv` +- Используем `poetry` для управления зависимостями +- Используем `loguru` для логирования +- Используем `requests` для выполнения запросов +- Можно выбрать любую библиотеку для работы с `xml` diff --git a/homeworks/At0mn1yIvan/6/poetry.lock b/homeworks/At0mn1yIvan/6/poetry.lock new file mode 100644 index 0000000..fe67d7e --- /dev/null +++ b/homeworks/At0mn1yIvan/6/poetry.lock @@ -0,0 +1,739 @@ +[[package]] +name = "astor" +version = "0.8.1" +description = "Read/rewrite/write Python ASTs" +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" + +[[package]] +name = "attrs" +version = "22.1.0" +description = "Classes Without Boilerplate" +category = "main" +optional = false +python-versions = ">=3.5" + +[package.extras] +dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] +docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] +tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] +tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] + +[[package]] +name = "bandit" +version = "1.7.4" +description = "Security oriented static analyser for python code." +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} +GitPython = ">=1.0.1" +PyYAML = ">=5.3.1" +stevedore = ">=1.20.0" + +[package.extras] +test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml"] +toml = ["toml"] +yaml = ["PyYAML"] + +[[package]] +name = "certifi" +version = "2022.9.24" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "charset-normalizer" +version = "2.1.1" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = ">=3.6.0" + +[package.extras] +unicode-backport = ["unicodedata2"] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" + +[[package]] +name = "darglint" +version = "1.8.1" +description = "A utility for ensuring Google-style docstrings stay up to date with the source code." +category = "main" +optional = false +python-versions = ">=3.6,<4.0" + +[[package]] +name = "docutils" +version = "0.19" +description = "Docutils -- Python Documentation Utilities" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "eradicate" +version = "2.1.0" +description = "Removes commented-out code." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "flake8" +version = "4.0.1" +description = "the modular source code checker: pep8 pyflakes and co" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +mccabe = ">=0.6.0,<0.7.0" +pycodestyle = ">=2.8.0,<2.9.0" +pyflakes = ">=2.4.0,<2.5.0" + +[[package]] +name = "flake8-bandit" +version = "3.0.0" +description = "Automated security testing with bandit and flake8." +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +bandit = ">=1.7.3" +flake8 = "*" +flake8-polyfill = "*" +pycodestyle = "*" + +[[package]] +name = "flake8-broken-line" +version = "0.5.0" +description = "Flake8 plugin to forbid backslashes for line breaks" +category = "main" +optional = false +python-versions = ">=3.6,<4.0" + +[package.dependencies] +flake8 = ">=3.5,<6" + +[[package]] +name = "flake8-bugbear" +version = "22.10.25" +description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +attrs = ">=19.2.0" +flake8 = ">=3.0.0" + +[package.extras] +dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "tox"] + +[[package]] +name = "flake8-commas" +version = "2.1.0" +description = "Flake8 lint for trailing commas." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = ">=2" + +[[package]] +name = "flake8-comprehensions" +version = "3.10.0" +description = "A flake8 plugin to help you write better list/set/dict comprehensions." +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +flake8 = ">=3.0,<3.2.0 || >3.2.0" + +[[package]] +name = "flake8-debugger" +version = "4.1.2" +description = "ipdb/pdb statement checker plugin for flake8" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +flake8 = ">=3.0" +pycodestyle = "*" + +[[package]] +name = "flake8-docstrings" +version = "1.6.0" +description = "Extension for flake8 which uses pydocstyle to check docstrings" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = ">=3" +pydocstyle = ">=2.1" + +[[package]] +name = "flake8-eradicate" +version = "1.4.0" +description = "Flake8 plugin to find commented out code" +category = "main" +optional = false +python-versions = ">=3.7,<4.0" + +[package.dependencies] +attrs = "*" +eradicate = ">=2.0,<3.0" +flake8 = ">=3.5,<6" + +[[package]] +name = "flake8-isort" +version = "4.2.0" +description = "flake8 plugin that integrates isort ." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = ">=3.2.1,<6" +isort = ">=4.3.5,<6" + +[package.extras] +test = ["pytest-cov"] + +[[package]] +name = "flake8-polyfill" +version = "1.0.2" +description = "Polyfill package for Flake8 plugins" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = "*" + +[[package]] +name = "flake8-quotes" +version = "3.3.1" +description = "Flake8 lint for quotes." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = "*" + +[[package]] +name = "flake8-rst-docstrings" +version = "0.2.7" +description = "Python docstring reStructuredText (RST) validator" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +flake8 = ">=3.0.0" +pygments = "*" +restructuredtext-lint = "*" + +[[package]] +name = "flake8-string-format" +version = "0.3.0" +description = "string format checker, plugin for flake8" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +flake8 = "*" + +[[package]] +name = "gitdb" +version = "4.0.9" +description = "Git Object Database" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +smmap = ">=3.0.1,<6" + +[[package]] +name = "gitpython" +version = "3.1.29" +description = "GitPython is a python library used to interact with Git repositories" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +gitdb = ">=4.0.1,<5" + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "isort" +version = "5.10.1" +description = "A Python utility / library to sort Python imports." +category = "main" +optional = false +python-versions = ">=3.6.1,<4.0" + +[package.extras] +colors = ["colorama (>=0.4.3,<0.5.0)"] +pipfile-deprecated-finder = ["pipreqs", "requirementslib"] +plugins = ["setuptools"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] + +[[package]] +name = "loguru" +version = "0.6.0" +description = "Python logging made (stupidly) simple" +category = "main" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} +win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} + +[package.extras] +dev = ["Sphinx (>=4.1.1)", "black (>=19.10b0)", "colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "isort (>=5.1.1)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "tox (>=3.9.0)"] + +[[package]] +name = "mccabe" +version = "0.6.1" +description = "McCabe checker, plugin for flake8" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "pbr" +version = "5.11.0" +description = "Python Build Reasonableness" +category = "main" +optional = false +python-versions = ">=2.6" + +[[package]] +name = "pep8-naming" +version = "0.13.2" +description = "Check PEP-8 naming conventions, plugin for flake8" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +flake8 = ">=3.9.1" + +[[package]] +name = "pycodestyle" +version = "2.8.0" +description = "Python style guide checker" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "pydocstyle" +version = "6.1.1" +description = "Python docstring style checker" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +snowballstemmer = "*" + +[package.extras] +toml = ["toml"] + +[[package]] +name = "pyflakes" +version = "2.4.0" +description = "passive checker of Python programs" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "pygments" +version = "2.13.0" +description = "Pygments is a syntax highlighting package written in Python." +category = "main" +optional = false +python-versions = ">=3.6" + +[package.extras] +plugins = ["importlib-metadata"] + +[[package]] +name = "pyyaml" +version = "6.0" +description = "YAML parser and emitter for Python" +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "requests" +version = "2.28.1" +description = "Python HTTP for Humans." +category = "main" +optional = false +python-versions = ">=3.7, <4" + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<3" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "restructuredtext-lint" +version = "1.4.0" +description = "reStructuredText linter" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +docutils = ">=0.11,<1.0" + +[[package]] +name = "smmap" +version = "5.0.0" +description = "A pure Python implementation of a sliding window memory map manager" +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "stevedore" +version = "4.1.0" +description = "Manage dynamic plugins for Python applications" +category = "main" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +pbr = ">=2.0.0,<2.1.0 || >2.1.0" + +[[package]] +name = "typing-extensions" +version = "4.4.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "urllib3" +version = "1.26.12" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "wemake-python-styleguide" +version = "0.17.0" +description = "The strictest and most opinionated python linter ever" +category = "main" +optional = false +python-versions = ">=3.7,<4.0" + +[package.dependencies] +astor = ">=0.8,<0.9" +attrs = "*" +darglint = ">=1.2,<2.0" +flake8 = ">=3.7,<5" +flake8-bandit = ">=2.1,<4" +flake8-broken-line = ">=0.5,<0.6" +flake8-bugbear = ">=22.9,<23.0" +flake8-commas = ">=2.0,<3.0" +flake8-comprehensions = ">=3.1,<4.0" +flake8-debugger = ">=4.0,<5.0" +flake8-docstrings = ">=1.3,<2.0" +flake8-eradicate = ">=1.0,<2.0" +flake8-isort = ">=4.0,<5.0" +flake8-quotes = ">=3.0,<4.0" +flake8-rst-docstrings = ">=0.2,<0.3" +flake8-string-format = ">=0.3,<0.4" +pep8-naming = ">=0.13,<0.14" +pygments = ">=2.4,<3.0" +typing_extensions = ">=4.0,<5.0" + +[[package]] +name = "win32-setctime" +version = "1.1.0" +description = "A small Python utility to set file creation time on Windows" +category = "main" +optional = false +python-versions = ">=3.5" + +[package.extras] +dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] + +[metadata] +lock-version = "1.1" +python-versions = "^3.8" +content-hash = "2228552cc9c8d881b72aea51ce2e4607a7d6698e7873c51de2080176a6631038" + +[metadata.files] +astor = [ + {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, + {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, +] +attrs = [ + {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, + {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, +] +bandit = [ + {file = "bandit-1.7.4-py3-none-any.whl", hash = "sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a"}, + {file = "bandit-1.7.4.tar.gz", hash = "sha256:2d63a8c573417bae338962d4b9b06fbc6080f74ecd955a092849e1e65c717bd2"}, +] +certifi = [ + {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"}, + {file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"}, +] +charset-normalizer = [ + {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, + {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, +] +colorama = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] +darglint = [ + {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, + {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, +] +docutils = [ + {file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"}, + {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"}, +] +eradicate = [ + {file = "eradicate-2.1.0-py3-none-any.whl", hash = "sha256:8bfaca181db9227dc88bdbce4d051a9627604c2243e7d85324f6d6ce0fd08bb2"}, + {file = "eradicate-2.1.0.tar.gz", hash = "sha256:aac7384ab25b1bf21c4c012de9b4bf8398945a14c98c911545b2ea50ab558014"}, +] +flake8 = [ + {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, + {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, +] +flake8-bandit = [ + {file = "flake8_bandit-3.0.0-py2.py3-none-any.whl", hash = "sha256:61b617f4f7cdaa0e2b1e6bf7b68afb2b619a227bb3e3ae00dd36c213bd17900a"}, + {file = "flake8_bandit-3.0.0.tar.gz", hash = "sha256:54d19427e6a8d50322a7b02e1841c0a7c22d856975f3459803320e0e18e2d6a1"}, +] +flake8-broken-line = [ + {file = "flake8-broken-line-0.5.0.tar.gz", hash = "sha256:7c98de9dd1385b71e888709c7f2aee3f0514107ecb5875bc95d0c03392191c97"}, + {file = "flake8_broken_line-0.5.0-py3-none-any.whl", hash = "sha256:daafb19b67eead0410ce7ba155d51a15b9d020ebe7630d87de9c2b93cedb6703"}, +] +flake8-bugbear = [ + {file = "flake8-bugbear-22.10.25.tar.gz", hash = "sha256:89e51284eb929fbb7f23fbd428491e7427f7cdc8b45a77248daffe86a039d696"}, + {file = "flake8_bugbear-22.10.25-py3-none-any.whl", hash = "sha256:584631b608dc0d7d3f9201046d5840a45502da4732d5e8df6c7ac1694a91cb9e"}, +] +flake8-commas = [ + {file = "flake8-commas-2.1.0.tar.gz", hash = "sha256:940441ab8ee544df564ae3b3f49f20462d75d5c7cac2463e0b27436e2050f263"}, + {file = "flake8_commas-2.1.0-py2.py3-none-any.whl", hash = "sha256:ebb96c31e01d0ef1d0685a21f3f0e2f8153a0381430e748bf0bbbb5d5b453d54"}, +] +flake8-comprehensions = [ + {file = "flake8-comprehensions-3.10.0.tar.gz", hash = "sha256:181158f7e7aa26a63a0a38e6017cef28c6adee71278ce56ce11f6ec9c4905058"}, + {file = "flake8_comprehensions-3.10.0-py3-none-any.whl", hash = "sha256:dad454fd3d525039121e98fa1dd90c46bc138708196a4ebbc949ad3c859adedb"}, +] +flake8-debugger = [ + {file = "flake8-debugger-4.1.2.tar.gz", hash = "sha256:52b002560941e36d9bf806fca2523dc7fb8560a295d5f1a6e15ac2ded7a73840"}, + {file = "flake8_debugger-4.1.2-py3-none-any.whl", hash = "sha256:0a5e55aeddcc81da631ad9c8c366e7318998f83ff00985a49e6b3ecf61e571bf"}, +] +flake8-docstrings = [ + {file = "flake8-docstrings-1.6.0.tar.gz", hash = "sha256:9fe7c6a306064af8e62a055c2f61e9eb1da55f84bb39caef2b84ce53708ac34b"}, + {file = "flake8_docstrings-1.6.0-py2.py3-none-any.whl", hash = "sha256:99cac583d6c7e32dd28bbfbef120a7c0d1b6dde4adb5a9fd441c4227a6534bde"}, +] +flake8-eradicate = [ + {file = "flake8-eradicate-1.4.0.tar.gz", hash = "sha256:3088cfd6717d1c9c6c3ac45ef2e5f5b6c7267f7504d5a74b781500e95cb9c7e1"}, + {file = "flake8_eradicate-1.4.0-py3-none-any.whl", hash = "sha256:e3bbd0871be358e908053c1ab728903c114f062ba596b4d40c852fd18f473d56"}, +] +flake8-isort = [ + {file = "flake8-isort-4.2.0.tar.gz", hash = "sha256:26571500cd54976bbc0cf1006ffbcd1a68dd102f816b7a1051b219616ba9fee0"}, + {file = "flake8_isort-4.2.0-py3-none-any.whl", hash = "sha256:5b87630fb3719bf4c1833fd11e0d9534f43efdeba524863e15d8f14a7ef6adbf"}, +] +flake8-polyfill = [ + {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"}, + {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, +] +flake8-quotes = [ + {file = "flake8-quotes-3.3.1.tar.gz", hash = "sha256:633adca6fb8a08131536af0d750b44d6985b9aba46f498871e21588c3e6f525a"}, +] +flake8-rst-docstrings = [ + {file = "flake8-rst-docstrings-0.2.7.tar.gz", hash = "sha256:2740067ab9237559dd45a3434d8c987792c7b259ca563621a3b95efe201f5382"}, + {file = "flake8_rst_docstrings-0.2.7-py3-none-any.whl", hash = "sha256:5d56075dce360bcc9c6775bfe7cb431aa395de600ca7e8d40580a28d50b2a803"}, +] +flake8-string-format = [ + {file = "flake8-string-format-0.3.0.tar.gz", hash = "sha256:65f3da786a1461ef77fca3780b314edb2853c377f2e35069723348c8917deaa2"}, + {file = "flake8_string_format-0.3.0-py2.py3-none-any.whl", hash = "sha256:812ff431f10576a74c89be4e85b8e075a705be39bc40c4b4278b5b13e2afa9af"}, +] +gitdb = [ + {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"}, + {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"}, +] +gitpython = [ + {file = "GitPython-3.1.29-py3-none-any.whl", hash = "sha256:41eea0deec2deea139b459ac03656f0dd28fc4a3387240ec1d3c259a2c47850f"}, + {file = "GitPython-3.1.29.tar.gz", hash = "sha256:cc36bfc4a3f913e66805a28e84703e419d9c264c1077e537b54f0e1af85dbefd"}, +] +idna = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] +isort = [ + {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, + {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, +] +loguru = [ + {file = "loguru-0.6.0-py3-none-any.whl", hash = "sha256:4e2414d534a2ab57573365b3e6d0234dfb1d84b68b7f3b948e6fb743860a77c3"}, + {file = "loguru-0.6.0.tar.gz", hash = "sha256:066bd06758d0a513e9836fd9c6b5a75bfb3fd36841f4b996bc60b547a309d41c"}, +] +mccabe = [ + {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, + {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, +] +pbr = [ + {file = "pbr-5.11.0-py2.py3-none-any.whl", hash = "sha256:db2317ff07c84c4c63648c9064a79fe9d9f5c7ce85a9099d4b6258b3db83225a"}, + {file = "pbr-5.11.0.tar.gz", hash = "sha256:b97bc6695b2aff02144133c2e7399d5885223d42b7912ffaec2ca3898e673bfe"}, +] +pep8-naming = [ + {file = "pep8-naming-0.13.2.tar.gz", hash = "sha256:93eef62f525fd12a6f8c98f4dcc17fa70baae2f37fa1f73bec00e3e44392fa48"}, + {file = "pep8_naming-0.13.2-py3-none-any.whl", hash = "sha256:59e29e55c478db69cffbe14ab24b5bd2cd615c0413edf790d47d3fb7ba9a4e23"}, +] +pycodestyle = [ + {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, + {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, +] +pydocstyle = [ + {file = "pydocstyle-6.1.1-py3-none-any.whl", hash = "sha256:6987826d6775056839940041beef5c08cc7e3d71d63149b48e36727f70144dc4"}, + {file = "pydocstyle-6.1.1.tar.gz", hash = "sha256:1d41b7c459ba0ee6c345f2eb9ae827cab14a7533a88c5c6f7e94923f72df92dc"}, +] +pyflakes = [ + {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, + {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, +] +pygments = [ + {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, + {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, +] +pyyaml = [ + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, + {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, + {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] +requests = [ + {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, + {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, +] +restructuredtext-lint = [ + {file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"}, +] +smmap = [ + {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, + {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, +] +snowballstemmer = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] +stevedore = [ + {file = "stevedore-4.1.0-py3-none-any.whl", hash = "sha256:3b1cbd592a87315f000d05164941ee5e164899f8fc0ce9a00bb0f321f40ef93e"}, + {file = "stevedore-4.1.0.tar.gz", hash = "sha256:02518a8f0d6d29be8a445b7f2ac63753ff29e8f2a2faa01777568d5500d777a6"}, +] +typing-extensions = [ + {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, + {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, +] +urllib3 = [ + {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, + {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, +] +wemake-python-styleguide = [ + {file = "wemake-python-styleguide-0.17.0.tar.gz", hash = "sha256:c8869fac392019c2bb3eae4287399245d10d2726b23f1b3c68d1564909c3a71a"}, + {file = "wemake_python_styleguide-0.17.0-py3-none-any.whl", hash = "sha256:d10b953bbe4fba83a34f4c224a0e1849ede89e486eacfc760690e6c87a28eaae"}, +] +win32-setctime = [ + {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, + {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, +] diff --git a/homeworks/At0mn1yIvan/6/pyproject.toml b/homeworks/At0mn1yIvan/6/pyproject.toml new file mode 100644 index 0000000..bd73e86 --- /dev/null +++ b/homeworks/At0mn1yIvan/6/pyproject.toml @@ -0,0 +1,17 @@ +[tool.poetry] +name = "hw6" +version = "0.1.0" +description = "" +authors = ["At0mn1yIvan "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.8" +loguru = "^0.6.0" +wemake-python-styleguide = "^0.17.0" +requests = "^2.28.1" + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/homeworks/At0mn1yIvan/6/setup.cfg b/homeworks/At0mn1yIvan/6/setup.cfg new file mode 100644 index 0000000..3b87bcf --- /dev/null +++ b/homeworks/At0mn1yIvan/6/setup.cfg @@ -0,0 +1,104 @@ +# All configuration for plugins and other utils is defined here. +# Read more about `setup.cfg`: +# https://docs.python.org/3/distutils/configfile.html + +[flake8] +# Base flake8 configuration: +# https://flake8.pycqa.org/en/latest/user/configuration.html +format = wemake +show-source = true +statistics = false +doctests = true + +# darglint configuration: +# https://github.com/terrencepreilly/darglint +strictness = long +docstring-style = numpy + +# Plugins: +max-complexity = 6 +max-line-length = 80 + +# wemake-python-styleguide settings: +i-control-code = false + +# Disable some pydocstyle checks: +# Exclude some pydoctest checks globally: +ignore = D100, D104, D106, D401, W504, X100, RST303, RST304, DAR103, DAR203 + +# Excluding some directories: +exclude = + .git + __pycache__ + .venv + venv + .eggs + *.egg + +# Ignoring some errors in some files: +per-file-ignores = + # Enable `assert` keyword and magic numbers for tests: + tests/*.py: S101, WPS226, WPS432 + + +[isort] +# isort configuration: +# https://pycqa.github.io/isort/docs/configuration/options.html +profile = wemake + + +[tool:pytest] +# Directories that are not visited by pytest collector: +norecursedirs = *.egg .eggs dist build docs .tox .git __pycache__ + +# Strict `@xfail` by default: +xfail_strict = true + +# Extra options: +addopts = + --strict-markers + --strict-config + --tb=short + --doctest-modules + --cov={{ cookiecutter.project_name.lower().replace('-', '_') }} + --cov-report=term-missing:skip-covered + --cov-report=html + --cov-report=xml + --cov-branch + --cov-fail-under=100 + + +[mypy] +# mypy configurations: http://bit.ly/2zEl9WI +enable_error_code = truthy-bool, redundant-expr, unused-awaitable + +allow_redefinition = false +check_untyped_defs = true +disallow_any_explicit = true +disallow_any_generics = true +disallow_untyped_calls = true +ignore_errors = false +ignore_missing_imports = true +implicit_reexport = false +local_partial_types = true +strict_optional = true +strict_equality = true +no_implicit_optional = true +warn_no_return = true +warn_unused_ignores = true +warn_redundant_casts = true +warn_unused_configs = true +warn_unreachable = true + + +[doc8] +# doc8 configuration: https://pypi.org/project/doc8/ +ignore-path = docs/_build +max-line-length = 80 +sphinx = true + + +long_string = ( + 'abc' + + 'def' +) \ No newline at end of file From 168703a4ce2732db6065c4f719a9bb3ac3e0ca20 Mon Sep 17 00:00:00 2001 From: At0mn1yIvan Date: Mon, 31 Oct 2022 21:59:04 +0300 Subject: [PATCH 8/9] Solution --- homeworks/At0mn1yIvan/6/code/Main.py | 2 +- homeworks/At0mn1yIvan/6/code/ReadCSV.py | 1 + homeworks/At0mn1yIvan/6/code/ToStart.py | 4 ++-- homeworks/At0mn1yIvan/6/code/__init__.py | 0 homeworks/At0mn1yIvan/6/setup.cfg | 8 ++++---- 5 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 homeworks/At0mn1yIvan/6/code/__init__.py diff --git a/homeworks/At0mn1yIvan/6/code/Main.py b/homeworks/At0mn1yIvan/6/code/Main.py index f9162da..1c48c17 100644 --- a/homeworks/At0mn1yIvan/6/code/Main.py +++ b/homeworks/At0mn1yIvan/6/code/Main.py @@ -1,7 +1,7 @@ from typing import Final -from ToStart import start from loguru import logger +from ToStart import start def main(): diff --git a/homeworks/At0mn1yIvan/6/code/ReadCSV.py b/homeworks/At0mn1yIvan/6/code/ReadCSV.py index 0118ec8..0559a3f 100644 --- a/homeworks/At0mn1yIvan/6/code/ReadCSV.py +++ b/homeworks/At0mn1yIvan/6/code/ReadCSV.py @@ -1,4 +1,5 @@ import csv + from loguru import logger diff --git a/homeworks/At0mn1yIvan/6/code/ToStart.py b/homeworks/At0mn1yIvan/6/code/ToStart.py index eb6d97a..239a96f 100644 --- a/homeworks/At0mn1yIvan/6/code/ToStart.py +++ b/homeworks/At0mn1yIvan/6/code/ToStart.py @@ -1,9 +1,9 @@ import re -from ReadCSV import read +from loguru import logger from ParsingJSON import get_email_id, get_user_info +from ReadCSV import read from Writer import write -from loguru import logger def start(emails_path: str, json_path: str): diff --git a/homeworks/At0mn1yIvan/6/code/__init__.py b/homeworks/At0mn1yIvan/6/code/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/homeworks/At0mn1yIvan/6/setup.cfg b/homeworks/At0mn1yIvan/6/setup.cfg index 3b87bcf..c595ce8 100644 --- a/homeworks/At0mn1yIvan/6/setup.cfg +++ b/homeworks/At0mn1yIvan/6/setup.cfg @@ -98,7 +98,7 @@ max-line-length = 80 sphinx = true -long_string = ( - 'abc' + - 'def' -) \ No newline at end of file +# long_string = ( +# 'abc' + +# 'def' +# ) \ No newline at end of file From 1766031bb3a37b6cbb774e24eb261fc542322a9e Mon Sep 17 00:00:00 2001 From: At0mn1yIvan Date: Mon, 31 Oct 2022 22:13:10 +0300 Subject: [PATCH 9/9] Solution --- homeworks/At0mn1yIvan/6/code/Main.py | 8 ++++---- .../6/code/{ParsingJSON.py => parsing_json.py} | 0 homeworks/At0mn1yIvan/6/code/{ReadCSV.py => read_csv.py} | 0 homeworks/At0mn1yIvan/6/code/{ToStart.py => to_start.py} | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) rename homeworks/At0mn1yIvan/6/code/{ParsingJSON.py => parsing_json.py} (100%) rename homeworks/At0mn1yIvan/6/code/{ReadCSV.py => read_csv.py} (100%) rename homeworks/At0mn1yIvan/6/code/{ToStart.py => to_start.py} (93%) diff --git a/homeworks/At0mn1yIvan/6/code/Main.py b/homeworks/At0mn1yIvan/6/code/Main.py index 1c48c17..43f9169 100644 --- a/homeworks/At0mn1yIvan/6/code/Main.py +++ b/homeworks/At0mn1yIvan/6/code/Main.py @@ -1,15 +1,15 @@ from typing import Final from loguru import logger -from ToStart import start +from to_start import start def main(): - """The Main method - starting point of our program""" + """The Main method do this code to be the starting point of our program.""" try: start(EMAILS_PATH, JSON_PATH) except Exception as ex: - logger.exception("Something went wrong.", ex) + logger.exception('Something went wrong.', ex) if __name__ == '__main__': @@ -18,4 +18,4 @@ def main(): try: main() except KeyboardInterrupt: - logger.critical("Something went wrong.") + logger.critical('Something went wrong.') diff --git a/homeworks/At0mn1yIvan/6/code/ParsingJSON.py b/homeworks/At0mn1yIvan/6/code/parsing_json.py similarity index 100% rename from homeworks/At0mn1yIvan/6/code/ParsingJSON.py rename to homeworks/At0mn1yIvan/6/code/parsing_json.py diff --git a/homeworks/At0mn1yIvan/6/code/ReadCSV.py b/homeworks/At0mn1yIvan/6/code/read_csv.py similarity index 100% rename from homeworks/At0mn1yIvan/6/code/ReadCSV.py rename to homeworks/At0mn1yIvan/6/code/read_csv.py diff --git a/homeworks/At0mn1yIvan/6/code/ToStart.py b/homeworks/At0mn1yIvan/6/code/to_start.py similarity index 93% rename from homeworks/At0mn1yIvan/6/code/ToStart.py rename to homeworks/At0mn1yIvan/6/code/to_start.py index 239a96f..90ce282 100644 --- a/homeworks/At0mn1yIvan/6/code/ToStart.py +++ b/homeworks/At0mn1yIvan/6/code/to_start.py @@ -1,9 +1,9 @@ import re from loguru import logger -from ParsingJSON import get_email_id, get_user_info -from ReadCSV import read -from Writer import write +from parsing_json import get_email_id, get_user_info +from read_csv import read +from writer import write def start(emails_path: str, json_path: str):