├── .dockerignore
├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── dockerfile
├── docs
├── Makefile
├── make.bat
└── source
│ ├── conf.py
│ └── index.rst
├── poetry.lock
├── poetry_template
├── __init__.py
├── package_one
│ ├── __init__.py
│ └── module_one.py
├── package_two
│ ├── __init__.py
│ └── module_two.py
├── profiler.py
├── runner.py
└── settings.py
├── pyproject.toml
└── tests
├── __init__.py
├── conftest.py
├── context.py
├── package_one
├── __init__.py
└── test_module_one.py
└── package_two
├── __init__.py
└── test_module_two.py
/.dockerignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MislavJaksic/Python-Project-Template/ed90180b36aafd3f2f883d94b6a70e0187ce1b28/.dockerignore
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | .hypothesis/
51 | .pytest_cache/
52 |
53 | # Translations
54 | *.mo
55 | *.pot
56 |
57 | # Django stuff:
58 | *.log
59 | local_settings.py
60 | db.sqlite3
61 |
62 | # Flask stuff:
63 | instance/
64 | .webassets-cache
65 |
66 | # Scrapy stuff:
67 | .scrapy
68 |
69 | # Sphinx documentation
70 | docs/_build/
71 |
72 | # PyBuilder
73 | target/
74 |
75 | # Jupyter Notebook
76 | .ipynb_checkpoints
77 |
78 | # IPython
79 | profile_default/
80 | ipython_config.py
81 |
82 | # pyenv
83 | .python-version
84 |
85 | # pipenv
86 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
87 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
88 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
89 | # install all needed dependencies.
90 | #Pipfile.lock
91 |
92 | # celery beat schedule file
93 | celerybeat-schedule
94 |
95 | # SageMath parsed files
96 | *.sage.py
97 |
98 | # Environments
99 | .env
100 | .venv
101 | env/
102 | venv/
103 | ENV/
104 | env.bak/
105 | venv.bak/
106 |
107 | # Spyder project settings
108 | .spyderproject
109 | .spyproject
110 |
111 | # Rope project settings
112 | .ropeproject
113 |
114 | # mkdocs documentation
115 | /site
116 |
117 | # mypy
118 | .mypy_cache/
119 | .dmypy.json
120 | dmypy.json
121 |
122 | # Pyre type checker
123 | .pyre/
124 |
125 | # Additional ignore
126 | .idea
127 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 MislavJaksic
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Python Project Template
2 |
3 | ```
4 | After creating a new git repository copy over:
5 | * docs
6 | * poetry_template
7 | * tests
8 | * pyproject.toml
9 | * README.md
10 |
11 | Go through the project and change the placeholder values. pyproject.toml contains the list of the most important values present throughout the project.
12 |
13 | Finally, delete this note.
14 | ```
15 |
16 | ## Development
17 |
18 | ```
19 | # Note: Install Python 3
20 | # You may also need to install or update pip, virtualenv (dependency encapsulator) and black (linter)
21 |
22 | # Note: install Poetry for your OS
23 | ```
24 |
25 | ```
26 | # Note: `.toml` project name and package have to match (poetry-template; poetry_template)
27 | $: poetry install # install all dependencies
28 | ```
29 |
30 | ### dist
31 |
32 | ```
33 | $: pip install dist/poetry_template-0.1.5-py3-none.any.whl
34 |
35 | $: poetry-template
36 | ```
37 |
38 | ### docs
39 |
40 | ```
41 | $: poetry shell
42 | $: cd docs
43 | # Note: review source/conf.py and source/index.rst
44 | $: make html
45 | # Note: see docs in docs/build/apidocs/index.html
46 | ```
47 |
48 | ### poetry_template
49 |
50 | ```
51 | $: poetry run poetry-template --help
52 | $: poetry run python ./poetry_template/runner.py --help
53 |
54 | $: poetry run python ./poetry_template/runner.py -x 2 -y -1 -tuple A B C -list D -list E -list F -move rock
55 | ```
56 |
57 | ### tests
58 |
59 | ```
60 | $: poetry run pytest --durations=0
61 | ```
62 |
63 | ```
64 | $: poetry run pytest --cov=poetry_template --cov-report=html tests
65 | # Note: see coverage report in htmlcov/index.html
66 | # Note: exclude directories from coverage report through .coveragerc
67 | ```
68 |
69 | ### poetry.lock
70 |
71 | Dependencies, Python version and the virtual environment are managed by `Poetry`.
72 |
73 | ```
74 | $: poetry search Package-Name
75 | $: poetry add [-D] Package-Name[==Package-Version]
76 | ```
77 |
78 | ### pyproject.toml
79 |
80 | Define project entry point and metadata.
81 |
82 |
83 | ### Linters
84 |
85 | ```
86 | $: poetry run black .
87 | ```
88 |
89 | ### MyPy
90 |
91 | ```
92 | $: poetry run mypy ./poetry_template ./tests
93 | ```
94 |
95 | ### cProfile
96 |
97 | ```
98 | $: poetry run python ./poetry_template/profiler.py
99 | ```
100 |
101 | ### Build and publish
102 |
103 | ```
104 | $: poetry build
105 |
106 | # Note: get the token from your PiPy account
107 | $: poetry config pypi-token.pypi PyPI-Api-Access-Token
108 | ```
109 |
110 | ```
111 | $: poetry publish --build
112 | ```
113 |
114 | ```
115 | https://pypi.org/project/poetry-template/
116 | ```
117 |
--------------------------------------------------------------------------------
/dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3
2 |
3 | ARG YOUR_ENV
4 |
5 | ENV YOUR_ENV=${YOUR_ENV} \
6 | PYTHONFAULTHANDLER=1 \
7 | PYTHONUNBUFFERED=1 \
8 | PYTHONHASHSEED=random \
9 | PIP_NO_CACHE_DIR=off \
10 | PIP_DISABLE_PIP_VERSION_CHECK=on \
11 | PIP_DEFAULT_TIMEOUT=100 \
12 | POETRY_VERSION=1.0.0
13 |
14 | # System deps:
15 | RUN pip install "poetry==$POETRY_VERSION"
16 |
17 | # Copy only requirements to cache them in docker layer
18 | COPY poetry.lock pyproject.toml README.md /
19 |
20 | # Project initialization:
21 | RUN poetry config virtualenvs.create false \
22 | && poetry install $(test "$YOUR_ENV" == production && echo "--no-dev") --no-interaction --no-ansi
23 |
24 | # Creating folders, and files for a project:
25 | COPY /poetry_template /poetry_template
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = source
9 | BUILDDIR = build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/docs/source/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # This file only contains a selection of the most common options. For a full
4 | # list see the documentation:
5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
6 |
7 | # -- Path setup --------------------------------------------------------------
8 |
9 | # If extensions (or modules to document with autodoc) are in another directory,
10 | # add these directories to sys.path here. If the directory is relative to the
11 | # documentation root, use os.path.abspath to make it absolute, like shown here.
12 | #
13 | import os
14 | import sys
15 |
16 | sys.path.insert(0, os.path.abspath("../../poetry_template"))
17 |
18 | # -- Project information -----------------------------------------------------
19 |
20 | project = "poetry-template"
21 | copyright = "2019, Mislav Jaksic"
22 | author = "Mislav Jaksic"
23 |
24 | # The full version, including alpha/beta/rc tags
25 | release = "0.1.5"
26 |
27 | # -- General configuration ---------------------------------------------------
28 |
29 | # Add any Sphinx extension module names here, as strings. They can be
30 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
31 | # ones.
32 | extensions = ["sphinx.ext.autodoc"]
33 |
34 | # Add any paths that contain templates here, relative to this directory.
35 | templates_path = ["_templates"]
36 |
37 | # List of patterns, relative to source directory, that match files and
38 | # directories to ignore when looking for source files.
39 | # This pattern also affects html_static_path and html_extra_path.
40 | exclude_patterns = []
41 |
42 | # -- Options for HTML output -------------------------------------------------
43 |
44 | # The theme to use for HTML and HTML Help pages. See the documentation for
45 | # a list of builtin themes.
46 | #
47 | html_theme = "alabaster"
48 |
49 | # Add any paths that contain custom static files (such as style sheets) here,
50 | # relative to this directory. They are copied after the builtin static files,
51 | # so a file named "default.css" will overwrite the builtin "default.css".
52 | html_static_path = ["_static"]
53 |
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | .. poetry-template documentation master file, created by
2 | sphinx-quickstart on Wed Sep 4 19:11:00 2019.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to poetry-template's documentation!
7 | ===========================================
8 |
9 | .. toctree::
10 | :maxdepth: 2
11 | :caption: Contents:
12 |
13 | poetry_template runner
14 | ----------------------
15 | .. automodule:: runner
16 | :members:
17 |
18 | poetry_template package_one module_one
19 | --------------------------------------
20 | .. automodule:: package_one.module_one
21 | :members:
22 |
23 | poetry_template package_two module_two
24 | --------------------------------------
25 | .. automodule:: package_two.module_two
26 | :members:
27 |
28 |
29 |
30 | Indices and tables
31 | ==================
32 |
33 | * :ref:`genindex`
34 | * :ref:`modindex`
35 | * :ref:`search`
36 |
--------------------------------------------------------------------------------
/poetry.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Poetry and should not be changed by hand.
2 |
3 | [[package]]
4 | name = "alabaster"
5 | version = "0.7.13"
6 | description = "A configurable sidebar-enabled Sphinx theme"
7 | category = "dev"
8 | optional = false
9 | python-versions = ">=3.6"
10 | files = [
11 | {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"},
12 | {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"},
13 | ]
14 |
15 | [[package]]
16 | name = "babel"
17 | version = "2.12.1"
18 | description = "Internationalization utilities"
19 | category = "dev"
20 | optional = false
21 | python-versions = ">=3.7"
22 | files = [
23 | {file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"},
24 | {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"},
25 | ]
26 |
27 | [package.dependencies]
28 | pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""}
29 |
30 | [[package]]
31 | name = "black"
32 | version = "23.3.0"
33 | description = "The uncompromising code formatter."
34 | category = "dev"
35 | optional = false
36 | python-versions = ">=3.7"
37 | files = [
38 | {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"},
39 | {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"},
40 | {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"},
41 | {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"},
42 | {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"},
43 | {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"},
44 | {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"},
45 | {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"},
46 | {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"},
47 | {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"},
48 | {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"},
49 | {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"},
50 | {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"},
51 | {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"},
52 | {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"},
53 | {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"},
54 | {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"},
55 | {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"},
56 | {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"},
57 | {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"},
58 | {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"},
59 | {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"},
60 | {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"},
61 | {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"},
62 | {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"},
63 | ]
64 |
65 | [package.dependencies]
66 | click = ">=8.0.0"
67 | mypy-extensions = ">=0.4.3"
68 | packaging = ">=22.0"
69 | pathspec = ">=0.9.0"
70 | platformdirs = ">=2"
71 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
72 | typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
73 |
74 | [package.extras]
75 | colorama = ["colorama (>=0.4.3)"]
76 | d = ["aiohttp (>=3.7.4)"]
77 | jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
78 | uvloop = ["uvloop (>=0.15.2)"]
79 |
80 | [[package]]
81 | name = "certifi"
82 | version = "2022.12.7"
83 | description = "Python package for providing Mozilla's CA Bundle."
84 | category = "main"
85 | optional = false
86 | python-versions = ">=3.6"
87 | files = [
88 | {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
89 | {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
90 | ]
91 |
92 | [[package]]
93 | name = "charset-normalizer"
94 | version = "3.1.0"
95 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
96 | category = "main"
97 | optional = false
98 | python-versions = ">=3.7.0"
99 | files = [
100 | {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"},
101 | {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"},
102 | {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"},
103 | {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"},
104 | {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"},
105 | {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"},
106 | {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"},
107 | {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"},
108 | {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"},
109 | {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"},
110 | {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"},
111 | {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"},
112 | {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"},
113 | {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"},
114 | {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"},
115 | {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"},
116 | {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"},
117 | {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"},
118 | {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"},
119 | {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"},
120 | {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"},
121 | {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"},
122 | {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"},
123 | {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"},
124 | {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"},
125 | {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"},
126 | {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"},
127 | {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"},
128 | {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"},
129 | {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"},
130 | {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"},
131 | {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"},
132 | {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"},
133 | {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"},
134 | {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"},
135 | {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"},
136 | {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"},
137 | {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"},
138 | {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"},
139 | {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"},
140 | {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"},
141 | {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"},
142 | {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"},
143 | {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"},
144 | {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"},
145 | {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"},
146 | {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"},
147 | {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"},
148 | {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"},
149 | {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"},
150 | {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"},
151 | {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"},
152 | {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"},
153 | {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"},
154 | {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"},
155 | {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"},
156 | {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"},
157 | {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"},
158 | {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"},
159 | {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"},
160 | {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"},
161 | {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"},
162 | {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"},
163 | {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"},
164 | {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"},
165 | {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"},
166 | {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"},
167 | {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"},
168 | {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"},
169 | {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"},
170 | {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"},
171 | {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"},
172 | {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"},
173 | {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"},
174 | {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"},
175 | ]
176 |
177 | [[package]]
178 | name = "click"
179 | version = "8.1.3"
180 | description = "Composable command line interface toolkit"
181 | category = "dev"
182 | optional = false
183 | python-versions = ">=3.7"
184 | files = [
185 | {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
186 | {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
187 | ]
188 |
189 | [package.dependencies]
190 | colorama = {version = "*", markers = "platform_system == \"Windows\""}
191 |
192 | [[package]]
193 | name = "colorama"
194 | version = "0.4.6"
195 | description = "Cross-platform colored terminal text."
196 | category = "main"
197 | optional = false
198 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
199 | files = [
200 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
201 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
202 | ]
203 |
204 | [[package]]
205 | name = "coverage"
206 | version = "7.2.3"
207 | description = "Code coverage measurement for Python"
208 | category = "dev"
209 | optional = false
210 | python-versions = ">=3.7"
211 | files = [
212 | {file = "coverage-7.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e58c0d41d336569d63d1b113bd573db8363bc4146f39444125b7f8060e4e04f5"},
213 | {file = "coverage-7.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:344e714bd0fe921fc72d97404ebbdbf9127bac0ca1ff66d7b79efc143cf7c0c4"},
214 | {file = "coverage-7.2.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:974bc90d6f6c1e59ceb1516ab00cf1cdfbb2e555795d49fa9571d611f449bcb2"},
215 | {file = "coverage-7.2.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0743b0035d4b0e32bc1df5de70fba3059662ace5b9a2a86a9f894cfe66569013"},
216 | {file = "coverage-7.2.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d0391fb4cfc171ce40437f67eb050a340fdbd0f9f49d6353a387f1b7f9dd4fa"},
217 | {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a42e1eff0ca9a7cb7dc9ecda41dfc7cbc17cb1d02117214be0561bd1134772b"},
218 | {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:be19931a8dcbe6ab464f3339966856996b12a00f9fe53f346ab3be872d03e257"},
219 | {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72fcae5bcac3333a4cf3b8f34eec99cea1187acd55af723bcbd559adfdcb5535"},
220 | {file = "coverage-7.2.3-cp310-cp310-win32.whl", hash = "sha256:aeae2aa38395b18106e552833f2a50c27ea0000122bde421c31d11ed7e6f9c91"},
221 | {file = "coverage-7.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:83957d349838a636e768251c7e9979e899a569794b44c3728eaebd11d848e58e"},
222 | {file = "coverage-7.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dfd393094cd82ceb9b40df4c77976015a314b267d498268a076e940fe7be6b79"},
223 | {file = "coverage-7.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:182eb9ac3f2b4874a1f41b78b87db20b66da6b9cdc32737fbbf4fea0c35b23fc"},
224 | {file = "coverage-7.2.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bb1e77a9a311346294621be905ea8a2c30d3ad371fc15bb72e98bfcfae532df"},
225 | {file = "coverage-7.2.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca0f34363e2634deffd390a0fef1aa99168ae9ed2af01af4a1f5865e362f8623"},
226 | {file = "coverage-7.2.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55416d7385774285b6e2a5feca0af9652f7f444a4fa3d29d8ab052fafef9d00d"},
227 | {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:06ddd9c0249a0546997fdda5a30fbcb40f23926df0a874a60a8a185bc3a87d93"},
228 | {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fff5aaa6becf2c6a1699ae6a39e2e6fb0672c2d42eca8eb0cafa91cf2e9bd312"},
229 | {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ea53151d87c52e98133eb8ac78f1206498c015849662ca8dc246255265d9c3c4"},
230 | {file = "coverage-7.2.3-cp311-cp311-win32.whl", hash = "sha256:8f6c930fd70d91ddee53194e93029e3ef2aabe26725aa3c2753df057e296b925"},
231 | {file = "coverage-7.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:fa546d66639d69aa967bf08156eb8c9d0cd6f6de84be9e8c9819f52ad499c910"},
232 | {file = "coverage-7.2.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b2317d5ed777bf5a033e83d4f1389fd4ef045763141d8f10eb09a7035cee774c"},
233 | {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be9824c1c874b73b96288c6d3de793bf7f3a597770205068c6163ea1f326e8b9"},
234 | {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c3b2803e730dc2797a017335827e9da6da0e84c745ce0f552e66400abdfb9a1"},
235 | {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f69770f5ca1994cb32c38965e95f57504d3aea96b6c024624fdd5bb1aa494a1"},
236 | {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1127b16220f7bfb3f1049ed4a62d26d81970a723544e8252db0efde853268e21"},
237 | {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:aa784405f0c640940595fa0f14064d8e84aff0b0f762fa18393e2760a2cf5841"},
238 | {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3146b8e16fa60427e03884301bf8209221f5761ac754ee6b267642a2fd354c48"},
239 | {file = "coverage-7.2.3-cp37-cp37m-win32.whl", hash = "sha256:1fd78b911aea9cec3b7e1e2622c8018d51c0d2bbcf8faaf53c2497eb114911c1"},
240 | {file = "coverage-7.2.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0f3736a5d34e091b0a611964c6262fd68ca4363df56185902528f0b75dbb9c1f"},
241 | {file = "coverage-7.2.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:981b4df72c93e3bc04478153df516d385317628bd9c10be699c93c26ddcca8ab"},
242 | {file = "coverage-7.2.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0045f8f23a5fb30b2eb3b8a83664d8dc4fb58faddf8155d7109166adb9f2040"},
243 | {file = "coverage-7.2.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f760073fcf8f3d6933178d67754f4f2d4e924e321f4bb0dcef0424ca0215eba1"},
244 | {file = "coverage-7.2.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c86bd45d1659b1ae3d0ba1909326b03598affbc9ed71520e0ff8c31a993ad911"},
245 | {file = "coverage-7.2.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:172db976ae6327ed4728e2507daf8a4de73c7cc89796483e0a9198fd2e47b462"},
246 | {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d2a3a6146fe9319926e1d477842ca2a63fe99af5ae690b1f5c11e6af074a6b5c"},
247 | {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f649dd53833b495c3ebd04d6eec58479454a1784987af8afb77540d6c1767abd"},
248 | {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c4ed4e9f3b123aa403ab424430b426a1992e6f4c8fd3cb56ea520446e04d152"},
249 | {file = "coverage-7.2.3-cp38-cp38-win32.whl", hash = "sha256:eb0edc3ce9760d2f21637766c3aa04822030e7451981ce569a1b3456b7053f22"},
250 | {file = "coverage-7.2.3-cp38-cp38-win_amd64.whl", hash = "sha256:63cdeaac4ae85a179a8d6bc09b77b564c096250d759eed343a89d91bce8b6367"},
251 | {file = "coverage-7.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:20d1a2a76bb4eb00e4d36b9699f9b7aba93271c9c29220ad4c6a9581a0320235"},
252 | {file = "coverage-7.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ea748802cc0de4de92ef8244dd84ffd793bd2e7be784cd8394d557a3c751e21"},
253 | {file = "coverage-7.2.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21b154aba06df42e4b96fc915512ab39595105f6c483991287021ed95776d934"},
254 | {file = "coverage-7.2.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd214917cabdd6f673a29d708574e9fbdb892cb77eb426d0eae3490d95ca7859"},
255 | {file = "coverage-7.2.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c2e58e45fe53fab81f85474e5d4d226eeab0f27b45aa062856c89389da2f0d9"},
256 | {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:87ecc7c9a1a9f912e306997ffee020297ccb5ea388421fe62a2a02747e4d5539"},
257 | {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:387065e420aed3c71b61af7e82c7b6bc1c592f7e3c7a66e9f78dd178699da4fe"},
258 | {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ea3f5bc91d7d457da7d48c7a732beaf79d0c8131df3ab278e6bba6297e23c6c4"},
259 | {file = "coverage-7.2.3-cp39-cp39-win32.whl", hash = "sha256:ae7863a1d8db6a014b6f2ff9c1582ab1aad55a6d25bac19710a8df68921b6e30"},
260 | {file = "coverage-7.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:3f04becd4fcda03c0160d0da9c8f0c246bc78f2f7af0feea1ec0930e7c93fa4a"},
261 | {file = "coverage-7.2.3-pp37.pp38.pp39-none-any.whl", hash = "sha256:965ee3e782c7892befc25575fa171b521d33798132692df428a09efacaffe8d0"},
262 | {file = "coverage-7.2.3.tar.gz", hash = "sha256:d298c2815fa4891edd9abe5ad6e6cb4207104c7dd9fd13aea3fdebf6f9b91259"},
263 | ]
264 |
265 | [package.dependencies]
266 | tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
267 |
268 | [package.extras]
269 | toml = ["tomli"]
270 |
271 | [[package]]
272 | name = "docutils"
273 | version = "0.19"
274 | description = "Docutils -- Python Documentation Utilities"
275 | category = "dev"
276 | optional = false
277 | python-versions = ">=3.7"
278 | files = [
279 | {file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"},
280 | {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"},
281 | ]
282 |
283 | [[package]]
284 | name = "exceptiongroup"
285 | version = "1.1.1"
286 | description = "Backport of PEP 654 (exception groups)"
287 | category = "dev"
288 | optional = false
289 | python-versions = ">=3.7"
290 | files = [
291 | {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"},
292 | {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"},
293 | ]
294 |
295 | [package.extras]
296 | test = ["pytest (>=6)"]
297 |
298 | [[package]]
299 | name = "idna"
300 | version = "3.4"
301 | description = "Internationalized Domain Names in Applications (IDNA)"
302 | category = "main"
303 | optional = false
304 | python-versions = ">=3.5"
305 | files = [
306 | {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
307 | {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
308 | ]
309 |
310 | [[package]]
311 | name = "imagesize"
312 | version = "1.4.1"
313 | description = "Getting image size from png/jpeg/jpeg2000/gif file"
314 | category = "dev"
315 | optional = false
316 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
317 | files = [
318 | {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"},
319 | {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"},
320 | ]
321 |
322 | [[package]]
323 | name = "importlib-metadata"
324 | version = "6.3.0"
325 | description = "Read metadata from Python packages"
326 | category = "dev"
327 | optional = false
328 | python-versions = ">=3.7"
329 | files = [
330 | {file = "importlib_metadata-6.3.0-py3-none-any.whl", hash = "sha256:8f8bd2af397cf33bd344d35cfe7f489219b7d14fc79a3f854b75b8417e9226b0"},
331 | {file = "importlib_metadata-6.3.0.tar.gz", hash = "sha256:23c2bcae4762dfb0bbe072d358faec24957901d75b6c4ab11172c0c982532402"},
332 | ]
333 |
334 | [package.dependencies]
335 | zipp = ">=0.5"
336 |
337 | [package.extras]
338 | docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
339 | perf = ["ipython"]
340 | testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "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 (>=0.9.2)"]
341 |
342 | [[package]]
343 | name = "iniconfig"
344 | version = "2.0.0"
345 | description = "brain-dead simple config-ini parsing"
346 | category = "dev"
347 | optional = false
348 | python-versions = ">=3.7"
349 | files = [
350 | {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
351 | {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
352 | ]
353 |
354 | [[package]]
355 | name = "jinja2"
356 | version = "3.1.2"
357 | description = "A very fast and expressive template engine."
358 | category = "dev"
359 | optional = false
360 | python-versions = ">=3.7"
361 | files = [
362 | {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
363 | {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
364 | ]
365 |
366 | [package.dependencies]
367 | MarkupSafe = ">=2.0"
368 |
369 | [package.extras]
370 | i18n = ["Babel (>=2.7)"]
371 |
372 | [[package]]
373 | name = "loguru"
374 | version = "0.7.0"
375 | description = "Python logging made (stupidly) simple"
376 | category = "main"
377 | optional = false
378 | python-versions = ">=3.5"
379 | files = [
380 | {file = "loguru-0.7.0-py3-none-any.whl", hash = "sha256:b93aa30099fa6860d4727f1b81f8718e965bb96253fa190fab2077aaad6d15d3"},
381 | {file = "loguru-0.7.0.tar.gz", hash = "sha256:1612053ced6ae84d7959dd7d5e431a0532642237ec21f7fd83ac73fe539e03e1"},
382 | ]
383 |
384 | [package.dependencies]
385 | colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""}
386 | win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""}
387 |
388 | [package.extras]
389 | dev = ["Sphinx (==5.3.0)", "colorama (==0.4.5)", "colorama (==0.4.6)", "freezegun (==1.1.0)", "freezegun (==1.2.2)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v0.990)", "pre-commit (==3.2.1)", "pytest (==6.1.2)", "pytest (==7.2.1)", "pytest-cov (==2.12.1)", "pytest-cov (==4.0.0)", "pytest-mypy-plugins (==1.10.1)", "pytest-mypy-plugins (==1.9.3)", "sphinx-autobuild (==2021.3.14)", "sphinx-rtd-theme (==1.2.0)", "tox (==3.27.1)", "tox (==4.4.6)"]
390 |
391 | [[package]]
392 | name = "markupsafe"
393 | version = "2.1.2"
394 | description = "Safely add untrusted strings to HTML/XML markup."
395 | category = "dev"
396 | optional = false
397 | python-versions = ">=3.7"
398 | files = [
399 | {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"},
400 | {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"},
401 | {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"},
402 | {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"},
403 | {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"},
404 | {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"},
405 | {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"},
406 | {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"},
407 | {file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"},
408 | {file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"},
409 | {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"},
410 | {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"},
411 | {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"},
412 | {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"},
413 | {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"},
414 | {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"},
415 | {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"},
416 | {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"},
417 | {file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"},
418 | {file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"},
419 | {file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"},
420 | {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"},
421 | {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"},
422 | {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"},
423 | {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"},
424 | {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"},
425 | {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"},
426 | {file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"},
427 | {file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"},
428 | {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"},
429 | {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"},
430 | {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"},
431 | {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"},
432 | {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"},
433 | {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"},
434 | {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"},
435 | {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"},
436 | {file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"},
437 | {file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"},
438 | {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"},
439 | {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"},
440 | {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"},
441 | {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"},
442 | {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"},
443 | {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"},
444 | {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"},
445 | {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"},
446 | {file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"},
447 | {file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"},
448 | {file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"},
449 | ]
450 |
451 | [[package]]
452 | name = "mypy"
453 | version = "1.2.0"
454 | description = "Optional static typing for Python"
455 | category = "dev"
456 | optional = false
457 | python-versions = ">=3.7"
458 | files = [
459 | {file = "mypy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:701189408b460a2ff42b984e6bd45c3f41f0ac9f5f58b8873bbedc511900086d"},
460 | {file = "mypy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fe91be1c51c90e2afe6827601ca14353bbf3953f343c2129fa1e247d55fd95ba"},
461 | {file = "mypy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d26b513225ffd3eacece727f4387bdce6469192ef029ca9dd469940158bc89e"},
462 | {file = "mypy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3a2d219775a120581a0ae8ca392b31f238d452729adbcb6892fa89688cb8306a"},
463 | {file = "mypy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:2e93a8a553e0394b26c4ca683923b85a69f7ccdc0139e6acd1354cc884fe0128"},
464 | {file = "mypy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3efde4af6f2d3ccf58ae825495dbb8d74abd6d176ee686ce2ab19bd025273f41"},
465 | {file = "mypy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:695c45cea7e8abb6f088a34a6034b1d273122e5530aeebb9c09626cea6dca4cb"},
466 | {file = "mypy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0e9464a0af6715852267bf29c9553e4555b61f5904a4fc538547a4d67617937"},
467 | {file = "mypy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8293a216e902ac12779eb7a08f2bc39ec6c878d7c6025aa59464e0c4c16f7eb9"},
468 | {file = "mypy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:f46af8d162f3d470d8ffc997aaf7a269996d205f9d746124a179d3abe05ac602"},
469 | {file = "mypy-1.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:031fc69c9a7e12bcc5660b74122ed84b3f1c505e762cc4296884096c6d8ee140"},
470 | {file = "mypy-1.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:390bc685ec209ada4e9d35068ac6988c60160b2b703072d2850457b62499e336"},
471 | {file = "mypy-1.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4b41412df69ec06ab141808d12e0bf2823717b1c363bd77b4c0820feaa37249e"},
472 | {file = "mypy-1.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4e4a682b3f2489d218751981639cffc4e281d548f9d517addfd5a2917ac78119"},
473 | {file = "mypy-1.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a197ad3a774f8e74f21e428f0de7f60ad26a8d23437b69638aac2764d1e06a6a"},
474 | {file = "mypy-1.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c9a084bce1061e55cdc0493a2ad890375af359c766b8ac311ac8120d3a472950"},
475 | {file = "mypy-1.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaeaa0888b7f3ccb7bcd40b50497ca30923dba14f385bde4af78fac713d6d6f6"},
476 | {file = "mypy-1.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bea55fc25b96c53affab852ad94bf111a3083bc1d8b0c76a61dd101d8a388cf5"},
477 | {file = "mypy-1.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:4c8d8c6b80aa4a1689f2a179d31d86ae1367ea4a12855cc13aa3ba24bb36b2d8"},
478 | {file = "mypy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:70894c5345bea98321a2fe84df35f43ee7bb0feec117a71420c60459fc3e1eed"},
479 | {file = "mypy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4a99fe1768925e4a139aace8f3fb66db3576ee1c30b9c0f70f744ead7e329c9f"},
480 | {file = "mypy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:023fe9e618182ca6317ae89833ba422c411469156b690fde6a315ad10695a521"},
481 | {file = "mypy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4d19f1a239d59f10fdc31263d48b7937c585810288376671eaf75380b074f238"},
482 | {file = "mypy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:2de7babe398cb7a85ac7f1fd5c42f396c215ab3eff731b4d761d68d0f6a80f48"},
483 | {file = "mypy-1.2.0-py3-none-any.whl", hash = "sha256:d8e9187bfcd5ffedbe87403195e1fc340189a68463903c39e2b63307c9fa0394"},
484 | {file = "mypy-1.2.0.tar.gz", hash = "sha256:f70a40410d774ae23fcb4afbbeca652905a04de7948eaf0b1789c8d1426b72d1"},
485 | ]
486 |
487 | [package.dependencies]
488 | mypy-extensions = ">=1.0.0"
489 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
490 | typing-extensions = ">=3.10"
491 |
492 | [package.extras]
493 | dmypy = ["psutil (>=4.0)"]
494 | install-types = ["pip"]
495 | python2 = ["typed-ast (>=1.4.0,<2)"]
496 | reports = ["lxml"]
497 |
498 | [[package]]
499 | name = "mypy-extensions"
500 | version = "1.0.0"
501 | description = "Type system extensions for programs checked with the mypy type checker."
502 | category = "dev"
503 | optional = false
504 | python-versions = ">=3.5"
505 | files = [
506 | {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
507 | {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
508 | ]
509 |
510 | [[package]]
511 | name = "packaging"
512 | version = "23.0"
513 | description = "Core utilities for Python packages"
514 | category = "dev"
515 | optional = false
516 | python-versions = ">=3.7"
517 | files = [
518 | {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"},
519 | {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"},
520 | ]
521 |
522 | [[package]]
523 | name = "pathspec"
524 | version = "0.11.1"
525 | description = "Utility library for gitignore style pattern matching of file paths."
526 | category = "dev"
527 | optional = false
528 | python-versions = ">=3.7"
529 | files = [
530 | {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"},
531 | {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
532 | ]
533 |
534 | [[package]]
535 | name = "platformdirs"
536 | version = "3.2.0"
537 | description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
538 | category = "dev"
539 | optional = false
540 | python-versions = ">=3.7"
541 | files = [
542 | {file = "platformdirs-3.2.0-py3-none-any.whl", hash = "sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e"},
543 | {file = "platformdirs-3.2.0.tar.gz", hash = "sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08"},
544 | ]
545 |
546 | [package.extras]
547 | docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"]
548 | test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
549 |
550 | [[package]]
551 | name = "pluggy"
552 | version = "1.0.0"
553 | description = "plugin and hook calling mechanisms for python"
554 | category = "dev"
555 | optional = false
556 | python-versions = ">=3.6"
557 | files = [
558 | {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
559 | {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
560 | ]
561 |
562 | [package.extras]
563 | dev = ["pre-commit", "tox"]
564 | testing = ["pytest", "pytest-benchmark"]
565 |
566 | [[package]]
567 | name = "pygments"
568 | version = "2.15.0"
569 | description = "Pygments is a syntax highlighting package written in Python."
570 | category = "dev"
571 | optional = false
572 | python-versions = ">=3.7"
573 | files = [
574 | {file = "Pygments-2.15.0-py3-none-any.whl", hash = "sha256:77a3299119af881904cd5ecd1ac6a66214b6e9bed1f2db16993b54adede64094"},
575 | {file = "Pygments-2.15.0.tar.gz", hash = "sha256:f7e36cffc4c517fbc252861b9a6e4644ca0e5abadf9a113c72d1358ad09b9500"},
576 | ]
577 |
578 | [package.extras]
579 | plugins = ["importlib-metadata"]
580 |
581 | [[package]]
582 | name = "pytest"
583 | version = "7.3.0"
584 | description = "pytest: simple powerful testing with Python"
585 | category = "dev"
586 | optional = false
587 | python-versions = ">=3.7"
588 | files = [
589 | {file = "pytest-7.3.0-py3-none-any.whl", hash = "sha256:933051fa1bfbd38a21e73c3960cebdad4cf59483ddba7696c48509727e17f201"},
590 | {file = "pytest-7.3.0.tar.gz", hash = "sha256:58ecc27ebf0ea643ebfdf7fb1249335da761a00c9f955bcd922349bcb68ee57d"},
591 | ]
592 |
593 | [package.dependencies]
594 | colorama = {version = "*", markers = "sys_platform == \"win32\""}
595 | exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
596 | iniconfig = "*"
597 | packaging = "*"
598 | pluggy = ">=0.12,<2.0"
599 | tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
600 |
601 | [package.extras]
602 | testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
603 |
604 | [[package]]
605 | name = "pytest-asyncio"
606 | version = "0.21.0"
607 | description = "Pytest support for asyncio"
608 | category = "dev"
609 | optional = false
610 | python-versions = ">=3.7"
611 | files = [
612 | {file = "pytest-asyncio-0.21.0.tar.gz", hash = "sha256:2b38a496aef56f56b0e87557ec313e11e1ab9276fc3863f6a7be0f1d0e415e1b"},
613 | {file = "pytest_asyncio-0.21.0-py3-none-any.whl", hash = "sha256:f2b3366b7cd501a4056858bd39349d5af19742aed2d81660b7998b6341c7eb9c"},
614 | ]
615 |
616 | [package.dependencies]
617 | pytest = ">=7.0.0"
618 |
619 | [package.extras]
620 | docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"]
621 | testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"]
622 |
623 | [[package]]
624 | name = "pytest-cov"
625 | version = "4.0.0"
626 | description = "Pytest plugin for measuring coverage."
627 | category = "dev"
628 | optional = false
629 | python-versions = ">=3.6"
630 | files = [
631 | {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"},
632 | {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"},
633 | ]
634 |
635 | [package.dependencies]
636 | coverage = {version = ">=5.2.1", extras = ["toml"]}
637 | pytest = ">=4.6"
638 |
639 | [package.extras]
640 | testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"]
641 |
642 | [[package]]
643 | name = "pytest-integration"
644 | version = "0.2.3"
645 | description = "Organizing pytests by integration or not"
646 | category = "dev"
647 | optional = false
648 | python-versions = ">=3.6"
649 | files = [
650 | {file = "pytest_integration-0.2.3-py3-none-any.whl", hash = "sha256:7f59ed1fa1cc8cb240f9495b68bc02c0421cce48589f78e49b7b842231604b12"},
651 | {file = "pytest_integration-0.2.3.tar.gz", hash = "sha256:b00988a5de8a6826af82d4c7a3485b43fbf32c11235e9f4a8b7225eef5fbcf65"},
652 | ]
653 |
654 | [[package]]
655 | name = "pytz"
656 | version = "2023.3"
657 | description = "World timezone definitions, modern and historical"
658 | category = "dev"
659 | optional = false
660 | python-versions = "*"
661 | files = [
662 | {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"},
663 | {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"},
664 | ]
665 |
666 | [[package]]
667 | name = "requests"
668 | version = "2.28.2"
669 | description = "Python HTTP for Humans."
670 | category = "main"
671 | optional = false
672 | python-versions = ">=3.7, <4"
673 | files = [
674 | {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"},
675 | {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"},
676 | ]
677 |
678 | [package.dependencies]
679 | certifi = ">=2017.4.17"
680 | charset-normalizer = ">=2,<4"
681 | idna = ">=2.5,<4"
682 | urllib3 = ">=1.21.1,<1.27"
683 |
684 | [package.extras]
685 | socks = ["PySocks (>=1.5.6,!=1.5.7)"]
686 | use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
687 |
688 | [[package]]
689 | name = "snowballstemmer"
690 | version = "2.2.0"
691 | description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
692 | category = "dev"
693 | optional = false
694 | python-versions = "*"
695 | files = [
696 | {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"},
697 | {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"},
698 | ]
699 |
700 | [[package]]
701 | name = "sphinx"
702 | version = "5.3.0"
703 | description = "Python documentation generator"
704 | category = "dev"
705 | optional = false
706 | python-versions = ">=3.6"
707 | files = [
708 | {file = "Sphinx-5.3.0.tar.gz", hash = "sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5"},
709 | {file = "sphinx-5.3.0-py3-none-any.whl", hash = "sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d"},
710 | ]
711 |
712 | [package.dependencies]
713 | alabaster = ">=0.7,<0.8"
714 | babel = ">=2.9"
715 | colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
716 | docutils = ">=0.14,<0.20"
717 | imagesize = ">=1.3"
718 | importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""}
719 | Jinja2 = ">=3.0"
720 | packaging = ">=21.0"
721 | Pygments = ">=2.12"
722 | requests = ">=2.5.0"
723 | snowballstemmer = ">=2.0"
724 | sphinxcontrib-applehelp = "*"
725 | sphinxcontrib-devhelp = "*"
726 | sphinxcontrib-htmlhelp = ">=2.0.0"
727 | sphinxcontrib-jsmath = "*"
728 | sphinxcontrib-qthelp = "*"
729 | sphinxcontrib-serializinghtml = ">=1.1.5"
730 |
731 | [package.extras]
732 | docs = ["sphinxcontrib-websupport"]
733 | lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.981)", "sphinx-lint", "types-requests", "types-typed-ast"]
734 | test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"]
735 |
736 | [[package]]
737 | name = "sphinxcontrib-applehelp"
738 | version = "1.0.4"
739 | description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books"
740 | category = "dev"
741 | optional = false
742 | python-versions = ">=3.8"
743 | files = [
744 | {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"},
745 | {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"},
746 | ]
747 |
748 | [package.extras]
749 | lint = ["docutils-stubs", "flake8", "mypy"]
750 | test = ["pytest"]
751 |
752 | [[package]]
753 | name = "sphinxcontrib-devhelp"
754 | version = "1.0.2"
755 | description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document."
756 | category = "dev"
757 | optional = false
758 | python-versions = ">=3.5"
759 | files = [
760 | {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"},
761 | {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"},
762 | ]
763 |
764 | [package.extras]
765 | lint = ["docutils-stubs", "flake8", "mypy"]
766 | test = ["pytest"]
767 |
768 | [[package]]
769 | name = "sphinxcontrib-htmlhelp"
770 | version = "2.0.1"
771 | description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
772 | category = "dev"
773 | optional = false
774 | python-versions = ">=3.8"
775 | files = [
776 | {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"},
777 | {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"},
778 | ]
779 |
780 | [package.extras]
781 | lint = ["docutils-stubs", "flake8", "mypy"]
782 | test = ["html5lib", "pytest"]
783 |
784 | [[package]]
785 | name = "sphinxcontrib-jsmath"
786 | version = "1.0.1"
787 | description = "A sphinx extension which renders display math in HTML via JavaScript"
788 | category = "dev"
789 | optional = false
790 | python-versions = ">=3.5"
791 | files = [
792 | {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"},
793 | {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"},
794 | ]
795 |
796 | [package.extras]
797 | test = ["flake8", "mypy", "pytest"]
798 |
799 | [[package]]
800 | name = "sphinxcontrib-qthelp"
801 | version = "1.0.3"
802 | description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document."
803 | category = "dev"
804 | optional = false
805 | python-versions = ">=3.5"
806 | files = [
807 | {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"},
808 | {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"},
809 | ]
810 |
811 | [package.extras]
812 | lint = ["docutils-stubs", "flake8", "mypy"]
813 | test = ["pytest"]
814 |
815 | [[package]]
816 | name = "sphinxcontrib-serializinghtml"
817 | version = "1.1.5"
818 | description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)."
819 | category = "dev"
820 | optional = false
821 | python-versions = ">=3.5"
822 | files = [
823 | {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"},
824 | {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"},
825 | ]
826 |
827 | [package.extras]
828 | lint = ["docutils-stubs", "flake8", "mypy"]
829 | test = ["pytest"]
830 |
831 | [[package]]
832 | name = "tomli"
833 | version = "2.0.1"
834 | description = "A lil' TOML parser"
835 | category = "dev"
836 | optional = false
837 | python-versions = ">=3.7"
838 | files = [
839 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
840 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
841 | ]
842 |
843 | [[package]]
844 | name = "typing-extensions"
845 | version = "4.5.0"
846 | description = "Backported and Experimental Type Hints for Python 3.7+"
847 | category = "dev"
848 | optional = false
849 | python-versions = ">=3.7"
850 | files = [
851 | {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"},
852 | {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"},
853 | ]
854 |
855 | [[package]]
856 | name = "urllib3"
857 | version = "1.26.15"
858 | description = "HTTP library with thread-safe connection pooling, file post, and more."
859 | category = "main"
860 | optional = false
861 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
862 | files = [
863 | {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"},
864 | {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"},
865 | ]
866 |
867 | [package.extras]
868 | brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
869 | secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
870 | socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
871 |
872 | [[package]]
873 | name = "win32-setctime"
874 | version = "1.1.0"
875 | description = "A small Python utility to set file creation time on Windows"
876 | category = "main"
877 | optional = false
878 | python-versions = ">=3.5"
879 | files = [
880 | {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"},
881 | {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"},
882 | ]
883 |
884 | [package.extras]
885 | dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"]
886 |
887 | [[package]]
888 | name = "zipp"
889 | version = "3.15.0"
890 | description = "Backport of pathlib-compatible object wrapper for zip files"
891 | category = "dev"
892 | optional = false
893 | python-versions = ">=3.7"
894 | files = [
895 | {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
896 | {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
897 | ]
898 |
899 | [package.extras]
900 | docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
901 | testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
902 |
903 | [metadata]
904 | lock-version = "2.0"
905 | python-versions = "^3.8"
906 | content-hash = "2d08fc61cdb75e55e9cc0f1f111986e8f60c3486aac4b828463c81421876006b"
907 |
--------------------------------------------------------------------------------
/poetry_template/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MislavJaksic/Python-Project-Template/ed90180b36aafd3f2f883d94b6a70e0187ce1b28/poetry_template/__init__.py
--------------------------------------------------------------------------------
/poetry_template/package_one/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MislavJaksic/Python-Project-Template/ed90180b36aafd3f2f883d94b6a70e0187ce1b28/poetry_template/package_one/__init__.py
--------------------------------------------------------------------------------
/poetry_template/package_one/module_one.py:
--------------------------------------------------------------------------------
1 | """
2 | Application module.
3 | """
4 | from typing import ClassVar
5 |
6 | from poetry_template import settings
7 | from poetry_template.package_two import module_two
8 |
9 |
10 | def get_setting():
11 | return settings.filename
12 |
13 |
14 | def add(x: int, y: int) -> int:
15 | """
16 | Add two numbers using a library.
17 |
18 | :param x: first whole number
19 | :param y: second whole number
20 | """
21 | return module_two.add_two_numbers(x, y)
22 |
23 |
24 | def multiply(x: int, y: int) -> int:
25 | """
26 | Multiply two numbers using a library.
27 |
28 | :param x: first whole number
29 | :param y: second whole number
30 | """
31 | return module_two.multiply_two_numbers(x, y)
32 |
33 |
34 | def raise_exception():
35 | """Raise an exception."""
36 | raise SystemExit(1)
37 |
38 |
39 | class Calculator:
40 | class_field: ClassVar[str] = "class_value"
41 | instance_field: str
42 |
43 | def __init__(self, instance_value: str):
44 | self.instance_field = instance_value
45 |
46 | def multiply(self, a: int, b: int) -> int:
47 | return a * b
48 |
--------------------------------------------------------------------------------
/poetry_template/package_two/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MislavJaksic/Python-Project-Template/ed90180b36aafd3f2f883d94b6a70e0187ce1b28/poetry_template/package_two/__init__.py
--------------------------------------------------------------------------------
/poetry_template/package_two/module_two.py:
--------------------------------------------------------------------------------
1 | """
2 | Library module.
3 | """
4 |
5 |
6 | def add_two_numbers(x: int, y: int) -> int:
7 | """
8 | Add two numbers.
9 |
10 | :param x: first whole number
11 | :param y: second whole number
12 | """
13 | return x + y
14 |
15 |
16 | def multiply_two_numbers(x: int, y: int) -> int:
17 | """
18 | Multiply two numbers.
19 |
20 | :param x: first whole number
21 | :param y: second whole number
22 | """
23 | return x * y
24 |
--------------------------------------------------------------------------------
/poetry_template/profiler.py:
--------------------------------------------------------------------------------
1 | import cProfile
2 |
3 | import runner # noqa
4 |
5 | cProfile.run("runner.main(None)")
6 |
--------------------------------------------------------------------------------
/poetry_template/runner.py:
--------------------------------------------------------------------------------
1 | """
2 | poetry-template.py
3 | ------------------
4 |
5 | Runs the project.
6 |
7 | :copyright: 2019 MislavJaksic
8 | :license: MIT License
9 | """
10 | import argparse
11 | import socket
12 | import sys
13 | from typing import Dict, Any
14 |
15 | from loguru import logger
16 |
17 | from poetry_template.package_one import module_one
18 | from poetry_template.package_one.module_one import raise_exception
19 |
20 | log_message = "who={username}, what={object}/{status}"
21 |
22 |
23 | def main() -> int:
24 | """main() will be run if you run this script directly"""
25 | args = get_cli_arguments()
26 |
27 | setup_loguru()
28 | try:
29 | raise_exception()
30 | except:
31 | logger.exception(log_message, username="1", object=2, status=3)
32 |
33 | print("Command line interface arguments:{}".format(args))
34 | x = args["first"]
35 | y = args["second"]
36 |
37 | print(module_one.add(x, y))
38 | print(module_one.multiply(x, y))
39 |
40 | return 0
41 |
42 |
43 | def get_cli_arguments() -> Dict[str, Any]:
44 | parser = argparse.ArgumentParser(description="Welcome to the command line interface!",
45 | epilog="Thank you for using the program!")
46 |
47 | parser.add_argument("-x", "--first", type=int, required=True, help="First number")
48 | parser.add_argument("-y", "--second", type=int, required=True, help="Second number")
49 | parser.add_argument("-o", "--optional", type=int, nargs='?', const=1, default=1, help="Optional number")
50 | parser.add_argument("-list", "--multiple", action="append", help="Can be specified many times")
51 | parser.add_argument("-tuple", "--triple", nargs=3, metavar=("password", "username", "secret"),
52 | help="(password, username, secret) tuple")
53 | parser.add_argument("-move", "--move", choices=["rock", "paper", "scissors"], help="Can only input a choice")
54 |
55 | return vars(parser.parse_args())
56 |
57 |
58 | def setup_loguru() -> None:
59 | host = socket.gethostname()
60 | ip = socket.gethostbyname(host)
61 |
62 | config = {
63 | "handlers": [
64 | {"sink": sys.stderr, "diagnose": False,
65 | "format": '{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} | {extra[host]}:{extra[ip]} | {process}:{thread} | {module}:{name}:{function}:{line} | {message}'},
66 | # {"sink": "file.log", "retention": "7 days", "compression": "zip", "serialize": True},
67 | ],
68 | "extra": {"host": host, "ip": ip},
69 | }
70 |
71 | logger.configure(**config) # type: ignore
72 |
73 |
74 | def run() -> None:
75 | """Entry point for the runnable script."""
76 | sys.exit(main())
77 |
78 |
79 | if __name__ == "__main__":
80 | """main calls run()."""
81 | run()
82 |
--------------------------------------------------------------------------------
/poetry_template/settings.py:
--------------------------------------------------------------------------------
1 | filename = "text.txt"
2 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "poetry-template"
3 | version = "0.1.5"
4 | description = "A minimal, strictly structured Python project template."
5 |
6 | license = "MIT"
7 | authors = ["Mislav Jaksic "]
8 | maintainers = []
9 | readme = "README.md"
10 |
11 | homepage = "https://github.com/MislavJaksic/Python-Project-Template"
12 | repository = "https://github.com/MislavJaksic/Python-Project-Template"
13 | documentation = "https://github.com/MislavJaksic/Python-Project-Template"
14 |
15 | keywords = []
16 |
17 | classifiers = []
18 |
19 | [tool.poetry.dependencies]
20 | python = "^3.8"
21 | requests = "^2.28.2"
22 | loguru = "^0.7.0"
23 |
24 | [tool.poetry.dev-dependencies]
25 | pytest-cov = "^4.0.0"
26 | pytest = "^7.3.0"
27 | pytest-asyncio = "^0.21.0"
28 | pytest-integration = "0.2.3"
29 | Sphinx = "^5.0.0"
30 | black = "^23.3.0"
31 | mypy = "^1.2.0"
32 |
33 | [tool.poetry.scripts]
34 | poetry-template = "poetry_template.runner:run"
35 |
36 | [tool.mypy]
37 | python_version = "3.8"
38 | ignore_missing_imports = true
39 | # plugins = pydantic.mypy
40 |
41 | [tool.pytest.ini_options]
42 | asyncio_mode = "auto"
43 | testpaths = "tests"
44 |
45 | [build-system]
46 | requires = ["poetry>=0.12"]
47 | build-backend = "poetry.masonry.api"
48 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MislavJaksic/Python-Project-Template/ed90180b36aafd3f2f883d94b6a70e0187ce1b28/tests/__init__.py
--------------------------------------------------------------------------------
/tests/conftest.py:
--------------------------------------------------------------------------------
1 | # pytest only exposes fixtures in a file called conftest.py!
2 |
3 | import pytest
4 |
5 |
6 | @pytest.fixture(scope="package")
7 | def package_level():
8 | yield 1
9 |
10 |
11 | @pytest.fixture(scope="session")
12 | def session_level():
13 | yield 1
14 |
--------------------------------------------------------------------------------
/tests/context.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 |
4 | # Adds "poetry_template" to sys.path
5 | # Now you can do import with "from poetry_template.Sub-Package ..."
6 | sys.path.insert(
7 | 0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "poetry_template"))
8 | )
9 |
--------------------------------------------------------------------------------
/tests/package_one/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MislavJaksic/Python-Project-Template/ed90180b36aafd3f2f883d94b6a70e0187ce1b28/tests/package_one/__init__.py
--------------------------------------------------------------------------------
/tests/package_one/test_module_one.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from poetry_template.package_one import module_one
4 | from poetry_template.package_one.module_one import add
5 | from poetry_template.package_two import module_two
6 |
7 |
8 | @pytest.fixture(scope="function")
9 | def basic_array():
10 | # setup
11 | yield [x for x in range(5)]
12 | # teardown
13 |
14 |
15 | @pytest.fixture(scope="module")
16 | def complex_array():
17 | yield [x for x in range(5)]
18 |
19 |
20 | def test_get_setting():
21 | assert module_one.get_setting() == "text.txt"
22 |
23 |
24 | @pytest.fixture(scope="function")
25 | def calculator():
26 | # setup
27 | calculator = module_one.Calculator("instance_value") # must be imported through module_one due to mocking!
28 | yield calculator
29 | # teardown
30 |
31 |
32 | class MockAdd: # used for mocking complex objects
33 | @staticmethod
34 | def ten():
35 | return 10
36 |
37 |
38 | @pytest.fixture(scope="function")
39 | def mock_add(monkeypatch):
40 | def mock(*args, **kwargs):
41 | return MockAdd().ten()
42 |
43 | monkeypatch.setattr(module_two, "add_two_numbers", mock)
44 |
45 |
46 | class MockCalculator: # used for mocking complex objects
47 | @staticmethod
48 | def multiply(a, b):
49 | return 99
50 |
51 |
52 | @pytest.fixture(scope="function")
53 | def mock_calculator(monkeypatch):
54 | def mock(*args, **kwargs):
55 | return MockCalculator()
56 |
57 | monkeypatch.setattr(module_one, "Calculator", mock)
58 |
59 |
60 | class TestClassForModuleOne:
61 | def test_add(self):
62 | assert module_one.add(1, 5) == 6
63 |
64 | def test_raise_exception(self):
65 | with pytest.raises(SystemExit):
66 | module_one.raise_exception()
67 |
68 |
69 | def test_temporary_directory_file(tmp_path):
70 | dir = tmp_path / "sub_dir"
71 | dir.mkdir()
72 | dir_file = dir / "file.txt"
73 | dir_file.write_text("hello world") # instantiates the file
74 | dir_file.write_text("world, hello")
75 |
76 | assert len(list(tmp_path.iterdir())) == 1
77 | assert dir_file.exists() == True
78 |
79 | assert dir_file.read_text() == "world, hello"
80 |
81 |
82 | def test_manipulate_array(basic_array):
83 | assert len(basic_array) == 5
84 |
85 |
86 | class TestCalculator:
87 | # def __init__(self): # Forbidden by pytest! Use fixtures instead
88 | # self.calculator = module_one.Calculator("instance_value")
89 |
90 | def test_multiply(self, calculator):
91 | assert calculator.multiply(1, 2) == 2
92 |
93 |
94 | class TestMockCalculator:
95 | def test_multiply_mock(self, mock_calculator, calculator): # mock_calculator must come before the real Class!
96 | assert calculator.multiply(1, 2) == 99
97 |
98 |
99 | class TestAddMock:
100 | def test_add_mock(self, mock_add):
101 | result = add(1, 1)
102 | assert result == 10
103 |
--------------------------------------------------------------------------------
/tests/package_two/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MislavJaksic/Python-Project-Template/ed90180b36aafd3f2f883d94b6a70e0187ce1b28/tests/package_two/__init__.py
--------------------------------------------------------------------------------
/tests/package_two/test_module_two.py:
--------------------------------------------------------------------------------
1 | from poetry_template.package_two import module_two
2 |
3 |
4 | class TestClassForModuleTwo:
5 | def test_add_two_numbers(self):
6 | assert module_two.add_two_numbers(1, 5) == 6
7 |
8 | def test_multiply_two_numbers(self):
9 | assert module_two.multiply_two_numbers(2, 4) == 8
10 |
--------------------------------------------------------------------------------