From 4d564b87d44481d0ae7e100fa0565d1180d33e99 Mon Sep 17 00:00:00 2001 From: ErmolaevDenis Date: Tue, 27 Sep 2022 21:49:33 +0300 Subject: [PATCH 1/7] array --- ErmolaevDenis/Array/Array.py | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 ErmolaevDenis/Array/Array.py diff --git a/ErmolaevDenis/Array/Array.py b/ErmolaevDenis/Array/Array.py new file mode 100644 index 0000000..f53154e --- /dev/null +++ b/ErmolaevDenis/Array/Array.py @@ -0,0 +1,43 @@ +class Array(object): + + def __init__(self, *args): + self._data = args + + def append(self, *args): + self._data += args + + def __add__(self, other): + res = Array(*self._data) + res._data += other._data + return res + + def __len__(self): + return len(self._data) + + def index(self, elem): + ind = -1 + for i in range(len(self._data)): + if (elem == self._data[i]): + ind = i + return ind + + def __iter__(self): + return iter(self._data) + + def __getitem__(self, ind): + return self._data[ind] + + +a1 = Array(1, 2, 3) +a2 = Array(4, 5, 6) +print(a1._data) +print(a2._data) +a2.append(7, 8) +print(a2._data) +a3 = a1 + a2 +print(a3._data) +print(len(a3)) +print(a3.index(4)) +print(a3[4]) +for element in a3: + print(element*100) From f64a05ba61f8133232e7795b3fb581b916217207 Mon Sep 17 00:00:00 2001 From: ErmolaevDenis Date: Wed, 5 Oct 2022 18:08:02 +0300 Subject: [PATCH 2/7] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=B4=D0=BE=D0=BC=D0=B0=D1=88=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- homeworks/ErmolaevDenis/2/Array.py | 43 +++++++++++++++++++++++++++ homeworks/ErmolaevDenis/4/contract.py | 30 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 homeworks/ErmolaevDenis/2/Array.py create mode 100644 homeworks/ErmolaevDenis/4/contract.py diff --git a/homeworks/ErmolaevDenis/2/Array.py b/homeworks/ErmolaevDenis/2/Array.py new file mode 100644 index 0000000..f53154e --- /dev/null +++ b/homeworks/ErmolaevDenis/2/Array.py @@ -0,0 +1,43 @@ +class Array(object): + + def __init__(self, *args): + self._data = args + + def append(self, *args): + self._data += args + + def __add__(self, other): + res = Array(*self._data) + res._data += other._data + return res + + def __len__(self): + return len(self._data) + + def index(self, elem): + ind = -1 + for i in range(len(self._data)): + if (elem == self._data[i]): + ind = i + return ind + + def __iter__(self): + return iter(self._data) + + def __getitem__(self, ind): + return self._data[ind] + + +a1 = Array(1, 2, 3) +a2 = Array(4, 5, 6) +print(a1._data) +print(a2._data) +a2.append(7, 8) +print(a2._data) +a3 = a1 + a2 +print(a3._data) +print(len(a3)) +print(a3.index(4)) +print(a3[4]) +for element in a3: + print(element*100) diff --git a/homeworks/ErmolaevDenis/4/contract.py b/homeworks/ErmolaevDenis/4/contract.py new file mode 100644 index 0000000..9adcca5 --- /dev/null +++ b/homeworks/ErmolaevDenis/4/contract.py @@ -0,0 +1,30 @@ +class ContractError(Exception): + """We use this error when someone breaks our contract.""" + pass + +#: 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(function): + def inner(*args): + if arg_types != None and arg_types != Any: + for ind in range(len(args)): + if arg_types[ind] != Any: + if type(args[ind]) != arg_types[ind]: + raise ContractError + try: + result = function(*args) + if return_type != None and return_type != Any: + if return_type != type(result): + raise ContractError + except Exception as ex: + raises = () + if type(ex) in raises: + raise ex + else: + raise ContractError from ex + return result + return inner + return contract_decorator \ No newline at end of file From 1ac7dd5b830a78428a26595cc056bf676cdaacf6 Mon Sep 17 00:00:00 2001 From: ErmolaevDenis Date: Wed, 5 Oct 2022 18:14:32 +0300 Subject: [PATCH 3/7] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=BB=D0=B8=D1=88=D0=BD=D1=8E=D1=8E=20=D0=BF=D0=B0=D0=BF=D0=BA?= =?UTF-8?q?=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ErmolaevDenis/Array/Array.py | 43 ------------------------------------ 1 file changed, 43 deletions(-) delete mode 100644 ErmolaevDenis/Array/Array.py diff --git a/ErmolaevDenis/Array/Array.py b/ErmolaevDenis/Array/Array.py deleted file mode 100644 index f53154e..0000000 --- a/ErmolaevDenis/Array/Array.py +++ /dev/null @@ -1,43 +0,0 @@ -class Array(object): - - def __init__(self, *args): - self._data = args - - def append(self, *args): - self._data += args - - def __add__(self, other): - res = Array(*self._data) - res._data += other._data - return res - - def __len__(self): - return len(self._data) - - def index(self, elem): - ind = -1 - for i in range(len(self._data)): - if (elem == self._data[i]): - ind = i - return ind - - def __iter__(self): - return iter(self._data) - - def __getitem__(self, ind): - return self._data[ind] - - -a1 = Array(1, 2, 3) -a2 = Array(4, 5, 6) -print(a1._data) -print(a2._data) -a2.append(7, 8) -print(a2._data) -a3 = a1 + a2 -print(a3._data) -print(len(a3)) -print(a3.index(4)) -print(a3[4]) -for element in a3: - print(element*100) From 60ce6b12516a17b7c807bcbead794ac0be253165 Mon Sep 17 00:00:00 2001 From: ErmolaevDenis Date: Wed, 12 Oct 2022 17:32:48 +0300 Subject: [PATCH 4/7] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=20hw5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- homeworks/ErmolaevDenis/5/todo/__init__.py | 0 homeworks/ErmolaevDenis/5/todo/__main__.py | 28 ++++++ homeworks/ErmolaevDenis/5/todo/commands.py | 99 +++++++++++++++++++ .../ErmolaevDenis/5/todo/custom_exceptions.py | 2 + homeworks/ErmolaevDenis/5/todo/models.py | 71 +++++++++++++ homeworks/ErmolaevDenis/5/todo/reflection.py | 34 +++++++ homeworks/ErmolaevDenis/5/todo/runtime.py | 52 ++++++++++ homeworks/ErmolaevDenis/5/todo/storage.py | 21 ++++ 8 files changed, 307 insertions(+) create mode 100644 homeworks/ErmolaevDenis/5/todo/__init__.py create mode 100644 homeworks/ErmolaevDenis/5/todo/__main__.py create mode 100644 homeworks/ErmolaevDenis/5/todo/commands.py create mode 100644 homeworks/ErmolaevDenis/5/todo/custom_exceptions.py create mode 100644 homeworks/ErmolaevDenis/5/todo/models.py create mode 100644 homeworks/ErmolaevDenis/5/todo/reflection.py create mode 100644 homeworks/ErmolaevDenis/5/todo/runtime.py create mode 100644 homeworks/ErmolaevDenis/5/todo/storage.py diff --git a/homeworks/ErmolaevDenis/5/todo/__init__.py b/homeworks/ErmolaevDenis/5/todo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/homeworks/ErmolaevDenis/5/todo/__main__.py b/homeworks/ErmolaevDenis/5/todo/__main__.py new file mode 100644 index 0000000..55f9f2c --- /dev/null +++ b/homeworks/ErmolaevDenis/5/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/ErmolaevDenis/5/todo/commands.py b/homeworks/ErmolaevDenis/5/todo/commands.py new file mode 100644 index 0000000..2f8892d --- /dev/null +++ b/homeworks/ErmolaevDenis/5/todo/commands.py @@ -0,0 +1,99 @@ + +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 ExitCommand(BaseCommand): + label = 'exit' + + def perform(self, _store): + raise UserExitException('See you next time!') + + +class DoneCommand(BaseCommand): + label = 'done' + + def perform(self, store): + num = int(input('Enter the number of item you want to change to done: ')) + if (num < 0) or num >= len(store.items): + raise IndexError('Wrong index, try again.') + + store.items[num].done = True + + +class UndoneCommand(BaseCommand): + label = 'undone' + + def perform(self, store): + num = int(input('Input number of item to change item status on undone: ')) + if (num < 0) or (num >= len(store.items)): + raise IndexError('Wrong index, try again.') + + store.items[num].done = False + + diff --git a/homeworks/ErmolaevDenis/5/todo/custom_exceptions.py b/homeworks/ErmolaevDenis/5/todo/custom_exceptions.py new file mode 100644 index 0000000..5e8963c --- /dev/null +++ b/homeworks/ErmolaevDenis/5/todo/custom_exceptions.py @@ -0,0 +1,2 @@ +class UserExitException(Exception): + """We use this exception when user wants to exit.""" diff --git a/homeworks/ErmolaevDenis/5/todo/models.py b/homeworks/ErmolaevDenis/5/todo/models.py new file mode 100644 index 0000000..8deb184 --- /dev/null +++ b/homeworks/ErmolaevDenis/5/todo/models.py @@ -0,0 +1,71 @@ +class BaseItem(object): + + status = {False : '-', True : '+'} + + 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 __str__(self): + return '{0} {1}'.format( + self.status[self.done], + self.__class__.__name__[:-4] + ) + + @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) + + +class ToReadItem(BaseItem): + def __init__(self, heading, url): + super().__init__(heading) + self.url = url + + def __str__(self): + return '{0}: {1} from {2}'.format( + super().__str__(), + self.heading, + self.url, + ) + + @classmethod + def construct(cls): + heading = input('Input heading: ') + url = input('Input url: ') + return cls(heading, url) \ No newline at end of file diff --git a/homeworks/ErmolaevDenis/5/todo/reflection.py b/homeworks/ErmolaevDenis/5/todo/reflection.py new file mode 100644 index 0000000..dee9f85 --- /dev/null +++ b/homeworks/ErmolaevDenis/5/todo/reflection.py @@ -0,0 +1,34 @@ +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/ErmolaevDenis/5/todo/runtime.py b/homeworks/ErmolaevDenis/5/todo/runtime.py new file mode 100644 index 0000000..c955fa3 --- /dev/null +++ b/homeworks/ErmolaevDenis/5/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/ErmolaevDenis/5/todo/storage.py b/homeworks/ErmolaevDenis/5/todo/storage.py new file mode 100644 index 0000000..ef58690 --- /dev/null +++ b/homeworks/ErmolaevDenis/5/todo/storage.py @@ -0,0 +1,21 @@ +class Storage(object): # storage = Storge() + """ + 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 fbb8c3ab61bb2abe41cacc44a487a58181be82b7 Mon Sep 17 00:00:00 2001 From: ErmolaevDenis Date: Tue, 1 Nov 2022 20:16:21 +0300 Subject: [PATCH 5/7] hw6 --- homeworks/ErmolaevDenis/6/README.md | 0 .../6/my-awesome-script/__init__.py | 0 .../6/my-awesome-script/__main__.py | 45 ++++++ homeworks/ErmolaevDenis/6/poetry.lock | 145 ++++++++++++++++++ homeworks/ErmolaevDenis/6/pyproject.toml | 24 +++ homeworks/ErmolaevDenis/6/tests/__init__.py | 0 6 files changed, 214 insertions(+) create mode 100644 homeworks/ErmolaevDenis/6/README.md create mode 100644 homeworks/ErmolaevDenis/6/my-awesome-script/__init__.py create mode 100644 homeworks/ErmolaevDenis/6/my-awesome-script/__main__.py create mode 100644 homeworks/ErmolaevDenis/6/poetry.lock create mode 100644 homeworks/ErmolaevDenis/6/pyproject.toml create mode 100644 homeworks/ErmolaevDenis/6/tests/__init__.py diff --git a/homeworks/ErmolaevDenis/6/README.md b/homeworks/ErmolaevDenis/6/README.md new file mode 100644 index 0000000..e69de29 diff --git a/homeworks/ErmolaevDenis/6/my-awesome-script/__init__.py b/homeworks/ErmolaevDenis/6/my-awesome-script/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/homeworks/ErmolaevDenis/6/my-awesome-script/__main__.py b/homeworks/ErmolaevDenis/6/my-awesome-script/__main__.py new file mode 100644 index 0000000..d1980a3 --- /dev/null +++ b/homeworks/ErmolaevDenis/6/my-awesome-script/__main__.py @@ -0,0 +1,45 @@ +import argparse +from pygments import highlight +from pygments.formatters import TerminalFormatter +from pygments.lexers import PythonLexer +from cowpy import cow +from datetime import datetime +import pytz + +def highligh_func(text: str): + print(highlight(text, PythonLexer(), TerminalFormatter())) + + +def cowsay(text: str): + print(cow.milk_random_cow(text)) + + +def time(timezone): + local_date = datetime.now(pytz.timezone(timezone)) + print("{0} {1}".format(local_date.date(), local_date.time())) + +def main(): + parse_input() + +comands_dict = {'highlight': highligh_func, 'cowsay': cowsay, 'time': time} + + +def parse_input(): + parser = argparse.ArgumentParser() + parser.add_argument('operation', type=str, + choices=['highlight', 'cowsay', 'time'], + help='Enter comand from this list' + ) + parser.add_argument('param', type=str, + help='''Enter for highlight or cowsay, + or for time''' + ) + args = parser.parse_args() + use_comand(args.operation, args.param) + + +def use_comand(comand, param): + comands_dict[comand](param) + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/homeworks/ErmolaevDenis/6/poetry.lock b/homeworks/ErmolaevDenis/6/poetry.lock new file mode 100644 index 0000000..aea47d7 --- /dev/null +++ b/homeworks/ErmolaevDenis/6/poetry.lock @@ -0,0 +1,145 @@ +[[package]] +name = "argparse" +version = "1.4.0" +description = "Python command-line parsing library" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "cowpy" +version = "1.1.5" +description = "" +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "datetime" +version = "4.7" +description = "This package provides a DateTime data type, as known from Zope. Unless you need to communicate with Zope APIs, you're probably better off using Python's built-in datetime module." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +pytz = "*" +"zope.interface" = "*" + +[[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 = "pytz" +version = "2022.5" +description = "World timezone definitions, modern and historical" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "setuptools" +version = "65.5.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mock", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "zope-interface" +version = "5.5.0" +description = "Interfaces for Python" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.dependencies] +setuptools = "*" + +[package.extras] +docs = ["Sphinx", "repoze.sphinx.autointerface"] +test = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] +testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] + +[metadata] +lock-version = "1.1" +python-versions = "^3.10" +content-hash = "427dbe263852ea34d11cd2796c9b62eb5242b8a53b78447786db16318c8aa861" + +[metadata.files] +argparse = [ + {file = "argparse-1.4.0-py2.py3-none-any.whl", hash = "sha256:c31647edb69fd3d465a847ea3157d37bed1f95f19760b11a47aa91c04b666314"}, + {file = "argparse-1.4.0.tar.gz", hash = "sha256:62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4"}, +] +cowpy = [ + {file = "cowpy-1.1.5-py3-none-any.whl", hash = "sha256:de5ae7646dd30b4936013666c6bd019af9cf411cc3b377c8538cfd8414262921"}, + {file = "cowpy-1.1.5.tar.gz", hash = "sha256:089172db1d88c30a2e1b741b18945ee84170bd943a3ca71948e4ae3a3255e554"}, +] +datetime = [ + {file = "DateTime-4.7-py2.py3-none-any.whl", hash = "sha256:b8d2d605cfb5fed0da86f9ad64d0973c6f84b21939d49265e135811b33ee8113"}, + {file = "DateTime-4.7.tar.gz", hash = "sha256:7ff7c4a857f08b73db17a85fc54f102d065ad16e7db0133e699c5f1b37e41478"}, +] +pygments = [ + {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, + {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, +] +pytz = [ + {file = "pytz-2022.5-py2.py3-none-any.whl", hash = "sha256:335ab46900b1465e714b4fda4963d87363264eb662aab5e65da039c25f1f5b22"}, + {file = "pytz-2022.5.tar.gz", hash = "sha256:c4d88f472f54d615e9cd582a5004d1e5f624854a6a27a6211591c251f22a6914"}, +] +setuptools = [ + {file = "setuptools-65.5.0-py3-none-any.whl", hash = "sha256:f62ea9da9ed6289bfe868cd6845968a2c854d1427f8548d52cae02a42b4f0356"}, + {file = "setuptools-65.5.0.tar.gz", hash = "sha256:512e5536220e38146176efb833d4a62aa726b7bbff82cfbc8ba9eaa3996e0b17"}, +] +zope-interface = [ + {file = "zope.interface-5.5.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:2cb3003941f5f4fa577479ac6d5db2b940acb600096dd9ea9bf07007f5cab46f"}, + {file = "zope.interface-5.5.0-cp27-cp27m-win32.whl", hash = "sha256:8c791f4c203ccdbcda588ea4c8a6e4353e10435ea48ddd3d8734a26fe9714cba"}, + {file = "zope.interface-5.5.0-cp27-cp27m-win_amd64.whl", hash = "sha256:3eedf3d04179774d750e8bb4463e6da350956a50ed44d7b86098e452d7ec385e"}, + {file = "zope.interface-5.5.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:58a66c2020a347973168a4a9d64317bac52f9fdfd3e6b80b252be30da881a64e"}, + {file = "zope.interface-5.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da7912ae76e1df6a1fb841b619110b1be4c86dfb36699d7fd2f177105cdea885"}, + {file = "zope.interface-5.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:423c074e404f13e6fa07f4454f47fdbb38d358be22945bc812b94289d9142374"}, + {file = "zope.interface-5.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7bdcec93f152e0e1942102537eed7b166d6661ae57835b20a52a2a3d6a3e1bf3"}, + {file = "zope.interface-5.5.0-cp310-cp310-win32.whl", hash = "sha256:03f5ae315db0d0de668125d983e2a819a554f3fdb2d53b7e934e3eb3c3c7375d"}, + {file = "zope.interface-5.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:8b9f153208d74ccfa25449a0c6cb756ab792ce0dc99d9d771d935f039b38740c"}, + {file = "zope.interface-5.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeac590cce44e68ee8ad0b8ecf4d7bf15801f102d564ca1b0eb1f12f584ee656"}, + {file = "zope.interface-5.5.0-cp35-cp35m-win32.whl", hash = "sha256:7d9ec1e6694af39b687045712a8ad14ddcb568670d5eb1b66b48b98b9312afba"}, + {file = "zope.interface-5.5.0-cp35-cp35m-win_amd64.whl", hash = "sha256:d18fb0f6c8169d26044128a2e7d3c39377a8a151c564e87b875d379dbafd3930"}, + {file = "zope.interface-5.5.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:0eb2b3e84f48dd9cfc8621c80fba905d7e228615c67f76c7df7c716065669bb6"}, + {file = "zope.interface-5.5.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df6593e150d13cfcce69b0aec5df7bc248cb91e4258a7374c129bb6d56b4e5ca"}, + {file = "zope.interface-5.5.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9dc4493aa3d87591e3d2bf1453e25b98038c839ca8e499df3d7106631b66fe83"}, + {file = "zope.interface-5.5.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5c6023ae7defd052cf76986ce77922177b0c2f3913bea31b5b28fbdf6cb7099e"}, + {file = "zope.interface-5.5.0-cp36-cp36m-win32.whl", hash = "sha256:a69c28d85bb7cf557751a5214cb3f657b2b035c8c96d71080c1253b75b79b69b"}, + {file = "zope.interface-5.5.0-cp36-cp36m-win_amd64.whl", hash = "sha256:85dd6dd9aaae7a176948d8bb62e20e2968588fd787c29c5d0d964ab475168d3d"}, + {file = "zope.interface-5.5.0-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:970661ece2029915b8f7f70892e88404340fbdefd64728380cad41c8dce14ff4"}, + {file = "zope.interface-5.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e3495bb0cdcea212154e558082c256f11b18031f05193ae2fb85d048848db14"}, + {file = "zope.interface-5.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3f68404edb1a4fb6aa8a94675521ca26c83ebbdbb90e894f749ae0dc4ca98418"}, + {file = "zope.interface-5.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:740f3c1b44380658777669bcc42f650f5348e53797f2cee0d93dc9b0f9d7cc69"}, + {file = "zope.interface-5.5.0-cp37-cp37m-win32.whl", hash = "sha256:006f8dd81fae28027fc28ada214855166712bf4f0bfbc5a8788f9b70982b9437"}, + {file = "zope.interface-5.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:43490ad65d4c64e45a30e51a2beb7a6b63e1ff395302ad22392224eb618476d6"}, + {file = "zope.interface-5.5.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f70726b60009433111fe9928f5d89cbb18962411d33c45fb19eb81b9bbd26fcd"}, + {file = "zope.interface-5.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfa614d049667bed1c737435c609c0956c5dc0dbafdc1145ee7935e4658582cb"}, + {file = "zope.interface-5.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:58a975f89e4584d0223ab813c5ba4787064c68feef4b30d600f5e01de90ae9ce"}, + {file = "zope.interface-5.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:37ec9ade9902f412cc7e7a32d71f79dec3035bad9bd0170226252eed88763c48"}, + {file = "zope.interface-5.5.0-cp38-cp38-win32.whl", hash = "sha256:be11fce0e6af6c0e8d93c10ef17b25aa7c4acb7ec644bff2596c0d639c49e20f"}, + {file = "zope.interface-5.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:cbbf83914b9a883ab324f728de869f4e406e0cbcd92df7e0a88decf6f9ab7d5a"}, + {file = "zope.interface-5.5.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:26c1456520fdcafecc5765bec4783eeafd2e893eabc636908f50ee31fe5c738c"}, + {file = "zope.interface-5.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47ff078734a1030c48103422a99e71a7662d20258c00306546441adf689416f7"}, + {file = "zope.interface-5.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:687cab7f9ae18d2c146f315d0ca81e5ffe89a139b88277afa70d52f632515854"}, + {file = "zope.interface-5.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d80f6236b57a95eb19d5e47eb68d0296119e1eff6deaa2971ab8abe3af918420"}, + {file = "zope.interface-5.5.0-cp39-cp39-win32.whl", hash = "sha256:9cdc4e898d3b1547d018829fd4a9f403e52e51bba24be0fbfa37f3174e1ef797"}, + {file = "zope.interface-5.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:6566b3d2657e7609cd8751bcb1eab1202b1692a7af223035a5887d64bb3a2f3b"}, + {file = "zope.interface-5.5.0.tar.gz", hash = "sha256:700ebf9662cf8df70e2f0cb4988e078c53f65ee3eefd5c9d80cf988c4175c8e3"}, +] diff --git a/homeworks/ErmolaevDenis/6/pyproject.toml b/homeworks/ErmolaevDenis/6/pyproject.toml new file mode 100644 index 0000000..9cf911a --- /dev/null +++ b/homeworks/ErmolaevDenis/6/pyproject.toml @@ -0,0 +1,24 @@ +[tool.poetry] +name = "my-awesome-script" +version = "0.1.0" +description = "" +authors = ["ErmolaevDenis "] +readme = "README.md" +packages = [{include = "my-awesome-script"}] + +[tool.poetry.dependencies] +python = "^3.10" +pygments = "^2.13.0" +pytz = "^2022.5" +cowpy = "^1.1.5" +argparse = "^1.4.0" +datetime = "^4.7" + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + + +[tool.poetry.scripts] +my-awesome-script = "my-awesome-script.__main__:main" \ No newline at end of file diff --git a/homeworks/ErmolaevDenis/6/tests/__init__.py b/homeworks/ErmolaevDenis/6/tests/__init__.py new file mode 100644 index 0000000..e69de29 From 8a60375e2a5b9153ea0816c63273373efe9b0369 Mon Sep 17 00:00:00 2001 From: ErmolaevDenis Date: Tue, 1 Nov 2022 20:33:43 +0300 Subject: [PATCH 6/7] hw6 --- homeworks/ErmolaevDenis/2/Array.py | 43 -------- homeworks/ErmolaevDenis/4/contract.py | 30 ------ homeworks/ErmolaevDenis/5/todo/__init__.py | 0 homeworks/ErmolaevDenis/5/todo/__main__.py | 28 ------ homeworks/ErmolaevDenis/5/todo/commands.py | 99 ------------------- .../ErmolaevDenis/5/todo/custom_exceptions.py | 2 - homeworks/ErmolaevDenis/5/todo/models.py | 71 ------------- homeworks/ErmolaevDenis/5/todo/reflection.py | 34 ------- homeworks/ErmolaevDenis/5/todo/runtime.py | 52 ---------- homeworks/ErmolaevDenis/5/todo/storage.py | 21 ---- 10 files changed, 380 deletions(-) delete mode 100644 homeworks/ErmolaevDenis/2/Array.py delete mode 100644 homeworks/ErmolaevDenis/4/contract.py delete mode 100644 homeworks/ErmolaevDenis/5/todo/__init__.py delete mode 100644 homeworks/ErmolaevDenis/5/todo/__main__.py delete mode 100644 homeworks/ErmolaevDenis/5/todo/commands.py delete mode 100644 homeworks/ErmolaevDenis/5/todo/custom_exceptions.py delete mode 100644 homeworks/ErmolaevDenis/5/todo/models.py delete mode 100644 homeworks/ErmolaevDenis/5/todo/reflection.py delete mode 100644 homeworks/ErmolaevDenis/5/todo/runtime.py delete mode 100644 homeworks/ErmolaevDenis/5/todo/storage.py diff --git a/homeworks/ErmolaevDenis/2/Array.py b/homeworks/ErmolaevDenis/2/Array.py deleted file mode 100644 index f53154e..0000000 --- a/homeworks/ErmolaevDenis/2/Array.py +++ /dev/null @@ -1,43 +0,0 @@ -class Array(object): - - def __init__(self, *args): - self._data = args - - def append(self, *args): - self._data += args - - def __add__(self, other): - res = Array(*self._data) - res._data += other._data - return res - - def __len__(self): - return len(self._data) - - def index(self, elem): - ind = -1 - for i in range(len(self._data)): - if (elem == self._data[i]): - ind = i - return ind - - def __iter__(self): - return iter(self._data) - - def __getitem__(self, ind): - return self._data[ind] - - -a1 = Array(1, 2, 3) -a2 = Array(4, 5, 6) -print(a1._data) -print(a2._data) -a2.append(7, 8) -print(a2._data) -a3 = a1 + a2 -print(a3._data) -print(len(a3)) -print(a3.index(4)) -print(a3[4]) -for element in a3: - print(element*100) diff --git a/homeworks/ErmolaevDenis/4/contract.py b/homeworks/ErmolaevDenis/4/contract.py deleted file mode 100644 index 9adcca5..0000000 --- a/homeworks/ErmolaevDenis/4/contract.py +++ /dev/null @@ -1,30 +0,0 @@ -class ContractError(Exception): - """We use this error when someone breaks our contract.""" - pass - -#: 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(function): - def inner(*args): - if arg_types != None and arg_types != Any: - for ind in range(len(args)): - if arg_types[ind] != Any: - if type(args[ind]) != arg_types[ind]: - raise ContractError - try: - result = function(*args) - if return_type != None and return_type != Any: - if return_type != type(result): - raise ContractError - except Exception as ex: - raises = () - if type(ex) in raises: - raise ex - else: - raise ContractError from ex - return result - return inner - return contract_decorator \ No newline at end of file diff --git a/homeworks/ErmolaevDenis/5/todo/__init__.py b/homeworks/ErmolaevDenis/5/todo/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/homeworks/ErmolaevDenis/5/todo/__main__.py b/homeworks/ErmolaevDenis/5/todo/__main__.py deleted file mode 100644 index 55f9f2c..0000000 --- a/homeworks/ErmolaevDenis/5/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/ErmolaevDenis/5/todo/commands.py b/homeworks/ErmolaevDenis/5/todo/commands.py deleted file mode 100644 index 2f8892d..0000000 --- a/homeworks/ErmolaevDenis/5/todo/commands.py +++ /dev/null @@ -1,99 +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 ExitCommand(BaseCommand): - label = 'exit' - - def perform(self, _store): - raise UserExitException('See you next time!') - - -class DoneCommand(BaseCommand): - label = 'done' - - def perform(self, store): - num = int(input('Enter the number of item you want to change to done: ')) - if (num < 0) or num >= len(store.items): - raise IndexError('Wrong index, try again.') - - store.items[num].done = True - - -class UndoneCommand(BaseCommand): - label = 'undone' - - def perform(self, store): - num = int(input('Input number of item to change item status on undone: ')) - if (num < 0) or (num >= len(store.items)): - raise IndexError('Wrong index, try again.') - - store.items[num].done = False - - diff --git a/homeworks/ErmolaevDenis/5/todo/custom_exceptions.py b/homeworks/ErmolaevDenis/5/todo/custom_exceptions.py deleted file mode 100644 index 5e8963c..0000000 --- a/homeworks/ErmolaevDenis/5/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/ErmolaevDenis/5/todo/models.py b/homeworks/ErmolaevDenis/5/todo/models.py deleted file mode 100644 index 8deb184..0000000 --- a/homeworks/ErmolaevDenis/5/todo/models.py +++ /dev/null @@ -1,71 +0,0 @@ -class BaseItem(object): - - status = {False : '-', True : '+'} - - 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 __str__(self): - return '{0} {1}'.format( - self.status[self.done], - self.__class__.__name__[:-4] - ) - - @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) - - -class ToReadItem(BaseItem): - def __init__(self, heading, url): - super().__init__(heading) - self.url = url - - def __str__(self): - return '{0}: {1} from {2}'.format( - super().__str__(), - self.heading, - self.url, - ) - - @classmethod - def construct(cls): - heading = input('Input heading: ') - url = input('Input url: ') - return cls(heading, url) \ No newline at end of file diff --git a/homeworks/ErmolaevDenis/5/todo/reflection.py b/homeworks/ErmolaevDenis/5/todo/reflection.py deleted file mode 100644 index dee9f85..0000000 --- a/homeworks/ErmolaevDenis/5/todo/reflection.py +++ /dev/null @@ -1,34 +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/ErmolaevDenis/5/todo/runtime.py b/homeworks/ErmolaevDenis/5/todo/runtime.py deleted file mode 100644 index c955fa3..0000000 --- a/homeworks/ErmolaevDenis/5/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/ErmolaevDenis/5/todo/storage.py b/homeworks/ErmolaevDenis/5/todo/storage.py deleted file mode 100644 index ef58690..0000000 --- a/homeworks/ErmolaevDenis/5/todo/storage.py +++ /dev/null @@ -1,21 +0,0 @@ -class Storage(object): # storage = Storge() - """ - 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 7894906c5a9e8b41fafced396347c3900dfcd3e2 Mon Sep 17 00:00:00 2001 From: ErmolaevDenis Date: Tue, 1 Nov 2022 21:01:05 +0300 Subject: [PATCH 7/7] fix --- homeworks/ErmolaevDenis/6/README.md | 0 homeworks/ErmolaevDenis/6/tests/__init__.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 homeworks/ErmolaevDenis/6/README.md delete mode 100644 homeworks/ErmolaevDenis/6/tests/__init__.py diff --git a/homeworks/ErmolaevDenis/6/README.md b/homeworks/ErmolaevDenis/6/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/homeworks/ErmolaevDenis/6/tests/__init__.py b/homeworks/ErmolaevDenis/6/tests/__init__.py deleted file mode 100644 index e69de29..0000000