├── .bumpversion.cfg ├── .github ├── CODE-OF-CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug-report.md │ └── feature-request.md ├── SECURITY.md ├── dependabot.yml ├── labeler.yml ├── pull_request_template.md ├── release-drafter.yml └── workflows │ ├── ci.yml │ ├── release-draft.yml │ ├── release.yml │ └── set-labels.yml ├── .gitignore ├── LICENSE ├── README.md ├── THIRD-PARTY-LICENSES ├── context_logging ├── __init__.py ├── config.py ├── context.py ├── log_record.py ├── logger.py └── utils.py ├── makefile ├── poetry.lock ├── pyproject.toml ├── setup.cfg └── tests ├── __init__.py ├── conftest.py └── test_context_logging.py /.bumpversion.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 1.1.0 3 | commit = True 4 | tag = True 5 | 6 | [bumpversion:file:pyproject.toml] 7 | search = version = "{current_version}" 8 | replace = version = "{new_version}" 9 | 10 | [bumpversion:file:context_logging/__init__.py] 11 | search = __version__ = '{current_version}' 12 | replace = __version__ = '{new_version}' 13 | 14 | -------------------------------------------------------------------------------- /.github/CODE-OF-CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to make participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies within all project spaces, and it also applies when 49 | an individual is representing the project or its community in public spaces. 50 | Examples of representing a project or community include using an official 51 | project e-mail address, posting via an official social media account, or acting 52 | as an appointed representative at an online or offline event. Representation of 53 | a project may be further defined and clarified by project maintainers. 54 | 55 | ## Attribution 56 | 57 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 58 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 59 | 60 | [homepage]: https://www.contributor-covenant.org 61 | 62 | For answers to common questions about this code of conduct, see 63 | https://www.contributor-covenant.org/faq 64 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | [legal]: https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license 4 | [license]: ../LICENSE 5 | [code-of-conduct]: CODE-OF-CONDUCT.md 6 | 7 | Hi! Thanks for your interest in contributing! 8 | 9 | We accept pull requests for bug fixes and features where we've discussed the approach in an issue and given the go-ahead for a community member to work on it. We'd also love to hear about ideas for new features as issues. 10 | 11 | Please do: 12 | 13 | * open an issue if things aren't working as expected 14 | * open an issue to propose a significant change 15 | * open a pull request to fix a bug 16 | * open a pull request to fix documentation about a command 17 | * open a pull request if one from core contributors has given the ok after discussion in an issue 18 | 19 | Please avoid: 20 | 21 | * adding installation instructions specifically for your OS/package manager 22 | 23 | ## Building the project 24 | 25 | Prerequisites: 26 | - python 3.7+ 27 | 28 | Init local environment with: `make init precommit_hook` 29 | 30 | Run autoformat with: `make pretty` 31 | 32 | Run linters with: `make lint` 33 | 34 | Run tests with: `make test` 35 | 36 | ## Submitting a pull request 37 | 38 | 1. Create a new branch: `git checkout -b my-branch-name` 39 | 1. Make your change, add tests, and ensure tests and linters pass 40 | 1. Submit a pull request 41 | 42 | Contributions to this project are [released][legal] to the public under the [project's open source license][license]. 43 | 44 | Please note that this project adheres to a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms. 45 | 46 | ## Resources 47 | 48 | - [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) 49 | - [Using Pull Requests](https://help.github.com/articles/about-pull-requests/) 50 | - [GitHub Help](https://help.github.com) 51 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "🐛 Bug report" 3 | about: Report a bug or unexpected behavior 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Describe the bug 11 | 12 | A clear and concise description of what the bug is. Include version of package. 13 | 14 | ### Steps to reproduce the behavior 15 | 16 | 1. Do this '...' 17 | 2. View the output '....' 18 | 3. See error 19 | 20 | ### Expected vs actual behavior 21 | 22 | A clear and concise description of what you expected to happen and what actually happened. 23 | 24 | ### Logs 25 | 26 | Paste the activity from your command line. Redact if needed. 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "🚀 Submit a request" 3 | about: Surface a feature or problem that you think should be solved 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Describe the feature or problem you’d like to solve 11 | 12 | A clear and concise description of what the feature or problem is. 13 | 14 | ### Proposed solution 15 | 16 | - 17 | 18 | ### Additional context 19 | 20 | Add any other context like screenshots or mockups are helpful, if applicable. 21 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | If you discover a security issue in this repository, please create new issue about it. 2 | Thanks for helping make Open Source safe for everyone. 3 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: pip 4 | directory: "/" 5 | schedule: 6 | interval: monthly 7 | time: "00:00" 8 | open-pull-requests-limit: 10 9 | assignees: 10 | - afonasev 11 | ignore: 12 | - dependency-name: mypy 13 | versions: 14 | - "0.790" 15 | - "0.800" 16 | - dependency-name: pytest 17 | versions: 18 | - 6.2.1 19 | - dependency-name: pytest-mock 20 | versions: 21 | - 3.4.0 22 | - dependency-name: pydantic 23 | versions: 24 | - 1.7.3 25 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | config: 2 | - "setup.cfg" 3 | - "Makefile" 4 | 5 | enhancement: 6 | - "context_logging/*" 7 | 8 | tests: 9 | - "tests/*" 10 | 11 | documentation: 12 | - "README.md" 13 | 14 | dependencies: 15 | - "poetry.lock" 16 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Summary 8 | 9 | closes #[issue number] 10 | 11 | ## Details 12 | 13 | - 14 | 15 | ## Check list 16 | 17 | - [ ] Tests 18 | - [ ] README.md changed if needed 19 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name-template: 'v$NEXT_PATCH_VERSION' 2 | tag-template: 'v$NEXT_PATCH_VERSION' 3 | 4 | categories: 5 | - title: '🚀 New Features' 6 | labels: 7 | - 'enhancement' 8 | - 'feature' 9 | 10 | - title: '🐛 Bugs Fixes' 11 | labels: 12 | - 'bug' 13 | - 'bug_fix' 14 | - 'fix' 15 | 16 | - title: '📄 Documentation' 17 | labels: 18 | - 'documentation' 19 | - 'docs' 20 | 21 | - title: '💊 Refactoring' 22 | labels: 23 | - 'refactoring' 24 | - 'refactor' 25 | 26 | - title: '🔧 Configuration' 27 | labels: 28 | - 'config' 29 | - 'conf' 30 | 31 | references: 32 | - master 33 | - v.+ 34 | 35 | exclude-labels: 36 | - 'skip-changelog' 37 | 38 | change-template: '- $TITLE @$AUTHOR (#$NUMBER)' 39 | template: | 40 | ## Changes 41 | $CHANGES 42 | 43 | ## 👍Contributors 44 | $CONTRIBUTORS 45 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: push 4 | 5 | jobs: 6 | ci: 7 | runs-on: ubuntu-18.04 8 | strategy: 9 | matrix: 10 | python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | 15 | - name: Set up Python ${{ matrix.python-version }} 16 | uses: actions/setup-python@v2 17 | with: 18 | python-version: ${{ matrix.python-version }} 19 | 20 | - name: Set up Poetry 21 | uses: dschep/install-poetry-action@v1.3 22 | with: 23 | version: 1.5.1 24 | 25 | - uses: actions/cache@v2 26 | id: cache 27 | with: 28 | path: ./.venv 29 | key: ${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }} 30 | restore-keys: ${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }} 31 | 32 | - name: Install dependencies 33 | if: steps.cache.outputs.cache-hit != 'true' 34 | run: | 35 | poetry config virtualenvs.create true 36 | poetry config virtualenvs.in-project true 37 | poetry install --no-interaction --no-ansi 38 | 39 | - name: Run linters and tests 40 | env: 41 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 42 | run: make ci 43 | -------------------------------------------------------------------------------- /.github/workflows/release-draft.yml: -------------------------------------------------------------------------------- 1 | name: release-draft 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | update-release-draft: 10 | runs-on: ubuntu-18.04 11 | 12 | steps: 13 | - name: Update GITHUB release-draft with changelog 14 | uses: release-drafter/release-drafter@v5 15 | env: 16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 17 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*.*.*' 7 | 8 | jobs: 9 | publish-to-pypi: 10 | runs-on: ubuntu-18.04 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | 15 | - name: Set up Python 3.11 16 | uses: actions/setup-python@v2 17 | with: 18 | python-version: 3.11 19 | 20 | - name: Set up Poetry 21 | uses: dschep/install-poetry-action@v1.3 22 | with: 23 | version: 1.5.1 24 | 25 | - name: Build and publish to pypi 26 | run: | 27 | poetry config pypi-token.pypi ${{ secrets.PYPI_TOKEN }} 28 | poetry publish --build 29 | -------------------------------------------------------------------------------- /.github/workflows/set-labels.yml: -------------------------------------------------------------------------------- 1 | name: set-labels 2 | 3 | on: pull_request 4 | 5 | jobs: 6 | set-labels: 7 | runs-on: ubuntu-18.04 8 | 9 | steps: 10 | - uses: actions/labeler@v2 11 | with: 12 | repo-token: ${{ secrets.GITHUB_TOKEN }} 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | # IDE 107 | .idea/ 108 | .vscode/ 109 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Evgeniy Afonasev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # context_logging 2 | 3 | [![pypi](https://badge.fury.io/py/context-logging.svg)](https://pypi.org/project/context_logging) 4 | [![Python: 3.7+](https://img.shields.io/badge/Python-3.7+-blue.svg)](https://pypi.org/project/context_logging) 5 | [![Downloads](https://img.shields.io/pypi/dm/context_logging.svg)](https://pypistats.org/packages/context_logging) 6 | ![CI Status](https://github.com/afonasev/context_logging/workflows/ci/badge.svg?branch=master) 7 | [![Code coverage](https://codecov.io/gh/Afonasev/context_logging/branch/master/graph/badge.svg)](https://codecov.io/gh/Afonasev/context_logging) 8 | [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://en.wikipedia.org/wiki/MIT_License) 9 | [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black) 10 | 11 | ## Description 12 | 13 | Tool for easy logging with current context information. 14 | 15 | ```python 16 | from context_logging import current_context 17 | 18 | logging.info('before context') 19 | # 2019-07-25 19:49:43 INFO before context 20 | 21 | with Context('my_context'): 22 | current_context['var'] = 1 23 | logging.info('in context') 24 | # 2019-07-25 19:49:43 INFO in context {'var': 1} 25 | 26 | # 2019-07-25 19:49:43 INFO 'my_context: executed in 00:00:01 {'var': 1}' 27 | 28 | logging.info('after context') 29 | # 2019-07-25 19:49:43 INFO after context 30 | ``` 31 | 32 | ## Installation 33 | 34 | pip install context_logging 35 | 36 | ## Usage 37 | 38 | ### Setup logging with context 39 | 40 | ```python 41 | import logging 42 | from context_logging import current_context, setup_log_record 43 | 44 | logging.basicConfig( 45 | format='%(asctime)s %(levelname)s %(name)s %(message)s %(context)s', 46 | level=logging.INFO, 47 | ) 48 | setup_log_record() 49 | 50 | current_context['var'] = 1 51 | logging.info('message') 52 | 53 | # 2019-07-25 19:49:43,892 INFO root message {'var': 1} 54 | ``` 55 | 56 | ### As contextmanager 57 | 58 | ```python 59 | from context_logging import Context, current_context 60 | 61 | with Context(var=1): 62 | assert current_context['var'] == 1 63 | 64 | assert 'var' not in current_context 65 | ``` 66 | 67 | ### Any nesting of contexts is allowed 68 | 69 | ```python 70 | with Context(var=1): 71 | assert current_context == {'var': 1} 72 | 73 | with Context(val=2, var=2): 74 | assert current_context == {'val': 2, 'var': 2} 75 | 76 | assert current_context == {'var': 1} 77 | 78 | assert 'var' not in current_context 79 | ``` 80 | 81 | ### As decorator 82 | 83 | ```python 84 | @Context(var=1) 85 | def f(): 86 | assert current_context['var'] == 1 87 | 88 | f() 89 | assert 'var' not in current_context 90 | ``` 91 | 92 | ### With start/finish [DEPRECATED] 93 | 94 | ```python 95 | ctx = Context(var=1) 96 | assert 'var' not in current_context 97 | 98 | ctx.start() 99 | assert current_context['var'] == 1 100 | 101 | ctx.finish() 102 | assert 'var' not in current_context 103 | ``` 104 | 105 | ### Add/remove values from current_context 106 | ```python 107 | with Context(): 108 | assert 'var' not in current_context 109 | current_context['var'] = 1 110 | assert current_context['var'] == 1 111 | ``` 112 | 113 | ### Explicit context name (else will be used path to the python module) 114 | 115 | ```python 116 | with Context('my_context'): 117 | pass 118 | ``` 119 | 120 | ### Execution time logged on exit from context (it can be disabled with `log_execution_time=False` argument) 121 | 122 | ```python 123 | with Context('my_context'): 124 | time.sleep(1) 125 | 126 | # INFO 'my_context: executed in 00:00:01', 127 | ``` 128 | 129 | Default value for log_execution_time param can be changed with env 130 | 131 | export CONTEXT_LOGGING_LOG_EXECUTION_TIME_DEFAULT=0 132 | 133 | ### Exceptions from context are populated with current_context (it can be disabled with `fill_exception_context=False` argument) 134 | 135 | ```python 136 | try: 137 | with Context(var=1): 138 | raise Exception(1) 139 | except Exception as exc: 140 | assert exc.args = (1, {'var': 1}) 141 | ``` 142 | 143 | Default value for fill_exception_context param can be changed with env 144 | 145 | export CONTEXT_LOGGING_FILL_EXEPTIONS_DEFAULT=0 146 | 147 | ### We can set data to root context that never will be closed 148 | 149 | ```python 150 | from context_logging import root_context 151 | 152 | root_context['env'] = 'test' 153 | ``` 154 | 155 | ### If you want to pass context to other threads use [ContextVarExecutor](https://github.com/hellysmile/contextvars_executor) 156 | 157 | ```python 158 | from context_logging import ContextVarExecutor 159 | 160 | with ContextVarExecutor() as executor: 161 | executor.submit(...) 162 | 163 | # OR 164 | 165 | loop.set_default_executor(ContextVarExecutor()) # for asyncio loop 166 | ``` 167 | 168 | ## For developers 169 | 170 | ### Create venv and install deps 171 | 172 | make init 173 | 174 | ### Install git precommit hook 175 | 176 | make precommit_hook 177 | 178 | ### Run linters, autoformat, tests etc. 179 | 180 | make pretty lint test 181 | 182 | ### Bump new version 183 | 184 | make bump_major 185 | make bump_minor 186 | make bump_patch 187 | -------------------------------------------------------------------------------- /THIRD-PARTY-LICENSES: -------------------------------------------------------------------------------- 1 | ******************************************************************************* 2 | https://github.com/Afonasev/cookiecutter-pypackage-poetry 3 | ******************************************************************************* 4 | 5 | MIT License 6 | 7 | Copyright (c) 2019 Afonasev Evgeniy 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | -------------------------------------------------------------------------------- /context_logging/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqaF401 2 | from contextvars_executor import ContextVarExecutor 3 | 4 | from .context import Context, current_context, root_context 5 | from .log_record import setup_log_record 6 | 7 | __version__ = '1.1.0' 8 | -------------------------------------------------------------------------------- /context_logging/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def parse_env_to_bool(val: str) -> bool: 5 | return val.lower() in ['yes', 'true', '1'] 6 | 7 | 8 | class Config: 9 | FILL_EXEPTIONS_DEFAULT: bool = parse_env_to_bool( 10 | os.getenv('CONTEXT_LOGGING_FILL_EXEPTIONS_DEFAULT', 'yes') 11 | ) 12 | LOG_EXECUTION_TIME_DEFAULT: bool = parse_env_to_bool( 13 | os.getenv('CONTEXT_LOGGING_LOG_EXECUTION_TIME_DEFAULT', 'yes') 14 | ) 15 | 16 | 17 | config = Config() 18 | -------------------------------------------------------------------------------- /context_logging/context.py: -------------------------------------------------------------------------------- 1 | import time 2 | from collections import UserDict 3 | from contextvars import ContextVar, Token 4 | from typing import Any, ChainMap, Dict, Optional, Type, cast 5 | 6 | from deprecated import deprecated 7 | 8 | from .config import config 9 | from .logger import logger 10 | from .utils import ( 11 | SyncAsyncContextDecorator, 12 | context_name_with_code_path, 13 | seconds_to_time_string, 14 | ) 15 | 16 | ROOT_CONTEXT_NAME = 'root' 17 | 18 | 19 | class ContextFactory(SyncAsyncContextDecorator): 20 | def __init__( 21 | self, 22 | name: Optional[str] = None, 23 | *, 24 | log_execution_time: Optional[bool] = None, 25 | fill_exception_context: Optional[bool] = None, 26 | **kwargs: Any 27 | ) -> None: 28 | self.name = name or context_name_with_code_path() 29 | self._context_data = kwargs 30 | 31 | if log_execution_time is None: 32 | log_execution_time = config.LOG_EXECUTION_TIME_DEFAULT 33 | self._log_execution_time = log_execution_time 34 | 35 | if fill_exception_context is None: 36 | fill_exception_context = config.FILL_EXEPTIONS_DEFAULT 37 | self._fill_exception_context = fill_exception_context 38 | 39 | @deprecated 40 | def start(self) -> None: 41 | self.__enter__() # pylint:disable=unnecessary-dunder-call 42 | 43 | @deprecated 44 | def finish(self) -> None: 45 | self.__exit__(None, None, None) 46 | 47 | def __enter__(self) -> 'ContextObject': 48 | context = self.create_context() 49 | context.start() 50 | return context 51 | 52 | def __exit__( 53 | self, 54 | exc_type: Optional[Type[Exception]], 55 | exc_value: Optional[Exception], 56 | traceback: Any, 57 | ) -> None: 58 | context = _current_context.get() 59 | context.finish(exc_value) 60 | 61 | def create_context(self) -> 'ContextObject': 62 | return ContextObject( 63 | name=self.name, 64 | log_execution_time=self._log_execution_time, 65 | fill_exception_context=self._fill_exception_context, 66 | context_data=self._context_data.copy(), 67 | ) 68 | 69 | 70 | class ContextObject(UserDict): # type: ignore 71 | def __init__( # pylint:disable=super-init-not-called 72 | self, 73 | name: str, 74 | log_execution_time: bool, 75 | fill_exception_context: bool, 76 | context_data: Dict[Any, Any], 77 | ) -> None: 78 | self.name = name 79 | 80 | self._log_execution_time = log_execution_time 81 | self._fill_exception_context = fill_exception_context 82 | self._context_data = context_data 83 | 84 | self._parent_context: Optional[ContextObject] = None 85 | self._parent_context_token: Optional[Token[ContextObject]] = None 86 | self._start_time: Optional[float] = None 87 | 88 | @property 89 | def data(self) -> ChainMap[Any, Any]: # type: ignore 90 | return ChainMap(self._context_data, self._parent_context or {}) 91 | 92 | def start(self) -> None: 93 | self._parent_context = _current_context.get() 94 | self._parent_context_token = _current_context.set(self) 95 | self._start_time = time.monotonic() 96 | 97 | def finish(self, exc: Optional[Exception] = None) -> None: 98 | if self._log_execution_time: 99 | finish_time = time.monotonic() - cast(float, self._start_time) 100 | 101 | logger.info( 102 | '%s: executed in %s', 103 | self.name, 104 | seconds_to_time_string(finish_time), 105 | ) 106 | 107 | if exc and self._fill_exception_context and current_context: 108 | if not getattr(exc, '__context_logging__', None): 109 | exc.__context_logging__ = True # type: ignore 110 | exc.args += (dict(current_context),) 111 | 112 | _current_context.reset( 113 | cast(Token, self._parent_context_token) # type: ignore 114 | ) 115 | 116 | 117 | root_context = ContextFactory(name=ROOT_CONTEXT_NAME).create_context() 118 | 119 | _current_context: ContextVar[ContextObject] = ContextVar( 120 | 'ctx', default=root_context 121 | ) 122 | 123 | 124 | class CurrentContextProxy(UserDict): # type: ignore 125 | def __init__(self) -> None: # pylint:disable=super-init-not-called 126 | pass 127 | 128 | @property 129 | def data(self) -> ContextObject: # type: ignore 130 | return _current_context.get() 131 | 132 | 133 | current_context = CurrentContextProxy() 134 | Context = ContextFactory # for backward compatibility 135 | -------------------------------------------------------------------------------- /context_logging/log_record.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from copy import deepcopy 3 | from typing import Any 4 | 5 | from .context import current_context 6 | 7 | 8 | class ContextLogRecord(logging.LogRecord): 9 | def __init__(self, *args: Any, **kwargs: Any) -> None: 10 | super().__init__(*args, **kwargs) 11 | self.context = deepcopy(current_context) or '' 12 | 13 | 14 | def setup_log_record() -> None: 15 | logging.setLogRecordFactory(ContextLogRecord) 16 | -------------------------------------------------------------------------------- /context_logging/logger.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | logger = logging.getLogger(__package__) 4 | logger.addHandler(logging.NullHandler()) 5 | -------------------------------------------------------------------------------- /context_logging/utils.py: -------------------------------------------------------------------------------- 1 | # pylint:disable=not-context-manager 2 | from contextlib import ContextDecorator 3 | from datetime import timedelta 4 | from functools import wraps 5 | from inspect import getframeinfo, iscoroutinefunction, stack 6 | from typing import Any, Callable 7 | 8 | 9 | class SyncAsyncContextDecorator(ContextDecorator): 10 | def __call__( # type:ignore 11 | self, func: Callable[..., Any] 12 | ) -> Callable[..., Any]: 13 | if iscoroutinefunction(func): 14 | 15 | @wraps(func) 16 | async def async_inner(*args: Any, **kwds: Any) -> Any: 17 | with self._recreate_cm(): # type: ignore 18 | return await func(*args, **kwds) 19 | 20 | return async_inner 21 | 22 | @wraps(func) 23 | def sync_inner(*args: Any, **kwds: Any) -> Any: 24 | with self._recreate_cm(): # type: ignore 25 | return func(*args, **kwds) 26 | 27 | return sync_inner 28 | 29 | 30 | def context_name_with_code_path() -> str: 31 | """ 32 | >>> _default_name() 33 | 'Context /path_to_code/code.py:10' 34 | """ 35 | caller = getframeinfo(stack()[2][0]) 36 | return f'Context {caller.filename}:{caller.lineno}' 37 | 38 | 39 | def seconds_to_time_string(seconds: float) -> str: 40 | """ 41 | >>> _seconds_to_time(seconds=10000) 42 | '2:46:40' 43 | """ 44 | return str(timedelta(seconds=seconds)) 45 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | BIN = .venv/bin/ 2 | CODE = context_logging 3 | 4 | .PHONY: init 5 | init: 6 | python3 -m venv .venv 7 | poetry install 8 | 9 | .PHONY: test 10 | test: 11 | $(BIN)pytest --verbosity=2 --showlocals --strict-markers --log-level=DEBUG --cov=$(CODE) $(args) 12 | 13 | .PHONY: lint 14 | lint: 15 | $(BIN)flake8 --jobs 4 --statistics --show-source $(CODE) tests 16 | $(BIN)pylint --jobs 4 --rcfile=setup.cfg $(CODE) 17 | $(BIN)mypy $(CODE) tests 18 | $(BIN)black --skip-string-normalization --line-length=79 --check $(CODE) tests 19 | $(BIN)pytest --dead-fixtures --dup-fixtures 20 | 21 | .PHONY: pretty 22 | pretty: 23 | $(BIN)isort --apply --recursive $(CODE) tests 24 | $(BIN)black --skip-string-normalization --line-length=79 $(CODE) tests 25 | $(BIN)unify --in-place --recursive $(CODE) tests 26 | 27 | .PHONY: precommit_hook 28 | precommit_hook: 29 | echo '#!/bin/sh\nmake lint test\n' > .git/hooks/pre-commit 30 | chmod +x .git/hooks/pre-commit 31 | 32 | .PHONY: bump_major 33 | bump_major: 34 | $(BIN)bumpversion major 35 | 36 | .PHONY: bump_minor 37 | bump_minor: 38 | $(BIN)bumpversion minor 39 | 40 | .PHONY: bump_patch 41 | bump_patch: 42 | $(BIN)bumpversion patch 43 | 44 | .PHONY: ci 45 | ci: lint test 46 | ci: $(BIN)codecov 47 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "astpretty" 5 | version = "2.1.0" 6 | description = "Pretty print the output of python stdlib `ast.parse`." 7 | optional = false 8 | python-versions = ">=3.6.1" 9 | files = [ 10 | {file = "astpretty-2.1.0-py2.py3-none-any.whl", hash = "sha256:f81f14b5636f7af81fadb1e3c09ca7702ce4615500d9cc6d6829befb2dec2e3c"}, 11 | {file = "astpretty-2.1.0.tar.gz", hash = "sha256:8a801fcda604ec741f010bb36d7cbadc3ec8a182ea6fb83e20ab663463e75ff6"}, 12 | ] 13 | 14 | [package.extras] 15 | typed = ["typed-ast"] 16 | 17 | [[package]] 18 | name = "astroid" 19 | version = "2.11.7" 20 | description = "An abstract syntax tree for Python with inference support." 21 | optional = false 22 | python-versions = ">=3.6.2" 23 | files = [ 24 | {file = "astroid-2.11.7-py3-none-any.whl", hash = "sha256:86b0a340a512c65abf4368b80252754cda17c02cdbbd3f587dddf98112233e7b"}, 25 | {file = "astroid-2.11.7.tar.gz", hash = "sha256:bb24615c77f4837c707669d16907331374ae8a964650a66999da3f5ca68dc946"}, 26 | ] 27 | 28 | [package.dependencies] 29 | lazy-object-proxy = ">=1.4.0" 30 | setuptools = ">=20.0" 31 | typed-ast = {version = ">=1.4.0,<2.0", markers = "implementation_name == \"cpython\" and python_version < \"3.8\""} 32 | typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} 33 | wrapt = ">=1.11,<2" 34 | 35 | [[package]] 36 | name = "astroid" 37 | version = "2.15.6" 38 | description = "An abstract syntax tree for Python with inference support." 39 | optional = false 40 | python-versions = ">=3.7.2" 41 | files = [ 42 | {file = "astroid-2.15.6-py3-none-any.whl", hash = "sha256:389656ca57b6108f939cf5d2f9a2a825a3be50ba9d589670f393236e0a03b91c"}, 43 | {file = "astroid-2.15.6.tar.gz", hash = "sha256:903f024859b7c7687d7a7f3a3f73b17301f8e42dfd9cc9df9d4418172d3e2dbd"}, 44 | ] 45 | 46 | [package.dependencies] 47 | lazy-object-proxy = ">=1.4.0" 48 | typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} 49 | wrapt = [ 50 | {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, 51 | {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, 52 | ] 53 | 54 | [[package]] 55 | name = "attrs" 56 | version = "23.1.0" 57 | description = "Classes Without Boilerplate" 58 | optional = false 59 | python-versions = ">=3.7" 60 | files = [ 61 | {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, 62 | {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, 63 | ] 64 | 65 | [package.dependencies] 66 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 67 | 68 | [package.extras] 69 | cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] 70 | dev = ["attrs[docs,tests]", "pre-commit"] 71 | docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] 72 | tests = ["attrs[tests-no-zope]", "zope-interface"] 73 | tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] 74 | 75 | [[package]] 76 | name = "bandit" 77 | version = "1.7.5" 78 | description = "Security oriented static analyser for python code." 79 | optional = false 80 | python-versions = ">=3.7" 81 | files = [ 82 | {file = "bandit-1.7.5-py3-none-any.whl", hash = "sha256:75665181dc1e0096369112541a056c59d1c5f66f9bb74a8d686c3c362b83f549"}, 83 | {file = "bandit-1.7.5.tar.gz", hash = "sha256:bdfc739baa03b880c2d15d0431b31c658ffc348e907fe197e54e0389dd59e11e"}, 84 | ] 85 | 86 | [package.dependencies] 87 | colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} 88 | GitPython = ">=1.0.1" 89 | PyYAML = ">=5.3.1" 90 | rich = "*" 91 | stevedore = ">=1.20.0" 92 | 93 | [package.extras] 94 | test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "tomli (>=1.1.0)"] 95 | toml = ["tomli (>=1.1.0)"] 96 | yaml = ["PyYAML"] 97 | 98 | [[package]] 99 | name = "black" 100 | version = "23.3.0" 101 | description = "The uncompromising code formatter." 102 | optional = false 103 | python-versions = ">=3.7" 104 | files = [ 105 | {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"}, 106 | {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"}, 107 | {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"}, 108 | {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"}, 109 | {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"}, 110 | {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"}, 111 | {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"}, 112 | {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"}, 113 | {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"}, 114 | {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"}, 115 | {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"}, 116 | {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"}, 117 | {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"}, 118 | {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"}, 119 | {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"}, 120 | {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"}, 121 | {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"}, 122 | {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"}, 123 | {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"}, 124 | {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"}, 125 | {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"}, 126 | {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"}, 127 | {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"}, 128 | {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"}, 129 | {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"}, 130 | ] 131 | 132 | [package.dependencies] 133 | click = ">=8.0.0" 134 | mypy-extensions = ">=0.4.3" 135 | packaging = ">=22.0" 136 | pathspec = ">=0.9.0" 137 | platformdirs = ">=2" 138 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 139 | typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} 140 | typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} 141 | 142 | [package.extras] 143 | colorama = ["colorama (>=0.4.3)"] 144 | d = ["aiohttp (>=3.7.4)"] 145 | jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] 146 | uvloop = ["uvloop (>=0.15.2)"] 147 | 148 | [[package]] 149 | name = "black" 150 | version = "23.7.0" 151 | description = "The uncompromising code formatter." 152 | optional = false 153 | python-versions = ">=3.8" 154 | files = [ 155 | {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"}, 156 | {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"}, 157 | {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"}, 158 | {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"}, 159 | {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"}, 160 | {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"}, 161 | {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"}, 162 | {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"}, 163 | {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"}, 164 | {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"}, 165 | {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"}, 166 | {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"}, 167 | {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"}, 168 | {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"}, 169 | {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"}, 170 | {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"}, 171 | {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"}, 172 | {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"}, 173 | {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"}, 174 | {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"}, 175 | {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"}, 176 | {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"}, 177 | ] 178 | 179 | [package.dependencies] 180 | click = ">=8.0.0" 181 | mypy-extensions = ">=0.4.3" 182 | packaging = ">=22.0" 183 | pathspec = ">=0.9.0" 184 | platformdirs = ">=2" 185 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 186 | typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} 187 | 188 | [package.extras] 189 | colorama = ["colorama (>=0.4.3)"] 190 | d = ["aiohttp (>=3.7.4)"] 191 | jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] 192 | uvloop = ["uvloop (>=0.15.2)"] 193 | 194 | [[package]] 195 | name = "certifi" 196 | version = "2023.7.22" 197 | description = "Python package for providing Mozilla's CA Bundle." 198 | optional = false 199 | python-versions = ">=3.6" 200 | files = [ 201 | {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, 202 | {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, 203 | ] 204 | 205 | [[package]] 206 | name = "charset-normalizer" 207 | version = "3.2.0" 208 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 209 | optional = false 210 | python-versions = ">=3.7.0" 211 | files = [ 212 | {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"}, 213 | {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"}, 214 | {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"}, 215 | {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"}, 216 | {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"}, 217 | {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"}, 218 | {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"}, 219 | {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"}, 220 | {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"}, 221 | {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"}, 222 | {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"}, 223 | {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"}, 224 | {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"}, 225 | {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"}, 226 | {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"}, 227 | {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"}, 228 | {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"}, 229 | {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"}, 230 | {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"}, 231 | {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"}, 232 | {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"}, 233 | {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"}, 234 | {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"}, 235 | {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"}, 236 | {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"}, 237 | {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"}, 238 | {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"}, 239 | {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"}, 240 | {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"}, 241 | {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"}, 242 | {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"}, 243 | {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"}, 244 | {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"}, 245 | {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"}, 246 | {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"}, 247 | {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"}, 248 | {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"}, 249 | {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"}, 250 | {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"}, 251 | {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"}, 252 | {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"}, 253 | {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"}, 254 | {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"}, 255 | {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"}, 256 | {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"}, 257 | {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"}, 258 | {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"}, 259 | {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"}, 260 | {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"}, 261 | {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"}, 262 | {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"}, 263 | {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"}, 264 | {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"}, 265 | {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"}, 266 | {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"}, 267 | {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"}, 268 | {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"}, 269 | {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"}, 270 | {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"}, 271 | {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"}, 272 | {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"}, 273 | {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"}, 274 | {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"}, 275 | {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"}, 276 | {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"}, 277 | {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"}, 278 | {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"}, 279 | {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"}, 280 | {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"}, 281 | {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"}, 282 | {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"}, 283 | {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"}, 284 | {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"}, 285 | {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"}, 286 | {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, 287 | ] 288 | 289 | [[package]] 290 | name = "click" 291 | version = "8.1.6" 292 | description = "Composable command line interface toolkit" 293 | optional = false 294 | python-versions = ">=3.7" 295 | files = [ 296 | {file = "click-8.1.6-py3-none-any.whl", hash = "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5"}, 297 | {file = "click-8.1.6.tar.gz", hash = "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd"}, 298 | ] 299 | 300 | [package.dependencies] 301 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 302 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 303 | 304 | [[package]] 305 | name = "codecov" 306 | version = "2.1.13" 307 | description = "Hosted coverage reports for GitHub, Bitbucket and Gitlab" 308 | optional = false 309 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 310 | files = [ 311 | {file = "codecov-2.1.13-py2.py3-none-any.whl", hash = "sha256:c2ca5e51bba9ebb43644c43d0690148a55086f7f5e6fd36170858fa4206744d5"}, 312 | {file = "codecov-2.1.13.tar.gz", hash = "sha256:2362b685633caeaf45b9951a9b76ce359cd3581dd515b430c6c3f5dfb4d92a8c"}, 313 | ] 314 | 315 | [package.dependencies] 316 | coverage = "*" 317 | requests = ">=2.7.9" 318 | 319 | [[package]] 320 | name = "colorama" 321 | version = "0.4.6" 322 | description = "Cross-platform colored terminal text." 323 | optional = false 324 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 325 | files = [ 326 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 327 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 328 | ] 329 | 330 | [[package]] 331 | name = "contextvars-executor" 332 | version = "0.0.1" 333 | description = "contextvars friendly ThreadPoolExecutor" 334 | optional = false 335 | python-versions = ">=3.7.0" 336 | files = [ 337 | {file = "contextvars_executor-0.0.1.tar.gz", hash = "sha256:7a47c1e8c29cbdb9006dae5d03be7fd329b5585fe8f0b62e0cd94eaf4db741bd"}, 338 | ] 339 | 340 | [[package]] 341 | name = "coverage" 342 | version = "7.2.7" 343 | description = "Code coverage measurement for Python" 344 | optional = false 345 | python-versions = ">=3.7" 346 | files = [ 347 | {file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"}, 348 | {file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"}, 349 | {file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"}, 350 | {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"}, 351 | {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"}, 352 | {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"}, 353 | {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"}, 354 | {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"}, 355 | {file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"}, 356 | {file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"}, 357 | {file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"}, 358 | {file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"}, 359 | {file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"}, 360 | {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"}, 361 | {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"}, 362 | {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"}, 363 | {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"}, 364 | {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"}, 365 | {file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"}, 366 | {file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"}, 367 | {file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"}, 368 | {file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"}, 369 | {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"}, 370 | {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"}, 371 | {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"}, 372 | {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"}, 373 | {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"}, 374 | {file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"}, 375 | {file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"}, 376 | {file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"}, 377 | {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"}, 378 | {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"}, 379 | {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"}, 380 | {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"}, 381 | {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"}, 382 | {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"}, 383 | {file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"}, 384 | {file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"}, 385 | {file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"}, 386 | {file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"}, 387 | {file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"}, 388 | {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"}, 389 | {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"}, 390 | {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"}, 391 | {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"}, 392 | {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"}, 393 | {file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"}, 394 | {file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"}, 395 | {file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"}, 396 | {file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"}, 397 | {file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"}, 398 | {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"}, 399 | {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"}, 400 | {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"}, 401 | {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"}, 402 | {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"}, 403 | {file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"}, 404 | {file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"}, 405 | {file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"}, 406 | {file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"}, 407 | ] 408 | 409 | [package.dependencies] 410 | tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} 411 | 412 | [package.extras] 413 | toml = ["tomli"] 414 | 415 | [[package]] 416 | name = "deprecated" 417 | version = "1.2.14" 418 | description = "Python @deprecated decorator to deprecate old python classes, functions or methods." 419 | optional = false 420 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 421 | files = [ 422 | {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, 423 | {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, 424 | ] 425 | 426 | [package.dependencies] 427 | wrapt = ">=1.10,<2" 428 | 429 | [package.extras] 430 | dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] 431 | 432 | [[package]] 433 | name = "dill" 434 | version = "0.3.7" 435 | description = "serialize all of Python" 436 | optional = false 437 | python-versions = ">=3.7" 438 | files = [ 439 | {file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"}, 440 | {file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"}, 441 | ] 442 | 443 | [package.extras] 444 | graph = ["objgraph (>=1.7.2)"] 445 | 446 | [[package]] 447 | name = "eradicate" 448 | version = "2.3.0" 449 | description = "Removes commented-out code." 450 | optional = false 451 | python-versions = "*" 452 | files = [ 453 | {file = "eradicate-2.3.0-py3-none-any.whl", hash = "sha256:2b29b3dd27171f209e4ddd8204b70c02f0682ae95eecb353f10e8d72b149c63e"}, 454 | {file = "eradicate-2.3.0.tar.gz", hash = "sha256:06df115be3b87d0fc1c483db22a2ebb12bcf40585722810d809cc770f5031c37"}, 455 | ] 456 | 457 | [[package]] 458 | name = "exceptiongroup" 459 | version = "1.1.3" 460 | description = "Backport of PEP 654 (exception groups)" 461 | optional = false 462 | python-versions = ">=3.7" 463 | files = [ 464 | {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, 465 | {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, 466 | ] 467 | 468 | [package.extras] 469 | test = ["pytest (>=6)"] 470 | 471 | [[package]] 472 | name = "flake8" 473 | version = "5.0.4" 474 | description = "the modular source code checker: pep8 pyflakes and co" 475 | optional = false 476 | python-versions = ">=3.6.1" 477 | files = [ 478 | {file = "flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248"}, 479 | {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"}, 480 | ] 481 | 482 | [package.dependencies] 483 | importlib-metadata = {version = ">=1.1.0,<4.3", markers = "python_version < \"3.8\""} 484 | mccabe = ">=0.7.0,<0.8.0" 485 | pycodestyle = ">=2.9.0,<2.10.0" 486 | pyflakes = ">=2.5.0,<2.6.0" 487 | 488 | [[package]] 489 | name = "flake8-annotations-complexity" 490 | version = "0.0.8" 491 | description = "A flake8 extension that checks for type annotations complexity" 492 | optional = false 493 | python-versions = ">=3.7" 494 | files = [ 495 | {file = "flake8_annotations_complexity-0.0.8-py3-none-any.whl", hash = "sha256:44e299dac0ab64f3af4b478fac7feb635c113a606036de8b39dadab3531da7ed"}, 496 | {file = "flake8_annotations_complexity-0.0.8.tar.gz", hash = "sha256:8914e76e31672c4063c928b0a250db6b935a16d1799de10457958a71d11bb665"}, 497 | ] 498 | 499 | [package.dependencies] 500 | flake8 = "*" 501 | 502 | [[package]] 503 | name = "flake8-awesome" 504 | version = "1.3.0" 505 | description = "Flake8 awesome plugins pack" 506 | optional = false 507 | python-versions = ">=3.6,<4.0" 508 | files = [ 509 | {file = "flake8-awesome-1.3.0.tar.gz", hash = "sha256:bc6b807abcd25474259a184311e9c394f0eb265b0ea7aa93b4c802a835da40ac"}, 510 | {file = "flake8_awesome-1.3.0-py3-none-any.whl", hash = "sha256:f2c6246432e8d38d6e25dd53b1622e6ab643913cf313a6a82e27d61f7cd8097f"}, 511 | ] 512 | 513 | [package.dependencies] 514 | flake8 = "*" 515 | flake8-annotations-complexity = "*" 516 | flake8-bandit = "*" 517 | flake8-breakpoint = "*" 518 | flake8-bugbear = "*" 519 | flake8-builtins = "*" 520 | flake8-comprehensions = "*" 521 | flake8-eradicate = "*" 522 | flake8-expression-complexity = "*" 523 | flake8-if-expr = "*" 524 | flake8-isort = "*" 525 | flake8-logging-format = "*" 526 | flake8-print = "*" 527 | flake8-pytest = "*" 528 | flake8-pytest-style = "*" 529 | flake8-requirements = "*" 530 | flake8-return = "*" 531 | pep8-naming = "*" 532 | 533 | [[package]] 534 | name = "flake8-bandit" 535 | version = "4.1.1" 536 | description = "Automated security testing with bandit and flake8." 537 | optional = false 538 | python-versions = ">=3.6" 539 | files = [ 540 | {file = "flake8_bandit-4.1.1-py3-none-any.whl", hash = "sha256:4c8a53eb48f23d4ef1e59293657181a3c989d0077c9952717e98a0eace43e06d"}, 541 | {file = "flake8_bandit-4.1.1.tar.gz", hash = "sha256:068e09287189cbfd7f986e92605adea2067630b75380c6b5733dab7d87f9a84e"}, 542 | ] 543 | 544 | [package.dependencies] 545 | bandit = ">=1.7.3" 546 | flake8 = ">=5.0.0" 547 | 548 | [[package]] 549 | name = "flake8-breakpoint" 550 | version = "1.1.0" 551 | description = "Flake8 plugin that check forgotten breakpoints" 552 | optional = false 553 | python-versions = ">=3.6,<4.0" 554 | files = [ 555 | {file = "flake8-breakpoint-1.1.0.tar.gz", hash = "sha256:5bc70d478f0437a3655d094e1d2fca81ddacabaa84d99db45ad3630bf2004064"}, 556 | {file = "flake8_breakpoint-1.1.0-py3-none-any.whl", hash = "sha256:27e0cb132647f9ef348b4a3c3126e7350bedbb22e8e221cd11712a223855ea0b"}, 557 | ] 558 | 559 | [package.dependencies] 560 | flake8-plugin-utils = ">=1.0,<2.0" 561 | 562 | [[package]] 563 | name = "flake8-bugbear" 564 | version = "23.3.12" 565 | description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." 566 | optional = false 567 | python-versions = ">=3.7" 568 | files = [ 569 | {file = "flake8-bugbear-23.3.12.tar.gz", hash = "sha256:e3e7f74c8a49ad3794a7183353026dabd68c74030d5f46571f84c1fb0eb79363"}, 570 | {file = "flake8_bugbear-23.3.12-py3-none-any.whl", hash = "sha256:beb5c7efcd7ccc2039ef66a77bb8db925e7be3531ff1cb4d0b7030d0e2113d72"}, 571 | ] 572 | 573 | [package.dependencies] 574 | attrs = ">=19.2.0" 575 | flake8 = ">=3.0.0" 576 | 577 | [package.extras] 578 | dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] 579 | 580 | [[package]] 581 | name = "flake8-builtins" 582 | version = "2.1.0" 583 | description = "Check for python builtins being used as variables or parameters." 584 | optional = false 585 | python-versions = ">=3.7" 586 | files = [ 587 | {file = "flake8-builtins-2.1.0.tar.gz", hash = "sha256:12ff1ee96dd4e1f3141141ee6c45a5c7d3b3c440d0949e9b8d345c42b39c51d4"}, 588 | {file = "flake8_builtins-2.1.0-py3-none-any.whl", hash = "sha256:469e8f03d6d0edf4b1e62b6d5a97dce4598592c8a13ec8f0952e7a185eba50a1"}, 589 | ] 590 | 591 | [package.dependencies] 592 | flake8 = "*" 593 | 594 | [package.extras] 595 | test = ["pytest"] 596 | 597 | [[package]] 598 | name = "flake8-comprehensions" 599 | version = "3.13.0" 600 | description = "A flake8 plugin to help you write better list/set/dict comprehensions." 601 | optional = false 602 | python-versions = ">=3.7" 603 | files = [ 604 | {file = "flake8_comprehensions-3.13.0-py3-none-any.whl", hash = "sha256:cc0d6dbb336ff4e9cdf4eb605a3f719ea59261f2d6ba52034871a173c40e1f60"}, 605 | {file = "flake8_comprehensions-3.13.0.tar.gz", hash = "sha256:83cf98e816c9e23360f36aaf47de59a5b21437fdff8a056c46e2ad49f81861bf"}, 606 | ] 607 | 608 | [package.dependencies] 609 | flake8 = ">=3.0,<3.2.0 || >3.2.0" 610 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 611 | 612 | [[package]] 613 | name = "flake8-eradicate" 614 | version = "1.4.0" 615 | description = "Flake8 plugin to find commented out code" 616 | optional = false 617 | python-versions = ">=3.7,<4.0" 618 | files = [ 619 | {file = "flake8-eradicate-1.4.0.tar.gz", hash = "sha256:3088cfd6717d1c9c6c3ac45ef2e5f5b6c7267f7504d5a74b781500e95cb9c7e1"}, 620 | {file = "flake8_eradicate-1.4.0-py3-none-any.whl", hash = "sha256:e3bbd0871be358e908053c1ab728903c114f062ba596b4d40c852fd18f473d56"}, 621 | ] 622 | 623 | [package.dependencies] 624 | attrs = "*" 625 | eradicate = ">=2.0,<3.0" 626 | flake8 = ">=3.5,<6" 627 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 628 | 629 | [[package]] 630 | name = "flake8-expression-complexity" 631 | version = "0.0.11" 632 | description = "A flake8 extension that checks expressions complexity" 633 | optional = false 634 | python-versions = ">=3.7" 635 | files = [ 636 | {file = "flake8_expression_complexity-0.0.11-py3-none-any.whl", hash = "sha256:b56bac37f7dd5d3d102a7111c89f6579c2cbd897b868147794c9ed12aadc627c"}, 637 | {file = "flake8_expression_complexity-0.0.11.tar.gz", hash = "sha256:4dd8909fecbc20f53814cdcef9d0b04f61532764278d9b6e8026686812e96631"}, 638 | ] 639 | 640 | [package.dependencies] 641 | astpretty = "*" 642 | flake8 = "*" 643 | 644 | [[package]] 645 | name = "flake8-if-expr" 646 | version = "1.0.4" 647 | description = "The plugin checks `if expressions` (ternary operator)" 648 | optional = false 649 | python-versions = ">=3.6,<4.0" 650 | files = [ 651 | {file = "flake8-if-expr-1.0.4.tar.gz", hash = "sha256:e0050b59b46114b6e20628d61175a7a608d3eb55fb5b90d87db0f9352a91a491"}, 652 | {file = "flake8_if_expr-1.0.4-py3-none-any.whl", hash = "sha256:3f2d45cc1e48b4cdf22377ca1624b2a59b6f1c7825ba1cdee99ff1e647e7ae3f"}, 653 | ] 654 | 655 | [package.dependencies] 656 | flake8-plugin-utils = ">=1.0,<2.0" 657 | 658 | [[package]] 659 | name = "flake8-isort" 660 | version = "6.0.0" 661 | description = "flake8 plugin that integrates isort ." 662 | optional = false 663 | python-versions = ">=3.7" 664 | files = [ 665 | {file = "flake8-isort-6.0.0.tar.gz", hash = "sha256:537f453a660d7e903f602ecfa36136b140de279df58d02eb1b6a0c84e83c528c"}, 666 | {file = "flake8_isort-6.0.0-py3-none-any.whl", hash = "sha256:aa0cac02a62c7739e370ce6b9c31743edac904bae4b157274511fc8a19c75bbc"}, 667 | ] 668 | 669 | [package.dependencies] 670 | flake8 = "*" 671 | isort = ">=5.0.0,<6" 672 | 673 | [package.extras] 674 | test = ["pytest"] 675 | 676 | [[package]] 677 | name = "flake8-logging-format" 678 | version = "0.9.0" 679 | description = "" 680 | optional = false 681 | python-versions = "*" 682 | files = [ 683 | {file = "flake8-logging-format-0.9.0.tar.gz", hash = "sha256:e830cc49091e4b8ab9ea3da69a3da074bd631ce9a7db300e5c89fb48ba4a6986"}, 684 | ] 685 | 686 | [package.extras] 687 | lint = ["flake8"] 688 | test = ["PyHamcrest", "pytest", "pytest-cov"] 689 | 690 | [[package]] 691 | name = "flake8-plugin-utils" 692 | version = "1.3.3" 693 | description = "The package provides base classes and utils for flake8 plugin writing" 694 | optional = false 695 | python-versions = ">=3.6,<4.0" 696 | files = [ 697 | {file = "flake8-plugin-utils-1.3.3.tar.gz", hash = "sha256:39f6f338d038b301c6fd344b06f2e81e382b68fa03c0560dff0d9b1791a11a2c"}, 698 | {file = "flake8_plugin_utils-1.3.3-py3-none-any.whl", hash = "sha256:e4848c57d9d50f19100c2d75fa794b72df068666a9041b4b0409be923356a3ed"}, 699 | ] 700 | 701 | [[package]] 702 | name = "flake8-print" 703 | version = "5.0.0" 704 | description = "print statement checker plugin for flake8" 705 | optional = false 706 | python-versions = ">=3.7" 707 | files = [ 708 | {file = "flake8-print-5.0.0.tar.gz", hash = "sha256:76915a2a389cc1c0879636c219eb909c38501d3a43cc8dae542081c9ba48bdf9"}, 709 | {file = "flake8_print-5.0.0-py3-none-any.whl", hash = "sha256:84a1a6ea10d7056b804221ac5e62b1cee1aefc897ce16f2e5c42d3046068f5d8"}, 710 | ] 711 | 712 | [package.dependencies] 713 | flake8 = ">=3.0" 714 | pycodestyle = "*" 715 | 716 | [[package]] 717 | name = "flake8-pytest" 718 | version = "1.4" 719 | description = "pytest assert checker plugin for flake8" 720 | optional = false 721 | python-versions = "*" 722 | files = [ 723 | {file = "flake8-pytest-1.4.tar.gz", hash = "sha256:19f543b2d1cc89d61b76f19d0a9e58e9a110a035175f701b3425c363a7732c56"}, 724 | {file = "flake8_pytest-1.4-py2.py3-none-any.whl", hash = "sha256:97328f258ffad9fe18babb3b0714a16b121505ad3ac87d4e33020874555d0784"}, 725 | ] 726 | 727 | [package.dependencies] 728 | flake8 = "*" 729 | 730 | [[package]] 731 | name = "flake8-pytest-style" 732 | version = "1.6.0" 733 | description = "A flake8 plugin checking common style issues or inconsistencies with pytest-based tests." 734 | optional = false 735 | python-versions = ">=3.6.2,<4.0.0" 736 | files = [ 737 | {file = "flake8-pytest-style-1.6.0.tar.gz", hash = "sha256:c1175713e9e11b78cd1a035ed0bca0d1e41d09c4af329a952750b61d4194ddac"}, 738 | {file = "flake8_pytest_style-1.6.0-py3-none-any.whl", hash = "sha256:5fedb371a950e9fe0e0e6bfc854be7d99151271208f34cd2cc517681ece27780"}, 739 | ] 740 | 741 | [package.dependencies] 742 | flake8-plugin-utils = ">=1.3.2,<2.0.0" 743 | 744 | [[package]] 745 | name = "flake8-requirements" 746 | version = "1.7.8" 747 | description = "Package requirements checker, plugin for flake8" 748 | optional = false 749 | python-versions = "*" 750 | files = [ 751 | {file = "flake8_requirements-1.7.8-py2.py3-none-any.whl", hash = "sha256:137e13d383823d821bccfd6f54a0244d592291312ddee21a4cf1c4c250813270"}, 752 | ] 753 | 754 | [package.dependencies] 755 | flake8 = ">=2.0.0" 756 | setuptools = ">=10.0.0" 757 | tomli = {version = ">=1.2.1", markers = "python_version < \"3.11\""} 758 | 759 | [[package]] 760 | name = "flake8-return" 761 | version = "1.2.0" 762 | description = "Flake8 plugin that checks return values" 763 | optional = false 764 | python-versions = ">=3.6,<4.0" 765 | files = [ 766 | {file = "flake8-return-1.2.0.tar.gz", hash = "sha256:68dfa56582cd704febd02ad86dcf5df67e38e0836d62f1ceae7930d76d3dd955"}, 767 | {file = "flake8_return-1.2.0-py3-none-any.whl", hash = "sha256:1f07af12954ed03ebe2c2aac2418f78b55374e9929d4956109664588f31582a1"}, 768 | ] 769 | 770 | [package.dependencies] 771 | flake8-plugin-utils = ">=1.0,<2.0" 772 | 773 | [[package]] 774 | name = "gitdb" 775 | version = "4.0.10" 776 | description = "Git Object Database" 777 | optional = false 778 | python-versions = ">=3.7" 779 | files = [ 780 | {file = "gitdb-4.0.10-py3-none-any.whl", hash = "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7"}, 781 | {file = "gitdb-4.0.10.tar.gz", hash = "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a"}, 782 | ] 783 | 784 | [package.dependencies] 785 | smmap = ">=3.0.1,<6" 786 | 787 | [[package]] 788 | name = "gitpython" 789 | version = "3.1.32" 790 | description = "GitPython is a Python library used to interact with Git repositories" 791 | optional = false 792 | python-versions = ">=3.7" 793 | files = [ 794 | {file = "GitPython-3.1.32-py3-none-any.whl", hash = "sha256:e3d59b1c2c6ebb9dfa7a184daf3b6dd4914237e7488a1730a6d8f6f5d0b4187f"}, 795 | {file = "GitPython-3.1.32.tar.gz", hash = "sha256:8d9b8cb1e80b9735e8717c9362079d3ce4c6e5ddeebedd0361b228c3a67a62f6"}, 796 | ] 797 | 798 | [package.dependencies] 799 | gitdb = ">=4.0.1,<5" 800 | typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.8\""} 801 | 802 | [[package]] 803 | name = "idna" 804 | version = "3.4" 805 | description = "Internationalized Domain Names in Applications (IDNA)" 806 | optional = false 807 | python-versions = ">=3.5" 808 | files = [ 809 | {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, 810 | {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, 811 | ] 812 | 813 | [[package]] 814 | name = "importlib-metadata" 815 | version = "4.2.0" 816 | description = "Read metadata from Python packages" 817 | optional = false 818 | python-versions = ">=3.6" 819 | files = [ 820 | {file = "importlib_metadata-4.2.0-py3-none-any.whl", hash = "sha256:057e92c15bc8d9e8109738a48db0ccb31b4d9d5cfbee5a8670879a30be66304b"}, 821 | {file = "importlib_metadata-4.2.0.tar.gz", hash = "sha256:b7e52a1f8dec14a75ea73e0891f3060099ca1d8e6a462a4dff11c3e119ea1b31"}, 822 | ] 823 | 824 | [package.dependencies] 825 | typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} 826 | zipp = ">=0.5" 827 | 828 | [package.extras] 829 | docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"] 830 | testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pep517", "pyfakefs", "pytest (>=4.6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy"] 831 | 832 | [[package]] 833 | name = "iniconfig" 834 | version = "2.0.0" 835 | description = "brain-dead simple config-ini parsing" 836 | optional = false 837 | python-versions = ">=3.7" 838 | files = [ 839 | {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, 840 | {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, 841 | ] 842 | 843 | [[package]] 844 | name = "isort" 845 | version = "5.11.5" 846 | description = "A Python utility / library to sort Python imports." 847 | optional = false 848 | python-versions = ">=3.7.0" 849 | files = [ 850 | {file = "isort-5.11.5-py3-none-any.whl", hash = "sha256:ba1d72fb2595a01c7895a5128f9585a5cc4b6d395f1c8d514989b9a7eb2a8746"}, 851 | {file = "isort-5.11.5.tar.gz", hash = "sha256:6be1f76a507cb2ecf16c7cf14a37e41609ca082330be4e3436a18ef74add55db"}, 852 | ] 853 | 854 | [package.extras] 855 | colors = ["colorama (>=0.4.3,<0.5.0)"] 856 | pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] 857 | plugins = ["setuptools"] 858 | requirements-deprecated-finder = ["pip-api", "pipreqs"] 859 | 860 | [[package]] 861 | name = "lazy-object-proxy" 862 | version = "1.9.0" 863 | description = "A fast and thorough lazy object proxy." 864 | optional = false 865 | python-versions = ">=3.7" 866 | files = [ 867 | {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, 868 | {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, 869 | {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, 870 | {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, 871 | {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, 872 | {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, 873 | {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, 874 | {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, 875 | {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, 876 | {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, 877 | {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, 878 | {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, 879 | {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, 880 | {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, 881 | {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, 882 | {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, 883 | {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, 884 | {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, 885 | {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, 886 | {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, 887 | {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, 888 | {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, 889 | {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, 890 | {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, 891 | {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, 892 | {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, 893 | {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, 894 | {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, 895 | {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, 896 | {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, 897 | {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, 898 | {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, 899 | {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, 900 | {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, 901 | {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, 902 | {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, 903 | ] 904 | 905 | [[package]] 906 | name = "markdown-it-py" 907 | version = "2.2.0" 908 | description = "Python port of markdown-it. Markdown parsing, done right!" 909 | optional = false 910 | python-versions = ">=3.7" 911 | files = [ 912 | {file = "markdown-it-py-2.2.0.tar.gz", hash = "sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1"}, 913 | {file = "markdown_it_py-2.2.0-py3-none-any.whl", hash = "sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30"}, 914 | ] 915 | 916 | [package.dependencies] 917 | mdurl = ">=0.1,<1.0" 918 | typing_extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} 919 | 920 | [package.extras] 921 | benchmarking = ["psutil", "pytest", "pytest-benchmark"] 922 | code-style = ["pre-commit (>=3.0,<4.0)"] 923 | compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] 924 | linkify = ["linkify-it-py (>=1,<3)"] 925 | plugins = ["mdit-py-plugins"] 926 | profiling = ["gprof2dot"] 927 | rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] 928 | testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] 929 | 930 | [[package]] 931 | name = "mccabe" 932 | version = "0.7.0" 933 | description = "McCabe checker, plugin for flake8" 934 | optional = false 935 | python-versions = ">=3.6" 936 | files = [ 937 | {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, 938 | {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, 939 | ] 940 | 941 | [[package]] 942 | name = "mdurl" 943 | version = "0.1.2" 944 | description = "Markdown URL utilities" 945 | optional = false 946 | python-versions = ">=3.7" 947 | files = [ 948 | {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, 949 | {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, 950 | ] 951 | 952 | [[package]] 953 | name = "mypy" 954 | version = "1.4.1" 955 | description = "Optional static typing for Python" 956 | optional = false 957 | python-versions = ">=3.7" 958 | files = [ 959 | {file = "mypy-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:566e72b0cd6598503e48ea610e0052d1b8168e60a46e0bfd34b3acf2d57f96a8"}, 960 | {file = "mypy-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ca637024ca67ab24a7fd6f65d280572c3794665eaf5edcc7e90a866544076878"}, 961 | {file = "mypy-1.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dde1d180cd84f0624c5dcaaa89c89775550a675aff96b5848de78fb11adabcd"}, 962 | {file = "mypy-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8c4d8e89aa7de683e2056a581ce63c46a0c41e31bd2b6d34144e2c80f5ea53dc"}, 963 | {file = "mypy-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:bfdca17c36ae01a21274a3c387a63aa1aafe72bff976522886869ef131b937f1"}, 964 | {file = "mypy-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7549fbf655e5825d787bbc9ecf6028731973f78088fbca3a1f4145c39ef09462"}, 965 | {file = "mypy-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:98324ec3ecf12296e6422939e54763faedbfcc502ea4a4c38502082711867258"}, 966 | {file = "mypy-1.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:141dedfdbfe8a04142881ff30ce6e6653c9685b354876b12e4fe6c78598b45e2"}, 967 | {file = "mypy-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8207b7105829eca6f3d774f64a904190bb2231de91b8b186d21ffd98005f14a7"}, 968 | {file = "mypy-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:16f0db5b641ba159eff72cff08edc3875f2b62b2fa2bc24f68c1e7a4e8232d01"}, 969 | {file = "mypy-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:470c969bb3f9a9efcedbadcd19a74ffb34a25f8e6b0e02dae7c0e71f8372f97b"}, 970 | {file = "mypy-1.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5952d2d18b79f7dc25e62e014fe5a23eb1a3d2bc66318df8988a01b1a037c5b"}, 971 | {file = "mypy-1.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:190b6bab0302cec4e9e6767d3eb66085aef2a1cc98fe04936d8a42ed2ba77bb7"}, 972 | {file = "mypy-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9d40652cc4fe33871ad3338581dca3297ff5f2213d0df345bcfbde5162abf0c9"}, 973 | {file = "mypy-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:01fd2e9f85622d981fd9063bfaef1aed6e336eaacca00892cd2d82801ab7c042"}, 974 | {file = "mypy-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2460a58faeea905aeb1b9b36f5065f2dc9a9c6e4c992a6499a2360c6c74ceca3"}, 975 | {file = "mypy-1.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2746d69a8196698146a3dbe29104f9eb6a2a4d8a27878d92169a6c0b74435b6"}, 976 | {file = "mypy-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ae704dcfaa180ff7c4cfbad23e74321a2b774f92ca77fd94ce1049175a21c97f"}, 977 | {file = "mypy-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:43d24f6437925ce50139a310a64b2ab048cb2d3694c84c71c3f2a1626d8101dc"}, 978 | {file = "mypy-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c482e1246726616088532b5e964e39765b6d1520791348e6c9dc3af25b233828"}, 979 | {file = "mypy-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:43b592511672017f5b1a483527fd2684347fdffc041c9ef53428c8dc530f79a3"}, 980 | {file = "mypy-1.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34a9239d5b3502c17f07fd7c0b2ae6b7dd7d7f6af35fbb5072c6208e76295816"}, 981 | {file = "mypy-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5703097c4936bbb9e9bce41478c8d08edd2865e177dc4c52be759f81ee4dd26c"}, 982 | {file = "mypy-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e02d700ec8d9b1859790c0475df4e4092c7bf3272a4fd2c9f33d87fac4427b8f"}, 983 | {file = "mypy-1.4.1-py3-none-any.whl", hash = "sha256:45d32cec14e7b97af848bddd97d85ea4f0db4d5a149ed9676caa4eb2f7402bb4"}, 984 | {file = "mypy-1.4.1.tar.gz", hash = "sha256:9bbcd9ab8ea1f2e1c8031c21445b511442cc45c89951e49bbf852cbb70755b1b"}, 985 | ] 986 | 987 | [package.dependencies] 988 | mypy-extensions = ">=1.0.0" 989 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 990 | typed-ast = {version = ">=1.4.0,<2", markers = "python_version < \"3.8\""} 991 | typing-extensions = ">=4.1.0" 992 | 993 | [package.extras] 994 | dmypy = ["psutil (>=4.0)"] 995 | install-types = ["pip"] 996 | python2 = ["typed-ast (>=1.4.0,<2)"] 997 | reports = ["lxml"] 998 | 999 | [[package]] 1000 | name = "mypy-extensions" 1001 | version = "1.0.0" 1002 | description = "Type system extensions for programs checked with the mypy type checker." 1003 | optional = false 1004 | python-versions = ">=3.5" 1005 | files = [ 1006 | {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, 1007 | {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, 1008 | ] 1009 | 1010 | [[package]] 1011 | name = "packaging" 1012 | version = "23.1" 1013 | description = "Core utilities for Python packages" 1014 | optional = false 1015 | python-versions = ">=3.7" 1016 | files = [ 1017 | {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, 1018 | {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, 1019 | ] 1020 | 1021 | [[package]] 1022 | name = "pathspec" 1023 | version = "0.11.2" 1024 | description = "Utility library for gitignore style pattern matching of file paths." 1025 | optional = false 1026 | python-versions = ">=3.7" 1027 | files = [ 1028 | {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, 1029 | {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, 1030 | ] 1031 | 1032 | [[package]] 1033 | name = "pbr" 1034 | version = "5.11.1" 1035 | description = "Python Build Reasonableness" 1036 | optional = false 1037 | python-versions = ">=2.6" 1038 | files = [ 1039 | {file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"}, 1040 | {file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"}, 1041 | ] 1042 | 1043 | [[package]] 1044 | name = "pep8-naming" 1045 | version = "0.13.3" 1046 | description = "Check PEP-8 naming conventions, plugin for flake8" 1047 | optional = false 1048 | python-versions = ">=3.7" 1049 | files = [ 1050 | {file = "pep8-naming-0.13.3.tar.gz", hash = "sha256:1705f046dfcd851378aac3be1cd1551c7c1e5ff363bacad707d43007877fa971"}, 1051 | {file = "pep8_naming-0.13.3-py3-none-any.whl", hash = "sha256:1a86b8c71a03337c97181917e2b472f0f5e4ccb06844a0d6f0a33522549e7a80"}, 1052 | ] 1053 | 1054 | [package.dependencies] 1055 | flake8 = ">=5.0.0" 1056 | 1057 | [[package]] 1058 | name = "platformdirs" 1059 | version = "3.10.0" 1060 | description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 1061 | optional = false 1062 | python-versions = ">=3.7" 1063 | files = [ 1064 | {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, 1065 | {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, 1066 | ] 1067 | 1068 | [package.dependencies] 1069 | typing-extensions = {version = ">=4.7.1", markers = "python_version < \"3.8\""} 1070 | 1071 | [package.extras] 1072 | docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] 1073 | test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] 1074 | 1075 | [[package]] 1076 | name = "pluggy" 1077 | version = "1.2.0" 1078 | description = "plugin and hook calling mechanisms for python" 1079 | optional = false 1080 | python-versions = ">=3.7" 1081 | files = [ 1082 | {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"}, 1083 | {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, 1084 | ] 1085 | 1086 | [package.dependencies] 1087 | importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} 1088 | 1089 | [package.extras] 1090 | dev = ["pre-commit", "tox"] 1091 | testing = ["pytest", "pytest-benchmark"] 1092 | 1093 | [[package]] 1094 | name = "py" 1095 | version = "1.11.0" 1096 | description = "library with cross-python path, ini-parsing, io, code, log facilities" 1097 | optional = false 1098 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 1099 | files = [ 1100 | {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, 1101 | {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, 1102 | ] 1103 | 1104 | [[package]] 1105 | name = "pycodestyle" 1106 | version = "2.9.1" 1107 | description = "Python style guide checker" 1108 | optional = false 1109 | python-versions = ">=3.6" 1110 | files = [ 1111 | {file = "pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b"}, 1112 | {file = "pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785"}, 1113 | ] 1114 | 1115 | [[package]] 1116 | name = "pyflakes" 1117 | version = "2.5.0" 1118 | description = "passive checker of Python programs" 1119 | optional = false 1120 | python-versions = ">=3.6" 1121 | files = [ 1122 | {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"}, 1123 | {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"}, 1124 | ] 1125 | 1126 | [[package]] 1127 | name = "pygments" 1128 | version = "2.16.1" 1129 | description = "Pygments is a syntax highlighting package written in Python." 1130 | optional = false 1131 | python-versions = ">=3.7" 1132 | files = [ 1133 | {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, 1134 | {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, 1135 | ] 1136 | 1137 | [package.extras] 1138 | plugins = ["importlib-metadata"] 1139 | 1140 | [[package]] 1141 | name = "pylint" 1142 | version = "2.13.9" 1143 | description = "python code static checker" 1144 | optional = false 1145 | python-versions = ">=3.6.2" 1146 | files = [ 1147 | {file = "pylint-2.13.9-py3-none-any.whl", hash = "sha256:705c620d388035bdd9ff8b44c5bcdd235bfb49d276d488dd2c8ff1736aa42526"}, 1148 | {file = "pylint-2.13.9.tar.gz", hash = "sha256:095567c96e19e6f57b5b907e67d265ff535e588fe26b12b5ebe1fc5645b2c731"}, 1149 | ] 1150 | 1151 | [package.dependencies] 1152 | astroid = ">=2.11.5,<=2.12.0-dev0" 1153 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 1154 | dill = ">=0.2" 1155 | isort = ">=4.2.5,<6" 1156 | mccabe = ">=0.6,<0.8" 1157 | platformdirs = ">=2.2.0" 1158 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 1159 | typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} 1160 | 1161 | [package.extras] 1162 | testutil = ["gitpython (>3)"] 1163 | 1164 | [[package]] 1165 | name = "pylint" 1166 | version = "2.17.5" 1167 | description = "python code static checker" 1168 | optional = false 1169 | python-versions = ">=3.7.2" 1170 | files = [ 1171 | {file = "pylint-2.17.5-py3-none-any.whl", hash = "sha256:73995fb8216d3bed149c8d51bba25b2c52a8251a2c8ac846ec668ce38fab5413"}, 1172 | {file = "pylint-2.17.5.tar.gz", hash = "sha256:f7b601cbc06fef7e62a754e2b41294c2aa31f1cb659624b9a85bcba29eaf8252"}, 1173 | ] 1174 | 1175 | [package.dependencies] 1176 | astroid = ">=2.15.6,<=2.17.0-dev0" 1177 | colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} 1178 | dill = [ 1179 | {version = ">=0.2", markers = "python_version < \"3.11\""}, 1180 | {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, 1181 | ] 1182 | isort = ">=4.2.5,<6" 1183 | mccabe = ">=0.6,<0.8" 1184 | platformdirs = ">=2.2.0" 1185 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 1186 | tomlkit = ">=0.10.1" 1187 | typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} 1188 | 1189 | [package.extras] 1190 | spelling = ["pyenchant (>=3.2,<4.0)"] 1191 | testutils = ["gitpython (>3)"] 1192 | 1193 | [[package]] 1194 | name = "pytest" 1195 | version = "7.4.3" 1196 | description = "pytest: simple powerful testing with Python" 1197 | optional = false 1198 | python-versions = ">=3.7" 1199 | files = [ 1200 | {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"}, 1201 | {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"}, 1202 | ] 1203 | 1204 | [package.dependencies] 1205 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 1206 | exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} 1207 | importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} 1208 | iniconfig = "*" 1209 | packaging = "*" 1210 | pluggy = ">=0.12,<2.0" 1211 | tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} 1212 | 1213 | [package.extras] 1214 | testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] 1215 | 1216 | [[package]] 1217 | name = "pytest-asyncio" 1218 | version = "0.21.1" 1219 | description = "Pytest support for asyncio" 1220 | optional = false 1221 | python-versions = ">=3.7" 1222 | files = [ 1223 | {file = "pytest-asyncio-0.21.1.tar.gz", hash = "sha256:40a7eae6dded22c7b604986855ea48400ab15b069ae38116e8c01238e9eeb64d"}, 1224 | {file = "pytest_asyncio-0.21.1-py3-none-any.whl", hash = "sha256:8666c1c8ac02631d7c51ba282e0c69a8a452b211ffedf2599099845da5c5c37b"}, 1225 | ] 1226 | 1227 | [package.dependencies] 1228 | pytest = ">=7.0.0" 1229 | typing-extensions = {version = ">=3.7.2", markers = "python_version < \"3.8\""} 1230 | 1231 | [package.extras] 1232 | docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] 1233 | testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] 1234 | 1235 | [[package]] 1236 | name = "pytest-cov" 1237 | version = "4.1.0" 1238 | description = "Pytest plugin for measuring coverage." 1239 | optional = false 1240 | python-versions = ">=3.7" 1241 | files = [ 1242 | {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, 1243 | {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, 1244 | ] 1245 | 1246 | [package.dependencies] 1247 | coverage = {version = ">=5.2.1", extras = ["toml"]} 1248 | pytest = ">=4.6" 1249 | 1250 | [package.extras] 1251 | testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] 1252 | 1253 | [[package]] 1254 | name = "pytest-deadfixtures" 1255 | version = "2.2.1" 1256 | description = "A simple plugin to list unused fixtures in pytest" 1257 | optional = false 1258 | python-versions = "*" 1259 | files = [ 1260 | {file = "pytest-deadfixtures-2.2.1.tar.gz", hash = "sha256:ca15938a4e8330993ccec9c6c847383d88b3cd574729530647dc6b492daa9c1e"}, 1261 | {file = "pytest_deadfixtures-2.2.1-py2.py3-none-any.whl", hash = "sha256:db71533f2d9456227084e00a1231e732973e299ccb7c37ab92e95032ab6c083e"}, 1262 | ] 1263 | 1264 | [package.dependencies] 1265 | pytest = ">=3.0.0" 1266 | 1267 | [[package]] 1268 | name = "pytest-mock" 1269 | version = "3.11.1" 1270 | description = "Thin-wrapper around the mock package for easier use with pytest" 1271 | optional = false 1272 | python-versions = ">=3.7" 1273 | files = [ 1274 | {file = "pytest-mock-3.11.1.tar.gz", hash = "sha256:7f6b125602ac6d743e523ae0bfa71e1a697a2f5534064528c6ff84c2f7c2fc7f"}, 1275 | {file = "pytest_mock-3.11.1-py3-none-any.whl", hash = "sha256:21c279fff83d70763b05f8874cc9cfb3fcacd6d354247a976f9529d19f9acf39"}, 1276 | ] 1277 | 1278 | [package.dependencies] 1279 | pytest = ">=5.0" 1280 | 1281 | [package.extras] 1282 | dev = ["pre-commit", "pytest-asyncio", "tox"] 1283 | 1284 | [[package]] 1285 | name = "pyyaml" 1286 | version = "6.0.1" 1287 | description = "YAML parser and emitter for Python" 1288 | optional = false 1289 | python-versions = ">=3.6" 1290 | files = [ 1291 | {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, 1292 | {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, 1293 | {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, 1294 | {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, 1295 | {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, 1296 | {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, 1297 | {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, 1298 | {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, 1299 | {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, 1300 | {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, 1301 | {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, 1302 | {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, 1303 | {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, 1304 | {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, 1305 | {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, 1306 | {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, 1307 | {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, 1308 | {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, 1309 | {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, 1310 | {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, 1311 | {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, 1312 | {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, 1313 | {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, 1314 | {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, 1315 | {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, 1316 | {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, 1317 | {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, 1318 | {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, 1319 | {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, 1320 | {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, 1321 | {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, 1322 | {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, 1323 | {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, 1324 | {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, 1325 | {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, 1326 | {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, 1327 | {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, 1328 | {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, 1329 | {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, 1330 | {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, 1331 | {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, 1332 | {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, 1333 | {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, 1334 | {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, 1335 | {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, 1336 | {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, 1337 | {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, 1338 | {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, 1339 | {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, 1340 | {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, 1341 | ] 1342 | 1343 | [[package]] 1344 | name = "requests" 1345 | version = "2.31.0" 1346 | description = "Python HTTP for Humans." 1347 | optional = false 1348 | python-versions = ">=3.7" 1349 | files = [ 1350 | {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, 1351 | {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, 1352 | ] 1353 | 1354 | [package.dependencies] 1355 | certifi = ">=2017.4.17" 1356 | charset-normalizer = ">=2,<4" 1357 | idna = ">=2.5,<4" 1358 | urllib3 = ">=1.21.1,<3" 1359 | 1360 | [package.extras] 1361 | socks = ["PySocks (>=1.5.6,!=1.5.7)"] 1362 | use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] 1363 | 1364 | [[package]] 1365 | name = "rich" 1366 | version = "13.5.2" 1367 | description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" 1368 | optional = false 1369 | python-versions = ">=3.7.0" 1370 | files = [ 1371 | {file = "rich-13.5.2-py3-none-any.whl", hash = "sha256:146a90b3b6b47cac4a73c12866a499e9817426423f57c5a66949c086191a8808"}, 1372 | {file = "rich-13.5.2.tar.gz", hash = "sha256:fb9d6c0a0f643c99eed3875b5377a184132ba9be4d61516a55273d3554d75a39"}, 1373 | ] 1374 | 1375 | [package.dependencies] 1376 | markdown-it-py = ">=2.2.0" 1377 | pygments = ">=2.13.0,<3.0.0" 1378 | typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.9\""} 1379 | 1380 | [package.extras] 1381 | jupyter = ["ipywidgets (>=7.5.1,<9)"] 1382 | 1383 | [[package]] 1384 | name = "setuptools" 1385 | version = "68.0.0" 1386 | description = "Easily download, build, install, upgrade, and uninstall Python packages" 1387 | optional = false 1388 | python-versions = ">=3.7" 1389 | files = [ 1390 | {file = "setuptools-68.0.0-py3-none-any.whl", hash = "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f"}, 1391 | {file = "setuptools-68.0.0.tar.gz", hash = "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"}, 1392 | ] 1393 | 1394 | [package.extras] 1395 | docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] 1396 | testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] 1397 | testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] 1398 | 1399 | [[package]] 1400 | name = "smmap" 1401 | version = "5.0.0" 1402 | description = "A pure Python implementation of a sliding window memory map manager" 1403 | optional = false 1404 | python-versions = ">=3.6" 1405 | files = [ 1406 | {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, 1407 | {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, 1408 | ] 1409 | 1410 | [[package]] 1411 | name = "stevedore" 1412 | version = "3.5.2" 1413 | description = "Manage dynamic plugins for Python applications" 1414 | optional = false 1415 | python-versions = ">=3.6" 1416 | files = [ 1417 | {file = "stevedore-3.5.2-py3-none-any.whl", hash = "sha256:fa2630e3d0ad3e22d4914aff2501445815b9a4467a6edc49387c667a38faf5bf"}, 1418 | {file = "stevedore-3.5.2.tar.gz", hash = "sha256:cf99f41fc0d5a4f185ca4d3d42b03be9011b0a1ec1a4ea1a282be1b4b306dcc2"}, 1419 | ] 1420 | 1421 | [package.dependencies] 1422 | importlib-metadata = {version = ">=1.7.0", markers = "python_version < \"3.8\""} 1423 | pbr = ">=2.0.0,<2.1.0 || >2.1.0" 1424 | 1425 | [[package]] 1426 | name = "tomli" 1427 | version = "2.0.1" 1428 | description = "A lil' TOML parser" 1429 | optional = false 1430 | python-versions = ">=3.7" 1431 | files = [ 1432 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 1433 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 1434 | ] 1435 | 1436 | [[package]] 1437 | name = "tomlkit" 1438 | version = "0.12.1" 1439 | description = "Style preserving TOML library" 1440 | optional = false 1441 | python-versions = ">=3.7" 1442 | files = [ 1443 | {file = "tomlkit-0.12.1-py3-none-any.whl", hash = "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899"}, 1444 | {file = "tomlkit-0.12.1.tar.gz", hash = "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86"}, 1445 | ] 1446 | 1447 | [[package]] 1448 | name = "typed-ast" 1449 | version = "1.5.5" 1450 | description = "a fork of Python 2 and 3 ast modules with type comment support" 1451 | optional = false 1452 | python-versions = ">=3.6" 1453 | files = [ 1454 | {file = "typed_ast-1.5.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4bc1efe0ce3ffb74784e06460f01a223ac1f6ab31c6bc0376a21184bf5aabe3b"}, 1455 | {file = "typed_ast-1.5.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5f7a8c46a8b333f71abd61d7ab9255440d4a588f34a21f126bbfc95f6049e686"}, 1456 | {file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:597fc66b4162f959ee6a96b978c0435bd63791e31e4f410622d19f1686d5e769"}, 1457 | {file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d41b7a686ce653e06c2609075d397ebd5b969d821b9797d029fccd71fdec8e04"}, 1458 | {file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5fe83a9a44c4ce67c796a1b466c270c1272e176603d5e06f6afbc101a572859d"}, 1459 | {file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d5c0c112a74c0e5db2c75882a0adf3133adedcdbfd8cf7c9d6ed77365ab90a1d"}, 1460 | {file = "typed_ast-1.5.5-cp310-cp310-win_amd64.whl", hash = "sha256:e1a976ed4cc2d71bb073e1b2a250892a6e968ff02aa14c1f40eba4f365ffec02"}, 1461 | {file = "typed_ast-1.5.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c631da9710271cb67b08bd3f3813b7af7f4c69c319b75475436fcab8c3d21bee"}, 1462 | {file = "typed_ast-1.5.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b445c2abfecab89a932b20bd8261488d574591173d07827c1eda32c457358b18"}, 1463 | {file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc95ffaaab2be3b25eb938779e43f513e0e538a84dd14a5d844b8f2932593d88"}, 1464 | {file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61443214d9b4c660dcf4b5307f15c12cb30bdfe9588ce6158f4a005baeb167b2"}, 1465 | {file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6eb936d107e4d474940469e8ec5b380c9b329b5f08b78282d46baeebd3692dc9"}, 1466 | {file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e48bf27022897577d8479eaed64701ecaf0467182448bd95759883300ca818c8"}, 1467 | {file = "typed_ast-1.5.5-cp311-cp311-win_amd64.whl", hash = "sha256:83509f9324011c9a39faaef0922c6f720f9623afe3fe220b6d0b15638247206b"}, 1468 | {file = "typed_ast-1.5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:44f214394fc1af23ca6d4e9e744804d890045d1643dd7e8229951e0ef39429b5"}, 1469 | {file = "typed_ast-1.5.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:118c1ce46ce58fda78503eae14b7664163aa735b620b64b5b725453696f2a35c"}, 1470 | {file = "typed_ast-1.5.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be4919b808efa61101456e87f2d4c75b228f4e52618621c77f1ddcaae15904fa"}, 1471 | {file = "typed_ast-1.5.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:fc2b8c4e1bc5cd96c1a823a885e6b158f8451cf6f5530e1829390b4d27d0807f"}, 1472 | {file = "typed_ast-1.5.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:16f7313e0a08c7de57f2998c85e2a69a642e97cb32f87eb65fbfe88381a5e44d"}, 1473 | {file = "typed_ast-1.5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:2b946ef8c04f77230489f75b4b5a4a6f24c078be4aed241cfabe9cbf4156e7e5"}, 1474 | {file = "typed_ast-1.5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2188bc33d85951ea4ddad55d2b35598b2709d122c11c75cffd529fbc9965508e"}, 1475 | {file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0635900d16ae133cab3b26c607586131269f88266954eb04ec31535c9a12ef1e"}, 1476 | {file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57bfc3cf35a0f2fdf0a88a3044aafaec1d2f24d8ae8cd87c4f58d615fb5b6311"}, 1477 | {file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:fe58ef6a764de7b4b36edfc8592641f56e69b7163bba9f9c8089838ee596bfb2"}, 1478 | {file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d09d930c2d1d621f717bb217bf1fe2584616febb5138d9b3e8cdd26506c3f6d4"}, 1479 | {file = "typed_ast-1.5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:d40c10326893ecab8a80a53039164a224984339b2c32a6baf55ecbd5b1df6431"}, 1480 | {file = "typed_ast-1.5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fd946abf3c31fb50eee07451a6aedbfff912fcd13cf357363f5b4e834cc5e71a"}, 1481 | {file = "typed_ast-1.5.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ed4a1a42df8a3dfb6b40c3d2de109e935949f2f66b19703eafade03173f8f437"}, 1482 | {file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:045f9930a1550d9352464e5149710d56a2aed23a2ffe78946478f7b5416f1ede"}, 1483 | {file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:381eed9c95484ceef5ced626355fdc0765ab51d8553fec08661dce654a935db4"}, 1484 | {file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bfd39a41c0ef6f31684daff53befddae608f9daf6957140228a08e51f312d7e6"}, 1485 | {file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8c524eb3024edcc04e288db9541fe1f438f82d281e591c548903d5b77ad1ddd4"}, 1486 | {file = "typed_ast-1.5.5-cp38-cp38-win_amd64.whl", hash = "sha256:7f58fabdde8dcbe764cef5e1a7fcb440f2463c1bbbec1cf2a86ca7bc1f95184b"}, 1487 | {file = "typed_ast-1.5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:042eb665ff6bf020dd2243307d11ed626306b82812aba21836096d229fdc6a10"}, 1488 | {file = "typed_ast-1.5.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:622e4a006472b05cf6ef7f9f2636edc51bda670b7bbffa18d26b255269d3d814"}, 1489 | {file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1efebbbf4604ad1283e963e8915daa240cb4bf5067053cf2f0baadc4d4fb51b8"}, 1490 | {file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0aefdd66f1784c58f65b502b6cf8b121544680456d1cebbd300c2c813899274"}, 1491 | {file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:48074261a842acf825af1968cd912f6f21357316080ebaca5f19abbb11690c8a"}, 1492 | {file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:429ae404f69dc94b9361bb62291885894b7c6fb4640d561179548c849f8492ba"}, 1493 | {file = "typed_ast-1.5.5-cp39-cp39-win_amd64.whl", hash = "sha256:335f22ccb244da2b5c296e6f96b06ee9bed46526db0de38d2f0e5a6597b81155"}, 1494 | {file = "typed_ast-1.5.5.tar.gz", hash = "sha256:94282f7a354f36ef5dbce0ef3467ebf6a258e370ab33d5b40c249fa996e590dd"}, 1495 | ] 1496 | 1497 | [[package]] 1498 | name = "types-deprecated" 1499 | version = "1.2.9.3" 1500 | description = "Typing stubs for Deprecated" 1501 | optional = false 1502 | python-versions = "*" 1503 | files = [ 1504 | {file = "types-Deprecated-1.2.9.3.tar.gz", hash = "sha256:ef87327adf3e3c4a4c7d8e06e58f6476710d3466ecfb53c49efb080804a70ef3"}, 1505 | {file = "types_Deprecated-1.2.9.3-py3-none-any.whl", hash = "sha256:24da9210763e5e1b3d0d4f6f8bba9ad3bb6af3fe7f6815fc37e3ede4681704f5"}, 1506 | ] 1507 | 1508 | [[package]] 1509 | name = "typing-extensions" 1510 | version = "4.7.1" 1511 | description = "Backported and Experimental Type Hints for Python 3.7+" 1512 | optional = false 1513 | python-versions = ">=3.7" 1514 | files = [ 1515 | {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, 1516 | {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, 1517 | ] 1518 | 1519 | [[package]] 1520 | name = "unify" 1521 | version = "0.5" 1522 | description = "Modifies strings to all use the same (single/double) quote where possible." 1523 | optional = false 1524 | python-versions = "*" 1525 | files = [ 1526 | {file = "unify-0.5.tar.gz", hash = "sha256:8ddce812b2457212b7598fe574c9e6eb3ad69710f445391338270c7f8a71723c"}, 1527 | ] 1528 | 1529 | [package.dependencies] 1530 | untokenize = "*" 1531 | 1532 | [[package]] 1533 | name = "untokenize" 1534 | version = "0.1.1" 1535 | description = "Transforms tokens into original source code (while preserving whitespace)." 1536 | optional = false 1537 | python-versions = "*" 1538 | files = [ 1539 | {file = "untokenize-0.1.1.tar.gz", hash = "sha256:3865dbbbb8efb4bb5eaa72f1be7f3e0be00ea8b7f125c69cbd1f5fda926f37a2"}, 1540 | ] 1541 | 1542 | [[package]] 1543 | name = "urllib3" 1544 | version = "2.0.4" 1545 | description = "HTTP library with thread-safe connection pooling, file post, and more." 1546 | optional = false 1547 | python-versions = ">=3.7" 1548 | files = [ 1549 | {file = "urllib3-2.0.4-py3-none-any.whl", hash = "sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"}, 1550 | {file = "urllib3-2.0.4.tar.gz", hash = "sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11"}, 1551 | ] 1552 | 1553 | [package.extras] 1554 | brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] 1555 | secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] 1556 | socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] 1557 | zstd = ["zstandard (>=0.18.0)"] 1558 | 1559 | [[package]] 1560 | name = "wrapt" 1561 | version = "1.15.0" 1562 | description = "Module for decorators, wrappers and monkey patching." 1563 | optional = false 1564 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 1565 | files = [ 1566 | {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, 1567 | {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, 1568 | {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, 1569 | {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, 1570 | {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, 1571 | {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, 1572 | {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, 1573 | {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, 1574 | {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, 1575 | {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, 1576 | {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, 1577 | {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, 1578 | {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, 1579 | {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, 1580 | {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, 1581 | {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, 1582 | {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, 1583 | {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, 1584 | {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, 1585 | {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, 1586 | {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, 1587 | {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, 1588 | {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, 1589 | {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, 1590 | {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, 1591 | {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, 1592 | {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, 1593 | {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, 1594 | {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, 1595 | {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, 1596 | {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, 1597 | {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, 1598 | {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, 1599 | {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, 1600 | {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, 1601 | {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, 1602 | {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, 1603 | {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, 1604 | {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, 1605 | {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, 1606 | {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, 1607 | {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, 1608 | {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, 1609 | {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, 1610 | {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, 1611 | {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, 1612 | {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, 1613 | {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, 1614 | {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, 1615 | {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, 1616 | {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, 1617 | {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, 1618 | {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, 1619 | {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, 1620 | {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, 1621 | {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, 1622 | {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, 1623 | {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, 1624 | {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, 1625 | {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, 1626 | {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, 1627 | {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, 1628 | {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, 1629 | {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, 1630 | {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, 1631 | {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, 1632 | {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, 1633 | {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, 1634 | {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, 1635 | {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, 1636 | {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, 1637 | {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, 1638 | {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, 1639 | {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, 1640 | {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, 1641 | ] 1642 | 1643 | [[package]] 1644 | name = "zipp" 1645 | version = "3.15.0" 1646 | description = "Backport of pathlib-compatible object wrapper for zip files" 1647 | optional = false 1648 | python-versions = ">=3.7" 1649 | files = [ 1650 | {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, 1651 | {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, 1652 | ] 1653 | 1654 | [package.extras] 1655 | docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] 1656 | testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] 1657 | 1658 | [metadata] 1659 | lock-version = "2.0" 1660 | python-versions = "^3.7" 1661 | content-hash = "5fb39de2b3fef2a1195dd2e79ddc4a37696966ce93bb2a6127c4c0f3216434b4" 1662 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "context_logging" 3 | version = "1.2.0" 4 | description = "Tool for easy logging with current context information" 5 | authors = ["Evgeniy Afonasev "] 6 | license = "MIT" 7 | readme = 'README.md' 8 | repository = "https://github.com/Afonasev/context_logging" 9 | homepage = "https://pypi.org/project/context_logging" 10 | keywords = ["logging", "logger", "context"] 11 | 12 | [tool.poetry.dependencies] 13 | python = "^3.7" 14 | contextvars_executor = "^0.0.1" 15 | deprecated = "^1.2.10" 16 | 17 | [tool.poetry.group.dev.dependencies] 18 | black = [ 19 | { version = ">=23.7", python = ">=3.8" }, 20 | { version = "<=23.7", python = "<3.8" } 21 | ] 22 | codecov = "^2.1.8" 23 | flake8-awesome = "^1" 24 | mypy = "*" 25 | pylint = [ 26 | { version = "^2.17.5", python = ">=3.8" }, 27 | { version = "^2", python = "<3.8" } 28 | ] 29 | py = "^1.11" 30 | pytest = "^7" 31 | pytest-asyncio = "^0.21" 32 | pytest-cov = "^4" 33 | pytest-deadfixtures = "^2" 34 | pytest-mock = "^3" 35 | types-deprecated = "^1.2.9.3" 36 | unify = "^0.5" 37 | 38 | [build-system] 39 | requires = ["poetry>=1.0"] 40 | build-backend = "poetry.masonry.api" 41 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | enable-extensions = G 3 | exclude = .git, .venv 4 | ignore = 5 | # 'id' is a python builtin, consider renaming the class attribute 6 | A003 7 | # line break before binary operator 8 | W503 9 | # Use of assert detected 10 | S101 11 | max-complexity = 8 12 | max-annotations-complexity = 3 13 | max-expression-complexity = 7 14 | max-line-length = 120 15 | show-source = true 16 | 17 | [mypy] 18 | check_untyped_defs = true 19 | disallow_any_generics = true 20 | disallow_incomplete_defs = true 21 | disallow_untyped_defs = true 22 | ignore_missing_imports = True 23 | no_implicit_optional = true 24 | 25 | [mypy-tests.*] 26 | disallow_untyped_defs = false 27 | 28 | [isort] 29 | balanced_wrapping = true 30 | default_section = THIRDPARTY 31 | include_trailing_comma=True 32 | known_first_party = context_logging, tests 33 | line_length = 79 34 | multi_line_output = 3 35 | 36 | [pylint] 37 | good-names=i,j,k,e,x,_,pk,id 38 | max-args=5 39 | max-attributes=10 40 | max-bool-expr=5 41 | max-module-lines=200 42 | max-nested-blocks=2 43 | max-public-methods=5 44 | max-returns=5 45 | max-statements=20 46 | output-format = colorized 47 | 48 | disable= 49 | C0103, # Constant name "api" doesn't conform to UPPER_CASE naming style (invalid-name) 50 | C0111, # Missing module docstring (missing-docstring) 51 | E0213, # Method should have "self" as first argument (no-self-argument) - N805 for flake8 52 | R0901, # Too many ancestors (m/n) (too-many-ancestors) 53 | R0903, # Too few public methods (m/n) (too-few-public-methods) 54 | 55 | ignored-classes= 56 | contextlib.closing, 57 | context_logging.context.ContextInfo, 58 | 59 | [coverage:run] 60 | omit = tests/*,**/__main__.py 61 | branch = True 62 | 63 | [coverage:report] 64 | show_missing = True 65 | skip_covered = True 66 | fail_under = 95 67 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/afonasev/context_logging/b85a1b24cf8304c1461e3b47e1e4b2b43142adb6/tests/__init__.py -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/afonasev/context_logging/b85a1b24cf8304c1461e3b47e1e4b2b43142adb6/tests/conftest.py -------------------------------------------------------------------------------- /tests/test_context_logging.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | import time 4 | from concurrent.futures import ThreadPoolExecutor 5 | from unittest.mock import ANY 6 | 7 | import pytest 8 | 9 | from context_logging import ContextVarExecutor 10 | from context_logging.context import ( 11 | Context, 12 | ContextObject, 13 | current_context, 14 | root_context, 15 | ) 16 | from context_logging.log_record import setup_log_record 17 | from context_logging.logger import logger 18 | 19 | 20 | def test_context_object_finish(caplog): 21 | context = ContextObject( 22 | name='name', 23 | log_execution_time=True, 24 | fill_exception_context=True, 25 | context_data={}, 26 | ) 27 | context.start() 28 | context.finish() 29 | assert 'name: executed in' in caplog.records[-1].message 30 | 31 | 32 | def test_root_context(): 33 | assert root_context == {} 34 | current_context['val'] = 1 35 | assert root_context == {'val': 1} 36 | root_context.clear() 37 | 38 | 39 | def test_current_context(): 40 | assert current_context == {} 41 | 42 | with Context(data='outer', outer=''): 43 | assert current_context == {'data': 'outer', 'outer': ''} 44 | 45 | with Context(data='inner', inner=''): 46 | assert current_context == { 47 | 'data': 'inner', 48 | 'outer': '', 49 | 'inner': '', 50 | } 51 | 52 | assert current_context == {'data': 'outer', 'outer': ''} 53 | 54 | assert current_context == {} 55 | 56 | 57 | def test_writing_to_context_info(): 58 | assert current_context == {} 59 | 60 | with Context(): 61 | assert current_context == {} 62 | 63 | current_context['test'] = 'test' 64 | assert current_context == {'test': 'test'} 65 | 66 | assert current_context == {} 67 | 68 | 69 | def test_context_as_decorator(): 70 | @Context(data='data') 71 | def wrapped(): 72 | assert current_context == {'data': 'data'} 73 | 74 | assert current_context == {} 75 | wrapped() 76 | assert current_context == {} 77 | 78 | 79 | def test_context_with_start_finish(): 80 | context = Context(data='data') 81 | assert current_context == {} 82 | 83 | context.start() 84 | assert current_context == {'data': 'data'} 85 | 86 | context.finish() 87 | assert current_context == {} 88 | 89 | 90 | def test_default_name(): 91 | assert 'test_context_logging.py' in Context().name 92 | 93 | 94 | def test_execution_time(mocker): 95 | mocker.spy(logger, 'info') 96 | context = Context() 97 | 98 | with context: 99 | pass 100 | 101 | logger.info.assert_called_once_with( # type: ignore 102 | '%s: executed in %s', context.name, ANY 103 | ) 104 | 105 | 106 | def test_fill_exception_context(): 107 | try: 108 | with Context(data=1): 109 | raise Exception('error') 110 | except Exception as exc: 111 | assert exc.args == ('error', {'data': 1}) # noqa:PT017 112 | 113 | 114 | def test_fill_exception_last_context(): 115 | try: 116 | with Context(data=1): 117 | with Context(data=2): 118 | raise Exception('error') 119 | except Exception as exc: 120 | assert exc.args == ('error', {'data': 2}) # noqa:PT017 121 | 122 | 123 | def test_log_record(caplog): 124 | setup_log_record() 125 | 126 | logging.info('test') 127 | assert caplog.records[-1].context == '' 128 | 129 | with Context(data=1): 130 | logging.info('test') 131 | assert caplog.records[-1].context == {'data': 1} 132 | 133 | 134 | def sync_task(): 135 | assert current_context['data'] == 1 136 | current_context['data'] = 2 137 | 138 | 139 | async def async_task(): 140 | sync_task() 141 | 142 | 143 | @pytest.mark.asyncio() 144 | async def test_context_passing_to_asyncio_task_with_context_leaking(): 145 | with Context(data=1): 146 | await asyncio.create_task(async_task()) 147 | assert current_context['data'] == 2 148 | 149 | 150 | @pytest.mark.asyncio() 151 | async def test_context_passing_to_asyncio_task_with_separate_context(): 152 | with Context(data=1): 153 | wrapped_task = Context()(async_task) 154 | await asyncio.create_task(wrapped_task()) # type: ignore 155 | assert current_context['data'] == 1 156 | 157 | 158 | def test_context_passing_to_thread_without_context_var_executor(): 159 | with Context(data=1): 160 | with ThreadPoolExecutor() as executor: 161 | with pytest.raises(KeyError): 162 | executor.submit(sync_task).result() 163 | 164 | 165 | def test_context_passing_to_thread_with_context_leaking(): 166 | with Context(data=1): 167 | with ContextVarExecutor() as executor: 168 | executor.submit(sync_task).result() 169 | 170 | assert current_context['data'] == 2 171 | 172 | 173 | def test_context_passing_to_thread_with_separate_context(): 174 | with Context(data=1): 175 | with ContextVarExecutor() as executor: 176 | wrapped_task = Context()(sync_task) 177 | executor.submit(wrapped_task).result() 178 | 179 | assert current_context['data'] == 1 180 | 181 | 182 | @Context() 183 | def not_safe_long_task(n): 184 | time.sleep(0.1) 185 | assert current_context['data'] == 'start' 186 | 187 | current_context['data'] = n 188 | assert current_context['data'] == n 189 | 190 | for _ in range(3): 191 | time.sleep(0.1) 192 | assert current_context['data'] == n 193 | 194 | 195 | def test_multithreading_context_leaking(): 196 | with Context(data='start'): 197 | with ContextVarExecutor() as executor: 198 | for _ in executor.map(not_safe_long_task, range(5)): 199 | pass 200 | 201 | assert current_context['data'] == 'start' 202 | --------------------------------------------------------------------------------