diff --git a/homeworks/SoldatovDaniil/2/hw2.py b/homeworks/SoldatovDaniil/2/hw2.py new file mode 100644 index 0000000..e2ccad7 --- /dev/null +++ b/homeworks/SoldatovDaniil/2/hw2.py @@ -0,0 +1,46 @@ +class Array(object): + + def __init__(self, *args): + self._data = tuple(args) + + def append(self, elem): + self._data = (*self._data, elem) + + def __add__(self, other): + return Array(*(self._data + other._data)) + + def __radd__(self, other): + return Array(*(other._data + self._data)) + + def show(self): + print(self._data) + + def __len__(self): + return len(self._data) + + def index(self, elem): + if elem in self._data: + return self._data.index(elem) + else: + return -1 + + def __getitem__(self, index): + return self._data[index] + + +a = Array(1, 2, 123, 56) +b = Array(1, 1000) + +a.show() +b.show() + +a += b +a = a + b +b = a + Array(0) + +a.show() +b.show() +print(a[3]) + +for i in a: + print(i) diff --git a/homeworks/SoldatovDaniil/3/hw3.py b/homeworks/SoldatovDaniil/3/hw3.py new file mode 100644 index 0000000..475f5fb --- /dev/null +++ b/homeworks/SoldatovDaniil/3/hw3.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 decorated_contract(func): + def wrapped(*args, **kwargs): + if arg_types is not None: + allArgs = tuple(args + tuple(kwargs.values())) + for index in range(len(arg_types)): + if arg_types[index] != Any: + if not isinstance(allArgs[index], arg_types[index]): + raise ContractError("ArgsType Error") + try: + result = func(*args, **kwargs) + except (Exception if raises is None or Any in raises else raises) as ex: + raise ex + except Exception as ex: + raise ContractError from ex + if return_type is not None: + if not isinstance(result, return_type): + raise ContractError("ReturnType Error") + return result + return wrapped + return decorated_contract + + +@contract(arg_types=(int, int), return_type=float, raises=(ZeroDivisionError,)) +def div(one, two): + return one / two + + +print(div(1, 234.5)) diff --git a/homeworks/SoldatovDaniil/4/tests/conftest.py b/homeworks/SoldatovDaniil/4/tests/conftest.py new file mode 100644 index 0000000..e846edf --- /dev/null +++ b/homeworks/SoldatovDaniil/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/SoldatovDaniil/4/tests/test_done_command.py b/homeworks/SoldatovDaniil/4/tests/test_done_command.py new file mode 100644 index 0000000..83a6927 --- /dev/null +++ b/homeworks/SoldatovDaniil/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/SoldatovDaniil/4/tests/test_representations.py b/homeworks/SoldatovDaniil/4/tests/test_representations.py new file mode 100644 index 0000000..07043c8 --- /dev/null +++ b/homeworks/SoldatovDaniil/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/SoldatovDaniil/4/tests/test_to_read_item.py b/homeworks/SoldatovDaniil/4/tests/test_to_read_item.py new file mode 100644 index 0000000..b1ea1e3 --- /dev/null +++ b/homeworks/SoldatovDaniil/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/SoldatovDaniil/4/tests/test_undone_command.py b/homeworks/SoldatovDaniil/4/tests/test_undone_command.py new file mode 100644 index 0000000..b25bedf --- /dev/null +++ b/homeworks/SoldatovDaniil/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/SoldatovDaniil/4/todo/__init__.py b/homeworks/SoldatovDaniil/4/todo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/homeworks/SoldatovDaniil/4/todo/__main__.py b/homeworks/SoldatovDaniil/4/todo/__main__.py new file mode 100644 index 0000000..55f9f2c --- /dev/null +++ b/homeworks/SoldatovDaniil/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/SoldatovDaniil/4/todo/commands.py b/homeworks/SoldatovDaniil/4/todo/commands.py new file mode 100644 index 0000000..e331c06 --- /dev/null +++ b/homeworks/SoldatovDaniil/4/todo/commands.py @@ -0,0 +1,128 @@ + +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): + x = 0 + + for obj in store.items: + if str(obj)[0] == self.char_command: + x += 1 + if x == 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") + except IndexError: + print("Bad index") + 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/SoldatovDaniil/4/todo/custom_exceptions.py b/homeworks/SoldatovDaniil/4/todo/custom_exceptions.py new file mode 100644 index 0000000..5e8963c --- /dev/null +++ b/homeworks/SoldatovDaniil/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/SoldatovDaniil/4/todo/models.py b/homeworks/SoldatovDaniil/4/todo/models.py new file mode 100644 index 0000000..8a4f40b --- /dev/null +++ b/homeworks/SoldatovDaniil/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), + 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), + self.heading, + self.price, + ) + + @classmethod + def construct(cls): + heading = input('Input heading: ') + price = input('Input price: ') + return cls(heading, price) diff --git a/homeworks/SoldatovDaniil/4/todo/reflection.py b/homeworks/SoldatovDaniil/4/todo/reflection.py new file mode 100644 index 0000000..dee9f85 --- /dev/null +++ b/homeworks/SoldatovDaniil/4/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/SoldatovDaniil/4/todo/runtime.py b/homeworks/SoldatovDaniil/4/todo/runtime.py new file mode 100644 index 0000000..c955fa3 --- /dev/null +++ b/homeworks/SoldatovDaniil/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/SoldatovDaniil/4/todo/storage.py b/homeworks/SoldatovDaniil/4/todo/storage.py new file mode 100644 index 0000000..ef58690 --- /dev/null +++ b/homeworks/SoldatovDaniil/4/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 diff --git a/homeworks/SoldatovDaniil/my-awesome-script/README.md b/homeworks/SoldatovDaniil/my-awesome-script/README.md new file mode 100644 index 0000000..e69de29 diff --git a/homeworks/SoldatovDaniil/my-awesome-script/my_awesome_script/__init__.py b/homeworks/SoldatovDaniil/my-awesome-script/my_awesome_script/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/homeworks/SoldatovDaniil/my-awesome-script/my_awesome_script/__main__.py b/homeworks/SoldatovDaniil/my-awesome-script/my_awesome_script/__main__.py new file mode 100644 index 0000000..544b826 --- /dev/null +++ b/homeworks/SoldatovDaniil/my-awesome-script/my_awesome_script/__main__.py @@ -0,0 +1,13 @@ +from cmdInput import cmd_input + + +def main(): + cmd_input() + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + print() + print('Smthng wrng bb!') diff --git a/homeworks/SoldatovDaniil/my-awesome-script/my_awesome_script/cmdInput.py b/homeworks/SoldatovDaniil/my-awesome-script/my_awesome_script/cmdInput.py new file mode 100644 index 0000000..ca058a8 --- /dev/null +++ b/homeworks/SoldatovDaniil/my-awesome-script/my_awesome_script/cmdInput.py @@ -0,0 +1,15 @@ +import argparse +from commands import task + + +def cmd_input(): + parser = argparse.ArgumentParser() + parser.add_argument("todo", type=str, help="highlight 'any text' or cowsay 'any text' or time 'Region/City'") + parser.add_argument("text", type=str, help="highligh:Text,cowsay:Text,Time: Region/City") + args = parser.parse_args() + + try: + task(args.todo, args.text) + except Exception as ex: + task("help") + raise ex diff --git a/homeworks/SoldatovDaniil/my-awesome-script/my_awesome_script/commands.py b/homeworks/SoldatovDaniil/my-awesome-script/my_awesome_script/commands.py new file mode 100644 index 0000000..7249589 --- /dev/null +++ b/homeworks/SoldatovDaniil/my-awesome-script/my_awesome_script/commands.py @@ -0,0 +1,37 @@ +from pygments import highlight +from pygments.formatters import TerminalFormatter +from pygments.lexers import PythonLexer +from cowpy import cow +from datetime import datetime, timedelta +from pytz import timezone +import pytz + + +def task(todo, text): + if todo != "help": + functions[todo](text) + else: + functions[todo]() + + +def highlight_(text): + print(highlight(text, PythonLexer(), TerminalFormatter())) + + +def cowsay_(text): + 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 help_(): + print("EXAMPLE COMMAND:") + print(" highlight 'any text'") + print(" cowsay 'any text'") + print(" time 'Region/City' (example: Europe/Moscow)") + + +functions = {"highlight": highlight_, "cowsay": cowsay_, "time": time_, "help": help_} diff --git a/homeworks/SoldatovDaniil/my-awesome-script/my_awesome_script/setup.cfg b/homeworks/SoldatovDaniil/my-awesome-script/my_awesome_script/setup.cfg new file mode 100644 index 0000000..3deb14b --- /dev/null +++ b/homeworks/SoldatovDaniil/my-awesome-script/my_awesome_script/setup.cfg @@ -0,0 +1,97 @@ +# 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 + .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 diff --git a/homeworks/SoldatovDaniil/my-awesome-script/poetry.lock b/homeworks/SoldatovDaniil/my-awesome-script/poetry.lock new file mode 100644 index 0000000..321c6bc --- /dev/null +++ b/homeworks/SoldatovDaniil/my-awesome-script/poetry.lock @@ -0,0 +1,395 @@ +[[package]] +name = "argparse" +version = "1.4.0" +description = "Python command-line parsing library" +category = "main" +optional = false +python-versions = "*" + +[[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 = "click" +version = "8.1.3" +description = "Composable command line interface toolkit" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.5" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[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 = "dparse" +version = "0.6.2" +description = "A parser for Python dependency files" +category = "main" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +packaging = "*" +toml = "*" + +[package.extras] +conda = ["pyyaml"] +pipenv = ["pipenv"] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "packaging" +version = "21.3" +description = "Core utilities for Python packages" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" + +[[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 = "pyparsing" +version = "3.0.9" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +category = "main" +optional = false +python-versions = ">=3.6.8" + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[package]] +name = "pytz" +version = "2022.5" +description = "World timezone definitions, modern and historical" +category = "main" +optional = false +python-versions = "*" + +[[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 = "ruamel-yaml" +version = "0.17.21" +description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +category = "main" +optional = false +python-versions = ">=3" + +[package.dependencies] +"ruamel.yaml.clib" = {version = ">=0.2.6", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""} + +[package.extras] +docs = ["ryd"] +jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] + +[[package]] +name = "ruamel-yaml-clib" +version = "0.2.6" +description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "safety" +version = "2.3.1" +description = "Checks installed dependencies for known vulnerabilities and licenses." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +Click = ">=8.0.2" +dparse = ">=0.6.2" +packaging = ">=21.0" +requests = "*" +"ruamel.yaml" = ">=0.17.21" +setuptools = ">=19.3" + +[package.extras] +github = ["jinja2 (>=3.1.0)", "pygithub (>=1.43.3)"] +gitlab = ["python-gitlab (>=1.3.0)"] + +[[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 = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +category = "main" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" + +[[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 = "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.8" +content-hash = "d7429f2a4839b7b2d9a34042be0a57cf72262b1fab484de12ab1061af86e035a" + +[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"}, +] +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"}, +] +click = [ + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, +] +colorama = [ + {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, + {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, +] +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"}, +] +dparse = [ + {file = "dparse-0.6.2-py3-none-any.whl", hash = "sha256:8097076f1dd26c377f30d4745e6ec18fef42f3bf493933b842ac5bafad8c345f"}, + {file = "dparse-0.6.2.tar.gz", hash = "sha256:d45255bda21f998bc7ddf2afd5e62505ba6134756ba2d42a84c56b0826614dfe"}, +] +idna = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] +packaging = [ + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, +] +pygments = [ + {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, + {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, +] +pyparsing = [ + {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, + {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, +] +pytz = [ + {file = "pytz-2022.5-py2.py3-none-any.whl", hash = "sha256:335ab46900b1465e714b4fda4963d87363264eb662aab5e65da039c25f1f5b22"}, + {file = "pytz-2022.5.tar.gz", hash = "sha256:c4d88f472f54d615e9cd582a5004d1e5f624854a6a27a6211591c251f22a6914"}, +] +requests = [ + {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, + {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, +] +ruamel-yaml = [ + {file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"}, + {file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"}, +] +ruamel-yaml-clib = [ + {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6e7be2c5bcb297f5b82fee9c665eb2eb7001d1050deaba8471842979293a80b0"}, + {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:066f886bc90cc2ce44df8b5f7acfc6a7e2b2e672713f027136464492b0c34d7c"}, + {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:221eca6f35076c6ae472a531afa1c223b9c29377e62936f61bc8e6e8bdc5f9e7"}, + {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win32.whl", hash = "sha256:1070ba9dd7f9370d0513d649420c3b362ac2d687fe78c6e888f5b12bf8bc7bee"}, + {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:77df077d32921ad46f34816a9a16e6356d8100374579bc35e15bab5d4e9377de"}, + {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:cfdb9389d888c5b74af297e51ce357b800dd844898af9d4a547ffc143fa56751"}, + {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7b2927e92feb51d830f531de4ccb11b320255ee95e791022555971c466af4527"}, + {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win32.whl", hash = "sha256:ada3f400d9923a190ea8b59c8f60680c4ef8a4b0dfae134d2f2ff68429adfab5"}, + {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win_amd64.whl", hash = "sha256:de9c6b8a1ba52919ae919f3ae96abb72b994dd0350226e28f3686cb4f142165c"}, + {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d67f273097c368265a7b81e152e07fb90ed395df6e552b9fa858c6d2c9f42502"}, + {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:72a2b8b2ff0a627496aad76f37a652bcef400fd861721744201ef1b45199ab78"}, + {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:d3c620a54748a3d4cf0bcfe623e388407c8e85a4b06b8188e126302bcab93ea8"}, + {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win32.whl", hash = "sha256:9efef4aab5353387b07f6b22ace0867032b900d8e91674b5d8ea9150db5cae94"}, + {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win_amd64.whl", hash = "sha256:846fc8336443106fe23f9b6d6b8c14a53d38cef9a375149d61f99d78782ea468"}, + {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0847201b767447fc33b9c235780d3aa90357d20dd6108b92be544427bea197dd"}, + {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:78988ed190206672da0f5d50c61afef8f67daa718d614377dcd5e3ed85ab4a99"}, + {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:210c8fcfeff90514b7133010bf14e3bad652c8efde6b20e00c43854bf94fa5a6"}, + {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win32.whl", hash = "sha256:a49e0161897901d1ac9c4a79984b8410f450565bbad64dbfcbf76152743a0cdb"}, + {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win_amd64.whl", hash = "sha256:bf75d28fa071645c529b5474a550a44686821decebdd00e21127ef1fd566eabe"}, + {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a32f8d81ea0c6173ab1b3da956869114cae53ba1e9f72374032e33ba3118c233"}, + {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7f7ecb53ae6848f959db6ae93bdff1740e651809780822270eab111500842a84"}, + {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:61bc5e5ca632d95925907c569daa559ea194a4d16084ba86084be98ab1cec1c6"}, + {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win32.whl", hash = "sha256:89221ec6d6026f8ae859c09b9718799fea22c0e8da8b766b0b2c9a9ba2db326b"}, + {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win_amd64.whl", hash = "sha256:31ea73e564a7b5fbbe8188ab8b334393e06d997914a4e184975348f204790277"}, + {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dc6a613d6c74eef5a14a214d433d06291526145431c3b964f5e16529b1842bed"}, + {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:1866cf2c284a03b9524a5cc00daca56d80057c5ce3cdc86a52020f4c720856f0"}, + {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:1b4139a6ffbca8ef60fdaf9b33dec05143ba746a6f0ae0f9d11d38239211d335"}, + {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win32.whl", hash = "sha256:3fb9575a5acd13031c57a62cc7823e5d2ff8bc3835ba4d94b921b4e6ee664104"}, + {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win_amd64.whl", hash = "sha256:825d5fccef6da42f3c8eccd4281af399f21c02b32d98e113dbc631ea6a6ecbc7"}, + {file = "ruamel.yaml.clib-0.2.6.tar.gz", hash = "sha256:4ff604ce439abb20794f05613c374759ce10e3595d1867764dd1ae675b85acbd"}, +] +safety = [ + {file = "safety-2.3.1-py3-none-any.whl", hash = "sha256:8f098d12b607db2756886280e85c28ece8db1bba4f45fc5f981f4663217bd619"}, + {file = "safety-2.3.1.tar.gz", hash = "sha256:6e6fcb7d4e8321098cf289f59b65051cafd3467f089c6e57c9f894ae32c23b71"}, +] +setuptools = [ + {file = "setuptools-65.5.0-py3-none-any.whl", hash = "sha256:f62ea9da9ed6289bfe868cd6845968a2c854d1427f8548d52cae02a42b4f0356"}, + {file = "setuptools-65.5.0.tar.gz", hash = "sha256:512e5536220e38146176efb833d4a62aa726b7bbff82cfbc8ba9eaa3996e0b17"}, +] +toml = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] +urllib3 = [ + {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, + {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, +] +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/SoldatovDaniil/my-awesome-script/pyproject.toml b/homeworks/SoldatovDaniil/my-awesome-script/pyproject.toml new file mode 100644 index 0000000..ad793fe --- /dev/null +++ b/homeworks/SoldatovDaniil/my-awesome-script/pyproject.toml @@ -0,0 +1,24 @@ +[tool.poetry] +name = "my-awesome-script" +version = "0.1.0" +description = "" +authors = ["SoldatovDaniil <92687673+SoldatovDaniil@users.noreply.github.com>"] +readme = "README.md" +packages = [{include = "my_awesome_script"}] + +[tool.poetry.dependencies] +python = "^3.8" +pygments = "^2.13.0" +cowpy = "^1.1.5" +pytz = "^2022.5" +datetime = "^4.7" +safety = "^2.3.1" +argparse = "^1.4.0" + + +[tool.poetry.group.dev.dependencies] +safety = "^2.3.1" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/homeworks/SoldatovDaniil/my-awesome-script/tests/__init__.py b/homeworks/SoldatovDaniil/my-awesome-script/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/practise/SoldatovDaniil/1/game.py b/practise/SoldatovDaniil/1/game.py new file mode 100644 index 0000000..c33513c --- /dev/null +++ b/practise/SoldatovDaniil/1/game.py @@ -0,0 +1,79 @@ +# `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(): + field = [] + for i in range(1, 16): + field.append(i) + field.append(EMPTY_MARK) + for i in range(100): + random.shuffle(field) + return field + + +def print_field(field): + for i in range(0, 16): + if field[i] == EMPTY_MARK or field[i] < 10: + print(' ', end='') + print(field[i], end=' | ') + if i % 4 == 3: + print() + + +def is_game_finished(field): + for i in range(0, 15): + if field[i] != i + 1: + return False + return True + + +def perform_move(field, key): + for i in range(0, 16): + if field[i] == EMPTY_MARK: + emptyIndex = i + + if emptyIndex % 4 == 3 and key == "d": + return None + if emptyIndex % 4 == 0 and key == "a": + return None + if MOVES[key] + emptyIndex < 0 and 15 < MOVES[key] + emptyIndex: + return None + field[emptyIndex] = field[emptyIndex + MOVES[key]] + field[emptyIndex + MOVES[key]] = EMPTY_MARK + return field + + +def handle_user_input(): + userMove = input() + if userMove not in ['w', 's', 'a', 'd']: + return None + return userMove + + +def main(): + myField = shuffle_field() + + while not(is_game_finished(myField)): + print_field(myField) + key = handle_user_input() + perform_move(myField, key) + + +if __name__ == '__main__': + # See what this means: + # http://stackoverflow.com/questions/419163/what-does-if-name-main-do + main()