├── src └── design_by_contract │ ├── py.typed │ └── __init__.py ├── doc ├── index.md ├── Makefile └── conf.py ├── .github └── workflows │ ├── pull_requests.yaml │ ├── release.yaml │ └── docs_pages.yaml ├── license.txt ├── .pre-commit-config.yaml ├── pyproject.toml ├── .gitignore ├── Readme.md ├── tests └── test_dbc.py └── poetry.lock /src/design_by_contract/py.typed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/index.md: -------------------------------------------------------------------------------- 1 | ```{include} ../Readme.md 2 | ``` 3 | 4 | ## API 5 | 6 | ```{eval-rst} 7 | .. automodule:: design_by_contract 8 | :members: contract, UnresolvedSymbol, ContractViolationError, ContractLogicError 9 | ``` 10 | 11 | -------------------------------------------------------------------------------- /.github/workflows/pull_requests.yaml: -------------------------------------------------------------------------------- 1 | name: Run tests 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@master 11 | with: 12 | fetch-depth: 0 13 | - uses: actions/setup-python@v3 14 | with: 15 | python-version: 3.10.2 16 | - name: Poetry 17 | uses: abatilo/actions-poetry@v2.1.5 18 | with: 19 | poetry-version: 1.1.13 20 | - name: Installation 21 | run: poetry install 22 | - name: Linting 23 | run: poetry run pre-commit run --all-files 24 | - name: Tests 25 | run: poetry run pytest 26 | -------------------------------------------------------------------------------- /doc/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 = . 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 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Publish release 2 | on: 3 | release: 4 | types: [published] 5 | 6 | jobs: 7 | upload: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@master 12 | with: 13 | fetch-depth: 0 14 | - uses: actions/setup-python@v3 15 | with: 16 | python-version: 3.10.2 17 | - name: Poetry 18 | uses: abatilo/actions-poetry@v2.1.5 19 | with: 20 | poetry-version: 1.1.13 21 | - name: Installation 22 | run: poetry install 23 | - name: Upload 24 | env: 25 | PYPI_USERNAME: __token__ 26 | PYPI_PASSWORD: ${{ secrets.PYPI_TOKEN }} 27 | run: poetry publish --build --username $PYPI_USERNAME --password $PYPI_PASSWORD 28 | -------------------------------------------------------------------------------- /.github/workflows/docs_pages.yaml: -------------------------------------------------------------------------------- 1 | # Found here: https://tomasfarias.dev/posts/sphinx-docs-with-poetry-and-github-pages/ 2 | 3 | name: Docs2Pages 4 | on: 5 | push: 6 | # tags: '*' 7 | branches: 8 | - main 9 | # pull_request: 10 | # branches: 11 | # - main 12 | 13 | jobs: 14 | build-docs: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@master 19 | with: 20 | fetch-depth: 0 21 | - uses: actions/setup-python@v3 22 | with: 23 | python-version: 3.10.2 24 | - uses: abatilo/actions-poetry@v2.1.4 25 | - name: install 26 | run: poetry install 27 | - name: Build documentation 28 | run: | 29 | mkdir gh-pages 30 | touch gh-pages/.nojekyll 31 | cd doc/ 32 | poetry run sphinx-build -b html . _build 33 | cp -r _build/* ../gh-pages/ 34 | - name: Deploy documentation 35 | if: ${{ github.event_name == 'push' }} 36 | uses: JamesIves/github-pages-deploy-action@4.1.4 37 | with: 38 | branch: gh-pages 39 | folder: gh-pages 40 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright 2022 Stefan Ulbrich 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # See https://pre-commit.com for more information 2 | # See https://pre-commit.com/hooks.html for more hooks 3 | # where are the environments stored https://stackoverflow.com/a/62539529 4 | # inspired by https://github.com/pronovic/apologies 5 | repos: 6 | - repo: https://github.com/pre-commit/pre-commit-hooks 7 | rev: v3.2.0 8 | hooks: 9 | - id: trailing-whitespace 10 | files: '.*\.(py|rst|json|yaml)' 11 | - id: end-of-file-fixer 12 | files: '.*\.(py|rst|json|yaml)' 13 | - id: check-yaml 14 | - id: check-added-large-files 15 | - repo: local 16 | hooks: 17 | - id: system 18 | name: Black 19 | entry: poetry run black src tests 20 | pass_filenames: false 21 | language: system 22 | - repo: local 23 | hooks: 24 | - id: system 25 | name: isort 26 | entry: poetry run isort src --profile black 27 | pass_filenames: false 28 | language: system 29 | # - repo: local 30 | # hooks: 31 | # - id: system 32 | # name: Safety 33 | # entry: poetry run safety check 34 | # pass_filenames: false 35 | # language: system 36 | - repo: local 37 | hooks: 38 | - id: system 39 | name: MyPy 40 | entry: poetry run mypy -p design_by_contract 41 | pass_filenames: false 42 | language: system 43 | - repo: local 44 | hooks: 45 | - id: system 46 | name: Pylint 47 | entry: poetry run pylint -j0 design_by_contract --disable=R,C,W 48 | pass_filenames: false 49 | language: system 50 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "design-by-contract" 3 | version = "0.3.1" 4 | description = "Handy decorator to define contracts with dependency injection in Python 3.10 and above" 5 | authors = ["Stefan Ulbrich"] 6 | license = "MIT" 7 | repository = "https://github.com/StefanUlbrich/design-by-contract" 8 | readme = "Readme.md" 9 | 10 | classifiers = [ 11 | "Topic :: Software Development :: Documentation", 12 | "Topic :: Software Development :: Quality Assurance", 13 | "Intended Audience :: Developers", 14 | "Development Status :: 3 - Alpha" 15 | ] 16 | 17 | include = ["license.txt"] 18 | 19 | [tool.poetry.dependencies] 20 | python = "^3.10" 21 | 22 | [tool.poetry.dev-dependencies] 23 | numpy = "^1.23.1" 24 | pandas = "^1.4.0" 25 | pylint = "^2.12.1,!=2.12.2" 26 | black = "^21.12b0" 27 | mypy = "0.971" 28 | pytest = "^6.2.5" 29 | ipykernel = "^6.9.1" 30 | sphinx-book-theme = "^0.2.0" 31 | myst-parser = "^0.17.0" 32 | pre-commit = "^2.17.0" 33 | 34 | [build-system] 35 | requires = ["poetry-core>=1.0.0"] 36 | build-backend = "poetry.core.masonry.api" 37 | 38 | [tool.mypy] 39 | python_version = "3.10" 40 | warn_unused_configs = true 41 | namespace_packages = true 42 | mypy_path = "src" 43 | show_error_codes = true 44 | strict = true 45 | 46 | [tool.isort] 47 | # https://pycqa.github.io/isort/docs/configuration/black_compatibility.html 48 | profile = "black" 49 | 50 | [[tool.mypy.overrides]] 51 | module = "decorator.*" 52 | ignore_missing_imports = true 53 | 54 | [tool.black] 55 | line-length = 120 56 | target_version = ["py310"] 57 | 58 | [tool.pylint.format] 59 | max-line-length=120 60 | 61 | [tool.pylint."MESSAGES CONTROL"] 62 | disable = [ 63 | "missing-module-docstring" 64 | ] 65 | 66 | [tool.pylint.basic] 67 | good-names=['R','i','j','k','ex','Run','_'] 68 | -------------------------------------------------------------------------------- /doc/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 | # sys.path.insert(0, os.path.abspath('.')) 16 | 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'Design by contract' 21 | copyright = '2022, Stefan Ulbrich' 22 | author = 'Stefan Ulbrich' 23 | 24 | # The full version, including alpha/beta/rc tags 25 | release = '0.3.0' 26 | 27 | 28 | # -- General configuration --------------------------------------------------- 29 | 30 | # Add any Sphinx extension module names here, as strings. They can be 31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 32 | # ones. 33 | extensions = [ 34 | "sphinx.ext.autodoc", 35 | "sphinx.ext.autosummary", # https://stackoverflow.com/a/62613202 36 | "sphinx.ext.coverage", 37 | "sphinx.ext.mathjax", 38 | "sphinx.ext.viewcode", 39 | "sphinx.ext.napoleon", 40 | "myst_parser" 41 | ] 42 | 43 | myst_enable_extensions = [ 44 | "dollarmath", 45 | "tasklist" 46 | ] 47 | # Add any paths that contain templates here, relative to this directory. 48 | templates_path = ['_templates'] 49 | 50 | # List of patterns, relative to source directory, that match files and 51 | # directories to ignore when looking for source files. 52 | # This pattern also affects html_static_path and html_extra_path. 53 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 54 | # source_suffix = [".rst", ".md"] # , ".ipynb"] 55 | 56 | 57 | # -- Options for HTML output ------------------------------------------------- 58 | 59 | # The theme to use for HTML and HTML Help pages. See the documentation for 60 | # a list of builtin themes. 61 | # 62 | html_theme = "sphinx_book_theme" 63 | 64 | # Add any paths that contain custom static files (such as style sheets) here, 65 | # relative to this directory. They are copied after the builtin static files, 66 | # so a file named "default.css" will overwrite the builtin "default.css". 67 | html_static_path = ['_static'] 68 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/python,visualstudiocode 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=python,visualstudiocode 4 | 5 | ### Python ### 6 | # Byte-compiled / optimized / DLL files 7 | __pycache__/ 8 | *.py[cod] 9 | *$py.class 10 | 11 | # C extensions 12 | *.so 13 | 14 | # Distribution / packaging 15 | .Python 16 | build/ 17 | develop-eggs/ 18 | dist/ 19 | downloads/ 20 | eggs/ 21 | .eggs/ 22 | lib/ 23 | lib64/ 24 | parts/ 25 | sdist/ 26 | var/ 27 | wheels/ 28 | share/python-wheels/ 29 | *.egg-info/ 30 | .installed.cfg 31 | *.egg 32 | MANIFEST 33 | 34 | # PyInstaller 35 | # Usually these files are written by a python script from a template 36 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 37 | *.manifest 38 | *.spec 39 | 40 | # Installer logs 41 | pip-log.txt 42 | pip-delete-this-directory.txt 43 | 44 | # Unit test / coverage reports 45 | htmlcov/ 46 | .tox/ 47 | .nox/ 48 | .coverage 49 | .coverage.* 50 | .cache 51 | nosetests.xml 52 | coverage.xml 53 | *.cover 54 | *.py,cover 55 | .hypothesis/ 56 | .pytest_cache/ 57 | cover/ 58 | 59 | # Translations 60 | *.mo 61 | *.pot 62 | 63 | # Django stuff: 64 | *.log 65 | local_settings.py 66 | db.sqlite3 67 | db.sqlite3-journal 68 | 69 | # Flask stuff: 70 | instance/ 71 | .webassets-cache 72 | 73 | # Scrapy stuff: 74 | .scrapy 75 | 76 | # Sphinx documentation 77 | docs/_build/ 78 | 79 | # PyBuilder 80 | .pybuilder/ 81 | target/ 82 | 83 | # Jupyter Notebook 84 | .ipynb_checkpoints 85 | 86 | # IPython 87 | profile_default/ 88 | ipython_config.py 89 | 90 | # pyenv 91 | # For a library or package, you might want to ignore these files since the code is 92 | # intended to run in multiple environments; otherwise, check them in: 93 | # .python-version 94 | 95 | # pipenv 96 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 97 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 98 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 99 | # install all needed dependencies. 100 | #Pipfile.lock 101 | 102 | # poetry 103 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 104 | # This is especially recommended for binary packages to ensure reproducibility, and is more 105 | # commonly ignored for libraries. 106 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 107 | #poetry.lock 108 | 109 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 110 | __pypackages__/ 111 | 112 | # Celery stuff 113 | celerybeat-schedule 114 | celerybeat.pid 115 | 116 | # SageMath parsed files 117 | *.sage.py 118 | 119 | # Environments 120 | .env 121 | .venv 122 | env/ 123 | venv/ 124 | ENV/ 125 | env.bak/ 126 | venv.bak/ 127 | 128 | # Spyder project settings 129 | .spyderproject 130 | .spyproject 131 | 132 | # Rope project settings 133 | .ropeproject 134 | 135 | # mkdocs documentation 136 | /site 137 | 138 | # mypy 139 | .mypy_cache/ 140 | .dmypy.json 141 | dmypy.json 142 | 143 | # Pyre type checker 144 | .pyre/ 145 | 146 | # pytype static type analyzer 147 | .pytype/ 148 | 149 | # Cython debug symbols 150 | cython_debug/ 151 | 152 | # PyCharm 153 | # JetBrains specific template is maintainted in a separate JetBrains.gitignore that can 154 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 155 | # and can be added to the global gitignore or merged into this file. For a more nuclear 156 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 157 | #.idea/ 158 | 159 | ### VisualStudioCode ### 160 | .vscode/* 161 | # !.vscode/settings.json 162 | # !.vscode/tasks.json 163 | # !.vscode/launch.json 164 | # !.vscode/extensions.json 165 | # !.vscode/*.code-snippets 166 | 167 | # Local History for Visual Studio Code 168 | .history/ 169 | 170 | # Built Visual Studio Code Extensions 171 | *.vsix 172 | 173 | ### VisualStudioCode Patch ### 174 | # Ignore all local history of files 175 | .history 176 | .ionide 177 | 178 | # Support for Project snippet scope 179 | 180 | # End of https://www.toptal.com/developers/gitignore/api/python,visualstudiocode 181 | 182 | publish.sh 183 | 184 | doc/_build -------------------------------------------------------------------------------- /src/design_by_contract/__init__.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from dataclasses import dataclass 3 | from functools import partial, wraps 4 | from inspect import get_annotations, getfullargspec, signature 5 | from typing import ( 6 | Annotated, 7 | Any, 8 | Callable, 9 | Optional, 10 | ParamSpec, 11 | TypeVar, 12 | Union, 13 | overload, 14 | ) 15 | 16 | logger = logging.getLogger(__name__) 17 | 18 | 19 | class ContractViolationError(Exception): 20 | """Raised when a contract is violated""" 21 | 22 | 23 | class ContractLogicError(Exception): 24 | """Raised when there is a syntactical error""" 25 | 26 | 27 | @dataclass 28 | class UnresolvedSymbol: 29 | """ 30 | Placeholder for unknown symbols in contracts. 31 | 32 | Overrides the equality operator to behave like an 33 | assignment. 34 | """ 35 | 36 | name: str 37 | value: Optional[Any] = None 38 | 39 | def __eq__(self, other: Any) -> Union["UnresolvedSymbol", bool]: # type: ignore[override] 40 | match other: 41 | case UnresolvedSymbol(name=name, value=None): 42 | if self.value is None: 43 | raise ContractViolationError(f"Symbols `{self.name}` and `{name}` undefined") 44 | other.value = self.value 45 | case UnresolvedSymbol(name=_, value=value) if self.value is None: 46 | self.value = value 47 | case UnresolvedSymbol(name=name, value=value) if value != self.value: 48 | raise ContractViolationError( 49 | f"Symbols `{self.name}` and `{name}` do not match: `{self.value}` != `{value}`" 50 | ) 51 | case self.value: 52 | return True 53 | case value if self.value is not None: 54 | raise ContractViolationError( 55 | f"Symbols `{self.name}` and `{other}` do not match: `{self.value}` != `{other}`" 56 | ) 57 | case value: 58 | self.value = value 59 | return self 60 | 61 | def __bool__(self) -> bool: 62 | return self.value is not None 63 | 64 | 65 | P = ParamSpec("P") 66 | R = TypeVar("R") 67 | 68 | 69 | @overload 70 | def contract(func: Callable[P, R]) -> Callable[P, R]: 71 | ... 72 | 73 | 74 | @overload 75 | def contract(*, reserved: str = "x", evaluate: bool = True) -> Callable[[Callable[P, R]], Callable[P, R]]: 76 | ... 77 | 78 | 79 | def contract( 80 | func: Optional[Callable[P, R]] = None, *, reserved: str = "x", evaluate: bool = True 81 | ) -> Union[Callable[[Callable[P, R]], Callable[P, R]], Callable[P, R]]: 82 | """ 83 | A decorator for enabling design by contract using :class:`typing.Annotated`. 84 | 85 | Define contract conditions as lambdas together with their type annotation. 86 | The decorator is overloaded so you can call it eigher with `@contract` or 87 | `@contract(...)` with our without arguments. Note that positional keywords 88 | are not allowed (i.e., you need to use keyword arguments) 89 | 90 | Parameters 91 | ---------- 92 | reserved : str, optional 93 | This symbol gets always replaced by the current argument name, by default "x". 94 | This is a keyword only argument. 95 | evaluate : bool, optional 96 | If False, the contracts are not evaluated, by default True. 97 | This is a keyword only argument. 98 | """ 99 | 100 | def wrapper(func: Callable[P, R], *args: Any, **kw: Any) -> R: 101 | """The actual logic""" 102 | 103 | if not evaluate: 104 | return func(*args, **kw) 105 | 106 | annotations = get_annotations(func) 107 | return_annotation = annotations.pop("return", None) 108 | 109 | if reserved in annotations.keys(): 110 | raise ValueError(f"Argument cannot be the reserved identifier `{reserved}`") 111 | 112 | # Resolved function arguments passed to func 113 | injectables = dict(zip(annotations.keys(), args)) 114 | logger.debug("injectables: %s", injectables) 115 | 116 | def evaluate_annotations(annotations: dict[str, Any]) -> None: 117 | nonlocal injectables 118 | for arg_name, annotation in annotations.items(): 119 | 120 | # Filter for typing.Annotation objects with extra annotations 121 | if hasattr(annotation, "__metadata__"): 122 | for meta in annotation.__metadata__: 123 | # Only consider lambdas/callables 124 | if callable(meta): 125 | meta_args = getfullargspec(meta).args 126 | # Only if the original argument's name is among its argument names 127 | # TODO we shold remove that 128 | if arg_name in meta_args or reserved in meta_args: 129 | 130 | # the reserved identifier is a shortcut 131 | injectables[reserved] = injectables[arg_name] 132 | dependencies = set(injectables.keys()).intersection(meta_args) 133 | logger.debug( 134 | "contract for `%s`, resolved: `%s`", 135 | arg_name, 136 | {i: injectables[i] for i in dependencies}, 137 | ) 138 | 139 | # Look for arguments that cannot be injected 140 | if unresolved := set(meta_args) - set(injectables.keys()): 141 | 142 | symbols = {i: UnresolvedSymbol(i) for i in unresolved} 143 | 144 | logger.debug( 145 | "contract for `%s`, unresolved: `%s`, %s", arg_name, unresolved, symbols 146 | ) 147 | 148 | if not meta(*[(symbols | injectables)[i] for i in meta_args]): 149 | raise ContractViolationError(f"Contract violated for argument: `{arg_name}`") 150 | 151 | if any([i.value is None for i in symbols.values()]): 152 | raise ContractLogicError( 153 | f"Not all symbols were resolved `{symbols}`", 154 | ) 155 | 156 | injectables |= {k: v.value for k, v in symbols.items()} 157 | 158 | else: 159 | 160 | # Evaluate contract by injecting values into the lambda 161 | if not meta(*(_args := [injectables[i] for i in meta_args])): 162 | raise ContractViolationError(f"Contract violated for argument: `{arg_name}`") 163 | 164 | logger.debug("Contract fulfilled for argument `%s`", arg_name) 165 | 166 | evaluate_annotations(annotations) 167 | 168 | result = func(*args, **kw) 169 | 170 | if return_annotation is not None: 171 | injectables["return"] = result 172 | logger.debug(injectables) 173 | evaluate_annotations({"return": return_annotation}) 174 | 175 | return result 176 | 177 | def decorator(func: Callable[P, R]) -> Callable[P, R]: 178 | return wraps(func)(partial(wrapper, func)) 179 | 180 | if func is not None: 181 | if not callable(func): 182 | raise TypeError("Not a callable. Did you use a non-keyword argument?") 183 | return wraps(func)(partial(wrapper, func)) 184 | 185 | return decorator 186 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Welcome to `design-by-contract` 2 | 3 | A minimalistic decorator for the [design by contract pattern](https://en.wikipedia.org/wiki/Design_by_contract) 4 | written in a just little more than 100 lines of modern Python 3.10 code (not counting documentation and logging). 5 | 6 | Contracts are useful to impose restrictions and constraints on function arguments in a way that 7 | 8 | * reduces boilerplate for argument validation in the function body 9 | (no more if blocks that raise value errors), 10 | * are exposed in the function signature, that is, they serve as a means of documentation 11 | that is always up-to-date, 12 | * allow relations between arguments. 13 | 14 | Install with 15 | 16 | ```sh 17 | pip install design-by-contract 18 | ``` 19 | 20 | **Warning** 21 | 22 | This project started as a weekend project to learn recent additions to the language (`typing.Annotated` and `typing.ParamSpec`, the [walrus operator](https://www.python.org/dev/peps/pep-0572/), [pattern matching](https://www.python.org/dev/peps/pep-0636/) and others). This means also that this package and its documentation should be considered as **work in progress**. 23 | You probably shouldn't use it in production yet! But if you do, let me know how it went. Please leave a star if you like this project! 24 | 25 | ## Application 26 | 27 | The decorator has been mainly designed with [numpy arrays](https://numpy.org) and [pandas DataFrames](https://pandas.pydata.org/) 28 | in mind but can be universally applied. 29 | Contracts are defined as lambda functions that are attached to the function arguments via the 30 | [new Annotated type](https://www.python.org/dev/peps/pep-0593/) that allows adding additional information 31 | to the arguments' and return value's type hint. Arguments are inserted into the lambda via 32 | [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection) and working with 33 | symbols to increase readability is supported. 34 | 35 | Let's look at an example for for matrix multiplication! 36 | 37 | ```python 38 | from typing import Annotated 39 | import numpy as np 40 | from design_by_contract import contract 41 | 42 | @contract 43 | def spam( 44 | first: Annotated[np.NDArray[np.floating[Any]], lambda first, m, n: (m, n) == first.shape], # symbols m and n represent the shape of `a` 45 | second: Annotated[np.NDArray[np.floating[Any]], lambda second, n, o: (n, o) == second.shape], # `b` number of columns matches the number of rows of `a` 46 | ) -> Annotated[np.NDArray[np.floating[Any]], lambda x, m, o: x.shape == (m, o)]: # `x` holds the return value. The shape of `x` must equal `x` times `o` 47 | """Matrix multiplication""" 48 | return first @ second 49 | ``` 50 | 51 | Contracts are lambdas with one argument named like the annotated argument. Alternatively, `x` can be used as a shortcut which means 52 | that you cannot use `x` as a function argument unless you choose another reserved (using the `reserved` argument `contractor` decorator). 53 | 54 | ```python 55 | @contract(reserved='y') 56 | def spam( 57 | first: Annotated[np.NDArray[np.floating[Any]], lambda y, m, n: (m, n) == y.shape], 58 | second: Annotated[np.NDArray[np.floating[Any]], lambda y, n, o: (n, o) == y.shape], 59 | ) -> Annotated[np.NDArray[np.floating[Any]], lambda y, m, o: y.shape == (m, o)]: 60 | """Matrix multiplication""" 61 | return first @ second 62 | ``` 63 | 64 | Symbolic calculus is supported to certain degree to make your life easier. The symbols `m`, `n` and `o` are defined in a way 65 | that 66 | 67 | $$ \text spam: R^{m \times x} \times R^{n\times o} \rightarrow R^{m\times o} $$ 68 | 69 | Note however, that this package does **not** intend to be a symbolic calculus package and therefore, there are some strong limitations. 70 | 71 | Python does not allow for assignments (`=`) in a lambda expression and therefore, 72 | the equality operator (`==`) is chosen to act a replacement. Unknown arguments are replaced under the hood by an instance of `UnresolvedSymbol` 73 | that overload this operator. As a consequence, each symbol, therefore has to be first appear in an equality before it can be used *in a different* lambda expression! 74 | 75 | The following example will raise an error for instance: 76 | 77 | ```Python 78 | @contract 79 | def spam( 80 | a: Annotated[np.NDArray[np.floating[Any]], lambda x, m, n: (m, n) == x.shape and m > 2], # you cannot "assign" and use `m` in the same lambda 81 | # Annotated[np.NDArray[np.floating[Any]], lambda x, m, n: (m, n) == x.shape, lambda x, m: m > 2] # this would work 82 | b: Annotated[np.NDArray[np.floating[Any]], lambda x, n, o: (n, o) == x.shape], 83 | ) -> Annotated[np.NDArray[np.floating[Any]], lambda x, m, o: x.shape == (m, o)]: 84 | return a @ b 85 | 86 | spam(a, b) # raises: '>' not supported between instances of 'UnresolvedSymbol' and 'int' 87 | ``` 88 | 89 | This design decision is arguably unclean but allows for elegant contract expressions and a very clean and compact implementation. 90 | Different approaches involving symbolic algebra packages like [sympy](https://www.sympy.org/en/index.html) or parsing a syntax trees were considered but turned out 91 | to be too complex to implement. The next best alternative is using a domain-specific language (DLS) as done in the excellent 92 | [pycontracts](https://github.com/AndreaCensi/contracts) package, which 93 | actually inspired this project. By using python, calculus in the contract can be arbitrarily 94 | complex without the need for extending the DSL (i.e., including python functions): 95 | 96 | ```python 97 | @contract 98 | def spam( 99 | a: Annotated[np.NDArray[np.floating[Any]], lambda x, m, o: (m, o) == x.shape], 100 | b: Annotated[np.NDArray[np.floating[Any]], lambda x, n, o: (n, o) == x.shape], 101 | ) -> Annotated[np.NDArray[np.floating[Any]], lambda x, m,n,o: x.shape == (m+n, o)]: 102 | print(np.vstack((a,b)).shape) 103 | return np.vstack((a,b)) 104 | spam(np.zeros((3, 2)), np.zeros(( 4, 2))) 105 | ``` 106 | 107 | The decorator is also quite handy for being used with pandas data frames: 108 | 109 | ```python 110 | @contract 111 | def spam(a: Annotated[pd.DataFrame, 112 | lambda x, c: c == {'C','B'}, # `x` or the argument name must be passed to the lambda 113 | lambda x, c: c.issubset(x.columns) # Remember, we need to use two lambdas here! 114 | ], 115 | b: Annotated[pd.DataFrame, 116 | lambda x, c: c <= set(x.columns) # equivalent to `issubset` but more elegant 117 | ] 118 | ) -> Annotated[pd.DataFrame, 119 | lambda x, c: c <= set(x.columns)]: 120 | """Matrix multiplication""" 121 | return pd.merge(a,b,on=['B','C']) 122 | 123 | spam(a, b) 124 | ``` 125 | 126 | Note that evaluation is not optimized. In production, you might consider disabling evaluation by passing 127 | `evaluate=False` as a parameter to the `contract` decorator. 128 | 129 | ## Features 130 | 131 | * [x] Simple to used design by contract. Does not require you to learn a domain specific language necessary. 132 | * [x] Uses python language features only. Some of them recently introduced (i.e., in Python 3.10) 133 | * [x] Preconditions written as lambda functions 134 | * [x] Additional symbols can be used to achieve compact contracts 135 | * [x] [Dependency injection](https://en.wikipedia.org/wiki/Dependency_injection) based on argument names 136 | * [x] Pre- and Postconditions 137 | * [x] Encourages static typing 138 | * [x] Does not break your type checking & code completion (tested with [mypy](https://mypy.readthedocs.io/en/stable/) and [visual studio code](https://code.visualstudio.com/)) 139 | * [x] Uses annotations for defining conditions 140 | * [ ] Optional dynamic type checking 141 | * [x] Preserves your docstrings (thanks to [`decorator`](https://github.com/micheles/decorator)). 142 | Plays well with [Sphinx](https://www.sphinx-doc.org/en/master/) 143 | * [x] Small, clean (opinionated) code base 144 | * [x] Implementation in a single file with ~100 lines of code! 145 | * [x] Currently only one runtime dependency! 146 | * [x] Documentation using [sphinx](https://www.sphinx-doc.org/en/master/), [myst](https://myst-parser.readthedocs.io/en/latest/index.html) and [sphinx book](https://sphinx-book-theme.readthedocs.io/en/stable/) 147 | * [x] Tested with pytest 148 | * [x] Type annotations 149 | * [x] code formatted ([black](https://github.com/psf/black)), linted ([pylint](https://pylint.org/)). Linting with [mypy](http://www.mypy-lang.org/) does not support pattern matching yet. 150 | * [x] GitHub action for GitHub pages 151 | * [ ] GitHub action for linting and formatting 152 | * [x] Precommit for linting and formatting 153 | * [ ] Speed. Well.. maybe. I haven't tested it yet. 154 | 155 | ## Why? 156 | 157 | I had the idea a while ago when reading about `typing.Annotated` in the release notes of Python 3.9. 158 | Eventually, it turned out to be a nice, small Weekend project and a welcomed 159 | opportunity to experiment with novel features in Python 3.10. 160 | In addition, it has been a good exercise to practice several aspects of modern and clean Python development and eventually 161 | might serve as an example for new Python developers: 162 | 163 | If you think it's cool, please leave a star. And who knows, it might actually be useful. 164 | 165 | ## Related (active) projects 166 | 167 | It appears that the related (still active) projects have significantly larger code bases 168 | (include parsers for a domain-specific language, automated testing, etc.) but also try to achieve 169 | additional and wider goals (automated testing, pure functions, etc.). The main strength 170 | of this project, in my opinion, lies in its compact codebase and intuitiveness of the 171 | dependency injection. 172 | 173 | * [PyContracts](https://github.com/AndreaCensi/contracts). 174 | Originally inspired this project. Although it requires a domain specific language, it supports implicitly defining variables for array shapes (see below). This package tries to achieve 175 | a similar goal in pure Python but it requires a formal definition of variables. 176 | 177 | ```python 178 | @contract 179 | @contract(a='list[ M ](type(x))', 180 | b='list[ N ](type(x))', 181 | returns='list[M+N](type(x))') 182 | def my_cat_equal(a, b): 183 | ''' Concatenate two lists together. ''' 184 | return a + b 185 | ``` 186 | 187 | * [icontract](https://github.com/Parquery/icontract) and [deal](https://github.com/life4/deal): 188 | Rely on conditions defined as lambdas much like this Project. They don't use the `Annotated` syntax 189 | and their codebases are significantly larger. 190 | 191 | ## Contributions 192 | 193 | Pull requests are welcome! 194 | 195 | ## Changelog 196 | 197 | * v0.3.0 (2022-06-17): Remove dependency to untyped `decorator`, add fully typed replacement 198 | * v0.2.2 (2022-06-16): Bug Fixes and passing Mypy in strict mode (thanks Alex Povel) 199 | * v0.2 (2022-03-05): Simple symbolic support 200 | * v0.1.1 (2022-01-30): Better documentation 201 | * v0.1.0 (2022-01-29): Initial release 202 | 203 | ## License 204 | 205 | MIT License, Copyright 2022 Stefan Ulbrich 206 | -------------------------------------------------------------------------------- /tests/test_dbc.py: -------------------------------------------------------------------------------- 1 | from inspect import signature 2 | from typing import Annotated, Any 3 | 4 | import numpy as np 5 | from numpy.typing import NDArray 6 | import pandas as pd 7 | import pytest 8 | from design_by_contract import contract, ContractViolationError, UnresolvedSymbol 9 | 10 | # pylint: skip-file 11 | class TestNumpy: 12 | def test_matmult_correct(self) -> None: 13 | @contract 14 | def spam( 15 | a: Annotated[NDArray[np.floating[Any]], lambda a, m, n: (m, n) == a.shape], 16 | b: Annotated[NDArray[np.floating[Any]], lambda b, n, o: (n, o) == b.shape], 17 | ) -> Annotated[NDArray[np.floating[Any]], lambda x, m, o: x.shape == (m, o)]: 18 | return a @ b 19 | 20 | spam(np.zeros((3, 2)), np.zeros((2, 4))) 21 | 22 | def test_matmult_correct_shortcut(self) -> None: 23 | @contract 24 | def spam( 25 | a: Annotated[NDArray[np.floating[Any]], lambda x, m, n: (m, n) == x.shape], 26 | b: Annotated[NDArray[np.floating[Any]], lambda x, n, o: (n, o) == x.shape], 27 | ) -> Annotated[NDArray[np.floating[Any]], lambda x, m, o: x.shape == (m, o)]: 28 | return a @ b 29 | 30 | spam(np.zeros((3, 2)), np.zeros((2, 4))) 31 | 32 | def test_matmult_violated_in_return(self) -> None: 33 | @contract 34 | def spam( 35 | a: Annotated[NDArray[np.floating[Any]], lambda x, m, n: (m, n) == x.shape], 36 | b: Annotated[NDArray[np.floating[Any]], lambda x, n, o: (n, o) == x.shape], 37 | ) -> Annotated[NDArray[np.floating[Any]], lambda x, m, n: x.shape == (m, n)]: 38 | return a @ b 39 | 40 | with pytest.raises(ContractViolationError) as exc_info: 41 | spam(np.zeros((3, 2)), np.zeros((2, 4))) 42 | 43 | assert str(exc_info.value) == ("Contract violated for argument: `return`") 44 | 45 | def test_matmult_violated_in_argument(self) -> None: 46 | @contract 47 | def spam( 48 | a: Annotated[NDArray[np.floating[Any]], lambda x, m, n: (m, n) == x.shape], 49 | b: Annotated[NDArray[np.floating[Any]], lambda x, n, o: (n, o) == x.shape], 50 | ) -> Annotated[NDArray[np.floating[Any]], lambda x, m, n: x.shape == (m, n)]: 51 | return a @ b 52 | 53 | with pytest.raises(ContractViolationError) as exc_info: 54 | spam(np.zeros((3, 2)), np.zeros((3, 4))) 55 | 56 | assert str(exc_info.value) == ("Contract violated for argument: `b`") 57 | 58 | def test_matmult_unresolved(self) -> None: 59 | @contract 60 | def spam( 61 | a: Annotated[NDArray[np.floating[Any]], lambda x, m, n: (m, n) == x.shape and m > 2], 62 | b: Annotated[NDArray[np.floating[Any]], lambda x, n, o: (n, o) == x.shape], 63 | ) -> Annotated[NDArray[np.floating[Any]], lambda x, m, o: x.shape == (m, o)]: 64 | return a @ b 65 | 66 | with pytest.raises(TypeError) as exc_info: 67 | spam(np.zeros((3, 2)), np.zeros((2, 4))) 68 | 69 | assert str(exc_info.value) == ("'>' not supported between instances of 'UnresolvedSymbol' and 'int'") 70 | 71 | def test_matmult_multi(self) -> None: 72 | @contract 73 | def spam( 74 | a: Annotated[NDArray[np.floating[Any]], lambda x, m, n: (m, n) == x.shape, lambda x: x.shape[1] == 2], 75 | b: Annotated[NDArray[np.floating[Any]], lambda x, n, o: (n, o) == x.shape], 76 | ) -> Annotated[NDArray[np.floating[Any]], lambda x, m, o: x.shape == (m, o)]: 77 | return a @ b 78 | 79 | spam(np.zeros((3, 2)), np.zeros((2, 4))) 80 | 81 | def test_matmult_mixed(self) -> None: 82 | @contract 83 | def spam( 84 | a: Annotated[NDArray[np.floating[Any]], lambda x, m, n: (m, n) == x.shape and x.shape[1] == 2], 85 | b: Annotated[NDArray[np.floating[Any]], lambda x, n, o: (n, o) == x.shape], 86 | ) -> Annotated[NDArray[np.floating[Any]], lambda x, m, o: x.shape == (m, o)]: 87 | return a @ b 88 | 89 | spam(np.zeros((3, 2)), np.zeros((2, 4))) 90 | 91 | def test_matmult_mixed_2(self) -> None: 92 | @contract 93 | def spam( 94 | a: Annotated[NDArray[np.floating[Any]], lambda x, n: (3, n) == x.shape], 95 | b: Annotated[NDArray[np.floating[Any]], lambda x, n, o: (n, o) == x.shape], 96 | ) -> Annotated[NDArray[np.floating[Any]], lambda x, o: x.shape == (3, o)]: 97 | return a @ b 98 | 99 | spam(np.zeros((3, 2)), np.zeros((2, 4))) 100 | 101 | def test_matmult_mixed_violated(self) -> None: 102 | @contract 103 | def spam( 104 | a: Annotated[NDArray[np.floating[Any]], lambda x, n: (4, n) == x.shape], 105 | b: Annotated[NDArray[np.floating[Any]], lambda x, n, o: (n, o) == x.shape], 106 | ) -> Annotated[NDArray[np.floating[Any]], lambda x, o: x.shape == (3, o)]: 107 | return a @ b 108 | 109 | # Here we would expect a contract violation 110 | # However, n==shape[1] will not be evaluated so the unresolved 111 | # error is raised first 112 | 113 | with pytest.raises(ContractViolationError) as exc_info: 114 | spam(np.zeros((3, 2)), np.zeros((2, 4))) 115 | 116 | assert str(exc_info.value) == ("Contract violated for argument: `a`") 117 | 118 | def test_vstack(self) -> None: 119 | @contract 120 | def spam( 121 | a: Annotated[NDArray[np.floating[Any]], lambda x, m, o: (m, o) == x.shape], 122 | b: Annotated[NDArray[np.floating[Any]], lambda x, n, o: (n, o) == x.shape], 123 | ) -> Annotated[NDArray[np.floating[Any]], lambda x, m, n, o: x.shape == (m + n, o)]: 124 | print(np.vstack((a, b)).shape) 125 | return np.vstack((a, b)) 126 | 127 | spam(np.zeros((3, 2)), np.zeros((4, 2))) 128 | 129 | 130 | class TestGeneral: 131 | def test_docstring(self) -> None: 132 | @contract 133 | def spam( 134 | a: NDArray[np.floating[Any]], b: Annotated[NDArray[np.floating[Any]], lambda b, m: b.shape == (m, 3)] 135 | ) -> None: 136 | """A spam function""" 137 | pass 138 | 139 | assert spam.__doc__ == "A spam function" 140 | 141 | def test_signature(self) -> None: 142 | @contract 143 | def spam( 144 | a: NDArray[np.floating[Any]], b: Annotated[NDArray[np.floating[Any]], lambda b, m: b.shape == (m, 3)] 145 | ) -> None: 146 | pass 147 | 148 | assert ( 149 | "(a: numpy.ndarray[typing.Any, numpy.dtype[numpy.floating[typing.Any]]], " 150 | "b: typing.Annotated[numpy.ndarray[typing.Any, numpy.dtype[numpy.floating[typing.Any]]]," 151 | in str(signature(spam)) 152 | ) 153 | 154 | def test_reserved(self) -> None: 155 | @contract(reserved="y") 156 | def spam( 157 | a: Annotated[NDArray[np.floating[Any]], lambda y, m, n: (m, n) == y.shape], 158 | b: Annotated[NDArray[np.floating[Any]], lambda y, n, o: (n, o) == y.shape], 159 | ) -> Annotated[NDArray[np.floating[Any]], lambda y, m, o: y.shape == (m, o)]: 160 | 161 | return a @ b 162 | 163 | def test_match(self) -> None: 164 | a, b = UnresolvedSymbol("a"), UnresolvedSymbol("b") 165 | a == 2 166 | b == a 167 | assert a.value == b.value 168 | 169 | def test_match_fail(self) -> None: 170 | a, b = UnresolvedSymbol("a"), UnresolvedSymbol("b") 171 | a == 2 172 | b == 1 173 | with pytest.raises(ContractViolationError) as exc_info: 174 | a == b 175 | 176 | def test_match_symmetry(self) -> None: 177 | a, b = UnresolvedSymbol("a"), UnresolvedSymbol("b") 178 | a == 2 179 | assert a.value == 2 180 | 181 | b = UnresolvedSymbol("a") 182 | 2 == b 183 | assert b.value == 2 184 | 185 | def test_match_fail2(self) -> None: 186 | a = UnresolvedSymbol("a") 187 | a == 2 188 | 189 | with pytest.raises(ContractViolationError) as exc_info: 190 | a == 3 191 | 192 | with pytest.raises(ContractViolationError) as exc_info: 193 | 3 == a 194 | 195 | a == 2 196 | 2 == a 197 | 198 | def test_matching(self) -> None: 199 | a = UnresolvedSymbol("a") 200 | b = UnresolvedSymbol("b") 201 | 202 | with pytest.raises(ContractViolationError) as exc_info: 203 | a == b 204 | 205 | assert str(exc_info.value) == ("Symbols `a` and `b` undefined") 206 | 207 | def test_decorator_non_kw(self) -> None: 208 | 209 | with pytest.raises(TypeError) as exc_info: 210 | 211 | @contract("y") # type: ignore 212 | def spam( 213 | a: Annotated[NDArray[np.floating[Any]], lambda y, m, n: (m, n) == y.shape], 214 | b: Annotated[NDArray[np.floating[Any]], lambda y, n, o: (n, o) == y.shape], 215 | ) -> Annotated[NDArray[np.floating[Any]], lambda y, m, o: y.shape == (m, o)]: 216 | 217 | return a @ b 218 | 219 | assert str(exc_info.value) == "Not a callable. Did you use a non-keyword argument?" 220 | 221 | def test_decorator_empty_paranthesis(self) -> None: 222 | @contract() 223 | def spam( 224 | a: Annotated[NDArray[np.floating[Any]], lambda x, m, n: (m, n) == x.shape], 225 | b: Annotated[NDArray[np.floating[Any]], lambda x, n, o: (n, o) == x.shape], 226 | ) -> Annotated[NDArray[np.floating[Any]], lambda x, m, o: x.shape == (m, o)]: 227 | return a @ b 228 | 229 | with pytest.raises(ContractViolationError) as exc_info: 230 | spam(np.zeros((3, 2)), np.zeros((3, 4))) 231 | 232 | assert str(exc_info.value) == ("Contract violated for argument: `b`") 233 | 234 | def test_no_symbols(self) -> None: 235 | @contract 236 | def spam( 237 | a: Annotated[NDArray[np.floating[Any]], lambda a, b: a.shape[1] == b.shape[0]], 238 | b: NDArray[np.floating[Any]], 239 | ) -> Annotated[NDArray[np.floating[Any]], lambda x, a, b: x.shape == (a.shape[0], b.shape[1])]: 240 | return a @ b 241 | 242 | spam(np.zeros((3, 2)), np.zeros((2, 4))) 243 | 244 | 245 | class TestPandas: 246 | def test_pandas_correct(self) -> None: 247 | a = pd.DataFrame(np.random.randint(0, 2, size=(10, 3)), columns=list("ABC")) 248 | b = pd.DataFrame(np.random.randint(0, 3, size=(10, 3)), columns=list("BCD")) 249 | 250 | @contract 251 | def spam( 252 | a: Annotated[pd.DataFrame, lambda x, c: c == {"C", "B"}, lambda x, c: c.issubset(x.columns)], 253 | b: Annotated[pd.DataFrame, lambda x, c: c <= set(x.columns)], 254 | ) -> Annotated[pd.DataFrame, lambda x, c: c <= set(x.columns)]: 255 | return pd.merge(a, b, on=["B", "C"]) 256 | 257 | spam(a, b) 258 | 259 | def test_pandas_violated_argument(self) -> None: 260 | a = pd.DataFrame(np.random.randint(0, 2, size=(10, 3)), columns=list("ABC")) 261 | b = pd.DataFrame(np.random.randint(0, 3, size=(10, 3)), columns=list("CDE")) 262 | 263 | @contract 264 | def spam( 265 | a: Annotated[pd.DataFrame, lambda x, c: c == {"C", "B"}, lambda x, c: c.issubset(x.columns)], 266 | b: Annotated[pd.DataFrame, lambda x, c: c <= set(x.columns)], 267 | ) -> Annotated[pd.DataFrame, lambda x, c: c <= set(x.columns)]: 268 | return pd.merge(a, b, on=["B", "C"]) 269 | 270 | with pytest.raises(ContractViolationError) as exc_info: 271 | spam(a, b) 272 | 273 | assert str(exc_info.value) == ("Contract violated for argument: `b`") 274 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "alabaster" 3 | version = "0.7.12" 4 | description = "A configurable sidebar-enabled Sphinx theme" 5 | category = "dev" 6 | optional = false 7 | python-versions = "*" 8 | 9 | [[package]] 10 | name = "appnope" 11 | version = "0.1.2" 12 | description = "Disable App Nap on macOS >= 10.9" 13 | category = "dev" 14 | optional = false 15 | python-versions = "*" 16 | 17 | [[package]] 18 | name = "astroid" 19 | version = "2.9.3" 20 | description = "An abstract syntax tree for Python with inference support." 21 | category = "dev" 22 | optional = false 23 | python-versions = ">=3.6.2" 24 | 25 | [package.dependencies] 26 | lazy-object-proxy = ">=1.4.0" 27 | wrapt = ">=1.11,<1.14" 28 | 29 | [[package]] 30 | name = "asttokens" 31 | version = "2.0.5" 32 | description = "Annotate AST trees with source code positions" 33 | category = "dev" 34 | optional = false 35 | python-versions = "*" 36 | 37 | [package.dependencies] 38 | six = "*" 39 | 40 | [package.extras] 41 | test = ["astroid", "pytest"] 42 | 43 | [[package]] 44 | name = "atomicwrites" 45 | version = "1.4.0" 46 | description = "Atomic file writes." 47 | category = "dev" 48 | optional = false 49 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 50 | 51 | [[package]] 52 | name = "attrs" 53 | version = "21.4.0" 54 | description = "Classes Without Boilerplate" 55 | category = "dev" 56 | optional = false 57 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 58 | 59 | [package.extras] 60 | dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] 61 | docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] 62 | tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] 63 | tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] 64 | 65 | [[package]] 66 | name = "babel" 67 | version = "2.9.1" 68 | description = "Internationalization utilities" 69 | category = "dev" 70 | optional = false 71 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 72 | 73 | [package.dependencies] 74 | pytz = ">=2015.7" 75 | 76 | [[package]] 77 | name = "backcall" 78 | version = "0.2.0" 79 | description = "Specifications for callback functions passed in to an API" 80 | category = "dev" 81 | optional = false 82 | python-versions = "*" 83 | 84 | [[package]] 85 | name = "beautifulsoup4" 86 | version = "4.10.0" 87 | description = "Screen-scraping library" 88 | category = "dev" 89 | optional = false 90 | python-versions = ">3.0.0" 91 | 92 | [package.dependencies] 93 | soupsieve = ">1.2" 94 | 95 | [package.extras] 96 | html5lib = ["html5lib"] 97 | lxml = ["lxml"] 98 | 99 | [[package]] 100 | name = "black" 101 | version = "21.12b0" 102 | description = "The uncompromising code formatter." 103 | category = "dev" 104 | optional = false 105 | python-versions = ">=3.6.2" 106 | 107 | [package.dependencies] 108 | click = ">=7.1.2" 109 | mypy-extensions = ">=0.4.3" 110 | pathspec = ">=0.9.0,<1" 111 | platformdirs = ">=2" 112 | tomli = ">=0.2.6,<2.0.0" 113 | typing-extensions = [ 114 | {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}, 115 | {version = "!=3.10.0.1", markers = "python_version >= \"3.10\""}, 116 | ] 117 | 118 | [package.extras] 119 | colorama = ["colorama (>=0.4.3)"] 120 | d = ["aiohttp (>=3.7.4)"] 121 | jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] 122 | python2 = ["typed-ast (>=1.4.3)"] 123 | uvloop = ["uvloop (>=0.15.2)"] 124 | 125 | [[package]] 126 | name = "certifi" 127 | version = "2021.10.8" 128 | description = "Python package for providing Mozilla's CA Bundle." 129 | category = "dev" 130 | optional = false 131 | python-versions = "*" 132 | 133 | [[package]] 134 | name = "cffi" 135 | version = "1.15.0" 136 | description = "Foreign Function Interface for Python calling C code." 137 | category = "dev" 138 | optional = false 139 | python-versions = "*" 140 | 141 | [package.dependencies] 142 | pycparser = "*" 143 | 144 | [[package]] 145 | name = "cfgv" 146 | version = "3.3.1" 147 | description = "Validate configuration and produce human readable error messages." 148 | category = "dev" 149 | optional = false 150 | python-versions = ">=3.6.1" 151 | 152 | [[package]] 153 | name = "charset-normalizer" 154 | version = "2.0.12" 155 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 156 | category = "dev" 157 | optional = false 158 | python-versions = ">=3.5.0" 159 | 160 | [package.extras] 161 | unicode_backport = ["unicodedata2"] 162 | 163 | [[package]] 164 | name = "click" 165 | version = "8.0.4" 166 | description = "Composable command line interface toolkit" 167 | category = "dev" 168 | optional = false 169 | python-versions = ">=3.6" 170 | 171 | [package.dependencies] 172 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 173 | 174 | [[package]] 175 | name = "colorama" 176 | version = "0.4.4" 177 | description = "Cross-platform colored terminal text." 178 | category = "dev" 179 | optional = false 180 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 181 | 182 | [[package]] 183 | name = "debugpy" 184 | version = "1.5.1" 185 | description = "An implementation of the Debug Adapter Protocol for Python" 186 | category = "dev" 187 | optional = false 188 | python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" 189 | 190 | [[package]] 191 | name = "decorator" 192 | version = "5.1.1" 193 | description = "Decorators for Humans" 194 | category = "dev" 195 | optional = false 196 | python-versions = ">=3.5" 197 | 198 | [[package]] 199 | name = "distlib" 200 | version = "0.3.4" 201 | description = "Distribution utilities" 202 | category = "dev" 203 | optional = false 204 | python-versions = "*" 205 | 206 | [[package]] 207 | name = "docutils" 208 | version = "0.16" 209 | description = "Docutils -- Python Documentation Utilities" 210 | category = "dev" 211 | optional = false 212 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 213 | 214 | [[package]] 215 | name = "entrypoints" 216 | version = "0.4" 217 | description = "Discover and load entry points from installed packages." 218 | category = "dev" 219 | optional = false 220 | python-versions = ">=3.6" 221 | 222 | [[package]] 223 | name = "executing" 224 | version = "0.8.3" 225 | description = "Get the currently executing AST node of a frame, and other information" 226 | category = "dev" 227 | optional = false 228 | python-versions = "*" 229 | 230 | [[package]] 231 | name = "filelock" 232 | version = "3.6.0" 233 | description = "A platform independent file lock." 234 | category = "dev" 235 | optional = false 236 | python-versions = ">=3.7" 237 | 238 | [package.extras] 239 | docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"] 240 | testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"] 241 | 242 | [[package]] 243 | name = "identify" 244 | version = "2.4.11" 245 | description = "File identification library for Python" 246 | category = "dev" 247 | optional = false 248 | python-versions = ">=3.7" 249 | 250 | [package.extras] 251 | license = ["ukkonen"] 252 | 253 | [[package]] 254 | name = "idna" 255 | version = "3.3" 256 | description = "Internationalized Domain Names in Applications (IDNA)" 257 | category = "dev" 258 | optional = false 259 | python-versions = ">=3.5" 260 | 261 | [[package]] 262 | name = "imagesize" 263 | version = "1.3.0" 264 | description = "Getting image size from png/jpeg/jpeg2000/gif file" 265 | category = "dev" 266 | optional = false 267 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 268 | 269 | [[package]] 270 | name = "iniconfig" 271 | version = "1.1.1" 272 | description = "iniconfig: brain-dead simple config-ini parsing" 273 | category = "dev" 274 | optional = false 275 | python-versions = "*" 276 | 277 | [[package]] 278 | name = "ipykernel" 279 | version = "6.9.1" 280 | description = "IPython Kernel for Jupyter" 281 | category = "dev" 282 | optional = false 283 | python-versions = ">=3.7" 284 | 285 | [package.dependencies] 286 | appnope = {version = "*", markers = "platform_system == \"Darwin\""} 287 | debugpy = ">=1.0.0,<2.0" 288 | ipython = ">=7.23.1" 289 | jupyter-client = "<8.0" 290 | matplotlib-inline = ">=0.1.0,<0.2.0" 291 | nest-asyncio = "*" 292 | tornado = ">=4.2,<7.0" 293 | traitlets = ">=5.1.0,<6.0" 294 | 295 | [package.extras] 296 | test = ["pytest (!=5.3.4)", "pytest-cov", "flaky", "ipyparallel"] 297 | 298 | [[package]] 299 | name = "ipython" 300 | version = "8.1.1" 301 | description = "IPython: Productive Interactive Computing" 302 | category = "dev" 303 | optional = false 304 | python-versions = ">=3.8" 305 | 306 | [package.dependencies] 307 | appnope = {version = "*", markers = "sys_platform == \"darwin\""} 308 | backcall = "*" 309 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 310 | decorator = "*" 311 | jedi = ">=0.16" 312 | matplotlib-inline = "*" 313 | pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} 314 | pickleshare = "*" 315 | prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0" 316 | pygments = ">=2.4.0" 317 | stack-data = "*" 318 | traitlets = ">=5" 319 | 320 | [package.extras] 321 | all = ["black", "Sphinx (>=1.3)", "ipykernel", "nbconvert", "nbformat", "ipywidgets", "notebook", "ipyparallel", "qtconsole", "curio", "matplotlib (!=3.2.0)", "numpy (>=1.19)", "pandas", "pytest", "testpath", "trio", "pytest-asyncio"] 322 | black = ["black"] 323 | doc = ["Sphinx (>=1.3)"] 324 | kernel = ["ipykernel"] 325 | nbconvert = ["nbconvert"] 326 | nbformat = ["nbformat"] 327 | notebook = ["ipywidgets", "notebook"] 328 | parallel = ["ipyparallel"] 329 | qtconsole = ["qtconsole"] 330 | test = ["pytest", "pytest-asyncio", "testpath"] 331 | test_extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.19)", "pandas", "pytest", "testpath", "trio"] 332 | 333 | [[package]] 334 | name = "isort" 335 | version = "5.10.1" 336 | description = "A Python utility / library to sort Python imports." 337 | category = "dev" 338 | optional = false 339 | python-versions = ">=3.6.1,<4.0" 340 | 341 | [package.extras] 342 | pipfile_deprecated_finder = ["pipreqs", "requirementslib"] 343 | requirements_deprecated_finder = ["pipreqs", "pip-api"] 344 | colors = ["colorama (>=0.4.3,<0.5.0)"] 345 | plugins = ["setuptools"] 346 | 347 | [[package]] 348 | name = "jedi" 349 | version = "0.18.1" 350 | description = "An autocompletion tool for Python that can be used for text editors." 351 | category = "dev" 352 | optional = false 353 | python-versions = ">=3.6" 354 | 355 | [package.dependencies] 356 | parso = ">=0.8.0,<0.9.0" 357 | 358 | [package.extras] 359 | qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] 360 | testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"] 361 | 362 | [[package]] 363 | name = "jinja2" 364 | version = "3.0.3" 365 | description = "A very fast and expressive template engine." 366 | category = "dev" 367 | optional = false 368 | python-versions = ">=3.6" 369 | 370 | [package.dependencies] 371 | MarkupSafe = ">=2.0" 372 | 373 | [package.extras] 374 | i18n = ["Babel (>=2.7)"] 375 | 376 | [[package]] 377 | name = "jupyter-client" 378 | version = "7.1.2" 379 | description = "Jupyter protocol implementation and client libraries" 380 | category = "dev" 381 | optional = false 382 | python-versions = ">=3.6.1" 383 | 384 | [package.dependencies] 385 | entrypoints = "*" 386 | jupyter-core = ">=4.6.0" 387 | nest-asyncio = ">=1.5" 388 | python-dateutil = ">=2.1" 389 | pyzmq = ">=13" 390 | tornado = ">=4.1" 391 | traitlets = "*" 392 | 393 | [package.extras] 394 | doc = ["myst-parser", "sphinx (>=1.3.6)", "sphinx-rtd-theme", "sphinxcontrib-github-alt"] 395 | test = ["codecov", "coverage", "ipykernel", "ipython", "mock", "mypy", "pre-commit", "pytest", "pytest-asyncio", "pytest-cov", "pytest-timeout", "jedi (<0.18)"] 396 | 397 | [[package]] 398 | name = "jupyter-core" 399 | version = "4.9.2" 400 | description = "Jupyter core package. A base package on which Jupyter projects rely." 401 | category = "dev" 402 | optional = false 403 | python-versions = ">=3.6" 404 | 405 | [package.dependencies] 406 | pywin32 = {version = ">=1.0", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} 407 | traitlets = "*" 408 | 409 | [[package]] 410 | name = "lazy-object-proxy" 411 | version = "1.7.1" 412 | description = "A fast and thorough lazy object proxy." 413 | category = "dev" 414 | optional = false 415 | python-versions = ">=3.6" 416 | 417 | [[package]] 418 | name = "markdown-it-py" 419 | version = "2.0.1" 420 | description = "Python port of markdown-it. Markdown parsing, done right!" 421 | category = "dev" 422 | optional = false 423 | python-versions = "~=3.6" 424 | 425 | [package.dependencies] 426 | attrs = ">=19,<22" 427 | mdurl = ">=0.1,<1.0" 428 | 429 | [package.extras] 430 | benchmarking = ["psutil", "pytest", "pytest-benchmark (>=3.2,<4.0)"] 431 | code_style = ["pre-commit (==2.6)"] 432 | compare = ["commonmark (>=0.9.1,<0.10.0)", "markdown (>=3.2.2,<3.3.0)", "mistletoe-ebp (>=0.10.0,<0.11.0)", "mistune (>=0.8.4,<0.9.0)", "panflute (>=1.12,<2.0)"] 433 | linkify = ["linkify-it-py (>=1.0,<2.0)"] 434 | plugins = ["mdit-py-plugins"] 435 | rtd = ["myst-nb (==0.13.0a1)", "pyyaml", "sphinx (>=2,<4)", "sphinx-copybutton", "sphinx-panels (>=0.4.0,<0.5.0)", "sphinx-book-theme"] 436 | testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] 437 | 438 | [[package]] 439 | name = "markupsafe" 440 | version = "2.1.0" 441 | description = "Safely add untrusted strings to HTML/XML markup." 442 | category = "dev" 443 | optional = false 444 | python-versions = ">=3.7" 445 | 446 | [[package]] 447 | name = "matplotlib-inline" 448 | version = "0.1.3" 449 | description = "Inline Matplotlib backend for Jupyter" 450 | category = "dev" 451 | optional = false 452 | python-versions = ">=3.5" 453 | 454 | [package.dependencies] 455 | traitlets = "*" 456 | 457 | [[package]] 458 | name = "mccabe" 459 | version = "0.6.1" 460 | description = "McCabe checker, plugin for flake8" 461 | category = "dev" 462 | optional = false 463 | python-versions = "*" 464 | 465 | [[package]] 466 | name = "mdit-py-plugins" 467 | version = "0.3.0" 468 | description = "Collection of plugins for markdown-it-py" 469 | category = "dev" 470 | optional = false 471 | python-versions = "~=3.6" 472 | 473 | [package.dependencies] 474 | markdown-it-py = ">=1.0.0,<3.0.0" 475 | 476 | [package.extras] 477 | code_style = ["pre-commit (==2.6)"] 478 | rtd = ["myst-parser (>=0.14.0,<0.15.0)", "sphinx-book-theme (>=0.1.0,<0.2.0)"] 479 | testing = ["coverage", "pytest (>=3.6,<4)", "pytest-cov", "pytest-regressions"] 480 | 481 | [[package]] 482 | name = "mdurl" 483 | version = "0.1.0" 484 | description = "Markdown URL utilities" 485 | category = "dev" 486 | optional = false 487 | python-versions = ">=3.6" 488 | 489 | [[package]] 490 | name = "mypy" 491 | version = "0.971" 492 | description = "Optional static typing for Python" 493 | category = "dev" 494 | optional = false 495 | python-versions = ">=3.6" 496 | 497 | [package.dependencies] 498 | mypy-extensions = ">=0.4.3" 499 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 500 | typing-extensions = ">=3.10" 501 | 502 | [package.extras] 503 | dmypy = ["psutil (>=4.0)"] 504 | python2 = ["typed-ast (>=1.4.0,<2)"] 505 | reports = ["lxml"] 506 | 507 | [[package]] 508 | name = "mypy-extensions" 509 | version = "0.4.3" 510 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 511 | category = "dev" 512 | optional = false 513 | python-versions = "*" 514 | 515 | [[package]] 516 | name = "myst-parser" 517 | version = "0.17.0" 518 | description = "An extended commonmark compliant parser, with bridges to docutils & sphinx." 519 | category = "dev" 520 | optional = false 521 | python-versions = ">=3.7" 522 | 523 | [package.dependencies] 524 | docutils = ">=0.15,<0.18" 525 | jinja2 = "*" 526 | markdown-it-py = ">=1.0.0,<3.0.0" 527 | mdit-py-plugins = ">=0.3.0,<0.4.0" 528 | pyyaml = "*" 529 | sphinx = ">=3.1,<5" 530 | typing-extensions = "*" 531 | 532 | [package.extras] 533 | code_style = ["pre-commit (>=2.12,<3.0)"] 534 | linkify = ["linkify-it-py (>=1.0,<2.0)"] 535 | rtd = ["ipython", "sphinx-book-theme (>=0.1.0,<0.2.0)", "sphinx-panels (>=0.5.2,<0.6.0)", "sphinxcontrib-bibtex (>=2.1,<3.0)", "sphinxext-rediraffe (>=0.2,<1.0)", "sphinxcontrib.mermaid (>=0.6.3,<0.7.0)", "sphinxext-opengraph (>=0.4.2,<0.5.0)"] 536 | testing = ["beautifulsoup4", "coverage", "docutils (>=0.17.0,<0.18.0)", "pytest (>=6,<7)", "pytest-cov", "pytest-regressions", "pytest-param-files (>=0.3.4,<0.4.0)"] 537 | 538 | [[package]] 539 | name = "nest-asyncio" 540 | version = "1.5.4" 541 | description = "Patch asyncio to allow nested event loops" 542 | category = "dev" 543 | optional = false 544 | python-versions = ">=3.5" 545 | 546 | [[package]] 547 | name = "nodeenv" 548 | version = "1.6.0" 549 | description = "Node.js virtual environment builder" 550 | category = "dev" 551 | optional = false 552 | python-versions = "*" 553 | 554 | [[package]] 555 | name = "numpy" 556 | version = "1.23.1" 557 | description = "NumPy is the fundamental package for array computing with Python." 558 | category = "dev" 559 | optional = false 560 | python-versions = ">=3.8" 561 | 562 | [[package]] 563 | name = "packaging" 564 | version = "21.3" 565 | description = "Core utilities for Python packages" 566 | category = "dev" 567 | optional = false 568 | python-versions = ">=3.6" 569 | 570 | [package.dependencies] 571 | pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" 572 | 573 | [[package]] 574 | name = "pandas" 575 | version = "1.4.1" 576 | description = "Powerful data structures for data analysis, time series, and statistics" 577 | category = "dev" 578 | optional = false 579 | python-versions = ">=3.8" 580 | 581 | [package.dependencies] 582 | numpy = {version = ">=1.21.0", markers = "python_version >= \"3.10\""} 583 | python-dateutil = ">=2.8.1" 584 | pytz = ">=2020.1" 585 | 586 | [package.extras] 587 | test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"] 588 | 589 | [[package]] 590 | name = "parso" 591 | version = "0.8.3" 592 | description = "A Python Parser" 593 | category = "dev" 594 | optional = false 595 | python-versions = ">=3.6" 596 | 597 | [package.extras] 598 | qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] 599 | testing = ["docopt", "pytest (<6.0.0)"] 600 | 601 | [[package]] 602 | name = "pathspec" 603 | version = "0.9.0" 604 | description = "Utility library for gitignore style pattern matching of file paths." 605 | category = "dev" 606 | optional = false 607 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 608 | 609 | [[package]] 610 | name = "pexpect" 611 | version = "4.8.0" 612 | description = "Pexpect allows easy control of interactive console applications." 613 | category = "dev" 614 | optional = false 615 | python-versions = "*" 616 | 617 | [package.dependencies] 618 | ptyprocess = ">=0.5" 619 | 620 | [[package]] 621 | name = "pickleshare" 622 | version = "0.7.5" 623 | description = "Tiny 'shelve'-like database with concurrency support" 624 | category = "dev" 625 | optional = false 626 | python-versions = "*" 627 | 628 | [[package]] 629 | name = "platformdirs" 630 | version = "2.5.1" 631 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 632 | category = "dev" 633 | optional = false 634 | python-versions = ">=3.7" 635 | 636 | [package.extras] 637 | docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] 638 | test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] 639 | 640 | [[package]] 641 | name = "pluggy" 642 | version = "1.0.0" 643 | description = "plugin and hook calling mechanisms for python" 644 | category = "dev" 645 | optional = false 646 | python-versions = ">=3.6" 647 | 648 | [package.extras] 649 | dev = ["pre-commit", "tox"] 650 | testing = ["pytest", "pytest-benchmark"] 651 | 652 | [[package]] 653 | name = "pre-commit" 654 | version = "2.17.0" 655 | description = "A framework for managing and maintaining multi-language pre-commit hooks." 656 | category = "dev" 657 | optional = false 658 | python-versions = ">=3.6.1" 659 | 660 | [package.dependencies] 661 | cfgv = ">=2.0.0" 662 | identify = ">=1.0.0" 663 | nodeenv = ">=0.11.1" 664 | pyyaml = ">=5.1" 665 | toml = "*" 666 | virtualenv = ">=20.0.8" 667 | 668 | [[package]] 669 | name = "prompt-toolkit" 670 | version = "3.0.28" 671 | description = "Library for building powerful interactive command lines in Python" 672 | category = "dev" 673 | optional = false 674 | python-versions = ">=3.6.2" 675 | 676 | [package.dependencies] 677 | wcwidth = "*" 678 | 679 | [[package]] 680 | name = "ptyprocess" 681 | version = "0.7.0" 682 | description = "Run a subprocess in a pseudo terminal" 683 | category = "dev" 684 | optional = false 685 | python-versions = "*" 686 | 687 | [[package]] 688 | name = "pure-eval" 689 | version = "0.2.2" 690 | description = "Safely evaluate AST nodes without side effects" 691 | category = "dev" 692 | optional = false 693 | python-versions = "*" 694 | 695 | [package.extras] 696 | tests = ["pytest"] 697 | 698 | [[package]] 699 | name = "py" 700 | version = "1.11.0" 701 | description = "library with cross-python path, ini-parsing, io, code, log facilities" 702 | category = "dev" 703 | optional = false 704 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 705 | 706 | [[package]] 707 | name = "pycparser" 708 | version = "2.21" 709 | description = "C parser in Python" 710 | category = "dev" 711 | optional = false 712 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 713 | 714 | [[package]] 715 | name = "pydata-sphinx-theme" 716 | version = "0.7.2" 717 | description = "Bootstrap-based Sphinx theme from the PyData community" 718 | category = "dev" 719 | optional = false 720 | python-versions = ">=3.5" 721 | 722 | [package.dependencies] 723 | beautifulsoup4 = "*" 724 | docutils = "!=0.17.0" 725 | sphinx = "*" 726 | 727 | [package.extras] 728 | coverage = ["pytest-cov", "codecov", "sphinx", "numpydoc", "recommonmark", "pandas", "pytest", "pytest-regressions", "beautifulsoup4", "sphinx-sitemap", "jupyter-sphinx", "plotly", "numpy", "xarray", "docutils (==0.16)"] 729 | test = ["sphinx", "numpydoc", "recommonmark", "pandas", "pytest", "pytest-regressions", "beautifulsoup4", "sphinx-sitemap", "jupyter-sphinx", "plotly", "numpy", "xarray", "docutils (==0.16)"] 730 | 731 | [[package]] 732 | name = "pygments" 733 | version = "2.11.2" 734 | description = "Pygments is a syntax highlighting package written in Python." 735 | category = "dev" 736 | optional = false 737 | python-versions = ">=3.5" 738 | 739 | [[package]] 740 | name = "pylint" 741 | version = "2.12.1" 742 | description = "python code static checker" 743 | category = "dev" 744 | optional = false 745 | python-versions = ">=3.6.2" 746 | 747 | [package.dependencies] 748 | astroid = ">=2.9.0,<2.10" 749 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 750 | isort = ">=4.2.5,<6" 751 | mccabe = ">=0.6,<0.7" 752 | platformdirs = ">=2.2.0" 753 | toml = ">=0.9.2" 754 | 755 | [[package]] 756 | name = "pyparsing" 757 | version = "3.0.7" 758 | description = "Python parsing module" 759 | category = "dev" 760 | optional = false 761 | python-versions = ">=3.6" 762 | 763 | [package.extras] 764 | diagrams = ["jinja2", "railroad-diagrams"] 765 | 766 | [[package]] 767 | name = "pytest" 768 | version = "6.2.5" 769 | description = "pytest: simple powerful testing with Python" 770 | category = "dev" 771 | optional = false 772 | python-versions = ">=3.6" 773 | 774 | [package.dependencies] 775 | atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} 776 | attrs = ">=19.2.0" 777 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 778 | iniconfig = "*" 779 | packaging = "*" 780 | pluggy = ">=0.12,<2.0" 781 | py = ">=1.8.2" 782 | toml = "*" 783 | 784 | [package.extras] 785 | testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] 786 | 787 | [[package]] 788 | name = "python-dateutil" 789 | version = "2.8.2" 790 | description = "Extensions to the standard Python datetime module" 791 | category = "dev" 792 | optional = false 793 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" 794 | 795 | [package.dependencies] 796 | six = ">=1.5" 797 | 798 | [[package]] 799 | name = "pytz" 800 | version = "2021.3" 801 | description = "World timezone definitions, modern and historical" 802 | category = "dev" 803 | optional = false 804 | python-versions = "*" 805 | 806 | [[package]] 807 | name = "pywin32" 808 | version = "303" 809 | description = "Python for Window Extensions" 810 | category = "dev" 811 | optional = false 812 | python-versions = "*" 813 | 814 | [[package]] 815 | name = "pyyaml" 816 | version = "6.0" 817 | description = "YAML parser and emitter for Python" 818 | category = "dev" 819 | optional = false 820 | python-versions = ">=3.6" 821 | 822 | [[package]] 823 | name = "pyzmq" 824 | version = "22.3.0" 825 | description = "Python bindings for 0MQ" 826 | category = "dev" 827 | optional = false 828 | python-versions = ">=3.6" 829 | 830 | [package.dependencies] 831 | cffi = {version = "*", markers = "implementation_name == \"pypy\""} 832 | py = {version = "*", markers = "implementation_name == \"pypy\""} 833 | 834 | [[package]] 835 | name = "requests" 836 | version = "2.27.1" 837 | description = "Python HTTP for Humans." 838 | category = "dev" 839 | optional = false 840 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 841 | 842 | [package.dependencies] 843 | certifi = ">=2017.4.17" 844 | charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} 845 | idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} 846 | urllib3 = ">=1.21.1,<1.27" 847 | 848 | [package.extras] 849 | socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] 850 | use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] 851 | 852 | [[package]] 853 | name = "six" 854 | version = "1.16.0" 855 | description = "Python 2 and 3 compatibility utilities" 856 | category = "dev" 857 | optional = false 858 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 859 | 860 | [[package]] 861 | name = "snowballstemmer" 862 | version = "2.2.0" 863 | description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." 864 | category = "dev" 865 | optional = false 866 | python-versions = "*" 867 | 868 | [[package]] 869 | name = "soupsieve" 870 | version = "2.3.1" 871 | description = "A modern CSS selector implementation for Beautiful Soup." 872 | category = "dev" 873 | optional = false 874 | python-versions = ">=3.6" 875 | 876 | [[package]] 877 | name = "sphinx" 878 | version = "4.4.0" 879 | description = "Python documentation generator" 880 | category = "dev" 881 | optional = false 882 | python-versions = ">=3.6" 883 | 884 | [package.dependencies] 885 | alabaster = ">=0.7,<0.8" 886 | babel = ">=1.3" 887 | colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} 888 | docutils = ">=0.14,<0.18" 889 | imagesize = "*" 890 | Jinja2 = ">=2.3" 891 | packaging = "*" 892 | Pygments = ">=2.0" 893 | requests = ">=2.5.0" 894 | snowballstemmer = ">=1.1" 895 | sphinxcontrib-applehelp = "*" 896 | sphinxcontrib-devhelp = "*" 897 | sphinxcontrib-htmlhelp = ">=2.0.0" 898 | sphinxcontrib-jsmath = "*" 899 | sphinxcontrib-qthelp = "*" 900 | sphinxcontrib-serializinghtml = ">=1.1.5" 901 | 902 | [package.extras] 903 | docs = ["sphinxcontrib-websupport"] 904 | lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.931)", "docutils-stubs", "types-typed-ast", "types-requests"] 905 | test = ["pytest", "pytest-cov", "html5lib", "cython", "typed-ast"] 906 | 907 | [[package]] 908 | name = "sphinx-book-theme" 909 | version = "0.2.0" 910 | description = "A clean book theme for scientific explanations and documentation with Sphinx" 911 | category = "dev" 912 | optional = false 913 | python-versions = ">=3.6" 914 | 915 | [package.dependencies] 916 | beautifulsoup4 = ">=4.6.1,<5" 917 | docutils = ">=0.15,<0.17" 918 | pydata-sphinx-theme = ">=0.7.2,<0.8.0" 919 | pyyaml = "*" 920 | sphinx = ">=3,<5" 921 | 922 | [package.extras] 923 | code_style = ["pre-commit (>=2.7.0,<2.8.0)"] 924 | live-dev = ["sphinx-autobuild", "web-compile (>=0.2.1,<0.3.0)"] 925 | sphinx = ["ablog (>=0.10.13,<0.11.0)", "ipywidgets", "folium", "numpy", "matplotlib", "myst-nb (>=0.13,<1.0)", "nbclient", "pandas", "plotly", "sphinx (>=4.0,<5.0)", "sphinx-design", "sphinx-copybutton", "sphinx-togglebutton (>=0.2.1)", "sphinx-thebe", "sphinxcontrib-bibtex (>=2.2,<3.0)", "sphinxext-opengraph"] 926 | testing = ["coverage", "myst-nb (>=0.13,<1.0)", "pytest (>=6.0.1,<6.1.0)", "pytest-cov", "pytest-regressions (>=2.0.1,<2.1.0)", "sphinx-thebe"] 927 | 928 | [[package]] 929 | name = "sphinxcontrib-applehelp" 930 | version = "1.0.2" 931 | description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" 932 | category = "dev" 933 | optional = false 934 | python-versions = ">=3.5" 935 | 936 | [package.extras] 937 | lint = ["flake8", "mypy", "docutils-stubs"] 938 | test = ["pytest"] 939 | 940 | [[package]] 941 | name = "sphinxcontrib-devhelp" 942 | version = "1.0.2" 943 | description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." 944 | category = "dev" 945 | optional = false 946 | python-versions = ">=3.5" 947 | 948 | [package.extras] 949 | lint = ["flake8", "mypy", "docutils-stubs"] 950 | test = ["pytest"] 951 | 952 | [[package]] 953 | name = "sphinxcontrib-htmlhelp" 954 | version = "2.0.0" 955 | description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" 956 | category = "dev" 957 | optional = false 958 | python-versions = ">=3.6" 959 | 960 | [package.extras] 961 | lint = ["flake8", "mypy", "docutils-stubs"] 962 | test = ["pytest", "html5lib"] 963 | 964 | [[package]] 965 | name = "sphinxcontrib-jsmath" 966 | version = "1.0.1" 967 | description = "A sphinx extension which renders display math in HTML via JavaScript" 968 | category = "dev" 969 | optional = false 970 | python-versions = ">=3.5" 971 | 972 | [package.extras] 973 | test = ["pytest", "flake8", "mypy"] 974 | 975 | [[package]] 976 | name = "sphinxcontrib-qthelp" 977 | version = "1.0.3" 978 | description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." 979 | category = "dev" 980 | optional = false 981 | python-versions = ">=3.5" 982 | 983 | [package.extras] 984 | lint = ["flake8", "mypy", "docutils-stubs"] 985 | test = ["pytest"] 986 | 987 | [[package]] 988 | name = "sphinxcontrib-serializinghtml" 989 | version = "1.1.5" 990 | description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." 991 | category = "dev" 992 | optional = false 993 | python-versions = ">=3.5" 994 | 995 | [package.extras] 996 | lint = ["flake8", "mypy", "docutils-stubs"] 997 | test = ["pytest"] 998 | 999 | [[package]] 1000 | name = "stack-data" 1001 | version = "0.2.0" 1002 | description = "Extract data from python stack frames and tracebacks for informative displays" 1003 | category = "dev" 1004 | optional = false 1005 | python-versions = "*" 1006 | 1007 | [package.dependencies] 1008 | asttokens = "*" 1009 | executing = "*" 1010 | pure-eval = "*" 1011 | 1012 | [package.extras] 1013 | tests = ["pytest", "typeguard", "pygments", "littleutils", "cython"] 1014 | 1015 | [[package]] 1016 | name = "toml" 1017 | version = "0.10.2" 1018 | description = "Python Library for Tom's Obvious, Minimal Language" 1019 | category = "dev" 1020 | optional = false 1021 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 1022 | 1023 | [[package]] 1024 | name = "tomli" 1025 | version = "1.2.3" 1026 | description = "A lil' TOML parser" 1027 | category = "dev" 1028 | optional = false 1029 | python-versions = ">=3.6" 1030 | 1031 | [[package]] 1032 | name = "tornado" 1033 | version = "6.1" 1034 | description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." 1035 | category = "dev" 1036 | optional = false 1037 | python-versions = ">= 3.5" 1038 | 1039 | [[package]] 1040 | name = "traitlets" 1041 | version = "5.1.1" 1042 | description = "Traitlets Python configuration system" 1043 | category = "dev" 1044 | optional = false 1045 | python-versions = ">=3.7" 1046 | 1047 | [package.extras] 1048 | test = ["pytest"] 1049 | 1050 | [[package]] 1051 | name = "typing-extensions" 1052 | version = "4.1.1" 1053 | description = "Backported and Experimental Type Hints for Python 3.6+" 1054 | category = "dev" 1055 | optional = false 1056 | python-versions = ">=3.6" 1057 | 1058 | [[package]] 1059 | name = "urllib3" 1060 | version = "1.26.8" 1061 | description = "HTTP library with thread-safe connection pooling, file post, and more." 1062 | category = "dev" 1063 | optional = false 1064 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" 1065 | 1066 | [package.extras] 1067 | brotli = ["brotlipy (>=0.6.0)"] 1068 | secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] 1069 | socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] 1070 | 1071 | [[package]] 1072 | name = "virtualenv" 1073 | version = "20.13.3" 1074 | description = "Virtual Python Environment builder" 1075 | category = "dev" 1076 | optional = false 1077 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 1078 | 1079 | [package.dependencies] 1080 | distlib = ">=0.3.1,<1" 1081 | filelock = ">=3.2,<4" 1082 | platformdirs = ">=2,<3" 1083 | six = ">=1.9.0,<2" 1084 | 1085 | [package.extras] 1086 | docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] 1087 | testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] 1088 | 1089 | [[package]] 1090 | name = "wcwidth" 1091 | version = "0.2.5" 1092 | description = "Measures the displayed width of unicode strings in a terminal" 1093 | category = "dev" 1094 | optional = false 1095 | python-versions = "*" 1096 | 1097 | [[package]] 1098 | name = "wrapt" 1099 | version = "1.13.3" 1100 | description = "Module for decorators, wrappers and monkey patching." 1101 | category = "dev" 1102 | optional = false 1103 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 1104 | 1105 | [metadata] 1106 | lock-version = "1.1" 1107 | python-versions = "^3.10" 1108 | content-hash = "c01fee18b25566e033fabf841a1fd83968df88c9ff737c8b06ff24862707d676" 1109 | 1110 | [metadata.files] 1111 | alabaster = [ 1112 | {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, 1113 | {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, 1114 | ] 1115 | appnope = [ 1116 | {file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"}, 1117 | {file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"}, 1118 | ] 1119 | astroid = [ 1120 | {file = "astroid-2.9.3-py3-none-any.whl", hash = "sha256:506daabe5edffb7e696ad82483ad0228245a9742ed7d2d8c9cdb31537decf9f6"}, 1121 | {file = "astroid-2.9.3.tar.gz", hash = "sha256:1efdf4e867d4d8ba4a9f6cf9ce07cd182c4c41de77f23814feb27ca93ca9d877"}, 1122 | ] 1123 | asttokens = [ 1124 | {file = "asttokens-2.0.5-py2.py3-none-any.whl", hash = "sha256:0844691e88552595a6f4a4281a9f7f79b8dd45ca4ccea82e5e05b4bbdb76705c"}, 1125 | {file = "asttokens-2.0.5.tar.gz", hash = "sha256:9a54c114f02c7a9480d56550932546a3f1fe71d8a02f1bc7ccd0ee3ee35cf4d5"}, 1126 | ] 1127 | atomicwrites = [ 1128 | {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, 1129 | {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, 1130 | ] 1131 | attrs = [ 1132 | {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, 1133 | {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, 1134 | ] 1135 | babel = [ 1136 | {file = "Babel-2.9.1-py2.py3-none-any.whl", hash = "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9"}, 1137 | {file = "Babel-2.9.1.tar.gz", hash = "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0"}, 1138 | ] 1139 | backcall = [ 1140 | {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, 1141 | {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, 1142 | ] 1143 | beautifulsoup4 = [ 1144 | {file = "beautifulsoup4-4.10.0-py3-none-any.whl", hash = "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf"}, 1145 | {file = "beautifulsoup4-4.10.0.tar.gz", hash = "sha256:c23ad23c521d818955a4151a67d81580319d4bf548d3d49f4223ae041ff98891"}, 1146 | ] 1147 | black = [ 1148 | {file = "black-21.12b0-py3-none-any.whl", hash = "sha256:a615e69ae185e08fdd73e4715e260e2479c861b5740057fde6e8b4e3b7dd589f"}, 1149 | {file = "black-21.12b0.tar.gz", hash = "sha256:77b80f693a569e2e527958459634f18df9b0ba2625ba4e0c2d5da5be42e6f2b3"}, 1150 | ] 1151 | certifi = [ 1152 | {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, 1153 | {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, 1154 | ] 1155 | cffi = [ 1156 | {file = "cffi-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962"}, 1157 | {file = "cffi-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0"}, 1158 | {file = "cffi-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14"}, 1159 | {file = "cffi-1.15.0-cp27-cp27m-win32.whl", hash = "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474"}, 1160 | {file = "cffi-1.15.0-cp27-cp27m-win_amd64.whl", hash = "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6"}, 1161 | {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27"}, 1162 | {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023"}, 1163 | {file = "cffi-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2"}, 1164 | {file = "cffi-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e"}, 1165 | {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7"}, 1166 | {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3"}, 1167 | {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c"}, 1168 | {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962"}, 1169 | {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382"}, 1170 | {file = "cffi-1.15.0-cp310-cp310-win32.whl", hash = "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55"}, 1171 | {file = "cffi-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0"}, 1172 | {file = "cffi-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e"}, 1173 | {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39"}, 1174 | {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc"}, 1175 | {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032"}, 1176 | {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8"}, 1177 | {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605"}, 1178 | {file = "cffi-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e"}, 1179 | {file = "cffi-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc"}, 1180 | {file = "cffi-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636"}, 1181 | {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4"}, 1182 | {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997"}, 1183 | {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b"}, 1184 | {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2"}, 1185 | {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7"}, 1186 | {file = "cffi-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66"}, 1187 | {file = "cffi-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029"}, 1188 | {file = "cffi-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880"}, 1189 | {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20"}, 1190 | {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024"}, 1191 | {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e"}, 1192 | {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728"}, 1193 | {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6"}, 1194 | {file = "cffi-1.15.0-cp38-cp38-win32.whl", hash = "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c"}, 1195 | {file = "cffi-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443"}, 1196 | {file = "cffi-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a"}, 1197 | {file = "cffi-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37"}, 1198 | {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a"}, 1199 | {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e"}, 1200 | {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796"}, 1201 | {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df"}, 1202 | {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8"}, 1203 | {file = "cffi-1.15.0-cp39-cp39-win32.whl", hash = "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a"}, 1204 | {file = "cffi-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139"}, 1205 | {file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"}, 1206 | ] 1207 | cfgv = [ 1208 | {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, 1209 | {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, 1210 | ] 1211 | charset-normalizer = [ 1212 | {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, 1213 | {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, 1214 | ] 1215 | click = [ 1216 | {file = "click-8.0.4-py3-none-any.whl", hash = "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1"}, 1217 | {file = "click-8.0.4.tar.gz", hash = "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"}, 1218 | ] 1219 | colorama = [ 1220 | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, 1221 | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, 1222 | ] 1223 | debugpy = [ 1224 | {file = "debugpy-1.5.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:70b422c63a833630c33e3f9cdbd9b6971f8c5afd452697e464339a21bbe862ba"}, 1225 | {file = "debugpy-1.5.1-cp310-cp310-win32.whl", hash = "sha256:3a457ad9c0059a21a6c7d563c1f18e924f5cf90278c722bd50ede6f56b77c7fe"}, 1226 | {file = "debugpy-1.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:5d76a4fd028d8009c3faf1185b4b78ceb2273dd2499447664b03939e0368bb90"}, 1227 | {file = "debugpy-1.5.1-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:16db27b4b91991442f91d73604d32080b30de655aca9ba821b1972ea8171021b"}, 1228 | {file = "debugpy-1.5.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2b073ad5e8d8c488fbb6a116986858bab0c9c4558f28deb8832c7a5a27405bd6"}, 1229 | {file = "debugpy-1.5.1-cp36-cp36m-win32.whl", hash = "sha256:318f81f37341e4e054b4267d39896b73cddb3612ca13b39d7eea45af65165e1d"}, 1230 | {file = "debugpy-1.5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b5b3157372e0e0a1297a8b6b5280bcf1d35a40f436c7973771c972726d1e32d5"}, 1231 | {file = "debugpy-1.5.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:1ec3a086e14bba6c472632025b8fe5bdfbaef2afa1ebd5c6615ce6ed8d89bc67"}, 1232 | {file = "debugpy-1.5.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:26fbe53cca45a608679094791ce587b6e2798acd1d4777a8b303b07622e85182"}, 1233 | {file = "debugpy-1.5.1-cp37-cp37m-win32.whl", hash = "sha256:d876db8c312eeb02d85611e0f696abe66a2c1515e6405943609e725d5ff36f2a"}, 1234 | {file = "debugpy-1.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4404a62fb5332ea5c8c9132290eef50b3a0ba38cecacad5529e969a783bcbdd7"}, 1235 | {file = "debugpy-1.5.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f3a3dca9104aa14fd4210edcce6d9ce2b65bd9618c0b222135a40b9d6e2a9eeb"}, 1236 | {file = "debugpy-1.5.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2df2c373e85871086bd55271c929670cd4e1dba63e94a08d442db830646203b"}, 1237 | {file = "debugpy-1.5.1-cp38-cp38-win32.whl", hash = "sha256:82f5f9ce93af6861a0713f804e62ab390bb12a17f113153e47fea8bbb1dfbe36"}, 1238 | {file = "debugpy-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:17a25ce9d7714f92fc97ef00cc06269d7c2b163094990ada30156ed31d9a5030"}, 1239 | {file = "debugpy-1.5.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:01e98c594b3e66d529e40edf314f849cd1a21f7a013298df58cd8e263bf8e184"}, 1240 | {file = "debugpy-1.5.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f73988422b17f071ad3c4383551ace1ba5ed810cbab5f9c362783d22d40a08dc"}, 1241 | {file = "debugpy-1.5.1-cp39-cp39-win32.whl", hash = "sha256:23df67fc56d59e386c342428a7953c2c06cc226d8525b11319153e96afb65b0c"}, 1242 | {file = "debugpy-1.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:a2aa64f6d2ca7ded8a7e8a4e7cae3bc71866b09876b7b05cecad231779cb9156"}, 1243 | {file = "debugpy-1.5.1-py2.py3-none-any.whl", hash = "sha256:194f95dd3e84568b5489aab5689a3a2c044e8fdc06f1890b8b4f70b6b89f2778"}, 1244 | {file = "debugpy-1.5.1.zip", hash = "sha256:d2b09e91fbd1efa4f4fda121d49af89501beda50c18ed7499712c71a4bf3452e"}, 1245 | ] 1246 | decorator = [ 1247 | {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, 1248 | {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, 1249 | ] 1250 | distlib = [ 1251 | {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, 1252 | {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, 1253 | ] 1254 | docutils = [ 1255 | {file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"}, 1256 | {file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"}, 1257 | ] 1258 | entrypoints = [ 1259 | {file = "entrypoints-0.4-py3-none-any.whl", hash = "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f"}, 1260 | {file = "entrypoints-0.4.tar.gz", hash = "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4"}, 1261 | ] 1262 | executing = [ 1263 | {file = "executing-0.8.3-py2.py3-none-any.whl", hash = "sha256:d1eef132db1b83649a3905ca6dd8897f71ac6f8cac79a7e58a1a09cf137546c9"}, 1264 | {file = "executing-0.8.3.tar.gz", hash = "sha256:c6554e21c6b060590a6d3be4b82fb78f8f0194d809de5ea7df1c093763311501"}, 1265 | ] 1266 | filelock = [ 1267 | {file = "filelock-3.6.0-py3-none-any.whl", hash = "sha256:f8314284bfffbdcfa0ff3d7992b023d4c628ced6feb957351d4c48d059f56bc0"}, 1268 | {file = "filelock-3.6.0.tar.gz", hash = "sha256:9cd540a9352e432c7246a48fe4e8712b10acb1df2ad1f30e8c070b82ae1fed85"}, 1269 | ] 1270 | identify = [] 1271 | idna = [ 1272 | {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, 1273 | {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, 1274 | ] 1275 | imagesize = [ 1276 | {file = "imagesize-1.3.0-py2.py3-none-any.whl", hash = "sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c"}, 1277 | {file = "imagesize-1.3.0.tar.gz", hash = "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d"}, 1278 | ] 1279 | iniconfig = [ 1280 | {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, 1281 | {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, 1282 | ] 1283 | ipykernel = [] 1284 | ipython = [ 1285 | {file = "ipython-8.1.1-py3-none-any.whl", hash = "sha256:6f56bfaeaa3247aa3b9cd3b8cbab3a9c0abf7428392f97b21902d12b2f42a381"}, 1286 | {file = "ipython-8.1.1.tar.gz", hash = "sha256:8138762243c9b3a3ffcf70b37151a2a35c23d3a29f9743878c33624f4207be3d"}, 1287 | ] 1288 | isort = [ 1289 | {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, 1290 | {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, 1291 | ] 1292 | jedi = [ 1293 | {file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"}, 1294 | {file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"}, 1295 | ] 1296 | jinja2 = [ 1297 | {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"}, 1298 | {file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"}, 1299 | ] 1300 | jupyter-client = [ 1301 | {file = "jupyter_client-7.1.2-py3-none-any.whl", hash = "sha256:d56f1c57bef42ff31e61b1185d3348a5b2bcde7c9a05523ae4dbe5ee0871797c"}, 1302 | {file = "jupyter_client-7.1.2.tar.gz", hash = "sha256:4ea61033726c8e579edb55626d8ee2e6bf0a83158ddf3751b8dd46b2c5cd1e96"}, 1303 | ] 1304 | jupyter-core = [ 1305 | {file = "jupyter_core-4.9.2-py3-none-any.whl", hash = "sha256:f875e4d27e202590311d468fa55f90c575f201490bd0c18acabe4e318db4a46d"}, 1306 | {file = "jupyter_core-4.9.2.tar.gz", hash = "sha256:d69baeb9ffb128b8cd2657fcf2703f89c769d1673c851812119e3a2a0e93ad9a"}, 1307 | ] 1308 | lazy-object-proxy = [ 1309 | {file = "lazy-object-proxy-1.7.1.tar.gz", hash = "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4"}, 1310 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb8c5fd1684d60a9902c60ebe276da1f2281a318ca16c1d0a96db28f62e9166b"}, 1311 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a57d51ed2997e97f3b8e3500c984db50a554bb5db56c50b5dab1b41339b37e36"}, 1312 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd45683c3caddf83abbb1249b653a266e7069a09f486daa8863fb0e7496a9fdb"}, 1313 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8561da8b3dd22d696244d6d0d5330618c993a215070f473b699e00cf1f3f6443"}, 1314 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fccdf7c2c5821a8cbd0a9440a456f5050492f2270bd54e94360cac663398739b"}, 1315 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-win32.whl", hash = "sha256:898322f8d078f2654d275124a8dd19b079080ae977033b713f677afcfc88e2b9"}, 1316 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:85b232e791f2229a4f55840ed54706110c80c0a210d076eee093f2b2e33e1bfd"}, 1317 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:46ff647e76f106bb444b4533bb4153c7370cdf52efc62ccfc1a28bdb3cc95442"}, 1318 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12f3bb77efe1367b2515f8cb4790a11cffae889148ad33adad07b9b55e0ab22c"}, 1319 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c19814163728941bb871240d45c4c30d33b8a2e85972c44d4e63dd7107faba44"}, 1320 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:e40f2013d96d30217a51eeb1db28c9ac41e9d0ee915ef9d00da639c5b63f01a1"}, 1321 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2052837718516a94940867e16b1bb10edb069ab475c3ad84fd1e1a6dd2c0fcfc"}, 1322 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win32.whl", hash = "sha256:6a24357267aa976abab660b1d47a34aaf07259a0c3859a34e536f1ee6e76b5bb"}, 1323 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:6aff3fe5de0831867092e017cf67e2750c6a1c7d88d84d2481bd84a2e019ec35"}, 1324 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6a6e94c7b02641d1311228a102607ecd576f70734dc3d5e22610111aeacba8a0"}, 1325 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ce15276a1a14549d7e81c243b887293904ad2d94ad767f42df91e75fd7b5b6"}, 1326 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e368b7f7eac182a59ff1f81d5f3802161932a41dc1b1cc45c1f757dc876b5d2c"}, 1327 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6ecbb350991d6434e1388bee761ece3260e5228952b1f0c46ffc800eb313ff42"}, 1328 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:553b0f0d8dbf21890dd66edd771f9b1b5f51bd912fa5f26de4449bfc5af5e029"}, 1329 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win32.whl", hash = "sha256:c7a683c37a8a24f6428c28c561c80d5f4fd316ddcf0c7cab999b15ab3f5c5c69"}, 1330 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:df2631f9d67259dc9620d831384ed7732a198eb434eadf69aea95ad18c587a28"}, 1331 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07fa44286cda977bd4803b656ffc1c9b7e3bc7dff7d34263446aec8f8c96f88a"}, 1332 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4dca6244e4121c74cc20542c2ca39e5c4a5027c81d112bfb893cf0790f96f57e"}, 1333 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ba172fc5b03978764d1df5144b4ba4ab13290d7bab7a50f12d8117f8630c38"}, 1334 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:043651b6cb706eee4f91854da4a089816a6606c1428fd391573ef8cb642ae4f7"}, 1335 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b9e89b87c707dd769c4ea91f7a31538888aad05c116a59820f28d59b3ebfe25a"}, 1336 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-win32.whl", hash = "sha256:9d166602b525bf54ac994cf833c385bfcc341b364e3ee71e3bf5a1336e677b55"}, 1337 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:8f3953eb575b45480db6568306893f0bd9d8dfeeebd46812aa09ca9579595148"}, 1338 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dd7ed7429dbb6c494aa9bc4e09d94b778a3579be699f9d67da7e6804c422d3de"}, 1339 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70ed0c2b380eb6248abdef3cd425fc52f0abd92d2b07ce26359fcbc399f636ad"}, 1340 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7096a5e0c1115ec82641afbdd70451a144558ea5cf564a896294e346eb611be1"}, 1341 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f769457a639403073968d118bc70110e7dce294688009f5c24ab78800ae56dc8"}, 1342 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:39b0e26725c5023757fc1ab2a89ef9d7ab23b84f9251e28f9cc114d5b59c1b09"}, 1343 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-win32.whl", hash = "sha256:2130db8ed69a48a3440103d4a520b89d8a9405f1b06e2cc81640509e8bf6548f"}, 1344 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61"}, 1345 | {file = "lazy_object_proxy-1.7.1-pp37.pp38-none-any.whl", hash = "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84"}, 1346 | ] 1347 | markdown-it-py = [ 1348 | {file = "markdown-it-py-2.0.1.tar.gz", hash = "sha256:7b5c153ae1ab2cde00a33938bce68f3ad5d68fbe363f946de7d28555bed4e08a"}, 1349 | {file = "markdown_it_py-2.0.1-py3-none-any.whl", hash = "sha256:31974138ca8cafbcb62213f4974b29571b940e78364584729233f59b8dfdb8bd"}, 1350 | ] 1351 | markupsafe = [ 1352 | {file = "MarkupSafe-2.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3028252424c72b2602a323f70fbf50aa80a5d3aa616ea6add4ba21ae9cc9da4c"}, 1353 | {file = "MarkupSafe-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:290b02bab3c9e216da57c1d11d2ba73a9f73a614bbdcc027d299a60cdfabb11a"}, 1354 | {file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e104c0c2b4cd765b4e83909cde7ec61a1e313f8a75775897db321450e928cce"}, 1355 | {file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24c3be29abb6b34052fd26fc7a8e0a49b1ee9d282e3665e8ad09a0a68faee5b3"}, 1356 | {file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204730fd5fe2fe3b1e9ccadb2bd18ba8712b111dcabce185af0b3b5285a7c989"}, 1357 | {file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d3b64c65328cb4cd252c94f83e66e3d7acf8891e60ebf588d7b493a55a1dbf26"}, 1358 | {file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:96de1932237abe0a13ba68b63e94113678c379dca45afa040a17b6e1ad7ed076"}, 1359 | {file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:75bb36f134883fdbe13d8e63b8675f5f12b80bb6627f7714c7d6c5becf22719f"}, 1360 | {file = "MarkupSafe-2.1.0-cp310-cp310-win32.whl", hash = "sha256:4056f752015dfa9828dce3140dbadd543b555afb3252507348c493def166d454"}, 1361 | {file = "MarkupSafe-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:d4e702eea4a2903441f2735799d217f4ac1b55f7d8ad96ab7d4e25417cb0827c"}, 1362 | {file = "MarkupSafe-2.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f0eddfcabd6936558ec020130f932d479930581171368fd728efcfb6ef0dd357"}, 1363 | {file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ddea4c352a488b5e1069069f2f501006b1a4362cb906bee9a193ef1245a7a61"}, 1364 | {file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09c86c9643cceb1d87ca08cdc30160d1b7ab49a8a21564868921959bd16441b8"}, 1365 | {file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0a0abef2ca47b33fb615b491ce31b055ef2430de52c5b3fb19a4042dbc5cadb"}, 1366 | {file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:736895a020e31b428b3382a7887bfea96102c529530299f426bf2e636aacec9e"}, 1367 | {file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:679cbb78914ab212c49c67ba2c7396dc599a8479de51b9a87b174700abd9ea49"}, 1368 | {file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:84ad5e29bf8bab3ad70fd707d3c05524862bddc54dc040982b0dbcff36481de7"}, 1369 | {file = "MarkupSafe-2.1.0-cp37-cp37m-win32.whl", hash = "sha256:8da5924cb1f9064589767b0f3fc39d03e3d0fb5aa29e0cb21d43106519bd624a"}, 1370 | {file = "MarkupSafe-2.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:454ffc1cbb75227d15667c09f164a0099159da0c1f3d2636aa648f12675491ad"}, 1371 | {file = "MarkupSafe-2.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:142119fb14a1ef6d758912b25c4e803c3ff66920635c44078666fe7cc3f8f759"}, 1372 | {file = "MarkupSafe-2.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b2a5a856019d2833c56a3dcac1b80fe795c95f401818ea963594b345929dffa7"}, 1373 | {file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d1fb9b2eec3c9714dd936860850300b51dbaa37404209c8d4cb66547884b7ed"}, 1374 | {file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62c0285e91414f5c8f621a17b69fc0088394ccdaa961ef469e833dbff64bd5ea"}, 1375 | {file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc3150f85e2dbcf99e65238c842d1cfe69d3e7649b19864c1cc043213d9cd730"}, 1376 | {file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f02cf7221d5cd915d7fa58ab64f7ee6dd0f6cddbb48683debf5d04ae9b1c2cc1"}, 1377 | {file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5653619b3eb5cbd35bfba3c12d575db2a74d15e0e1c08bf1db788069d410ce8"}, 1378 | {file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7d2f5d97fcbd004c03df8d8fe2b973fe2b14e7bfeb2cfa012eaa8759ce9a762f"}, 1379 | {file = "MarkupSafe-2.1.0-cp38-cp38-win32.whl", hash = "sha256:3cace1837bc84e63b3fd2dfce37f08f8c18aeb81ef5cf6bb9b51f625cb4e6cd8"}, 1380 | {file = "MarkupSafe-2.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:fabbe18087c3d33c5824cb145ffca52eccd053061df1d79d4b66dafa5ad2a5ea"}, 1381 | {file = "MarkupSafe-2.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:023af8c54fe63530545f70dd2a2a7eed18d07a9a77b94e8bf1e2ff7f252db9a3"}, 1382 | {file = "MarkupSafe-2.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d66624f04de4af8bbf1c7f21cc06649c1c69a7f84109179add573ce35e46d448"}, 1383 | {file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c532d5ab79be0199fa2658e24a02fce8542df196e60665dd322409a03db6a52c"}, 1384 | {file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ec74fada3841b8c5f4c4f197bea916025cb9aa3fe5abf7d52b655d042f956"}, 1385 | {file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c653fde75a6e5eb814d2a0a89378f83d1d3f502ab710904ee585c38888816c"}, 1386 | {file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:961eb86e5be7d0973789f30ebcf6caab60b844203f4396ece27310295a6082c7"}, 1387 | {file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:598b65d74615c021423bd45c2bc5e9b59539c875a9bdb7e5f2a6b92dfcfc268d"}, 1388 | {file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:599941da468f2cf22bf90a84f6e2a65524e87be2fce844f96f2dd9a6c9d1e635"}, 1389 | {file = "MarkupSafe-2.1.0-cp39-cp39-win32.whl", hash = "sha256:e6f7f3f41faffaea6596da86ecc2389672fa949bd035251eab26dc6697451d05"}, 1390 | {file = "MarkupSafe-2.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:b8811d48078d1cf2a6863dafb896e68406c5f513048451cd2ded0473133473c7"}, 1391 | {file = "MarkupSafe-2.1.0.tar.gz", hash = "sha256:80beaf63ddfbc64a0452b841d8036ca0611e049650e20afcb882f5d3c266d65f"}, 1392 | ] 1393 | matplotlib-inline = [ 1394 | {file = "matplotlib-inline-0.1.3.tar.gz", hash = "sha256:a04bfba22e0d1395479f866853ec1ee28eea1485c1d69a6faf00dc3e24ff34ee"}, 1395 | {file = "matplotlib_inline-0.1.3-py3-none-any.whl", hash = "sha256:aed605ba3b72462d64d475a21a9296f400a19c4f74a31b59103d2a99ffd5aa5c"}, 1396 | ] 1397 | mccabe = [ 1398 | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, 1399 | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, 1400 | ] 1401 | mdit-py-plugins = [ 1402 | {file = "mdit-py-plugins-0.3.0.tar.gz", hash = "sha256:ecc24f51eeec6ab7eecc2f9724e8272c2fb191c2e93cf98109120c2cace69750"}, 1403 | {file = "mdit_py_plugins-0.3.0-py3-none-any.whl", hash = "sha256:b1279701cee2dbf50e188d3da5f51fee8d78d038cdf99be57c6b9d1aa93b4073"}, 1404 | ] 1405 | mdurl = [ 1406 | {file = "mdurl-0.1.0-py3-none-any.whl", hash = "sha256:40654d6dcb8d21501ed13c21cc0bd6fc42ff07ceb8be30029e5ae63ebc2ecfda"}, 1407 | {file = "mdurl-0.1.0.tar.gz", hash = "sha256:94873a969008ee48880fb21bad7de0349fef529f3be178969af5817239e9b990"}, 1408 | ] 1409 | mypy = [] 1410 | mypy-extensions = [ 1411 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, 1412 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, 1413 | ] 1414 | myst-parser = [ 1415 | {file = "myst-parser-0.17.0.tar.gz", hash = "sha256:d412347a5cacb77ebc03d7f7ffef050cd61957d46f234313d350e84e24972260"}, 1416 | {file = "myst_parser-0.17.0-py3-none-any.whl", hash = "sha256:555ec2950aba5ae5dac5c162c7e9a43ad4a7291cfac644d8f5f84da8efa6f356"}, 1417 | ] 1418 | nest-asyncio = [ 1419 | {file = "nest_asyncio-1.5.4-py3-none-any.whl", hash = "sha256:3fdd0d6061a2bb16f21fe8a9c6a7945be83521d81a0d15cff52e9edee50101d6"}, 1420 | {file = "nest_asyncio-1.5.4.tar.gz", hash = "sha256:f969f6013a16fadb4adcf09d11a68a4f617c6049d7af7ac2c676110169a63abd"}, 1421 | ] 1422 | nodeenv = [ 1423 | {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"}, 1424 | {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"}, 1425 | ] 1426 | numpy = [] 1427 | packaging = [ 1428 | {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, 1429 | {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, 1430 | ] 1431 | pandas = [ 1432 | {file = "pandas-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3dfb32ed50122fe8c5e7f2b8d97387edd742cc78f9ec36f007ee126cd3720907"}, 1433 | {file = "pandas-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0259cd11e7e6125aaea3af823b80444f3adad6149ff4c97fef760093598b3e34"}, 1434 | {file = "pandas-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:96e9ece5759f9b47ae43794b6359bbc54805d76e573b161ae770c1ea59393106"}, 1435 | {file = "pandas-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:508c99debccd15790d526ce6b1624b97a5e1e4ca5b871319fb0ebfd46b8f4dad"}, 1436 | {file = "pandas-1.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e6a7bbbb7950063bfc942f8794bc3e31697c020a14f1cd8905fc1d28ec674a01"}, 1437 | {file = "pandas-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:c614001129b2a5add5e3677c3a213a9e6fd376204cb8d17c04e84ff7dfc02a73"}, 1438 | {file = "pandas-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:4e1176f45981c8ccc8161bc036916c004ca51037a7ed73f2d2a9857e6dbe654f"}, 1439 | {file = "pandas-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bbb15ad79050e8b8d39ec40dd96a30cd09b886a2ae8848d0df1abba4d5502a67"}, 1440 | {file = "pandas-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6d6ad1da00c7cc7d8dd1559a6ba59ba3973be6b15722d49738b2be0977eb8a0c"}, 1441 | {file = "pandas-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:358b0bc98a5ff067132d23bf7a2242ee95db9ea5b7bbc401cf79205f11502fd3"}, 1442 | {file = "pandas-1.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6105af6533f8b63a43ea9f08a2ede04e8f43e49daef0209ab0d30352bcf08bee"}, 1443 | {file = "pandas-1.4.1-cp38-cp38-win32.whl", hash = "sha256:04dd15d9db538470900c851498e532ef28d4e56bfe72c9523acb32042de43dfb"}, 1444 | {file = "pandas-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:1b384516dbb4e6aae30e3464c2e77c563da5980440fbdfbd0968e3942f8f9d70"}, 1445 | {file = "pandas-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f02e85e6d832be37d7f16cf6ac8bb26b519ace3e5f3235564a91c7f658ab2a43"}, 1446 | {file = "pandas-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0b1a13f647e4209ed7dbb5da3497891d0045da9785327530ab696417ef478f84"}, 1447 | {file = "pandas-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:19f7c632436b1b4f84615c3b127bbd7bc603db95e3d4332ed259dc815c9aaa26"}, 1448 | {file = "pandas-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ea47ba1d6f359680130bd29af497333be6110de8f4c35b9211eec5a5a9630fa"}, 1449 | {file = "pandas-1.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e5a7a1e0ecaac652326af627a3eca84886da9e667d68286866d4e33f6547caf"}, 1450 | {file = "pandas-1.4.1-cp39-cp39-win32.whl", hash = "sha256:1d85d5f6be66dfd6d1d8d13b9535e342a2214260f1852654b19fa4d7b8d1218b"}, 1451 | {file = "pandas-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:3129a35d9dad1d80c234dd78f8f03141b914395d23f97cf92a366dcd19f8f8bf"}, 1452 | {file = "pandas-1.4.1.tar.gz", hash = "sha256:8db93ec98ac7cb5f8ac1420c10f5e3c43533153f253fe7fb6d891cf5aa2b80d2"}, 1453 | ] 1454 | parso = [ 1455 | {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, 1456 | {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, 1457 | ] 1458 | pathspec = [ 1459 | {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, 1460 | {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, 1461 | ] 1462 | pexpect = [ 1463 | {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, 1464 | {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, 1465 | ] 1466 | pickleshare = [ 1467 | {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, 1468 | {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, 1469 | ] 1470 | platformdirs = [ 1471 | {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"}, 1472 | {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"}, 1473 | ] 1474 | pluggy = [ 1475 | {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, 1476 | {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, 1477 | ] 1478 | pre-commit = [] 1479 | prompt-toolkit = [ 1480 | {file = "prompt_toolkit-3.0.28-py3-none-any.whl", hash = "sha256:30129d870dcb0b3b6a53efdc9d0a83ea96162ffd28ffe077e94215b233dc670c"}, 1481 | {file = "prompt_toolkit-3.0.28.tar.gz", hash = "sha256:9f1cd16b1e86c2968f2519d7fb31dd9d669916f515612c269d14e9ed52b51650"}, 1482 | ] 1483 | ptyprocess = [ 1484 | {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, 1485 | {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, 1486 | ] 1487 | pure-eval = [ 1488 | {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, 1489 | {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, 1490 | ] 1491 | py = [ 1492 | {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, 1493 | {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, 1494 | ] 1495 | pycparser = [ 1496 | {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, 1497 | {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, 1498 | ] 1499 | pydata-sphinx-theme = [ 1500 | {file = "pydata-sphinx-theme-0.7.2.tar.gz", hash = "sha256:671df35fcdd290eafbd23d0595e6d359dbe90b2e64e6c3f4dc88276eed4a065e"}, 1501 | {file = "pydata_sphinx_theme-0.7.2-py3-none-any.whl", hash = "sha256:bc1abc45e103b254c6c7a8f2ddabbaf8aa1f0817d85cae65dd163dd554c52700"}, 1502 | ] 1503 | pygments = [ 1504 | {file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"}, 1505 | {file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"}, 1506 | ] 1507 | pylint = [] 1508 | pyparsing = [ 1509 | {file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"}, 1510 | {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"}, 1511 | ] 1512 | pytest = [ 1513 | {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, 1514 | {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, 1515 | ] 1516 | python-dateutil = [ 1517 | {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, 1518 | {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, 1519 | ] 1520 | pytz = [ 1521 | {file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"}, 1522 | {file = "pytz-2021.3.tar.gz", hash = "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"}, 1523 | ] 1524 | pywin32 = [ 1525 | {file = "pywin32-303-cp310-cp310-win32.whl", hash = "sha256:6fed4af057039f309263fd3285d7b8042d41507343cd5fa781d98fcc5b90e8bb"}, 1526 | {file = "pywin32-303-cp310-cp310-win_amd64.whl", hash = "sha256:51cb52c5ec6709f96c3f26e7795b0bf169ee0d8395b2c1d7eb2c029a5008ed51"}, 1527 | {file = "pywin32-303-cp311-cp311-win32.whl", hash = "sha256:d9b5d87ca944eb3aa4cd45516203ead4b37ab06b8b777c54aedc35975dec0dee"}, 1528 | {file = "pywin32-303-cp311-cp311-win_amd64.whl", hash = "sha256:fcf44032f5b14fcda86028cdf49b6ebdaea091230eb0a757282aa656e4732439"}, 1529 | {file = "pywin32-303-cp36-cp36m-win32.whl", hash = "sha256:aad484d52ec58008ca36bd4ad14a71d7dd0a99db1a4ca71072213f63bf49c7d9"}, 1530 | {file = "pywin32-303-cp36-cp36m-win_amd64.whl", hash = "sha256:2a09632916b6bb231ba49983fe989f2f625cea237219530e81a69239cd0c4559"}, 1531 | {file = "pywin32-303-cp37-cp37m-win32.whl", hash = "sha256:b1675d82bcf6dbc96363fca747bac8bff6f6e4a447a4287ac652aa4b9adc796e"}, 1532 | {file = "pywin32-303-cp37-cp37m-win_amd64.whl", hash = "sha256:c268040769b48a13367221fced6d4232ed52f044ffafeda247bd9d2c6bdc29ca"}, 1533 | {file = "pywin32-303-cp38-cp38-win32.whl", hash = "sha256:5f9ec054f5a46a0f4dfd72af2ce1372f3d5a6e4052af20b858aa7df2df7d355b"}, 1534 | {file = "pywin32-303-cp38-cp38-win_amd64.whl", hash = "sha256:793bf74fce164bcffd9d57bb13c2c15d56e43c9542a7b9687b4fccf8f8a41aba"}, 1535 | {file = "pywin32-303-cp39-cp39-win32.whl", hash = "sha256:7d3271c98434617a11921c5ccf74615794d97b079e22ed7773790822735cc352"}, 1536 | {file = "pywin32-303-cp39-cp39-win_amd64.whl", hash = "sha256:79cbb862c11b9af19bcb682891c1b91942ec2ff7de8151e2aea2e175899cda34"}, 1537 | ] 1538 | pyyaml = [ 1539 | {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, 1540 | {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, 1541 | {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, 1542 | {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, 1543 | {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, 1544 | {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, 1545 | {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, 1546 | {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, 1547 | {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, 1548 | {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, 1549 | {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, 1550 | {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, 1551 | {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, 1552 | {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, 1553 | {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, 1554 | {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, 1555 | {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, 1556 | {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, 1557 | {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, 1558 | {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, 1559 | {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, 1560 | {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, 1561 | {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, 1562 | {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, 1563 | {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, 1564 | {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, 1565 | {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, 1566 | {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, 1567 | {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, 1568 | {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, 1569 | {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, 1570 | {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, 1571 | {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, 1572 | ] 1573 | pyzmq = [ 1574 | {file = "pyzmq-22.3.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:6b217b8f9dfb6628f74b94bdaf9f7408708cb02167d644edca33f38746ca12dd"}, 1575 | {file = "pyzmq-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2841997a0d85b998cbafecb4183caf51fd19c4357075dfd33eb7efea57e4c149"}, 1576 | {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f89468059ebc519a7acde1ee50b779019535db8dcf9b8c162ef669257fef7a93"}, 1577 | {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea12133df25e3a6918718fbb9a510c6ee5d3fdd5a346320421aac3882f4feeea"}, 1578 | {file = "pyzmq-22.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c532fd68b93998aab92356be280deec5de8f8fe59cd28763d2cc8a58747b7f"}, 1579 | {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f907c7359ce8bf7f7e63c82f75ad0223384105f5126f313400b7e8004d9b33c3"}, 1580 | {file = "pyzmq-22.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:902319cfe23366595d3fa769b5b751e6ee6750a0a64c5d9f757d624b2ac3519e"}, 1581 | {file = "pyzmq-22.3.0-cp310-cp310-win32.whl", hash = "sha256:67db33bea0a29d03e6eeec55a8190e033318cee3cbc732ba8fd939617cbf762d"}, 1582 | {file = "pyzmq-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7661fc1d5cb73481cf710a1418a4e1e301ed7d5d924f91c67ba84b2a1b89defd"}, 1583 | {file = "pyzmq-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79244b9e97948eaf38695f4b8e6fc63b14b78cc37f403c6642ba555517ac1268"}, 1584 | {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab888624ed68930442a3f3b0b921ad7439c51ba122dbc8c386e6487a658e4a4e"}, 1585 | {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18cd854b423fce44951c3a4d3e686bac8f1243d954f579e120a1714096637cc0"}, 1586 | {file = "pyzmq-22.3.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:de8df0684398bd74ad160afdc2a118ca28384ac6f5e234eb0508858d8d2d9364"}, 1587 | {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:62bcade20813796c426409a3e7423862d50ff0639f5a2a95be4b85b09a618666"}, 1588 | {file = "pyzmq-22.3.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ea5a79e808baef98c48c884effce05c31a0698c1057de8fc1c688891043c1ce1"}, 1589 | {file = "pyzmq-22.3.0-cp36-cp36m-win32.whl", hash = "sha256:3c1895c95be92600233e476fe283f042e71cf8f0b938aabf21b7aafa62a8dac9"}, 1590 | {file = "pyzmq-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:851977788b9caa8ed011f5f643d3ee8653af02c5fc723fa350db5125abf2be7b"}, 1591 | {file = "pyzmq-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4ebed0977f92320f6686c96e9e8dd29eed199eb8d066936bac991afc37cbb70"}, 1592 | {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42abddebe2c6a35180ca549fadc7228d23c1e1f76167c5ebc8a936b5804ea2df"}, 1593 | {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1e41b32d6f7f9c26bc731a8b529ff592f31fc8b6ef2be9fa74abd05c8a342d7"}, 1594 | {file = "pyzmq-22.3.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:be4e0f229cf3a71f9ecd633566bd6f80d9fa6afaaff5489492be63fe459ef98c"}, 1595 | {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08c4e315a76ef26eb833511ebf3fa87d182152adf43dedee8d79f998a2162a0b"}, 1596 | {file = "pyzmq-22.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:badb868fff14cfd0e200eaa845887b1011146a7d26d579aaa7f966c203736b92"}, 1597 | {file = "pyzmq-22.3.0-cp37-cp37m-win32.whl", hash = "sha256:7c58f598d9fcc52772b89a92d72bf8829c12d09746a6d2c724c5b30076c1f11d"}, 1598 | {file = "pyzmq-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2b97502c16a5ec611cd52410bdfaab264997c627a46b0f98d3f666227fd1ea2d"}, 1599 | {file = "pyzmq-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d728b08448e5ac3e4d886b165385a262883c34b84a7fe1166277fe675e1c197a"}, 1600 | {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:480b9931bfb08bf8b094edd4836271d4d6b44150da051547d8c7113bf947a8b0"}, 1601 | {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7dc09198e4073e6015d9a8ea093fc348d4e59de49382476940c3dd9ae156fba8"}, 1602 | {file = "pyzmq-22.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ca6cd58f62a2751728016d40082008d3b3412a7f28ddfb4a2f0d3c130f69e74"}, 1603 | {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:468bd59a588e276961a918a3060948ae68f6ff5a7fa10bb2f9160c18fe341067"}, 1604 | {file = "pyzmq-22.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c88fa7410e9fc471e0858638f403739ee869924dd8e4ae26748496466e27ac59"}, 1605 | {file = "pyzmq-22.3.0-cp38-cp38-win32.whl", hash = "sha256:c0f84360dcca3481e8674393bdf931f9f10470988f87311b19d23cda869bb6b7"}, 1606 | {file = "pyzmq-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:f762442bab706fd874064ca218b33a1d8e40d4938e96c24dafd9b12e28017f45"}, 1607 | {file = "pyzmq-22.3.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:954e73c9cd4d6ae319f1c936ad159072b6d356a92dcbbabfd6e6204b9a79d356"}, 1608 | {file = "pyzmq-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f43b4a2e6218371dd4f41e547bd919ceeb6ebf4abf31a7a0669cd11cd91ea973"}, 1609 | {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:acebba1a23fb9d72b42471c3771b6f2f18dcd46df77482612054bd45c07dfa36"}, 1610 | {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cf98fd7a6c8aaa08dbc699ffae33fd71175696d78028281bc7b832b26f00ca57"}, 1611 | {file = "pyzmq-22.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d072f7dfbdb184f0786d63bda26e8a0882041b1e393fbe98940395f7fab4c5e2"}, 1612 | {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:53f4fd13976789ffafedd4d46f954c7bb01146121812b72b4ddca286034df966"}, 1613 | {file = "pyzmq-22.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1b5d457acbadcf8b27561deeaa386b0217f47626b29672fa7bd31deb6e91e1b"}, 1614 | {file = "pyzmq-22.3.0-cp39-cp39-win32.whl", hash = "sha256:e6a02cf7271ee94674a44f4e62aa061d2d049001c844657740e156596298b70b"}, 1615 | {file = "pyzmq-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d3dcb5548ead4f1123851a5ced467791f6986d68c656bc63bfff1bf9e36671e2"}, 1616 | {file = "pyzmq-22.3.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3a4c9886d61d386b2b493377d980f502186cd71d501fffdba52bd2a0880cef4f"}, 1617 | {file = "pyzmq-22.3.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:80e043a89c6cadefd3a0712f8a1322038e819ebe9dbac7eca3bce1721bcb63bf"}, 1618 | {file = "pyzmq-22.3.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1621e7a2af72cced1f6ec8ca8ca91d0f76ac236ab2e8828ac8fe909512d566cb"}, 1619 | {file = "pyzmq-22.3.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:d6157793719de168b199194f6b6173f0ccd3bf3499e6870fac17086072e39115"}, 1620 | {file = "pyzmq-22.3.0.tar.gz", hash = "sha256:8eddc033e716f8c91c6a2112f0a8ebc5e00532b4a6ae1eb0ccc48e027f9c671c"}, 1621 | ] 1622 | requests = [ 1623 | {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, 1624 | {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, 1625 | ] 1626 | six = [ 1627 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 1628 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 1629 | ] 1630 | snowballstemmer = [ 1631 | {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, 1632 | {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, 1633 | ] 1634 | soupsieve = [ 1635 | {file = "soupsieve-2.3.1-py3-none-any.whl", hash = "sha256:1a3cca2617c6b38c0343ed661b1fa5de5637f257d4fe22bd9f1338010a1efefb"}, 1636 | {file = "soupsieve-2.3.1.tar.gz", hash = "sha256:b8d49b1cd4f037c7082a9683dfa1801aa2597fb11c3a1155b7a5b94829b4f1f9"}, 1637 | ] 1638 | sphinx = [ 1639 | {file = "Sphinx-4.4.0-py3-none-any.whl", hash = "sha256:5da895959511473857b6d0200f56865ed62c31e8f82dd338063b84ec022701fe"}, 1640 | {file = "Sphinx-4.4.0.tar.gz", hash = "sha256:6caad9786055cb1fa22b4a365c1775816b876f91966481765d7d50e9f0dd35cc"}, 1641 | ] 1642 | sphinx-book-theme = [ 1643 | {file = "sphinx-book-theme-0.2.0.tar.gz", hash = "sha256:9f9762f2c6372e7ebaac905707628efe80386d3e5160945d8965d309aeed940d"}, 1644 | {file = "sphinx_book_theme-0.2.0-py3-none-any.whl", hash = "sha256:4247c7fb938da804dda6a92b617c65eb44a10838ba891b62ddfeb8da4d934554"}, 1645 | ] 1646 | sphinxcontrib-applehelp = [ 1647 | {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, 1648 | {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"}, 1649 | ] 1650 | sphinxcontrib-devhelp = [ 1651 | {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, 1652 | {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, 1653 | ] 1654 | sphinxcontrib-htmlhelp = [ 1655 | {file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"}, 1656 | {file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"}, 1657 | ] 1658 | sphinxcontrib-jsmath = [ 1659 | {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, 1660 | {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, 1661 | ] 1662 | sphinxcontrib-qthelp = [ 1663 | {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, 1664 | {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, 1665 | ] 1666 | sphinxcontrib-serializinghtml = [ 1667 | {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, 1668 | {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, 1669 | ] 1670 | stack-data = [ 1671 | {file = "stack_data-0.2.0-py3-none-any.whl", hash = "sha256:999762f9c3132308789affa03e9271bbbe947bf78311851f4d485d8402ed858e"}, 1672 | {file = "stack_data-0.2.0.tar.gz", hash = "sha256:45692d41bd633a9503a5195552df22b583caf16f0b27c4e58c98d88c8b648e12"}, 1673 | ] 1674 | toml = [ 1675 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, 1676 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, 1677 | ] 1678 | tomli = [ 1679 | {file = "tomli-1.2.3-py3-none-any.whl", hash = "sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c"}, 1680 | {file = "tomli-1.2.3.tar.gz", hash = "sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f"}, 1681 | ] 1682 | tornado = [ 1683 | {file = "tornado-6.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:d371e811d6b156d82aa5f9a4e08b58debf97c302a35714f6f45e35139c332e32"}, 1684 | {file = "tornado-6.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:0d321a39c36e5f2c4ff12b4ed58d41390460f798422c4504e09eb5678e09998c"}, 1685 | {file = "tornado-6.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9de9e5188a782be6b1ce866e8a51bc76a0fbaa0e16613823fc38e4fc2556ad05"}, 1686 | {file = "tornado-6.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:61b32d06ae8a036a6607805e6720ef00a3c98207038444ba7fd3d169cd998910"}, 1687 | {file = "tornado-6.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:3e63498f680547ed24d2c71e6497f24bca791aca2fe116dbc2bd0ac7f191691b"}, 1688 | {file = "tornado-6.1-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:6c77c9937962577a6a76917845d06af6ab9197702a42e1346d8ae2e76b5e3675"}, 1689 | {file = "tornado-6.1-cp35-cp35m-win32.whl", hash = "sha256:6286efab1ed6e74b7028327365cf7346b1d777d63ab30e21a0f4d5b275fc17d5"}, 1690 | {file = "tornado-6.1-cp35-cp35m-win_amd64.whl", hash = "sha256:fa2ba70284fa42c2a5ecb35e322e68823288a4251f9ba9cc77be04ae15eada68"}, 1691 | {file = "tornado-6.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0a00ff4561e2929a2c37ce706cb8233b7907e0cdc22eab98888aca5dd3775feb"}, 1692 | {file = "tornado-6.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:748290bf9112b581c525e6e6d3820621ff020ed95af6f17fedef416b27ed564c"}, 1693 | {file = "tornado-6.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:e385b637ac3acaae8022e7e47dfa7b83d3620e432e3ecb9a3f7f58f150e50921"}, 1694 | {file = "tornado-6.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:25ad220258349a12ae87ede08a7b04aca51237721f63b1808d39bdb4b2164558"}, 1695 | {file = "tornado-6.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:65d98939f1a2e74b58839f8c4dab3b6b3c1ce84972ae712be02845e65391ac7c"}, 1696 | {file = "tornado-6.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:e519d64089b0876c7b467274468709dadf11e41d65f63bba207e04217f47c085"}, 1697 | {file = "tornado-6.1-cp36-cp36m-win32.whl", hash = "sha256:b87936fd2c317b6ee08a5741ea06b9d11a6074ef4cc42e031bc6403f82a32575"}, 1698 | {file = "tornado-6.1-cp36-cp36m-win_amd64.whl", hash = "sha256:cc0ee35043162abbf717b7df924597ade8e5395e7b66d18270116f8745ceb795"}, 1699 | {file = "tornado-6.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7250a3fa399f08ec9cb3f7b1b987955d17e044f1ade821b32e5f435130250d7f"}, 1700 | {file = "tornado-6.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ed3ad863b1b40cd1d4bd21e7498329ccaece75db5a5bf58cd3c9f130843e7102"}, 1701 | {file = "tornado-6.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:dcef026f608f678c118779cd6591c8af6e9b4155c44e0d1bc0c87c036fb8c8c4"}, 1702 | {file = "tornado-6.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:70dec29e8ac485dbf57481baee40781c63e381bebea080991893cd297742b8fd"}, 1703 | {file = "tornado-6.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:d3f7594930c423fd9f5d1a76bee85a2c36fd8b4b16921cae7e965f22575e9c01"}, 1704 | {file = "tornado-6.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:3447475585bae2e77ecb832fc0300c3695516a47d46cefa0528181a34c5b9d3d"}, 1705 | {file = "tornado-6.1-cp37-cp37m-win32.whl", hash = "sha256:e7229e60ac41a1202444497ddde70a48d33909e484f96eb0da9baf8dc68541df"}, 1706 | {file = "tornado-6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:cb5ec8eead331e3bb4ce8066cf06d2dfef1bfb1b2a73082dfe8a161301b76e37"}, 1707 | {file = "tornado-6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:20241b3cb4f425e971cb0a8e4ffc9b0a861530ae3c52f2b0434e6c1b57e9fd95"}, 1708 | {file = "tornado-6.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:c77da1263aa361938476f04c4b6c8916001b90b2c2fdd92d8d535e1af48fba5a"}, 1709 | {file = "tornado-6.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:fba85b6cd9c39be262fcd23865652920832b61583de2a2ca907dbd8e8a8c81e5"}, 1710 | {file = "tornado-6.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:1e8225a1070cd8eec59a996c43229fe8f95689cb16e552d130b9793cb570a288"}, 1711 | {file = "tornado-6.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d14d30e7f46a0476efb0deb5b61343b1526f73ebb5ed84f23dc794bdb88f9d9f"}, 1712 | {file = "tornado-6.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8f959b26f2634a091bb42241c3ed8d3cedb506e7c27b8dd5c7b9f745318ddbb6"}, 1713 | {file = "tornado-6.1-cp38-cp38-win32.whl", hash = "sha256:34ca2dac9e4d7afb0bed4677512e36a52f09caa6fded70b4e3e1c89dbd92c326"}, 1714 | {file = "tornado-6.1-cp38-cp38-win_amd64.whl", hash = "sha256:6196a5c39286cc37c024cd78834fb9345e464525d8991c21e908cc046d1cc02c"}, 1715 | {file = "tornado-6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0ba29bafd8e7e22920567ce0d232c26d4d47c8b5cf4ed7b562b5db39fa199c5"}, 1716 | {file = "tornado-6.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:33892118b165401f291070100d6d09359ca74addda679b60390b09f8ef325ffe"}, 1717 | {file = "tornado-6.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7da13da6f985aab7f6f28debab00c67ff9cbacd588e8477034c0652ac141feea"}, 1718 | {file = "tornado-6.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:e0791ac58d91ac58f694d8d2957884df8e4e2f6687cdf367ef7eb7497f79eaa2"}, 1719 | {file = "tornado-6.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:66324e4e1beede9ac79e60f88de548da58b1f8ab4b2f1354d8375774f997e6c0"}, 1720 | {file = "tornado-6.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:a48900ecea1cbb71b8c71c620dee15b62f85f7c14189bdeee54966fbd9a0c5bd"}, 1721 | {file = "tornado-6.1-cp39-cp39-win32.whl", hash = "sha256:d3d20ea5782ba63ed13bc2b8c291a053c8d807a8fa927d941bd718468f7b950c"}, 1722 | {file = "tornado-6.1-cp39-cp39-win_amd64.whl", hash = "sha256:548430be2740e327b3fe0201abe471f314741efcb0067ec4f2d7dcfb4825f3e4"}, 1723 | {file = "tornado-6.1.tar.gz", hash = "sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791"}, 1724 | ] 1725 | traitlets = [ 1726 | {file = "traitlets-5.1.1-py3-none-any.whl", hash = "sha256:2d313cc50a42cd6c277e7d7dc8d4d7fedd06a2c215f78766ae7b1a66277e0033"}, 1727 | {file = "traitlets-5.1.1.tar.gz", hash = "sha256:059f456c5a7c1c82b98c2e8c799f39c9b8128f6d0d46941ee118daace9eb70c7"}, 1728 | ] 1729 | typing-extensions = [ 1730 | {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, 1731 | {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, 1732 | ] 1733 | urllib3 = [ 1734 | {file = "urllib3-1.26.8-py2.py3-none-any.whl", hash = "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed"}, 1735 | {file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"}, 1736 | ] 1737 | virtualenv = [] 1738 | wcwidth = [ 1739 | {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, 1740 | {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, 1741 | ] 1742 | wrapt = [ 1743 | {file = "wrapt-1.13.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:e05e60ff3b2b0342153be4d1b597bbcfd8330890056b9619f4ad6b8d5c96a81a"}, 1744 | {file = "wrapt-1.13.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:85148f4225287b6a0665eef08a178c15097366d46b210574a658c1ff5b377489"}, 1745 | {file = "wrapt-1.13.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:2dded5496e8f1592ec27079b28b6ad2a1ef0b9296d270f77b8e4a3a796cf6909"}, 1746 | {file = "wrapt-1.13.3-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:e94b7d9deaa4cc7bac9198a58a7240aaf87fe56c6277ee25fa5b3aa1edebd229"}, 1747 | {file = "wrapt-1.13.3-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:498e6217523111d07cd67e87a791f5e9ee769f9241fcf8a379696e25806965af"}, 1748 | {file = "wrapt-1.13.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ec7e20258ecc5174029a0f391e1b948bf2906cd64c198a9b8b281b811cbc04de"}, 1749 | {file = "wrapt-1.13.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:87883690cae293541e08ba2da22cacaae0a092e0ed56bbba8d018cc486fbafbb"}, 1750 | {file = "wrapt-1.13.3-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:f99c0489258086308aad4ae57da9e8ecf9e1f3f30fa35d5e170b4d4896554d80"}, 1751 | {file = "wrapt-1.13.3-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6a03d9917aee887690aa3f1747ce634e610f6db6f6b332b35c2dd89412912bca"}, 1752 | {file = "wrapt-1.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:936503cb0a6ed28dbfa87e8fcd0a56458822144e9d11a49ccee6d9a8adb2ac44"}, 1753 | {file = "wrapt-1.13.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f9c51d9af9abb899bd34ace878fbec8bf357b3194a10c4e8e0a25512826ef056"}, 1754 | {file = "wrapt-1.13.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:220a869982ea9023e163ba915077816ca439489de6d2c09089b219f4e11b6785"}, 1755 | {file = "wrapt-1.13.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0877fe981fd76b183711d767500e6b3111378ed2043c145e21816ee589d91096"}, 1756 | {file = "wrapt-1.13.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:43e69ffe47e3609a6aec0fe723001c60c65305784d964f5007d5b4fb1bc6bf33"}, 1757 | {file = "wrapt-1.13.3-cp310-cp310-win32.whl", hash = "sha256:78dea98c81915bbf510eb6a3c9c24915e4660302937b9ae05a0947164248020f"}, 1758 | {file = "wrapt-1.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:ea3e746e29d4000cd98d572f3ee2a6050a4f784bb536f4ac1f035987fc1ed83e"}, 1759 | {file = "wrapt-1.13.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:8c73c1a2ec7c98d7eaded149f6d225a692caa1bd7b2401a14125446e9e90410d"}, 1760 | {file = "wrapt-1.13.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:086218a72ec7d986a3eddb7707c8c4526d677c7b35e355875a0fe2918b059179"}, 1761 | {file = "wrapt-1.13.3-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:e92d0d4fa68ea0c02d39f1e2f9cb5bc4b4a71e8c442207433d8db47ee79d7aa3"}, 1762 | {file = "wrapt-1.13.3-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:d4a5f6146cfa5c7ba0134249665acd322a70d1ea61732723c7d3e8cc0fa80755"}, 1763 | {file = "wrapt-1.13.3-cp35-cp35m-win32.whl", hash = "sha256:8aab36778fa9bba1a8f06a4919556f9f8c7b33102bd71b3ab307bb3fecb21851"}, 1764 | {file = "wrapt-1.13.3-cp35-cp35m-win_amd64.whl", hash = "sha256:944b180f61f5e36c0634d3202ba8509b986b5fbaf57db3e94df11abee244ba13"}, 1765 | {file = "wrapt-1.13.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2ebdde19cd3c8cdf8df3fc165bc7827334bc4e353465048b36f7deeae8ee0918"}, 1766 | {file = "wrapt-1.13.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:610f5f83dd1e0ad40254c306f4764fcdc846641f120c3cf424ff57a19d5f7ade"}, 1767 | {file = "wrapt-1.13.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5601f44a0f38fed36cc07db004f0eedeaadbdcec90e4e90509480e7e6060a5bc"}, 1768 | {file = "wrapt-1.13.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:e6906d6f48437dfd80464f7d7af1740eadc572b9f7a4301e7dd3d65db285cacf"}, 1769 | {file = "wrapt-1.13.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:766b32c762e07e26f50d8a3468e3b4228b3736c805018e4b0ec8cc01ecd88125"}, 1770 | {file = "wrapt-1.13.3-cp36-cp36m-win32.whl", hash = "sha256:5f223101f21cfd41deec8ce3889dc59f88a59b409db028c469c9b20cfeefbe36"}, 1771 | {file = "wrapt-1.13.3-cp36-cp36m-win_amd64.whl", hash = "sha256:f122ccd12fdc69628786d0c947bdd9cb2733be8f800d88b5a37c57f1f1d73c10"}, 1772 | {file = "wrapt-1.13.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:46f7f3af321a573fc0c3586612db4decb7eb37172af1bc6173d81f5b66c2e068"}, 1773 | {file = "wrapt-1.13.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:778fd096ee96890c10ce96187c76b3e99b2da44e08c9e24d5652f356873f6709"}, 1774 | {file = "wrapt-1.13.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0cb23d36ed03bf46b894cfec777eec754146d68429c30431c99ef28482b5c1df"}, 1775 | {file = "wrapt-1.13.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:96b81ae75591a795d8c90edc0bfaab44d3d41ffc1aae4d994c5aa21d9b8e19a2"}, 1776 | {file = "wrapt-1.13.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7dd215e4e8514004c8d810a73e342c536547038fb130205ec4bba9f5de35d45b"}, 1777 | {file = "wrapt-1.13.3-cp37-cp37m-win32.whl", hash = "sha256:47f0a183743e7f71f29e4e21574ad3fa95676136f45b91afcf83f6a050914829"}, 1778 | {file = "wrapt-1.13.3-cp37-cp37m-win_amd64.whl", hash = "sha256:fd76c47f20984b43d93de9a82011bb6e5f8325df6c9ed4d8310029a55fa361ea"}, 1779 | {file = "wrapt-1.13.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b73d4b78807bd299b38e4598b8e7bd34ed55d480160d2e7fdaabd9931afa65f9"}, 1780 | {file = "wrapt-1.13.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ec9465dd69d5657b5d2fa6133b3e1e989ae27d29471a672416fd729b429eb554"}, 1781 | {file = "wrapt-1.13.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dd91006848eb55af2159375134d724032a2d1d13bcc6f81cd8d3ed9f2b8e846c"}, 1782 | {file = "wrapt-1.13.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ae9de71eb60940e58207f8e71fe113c639da42adb02fb2bcbcaccc1ccecd092b"}, 1783 | {file = "wrapt-1.13.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:51799ca950cfee9396a87f4a1240622ac38973b6df5ef7a41e7f0b98797099ce"}, 1784 | {file = "wrapt-1.13.3-cp38-cp38-win32.whl", hash = "sha256:4b9c458732450ec42578b5642ac53e312092acf8c0bfce140ada5ca1ac556f79"}, 1785 | {file = "wrapt-1.13.3-cp38-cp38-win_amd64.whl", hash = "sha256:7dde79d007cd6dfa65afe404766057c2409316135cb892be4b1c768e3f3a11cb"}, 1786 | {file = "wrapt-1.13.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:981da26722bebb9247a0601e2922cedf8bb7a600e89c852d063313102de6f2cb"}, 1787 | {file = "wrapt-1.13.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:705e2af1f7be4707e49ced9153f8d72131090e52be9278b5dbb1498c749a1e32"}, 1788 | {file = "wrapt-1.13.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:25b1b1d5df495d82be1c9d2fad408f7ce5ca8a38085e2da41bb63c914baadff7"}, 1789 | {file = "wrapt-1.13.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:77416e6b17926d953b5c666a3cb718d5945df63ecf922af0ee576206d7033b5e"}, 1790 | {file = "wrapt-1.13.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:865c0b50003616f05858b22174c40ffc27a38e67359fa1495605f96125f76640"}, 1791 | {file = "wrapt-1.13.3-cp39-cp39-win32.whl", hash = "sha256:0a017a667d1f7411816e4bf214646d0ad5b1da2c1ea13dec6c162736ff25a374"}, 1792 | {file = "wrapt-1.13.3-cp39-cp39-win_amd64.whl", hash = "sha256:81bd7c90d28a4b2e1df135bfbd7c23aee3050078ca6441bead44c42483f9ebfb"}, 1793 | {file = "wrapt-1.13.3.tar.gz", hash = "sha256:1fea9cd438686e6682271d36f3481a9f3636195578bab9ca3382e2f5f01fc185"}, 1794 | ] 1795 | --------------------------------------------------------------------------------