diff --git a/.circleci/config.yml b/.circleci/config.yml index 1a667fa..5766a7d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,7 +12,7 @@ workflows: jobs: test-3.6: &test-template docker: - - image: circleci/python:3.6-buster + - image: circleci/python:3.6-buster filters: branches: only: @@ -42,7 +42,7 @@ jobs: command: | . venv/bin/activate nosetests --with-coverage --cover-package=traces - coveralls + codecov pycodestyle traces/ pytest --mpl tests/test_plot.py --mpl-results-path=/tmp/artifacts - store_artifacts: diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..461ca0d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +max_line_length = 80 + +[*.json] +indent_style = space +indent_size = 2 diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index dc50455..f13b172 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,5 +1,5 @@ -* Simplicity is better than functionality -* The API matters most, everything else is secondary +- Simplicity is better than functionality +- The API matters most, everything else is secondary For feature requests, please include a description of why the feature will be useful to most users. diff --git a/.github/actions/setup-poetry-env/action.yml b/.github/actions/setup-poetry-env/action.yml new file mode 100644 index 0000000..22e4053 --- /dev/null +++ b/.github/actions/setup-poetry-env/action.yml @@ -0,0 +1,33 @@ +name: "setup-poetry-env" +description: "Composite action to setup the Python and poetry environment." + +inputs: + python-version: + required: false + description: "The python version to use" + default: "3.11" + +runs: + using: "composite" + steps: + - name: Set up python + uses: actions/setup-python@v4 + with: + python-version: ${{ inputs.python-version }} + + - name: Install Poetry + uses: snok/install-poetry@v1 + with: + virtualenvs-in-project: true + + - name: Load cached venv + id: cached-poetry-dependencies + uses: actions/cache@v3 + with: + path: .venv + key: venv-${{ runner.os }}-${{ inputs.python-version }}-${{ hashFiles('poetry.lock') }} + + - name: Install dependencies + if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' + run: poetry install --no-interaction + shell: bash diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..bdf879d --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,74 @@ +name: Main + +on: + push: + branches: + - main + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + quality: + runs-on: ubuntu-latest + steps: + - name: Check out + uses: actions/checkout@v3 + + - uses: actions/cache@v3 + with: + path: ~/.cache/pre-commit + key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} + + - name: Set up the environment + uses: ./.github/actions/setup-poetry-env + + - name: Run checks + run: make check + + tox: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11"] + fail-fast: false + steps: + - name: Check out + uses: actions/checkout@v3 + + - name: Set up python + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Poetry + uses: snok/install-poetry@v1 + + - name: Load cached venv + uses: actions/cache@v3 + with: + path: .tox + key: venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }} + + - name: Install tox + run: | + python -m pip install --upgrade pip + python -m pip install tox tox-gh-actions + + - name: Test with tox + run: tox + + - name: Upload coverage reports to Codecov with GitHub Action on Python 3.11 + uses: codecov/codecov-action@v3 + if: ${{ matrix.python-version == '3.11' }} + + check-docs: + runs-on: ubuntu-latest + steps: + - name: Check out + uses: actions/checkout@v3 + + - name: Set up the environment + uses: ./.github/actions/setup-poetry-env + + - name: Check if documentation can be built + run: poetry run mkdocs build -s diff --git a/.github/workflows/on-release-main.yml b/.github/workflows/on-release-main.yml new file mode 100644 index 0000000..96327f9 --- /dev/null +++ b/.github/workflows/on-release-main.yml @@ -0,0 +1,42 @@ +name: release-main + +on: + release: + types: [published] + branches: [main] + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - name: Check out + uses: actions/checkout@v3 + + - name: Set up the environment + uses: ./.github/actions/setup-poetry-env + + - name: Export tag + id: vars + run: echo tag=${GITHUB_REF#refs/*/} >> $GITHUB_OUTPUT + + - name: Build and publish + run: | + source .venv/bin/activate + poetry version $RELEASE_VERSION + make build-and-publish + env: + PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} + RELEASE_VERSION: ${{ steps.vars.outputs.tag }} + + deploy-docs: + needs: publish + runs-on: ubuntu-latest + steps: + - name: Check out + uses: actions/checkout@v3 + + - name: Set up the environment + uses: ./.github/actions/setup-poetry-env + + - name: Deploy documentation + run: poetry run mkdocs gh-deploy --force diff --git a/.github/workflows/validate-codecov-config.yml b/.github/workflows/validate-codecov-config.yml new file mode 100644 index 0000000..d063161 --- /dev/null +++ b/.github/workflows/validate-codecov-config.yml @@ -0,0 +1,15 @@ +name: validate-codecov-config + +on: + pull_request: + paths: [codecov.yaml] + push: + branches: [main] + +jobs: + validate-codecov-config: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + - name: Validate codecov configuration + run: curl -sSL --fail-with-body --data-binary @codecov.yaml https://codecov.io/validate diff --git a/.gitignore b/.gitignore index 36bfed8..9823e6a 100644 --- a/.gitignore +++ b/.gitignore @@ -47,8 +47,8 @@ cover *.mo *.pot -# Django stuff: -*.log +# IPython stuff +.ipynb_checkpoints/ # mkdocs docs/_build @@ -56,3 +56,171 @@ docs/_build # PyBuilder target/ .vscode + +docs/source + +# From https://raw.githubusercontent.com/github/gitignore/main/Python.gitignore + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# Vscode config files +.vscode/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..5e3015b --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,22 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: "v4.4.0" + hooks: + - id: check-case-conflict + - id: check-merge-conflict + - id: check-toml + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: "v0.1.6" + hooks: + - id: ruff + args: [--exit-non-zero-on-fix] + - id: ruff-format + + - repo: https://github.com/pre-commit/mirrors-prettier + rev: "v3.0.3" + hooks: + - id: prettier diff --git a/CHANGELOG.md b/CHANGELOG.md index a5693d9..825c32f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1 @@ -Changelog -========= +# Changelog diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ecd15b..b2554f0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,147 +1,149 @@ -Authors (chronological) -======================= +# Authors (chronological) -- [Mike Stringer](https://datascopeanalytics.com/team/mike-stringer/) -- [Vlad Seghete](https://datascopeanalytics.com/team/vlad-seghete/) -- [Yoke Peng - Leong](https://datascopeanalytics.com/team/yoke-peng-leong/) +- [Mike Stringer](https://datascopeanalytics.com/team/mike-stringer/) +- [Vlad Seghete](https://datascopeanalytics.com/team/vlad-seghete/) +- [Yoke Peng Leong](https://datascopeanalytics.com/team/yoke-peng-leong/) -Contributing -============ +# Design Philosophy -Contributions are welcome, and they are greatly appreciated! Every -little bit helps, and credit will always be given. You can contribute in -many ways. +- "Simplicity is better than functionality." - Pieter Hintjens +- "The API matters most, everything else is secondary." - Kenneth + Reitz -Design Philosophy ------------------ +# Contributing to `traces` -- "Simplicity is better than functionality." - Pieter Hintjens -- "The API matters most, everything else is secondary." - Kenneth - Reitz +Contributions are welcome, and they are greatly appreciated! +Every little bit helps, and credit will always be given. -Types of Contributions ----------------------- +You can contribute in many ways: -### Report Bugs +# Types of Contributions -Report bugs at . +## Report Bugs + +Report bugs at https://github.com/stringertheory/traces/issues If you are reporting a bug, please include: -- Your operating system name and version. -- Any details about your local setup that might be helpful - in troubleshooting. -- Detailed steps to reproduce the bug. +- Your operating system name and version. +- Any details about your local setup that might be helpful in troubleshooting. +- Detailed steps to reproduce the bug. -### Fix Bugs +## Fix Bugs -Look through the GitHub issues for bugs. Anything tagged with "bug" and -"help wanted" is open to whoever wants to implement it. +Look through the GitHub issues for bugs. Anything tagged with "bug" +and "help wanted" is open to whoever wants to implement a fix for it. -### Implement Features +## Implement Features Look through the GitHub issues for features. Anything tagged with "enhancement" and "help wanted" is open to whoever wants to implement it. -### Write Documentation +## Write Documentation -traces could always use more documentation, whether as part of the -official traces docs, in docstrings, or even on the web in blog posts, +Traces could always use more documentation, whether as part of the +official docs, in docstrings, or even on the web in blog posts, articles, and such. -### Submit Feedback +## Submit Feedback The best way to send feedback is to file an issue at -. +https://github.com/stringertheory/traces/issues. + +If you are proposing a new feature: + +- Explain in detail how it would work. +- Keep the scope as narrow as possible, to make it easier to implement. +- Remember that this is a volunteer-driven project, and that contributions + are welcome :) + +# Get Started! + +Ready to contribute? Here's how to set up `traces` for local development. +Please note this documentation assumes you already have `poetry` and `Git` installed and ready to go. -If you are proposing a feature: +1. Fork the `traces` repo on GitHub. -- Explain in detail how it would work. -- Keep the scope as narrow as possible, to make it easier - to implement. -- Remember that this is a volunteer-driven project, and that - contributions are welcome :) +2. Clone your fork locally: -When you are suggesting an enhancement, please include specific use -cases that demonstrate why the proposed enhancement is useful and make -sure that the proposed enhancement is aligned with the goals of the -project. +```bash +cd +git clone git@github.com:YOUR_NAME/traces.git +``` -Get Started! ------------- +3. Now we need to install the environment. Navigate into the directory -Ready to contribute? Here's how to set up `traces` for local -development. +```bash +cd traces +``` -1. Fork the `traces` repo on GitHub. -2. Clone your fork locally: +If you are using `pyenv`, select a version to use locally. (See installed versions with `pyenv versions`) - ``` {.sourceCode .bash} - $ git clone git@github.com:your_name_here/traces.git - ``` +```bash +pyenv local +``` -3. Install your local copy into a virtualenv. Assuming you have - virtualenvwrapper installed, this is how you set up your fork for - local development: +Then, install and activate the environment with: - ``` {.sourceCode .bash} - $ mkvirtualenv traces - $ cd traces/ - $ python setup.py develop - ``` +```bash +poetry install +poetry shell +``` -4. Create a branch for local development: +4. Install pre-commit to run linters/formatters at commit time: - ``` {.sourceCode .bash} - $ git checkout -b name-of-your-bugfix-or-feature - ``` +```bash +poetry run pre-commit install +``` + +5. Create a branch for local development: + +```bash +git checkout -b name-of-your-bugfix-or-feature +``` Now you can make your changes locally. -5. When you're done making changes, check that your changes pass flake8 - and the tests, including testing other Python versions with tox: +6. Don't forget to add test cases for your added functionality to the `tests` directory. - .. code:: bash +7. When you're done making changes, check that your changes pass the formatting tests. - > \$ flake8 traces tests \$ python setup.py test or py.test \$ tox +```bash +make check +``` -To get flake8 and tox, just pip install them into your virtualenv. +Now, validate that all unit tests are passing: -6. Commit your changes and push your branch to GitHub: +```bash +make test +``` - ``` {.sourceCode .bash} - $ git add . - $ git commit -m "Your detailed description of your changes." - $ git push origin name-of-your-bugfix-or-feature - ``` +9. Before raising a pull request you should also run tox. + This will run the tests across different versions of Python: -7. Submit a pull request through the GitHub website. +```bash +tox +``` -Pull Request Guidelines ------------------------ +This requires you to have multiple versions of python installed. +This step is also triggered in the CI/CD pipeline, so you could also choose to skip this step locally. -Pull requests are welcome! If the pull request is in response to an -existing Bug Report or Enhancement Request, please refer to it in the -description. Otherwise, if the pull request is a bug fix then make sure -to describe the bug just like if it were a bug report issue. If it's an -enhancement, describe the uses cases like you would when creating an -enhancement request. +10. Commit your changes and push your branch to GitHub: -Before you submit a pull request, check that it meets these guidelines: +```bash +git add . +git commit -m "Your detailed description of your changes." +git push origin name-of-your-bugfix-or-feature +``` -1. The pull request should include tests. -2. If the pull request adds functionality, the docs should be updated. - Put your new functionality into a function with a docstring, and add - the feature to the list in README.rst. -3. The pull request should work for Python 3.5-3.8. Check - and make sure - that the tests pass for all supported Python versions. +11. Submit a pull request through the GitHub website. -Tips ----- +# Pull Request Guidelines + +Before you submit a pull request, check that it meets these guidelines: -To run a subset of tests: +1. The pull request should include tests. - $ python -m unittest tests.test_traces +2. If the pull request adds functionality, the docs should be updated. + Put your new functionality into a function with a docstring, and add the feature to the list in `README.md`. diff --git a/LICENSE b/LICENSE index 7a513dc..af7ef8d 100755 --- a/LICENSE +++ b/LICENSE @@ -8,4 +8,3 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/Makefile b/Makefile index 798eec2..dd50a46 100644 --- a/Makefile +++ b/Makefile @@ -1,82 +1,55 @@ -.PHONY: clean clean-test clean-pyc clean-build docs help -.DEFAULT_GOAL := help -define BROWSER_PYSCRIPT -import os, webbrowser, sys -try: - from urllib import pathname2url -except: - from urllib.request import pathname2url - -webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1]))) -endef -export BROWSER_PYSCRIPT - -define PRINT_HELP_PYSCRIPT -import re, sys - -for line in sys.stdin: - match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line) - if match: - target, help = match.groups() - print("%-20s %s" % (target, help)) -endef -export PRINT_HELP_PYSCRIPT -BROWSER := python -c "$$BROWSER_PYSCRIPT" - +.PHONY: install +install: ## Install the poetry environment and install the pre-commit hooks + @echo "🚀 Creating virtual environment using pyenv and poetry" + @poetry install + @ poetry run pre-commit install + @poetry shell + +.PHONY: check +check: ## Run code quality tools. + @echo "🚀 Checking Poetry lock file consistency with 'pyproject.toml': Running poetry lock --check" + @poetry check --lock + @echo "🚀 Linting code: Running pre-commit" + @poetry run pre-commit run -a + # @echo "🚀 Static type checking: Running mypy" + # @poetry run mypy + +.PHONY: test +test: ## Test the code with pytest + @echo "🚀 Testing code: Running pytest" + @poetry run pytest --cov --cov-config=pyproject.toml --cov-report=xml + +.PHONY: build +build: clean-build ## Build wheel file using poetry + @echo "🚀 Creating wheel file" + @poetry build + +.PHONY: clean-build +clean-build: ## clean build artifacts + @rm -rf dist + +.PHONY: publish +publish: ## publish a release to pypi. + @echo "🚀 Publishing: Dry run." + @poetry config pypi-token.pypi $(PYPI_TOKEN) + @poetry publish --dry-run + @echo "🚀 Publishing." + @poetry publish + +.PHONY: build-and-publish +build-and-publish: build publish ## Build and publish. + +.PHONY: docs-test +docs-test: ## Test if documentation can be built without warnings or errors + @poetry run mkdocs build -s + +.PHONY: docs +docs: ## Build and serve the documentation + # @poetry run mkdocs serve -a localhost:8002 + @poetry run sphinx-autobuild --port 8002 docs docs/_build/html + +.PHONY: help help: - @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) - -clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts - - -clean-build: ## remove build artifacts - rm -fr build/ - rm -fr dist/ - rm -fr .eggs/ - find . -name '*.egg-info' -exec rm -fr {} + - find . -name '*.egg' -exec rm -f {} + - -clean-pyc: ## remove Python file artifacts - find . -name '*.pyc' -exec rm -f {} + - find . -name '*.pyo' -exec rm -f {} + - find . -name '*~' -exec rm -f {} + - find . -name '__pycache__' -exec rm -fr {} + - -clean-test: ## remove test and coverage artifacts - rm -fr .tox/ - rm -f .coverage - rm -fr htmlcov/ + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' -lint: ## check style with flake8 - flake8 traces tests - -test: ## run tests quickly with the default Python - nosetests --with-coverage --cover-package=traces - pycodestyle traces - pytest --mpl tests/test_plot.py - -test-all: ## run tests on every Python version with tox - tox - -coverage: ## check code coverage quickly with the default Python - coverage run --source traces setup.py test - coverage report -m - coverage html - $(BROWSER) htmlcov/index.html - -docs: ## generate HTML documentation - cd docs && make html - -servedocs: ## compile the docs watching for changes - sphinx-autobuild -z traces/ docs docs/_build/html - -release: clean ## package and upload a release - python setup.py sdist bdist_wheel - twine upload dist/* - -dist: clean ## builds source and wheel package - python setup.py sdist bdist_wheel - ls -l dist - -install: clean ## install the package to the active Python's site-packages - python setup.py install +.DEFAULT_GOAL := help diff --git a/codecov.yaml b/codecov.yaml new file mode 100644 index 0000000..058cfb7 --- /dev/null +++ b/codecov.yaml @@ -0,0 +1,9 @@ +coverage: + range: 70..100 + round: down + precision: 1 + status: + project: + default: + target: 90% + threshold: 0.5% diff --git a/docs/_templates/side-primary.html b/docs/_templates/side-primary.html index d7d9ef1..ea93984 100644 --- a/docs/_templates/side-primary.html +++ b/docs/_templates/side-primary.html @@ -1,19 +1,29 @@

-

- Traces is a Python library for unevenly-spaced time series analysis. + Traces is a Python library for unevenly-spaced time + series analysis.

{{ _('Table Of Contents') }}

diff --git a/docs/_themes/LICENSE b/docs/_themes/LICENSE index 77f0e21..6660860 100755 --- a/docs/_themes/LICENSE +++ b/docs/_themes/LICENSE @@ -1,10 +1,10 @@ -Modifications: +Modifications: Copyright (c) 2010 Kenneth Reitz. Copyright (c) 2016 Mike Stringer. -Original Project: +Original Project: Copyright (c) 2010 by Armin Ronacher. diff --git a/docs/_themes/ms/layout.html b/docs/_themes/ms/layout.html index 4d67ec1..6ace260 100755 --- a/docs/_themes/ms/layout.html +++ b/docs/_themes/ms/layout.html @@ -1,18 +1,26 @@ -{%- extends "basic/layout.html" %} -{%- block extrahead %} - {{ super() }} - {% if theme_touch_icon %} - - {% endif %} - +{%- extends "basic/layout.html" %} {%- block extrahead %} {{ super() }} {% if +theme_touch_icon %} + +{% endif %} + - - -{% endblock %} -{%- block relbar2 %}{% endblock %} -{%- block footer %} - + + +{% endblock %} {%- block relbar2 %}{% endblock %} {%- block footer %} + {%- endblock %} diff --git a/docs/_themes/ms/relations.html b/docs/_themes/ms/relations.html index 3bbcde8..ea411e0 100755 --- a/docs/_themes/ms/relations.html +++ b/docs/_themes/ms/relations.html @@ -1,19 +1,36 @@

Related Topics

diff --git a/docs/_themes/ms/static/flasky.css_t b/docs/_themes/ms/static/flasky.css_t index 6cc5de0..080295d 100755 --- a/docs/_themes/ms/static/flasky.css_t +++ b/docs/_themes/ms/static/flasky.css_t @@ -459,4 +459,4 @@ a:hover tt { .revsys-inline { display: none!important; -} \ No newline at end of file +} diff --git a/docs/_themes/ms/static/small_flask.css b/docs/_themes/ms/static/small_flask.css index 8d55e95..c8e4969 100755 --- a/docs/_themes/ms/static/small_flask.css +++ b/docs/_themes/ms/static/small_flask.css @@ -7,84 +7,86 @@ */ body { - margin: 0; - padding: 20px 30px; + margin: 0; + padding: 20px 30px; } div.documentwrapper { - float: none; - background: white; + float: none; + background: white; } div.sphinxsidebar { - display: block; - float: none; - width: 102.5%; - margin: 50px -30px -20px -30px; - padding: 10px 20px; - background: #333; - color: white; -} - -div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: white; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4, +div.sphinxsidebar p, div.sphinxsidebar h3 a { - color: white; + color: white; } div.sphinxsidebar a { - color: #aaa; + color: #aaa; } div.sphinxsidebar p.logo { - display: none; + display: none; } div.document { - width: 100%; - margin: 0; + width: 100%; + margin: 0; } div.related { - display: block; - margin: 0; - padding: 10px 0 20px 0; + display: block; + margin: 0; + padding: 10px 0 20px 0; } div.related ul, div.related ul li { - margin: 0; - padding: 0; + margin: 0; + padding: 0; } div.footer { - display: none; + display: none; } div.bodywrapper { - margin: 0; + margin: 0; } div.body { - min-height: 0; - padding: 0; + min-height: 0; + padding: 0; } .rtd_doc_footer { - display: none; + display: none; } .document { - width: auto; + width: auto; } .footer { - width: auto; + width: auto; } .footer { - width: auto; + width: auto; } .github { - display: none; -} \ No newline at end of file + display: none; +} diff --git a/docs/_themes/ms/theme.conf b/docs/_themes/ms/theme.conf index 307a1f0..07698f6 100755 --- a/docs/_themes/ms/theme.conf +++ b/docs/_themes/ms/theme.conf @@ -4,4 +4,4 @@ stylesheet = flasky.css pygments_style = flask_theme_support.FlaskyStyle [options] -touch_icon = +touch_icon = diff --git a/docs/conf.py b/docs/conf.py index 6ea1049..089357d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # traces documentation build configuration file, created by # sphinx-quickstart @@ -16,83 +15,83 @@ # directory, add these directories to sys.path here. If the directory # is relative to the documentation root, use os.path.abspath to make # it absolute, like shown here. +import datetime import os import sys -import datetime -sys.path.insert(0, os.path.abspath('..')) + +sys.path.insert(0, os.path.abspath("..")) sys.path.append(os.path.abspath("_themes")) -import traces -from recommonmark.parser import CommonMarkParser +from recommonmark.parser import CommonMarkParser # noqa: E402 # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.mathjax', - 'sphinx.ext.viewcode', - 'sphinxcontrib.napoleon', + "sphinx.ext.autodoc", + "sphinx.ext.mathjax", + "sphinx.ext.viewcode", + "sphinx.ext.napoleon", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. You can specify multiple suffix # as a list of string: source_parsers = { - '.md': CommonMarkParser, + ".md": CommonMarkParser, } -source_suffix = ['.rst', '.md'] +source_suffix = [".rst", ".md"] # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = u'traces' -copyright = u'2016-{}, Mike Stringer'.format(datetime.date.today().year) -author = u'Mike Stringer' +project = "traces" +copyright = f"2016-{datetime.date.today().year}, Mike Stringer" # noqa: A001 +author = "Mike Stringer" # The version info for the project you're documenting, acts as # replacement for |version| and |release|, also used in various other # places throughout the built documents. The short X.Y version: -version = u'0.6.0' +version = "0.6.0" # The full version, including alpha/beta/rc tags: -release = u'0.6.0' +release = "0.6.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = "en" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'ms' +html_theme = "ms" # Add any paths that contain custom themes here, relative to this directory. -html_theme_path = ['_themes'] +html_theme_path = ["_themes"] # The name of an image file (relative to this directory) to use as a favicon of # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -html_favicon = '_static/img/favicon.ico' +html_favicon = "_static/img/favicon.ico" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. @@ -100,14 +99,14 @@ # Custom sidebar templates, maps document names to template names. html_sidebars = { - '**': ['side-primary.html'], + "**": ["side-primary.html"], } # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. html_show_copyright = True # Output file base name for HTML help builder. -htmlhelp_basename = 'tracesdoc' +htmlhelp_basename = "tracesdoc" latex_elements = {} @@ -115,22 +114,30 @@ # start file, target name, title, author, documentclass [howto, # manual, or own class]). latex_documents = [ - (master_doc, 'traces.tex', u'traces Documentation', - u'Mike Stringer', 'manual'), + ( + master_doc, + "traces.tex", + "traces Documentation", + "Mike Stringer", + "manual", + ), ] # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'traces', u'traces Documentation', - [author], 1) -] +man_pages = [(master_doc, "traces", "traces Documentation", [author], 1)] # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'traces', u'traces Documentation', - author, 'traces', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "traces", + "traces Documentation", + author, + "traces", + "One line description of project.", + "Miscellaneous", + ), ] diff --git a/docs/index.rst b/docs/index.rst index a43d3a6..7db8193 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -34,7 +34,7 @@ To install traces, run this command in your terminal: .. code:: bash $ pip install traces - + Quickstart: using traces ------------------------ @@ -99,7 +99,7 @@ one ``TimeSeries`` where the each value is a list of all lights. We also applied a ``sum`` operation to the list of states to get the ``TimeSeries`` of the number of lights that are on. - + .. figure:: _static/img/count.svg :alt: many light switch count @@ -120,7 +120,7 @@ that can be used to get summary metrics such as the mean or quantiles. It's flexible +++++++++++++ - + The measurements points (keys) in a ``TimeSeries`` can be in any units as long as they can be ordered. The values can be anything. @@ -137,7 +137,7 @@ of a grocery basket by the number of minutes within a shopping trip. To learn more, check the :ref:`examples ` and the detailed :ref:`reference `. - + More info --------- diff --git a/examples/Plot.ipynb b/examples/Plot.ipynb new file mode 100644 index 0000000..7e746bf --- /dev/null +++ b/examples/Plot.ipynb @@ -0,0 +1,93 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "%config InlineBackend.figure_format = 'retina'" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import traces" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "ts = traces.TimeSeries()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "ts[0] = 0\n", + "ts[1] = 1\n", + "ts[2] = 0\n", + "ts[5] = 2\n", + "ts[10] = 2" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABU8AAADFCAYAAABkSAN6AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAAgAElEQVR4nO3de5Bc110n8K8iW1KkSGjFGDlYKyUSC1RMBAGHJEAqDgnaJRQGli2eYQlZvGdJeInHQiU8QsDFowCR3SxwooUQ4yVAFQEECYU34IgKjyJxyDqQsLAWq7EUS6uxIqSMrJFHmf2je4Qj91gt1DO3T8/nU6VqT/ftvr+r0de3+9fnnrNmYWEhAAAAAAB8vKd0XQAAAAAAwDjSPAUAAAAAGEDzFAAAAABgAM1TAAAAAIABNE8BAAAAAAbQPAUAAAAAGEDzFAAAAABgAM1TAAAAAIABNE8BAAAAAAbQPAUAAAAAGEDzFAAAAABgAM1TAAAAAIABNE8BAAAAAAbQPAUAAAAAGOCGUb1QKWVrkv1JvjLJM5NcTPK3Sd6c5JdqrZdGtS8AAAAAgOW2ZmFh4bpfpJTyKUnemWRX/66HkmxLsqn/8x8l+ZJa69x17wwAAAAAYAVc98jTUsraJL+dXuP0j5N8c631H0opa5J8UZJfTvKSJD+S5Puvd38DXH/3FwAAAACYdGuu+QnXO/K0lPLSJP8zyYeTfGqtdfaKx1+S3qjUf0yyrdb6seva4RNpngIAAAAAV3PNzdNRzHm6p3/71isbp333JZlN8glJtid5eAT7BACAJ3j00Udz77335qGHHsrOnTuzb9++bNiwoeuyAADGivdMwxtF8/RQkk9LcmCJxxeSLI42fWwE+1u1Tp06lSS56aabOq4EuBp5hTbI6mR54IEHcuedd2ZmZubyfVNTUzl48GD27t3bYWWMgrxCG2QVxp/3TNdmJAtGPZlSyvOT/HmSD9Van7UMu1g1l+0fOXIkSbJ79+6OKwGuRl6hDbI6OS5cuJAXvehFH/chYNHU1FQOHz5sNEXj5BXaIKsw3rxn6uay/SWVUp6S5Cf6P/74NTzv/mG3rbUm6f0P+vH/cz5x4kTOnz+f7du3Z9OmTUmSs2fPZmZmJps3b778Ldj8/Hymp6ezdu3a7Nq16/Lzjx07losXL+aWW27J+vXrkySnT5/OmTNnsnXr1mzbti1JMjc3l+PHj2fdunXZsWPH5ecfPXo0ly5dys6dO3PDDb2/5lOnTuXcuXOZmprKli1bkiSzs7M5efJkNm7cmJtvvvny8wedcG688cY89thjmZ2dnZhjmsTfk2NyTFu3bs3U1NTEHdMk/p4ck2OamprKzMzMqngfMenH9Ed/9EcDPwQkyczMTG699daBjwEA0DMzM5N77rkn3/AN3zCW7/eu5z3s9Xyh85R/9jOH85okL0ry+0nuWeZ9Tbwbb7yx6xKAIW3ZsuXyiQEYX3I6Oaanp7suAQCgeQ8/bKmiKy3bZfullC9P8rYkR5PcVmt9ZFl2tIou2wcAYLBDhw5l//79Sz5+4MCB3HHHHStYEQDA+PGe6dov21+W5mkp5bYkf5LkUpLPr7U+MPKd/JNV0zydnZ1NksvDlIHxJa/QBlmdHObvmnzyCm2QVRhv3jNde/N05Jftl1J2Jvm9JOuTfM0yN05XlZMnT+bkyZNdlwEMQV6hDbI6OTZs2JCDBw9ennN60eLKsRP+IWBVkFdog6zCePOe6dqNdMGoUsqW9OY3vTnJd9Za3z7K11/tNm7c2HUJwJDkFdogq5Nl7969OXz48OXFoQ4cOJB9+/b5EDAh5BXaIKsw/hbfM/3mb/5mPvzhD+dZz3qW90xPYmSX7ZdSbkhyKMkXJ/mFJK+uta7EJfWr5rJ9AACubs+ePUmSBx98sONKAAAYM91ctl9KWZPkDek1Tu9N8u0r1DgFAAAAAFgWo5rz9FX9Px9K8lW11vkRvS4AAAAAQCeu+7L9UsqmJDNJNvRvH1li04Ukb6q1HriuHQ5+3VXhyJEjSZLdu3d3XAlwNfIKbZDVyeSy/ckkr9AGWYV2rNK8XvNl+6NYMOqxJO9P8vwkU/0/S3nGCPYHAAAAALDsRrZgVIeaPwAAAEbHyFMAAJbQzYJRAAAAAACTRvMUAAAAAGAAzdOGnDhxIidOnOi6DGAI8gptkFVoh7xCG2QV2iGvwxnFglGskPPnz3ddAjAkeYU2yCq0Q16hDbIK7ZDX4WieNmT79u1dlwAMSV6hDbIK7ZBXaIOsQjvkdTiapw3ZtGlT1yUAQ5JXaIOsQjvkFdogq9AOeR2OOU8BAAAAAAbQPG3I2bNnc/bs2a7LAIYgr9AGWYV2yCu0QVahHfI6HJftN2RmZiZJsmXLlo4rAa5GXqENsgrtkFdog6xCO+R1OJqnDdm8eXPXJQBDkldog6xCO+QV2iCr0A55Hc6ahYWFrmu4Xs0fAAAAo7Nnz54kyYMPPthxJQAAjJk11/oEc54CAAAAAAygedqQ+fn5zM/Pd10GMAR5hTbIKrRDXqENsgrtkNfhaJ42ZHp6OtPT012XAQxBXqENsgrtkFdog6xCO+R1OBaMasjatWu7LgEYkrxCG2QV2iGv0AZZhXbI63AsGAUAwESxYBQAAEuwYBQAAAAAwChongIAAAAADKB52pBjx47l2LFjXZcBDEFeoQ2yCu2QV2iDrEI75HU4FoxqyMWLF7suARiSvEIbZBXaIa/QBlmFdsjrcCwY1ZC5ubkkyfr16zuuBLgaeYU2yOpksmDUZJJXaIOsQjtWaV6vecEoI08bssr+MUPT5BXaIKvQDnmFNsgqtENeh2POUwAAAACAATRPG3L69OmcPn266zKAIcgrtEFWoR3yCm2QVWiHvA5H87QhZ86cyZkzZ7ouAxiCvEIbZBXaIa/QBlmFdsjrcMx52pCtW7d2XQIwJHmFNsgqtENeoQ2yCu2Q1+GsWVhofrH65g8AAIDR2bNnT5LkwQcf7LgSAADGzJprfYLL9gEAAAAABtA8bcjc3Fzm5ua6LgMYgrxCG2QV2iGv0AZZhXbI63A0Txty/PjxHD9+vOsygCHIK7RBVqEd8gptkFVoh7wOx4JRDVm3bl3XJQBDkldog6xCO+QV2iCr0A55HY4FowAAmCgWjAIAYAkWjAIAAAAAGAXNUwAAAACAATRPG3L06NEcPXq06zKAIcgrtEFWoR3yCm2QVWiHvA7HglENuXTpUtclAEOSV2iDrEI75BXaIKvQDnkdzrIuGFVK+Ywkv5jk05O8rNb6l8uwm1WzYNT8/HyS5IYb9Lxh3MkrtEFWJ5MFoyaTvEIbZBXasUrzes0LRi3b304p5eVJ3pTkqf27viTJcjRPV41V9o8Zmiav0AZZhXbIK7RBVqEd8jqckf8tlVJuTPJzSV6VZD7JB5I8O8naUe8LAAAAAGC5LMeCUXel1zg9muSFSd62DPtYlU6dOpVTp051XQYwBHmFNsgqtENeoQ2yCu2Q1+EsR/P03Ul+Jslzaq1/sQyvv2qdO3cu586d67oMRujRRx/N7/7u7+aNb3xjDh06lAsXLnRdEiMir9AGWYV2yCu0QVahHfI6nJFftl9rPZTk0Khfl2RqaqrrEhihBx54IHfeeWdmZmYu3zc1NZWDBw9m7969HVbGKMgrtEFWoR3yCm2QVWiHvA7HzLAN2bJlS9clMCIXLlx4QuM0SWZmZnLnnXfm8OHD2bBhQ0fVMQryCm2QVWiHvEIbZBXaIa/DGcvmaSnl/mG3rbUmSY4cOZLdu3dfvv/EiRM5f/58tm/fnk2bNiVJzp49m5mZmWzevDk33XRTkmR+fj7T09NZu3Ztdu3adfn5x44dy8WLF3PLLbdk/fr1SZLTp0/nzJkz2bp1a7Zt25YkmZuby/Hjx7Nu3brs2LHj8vOPHj2aS5cuZefOnZdXLzt16lTOnTuXqampy/9AZ2dnc/LkyWzcuDE333zz5ecfOXIkSRzThB7Tvffe+4TG6aKZmZnceuutAx+jLbfffnt+/ud/fqz+7SWTlyfH5Jgck2O68piuNAnHNIm/J8fkmByTY3JMjskxOaaVOqbHv+a1Wo45T1km8/PzXZfAiExPT3ddAivgXe96V9clAFcxOzvbdQnAkB599FGZhQbMzs5mbm6u6zKAISwsLDi3DmHNwsLCsu6glPK6JD+c5K5a6w8swy6W9wDGyKAOPG06dOhQ9u/fv+TjBw4cyB133LGCFTFqe/bsSZI8+OCDHVcCPBnn1snk/8GTSV6hDbIK7VileV1zrU8Yy8v2GWzjxo1dl8CI7Nu3L1NTUwMv3Z+amsq+ffs6qApg9XFuhXbIK7RBVqEd8joczdOGPH4eCNq2YcOGHDx48AmLRk1NTeXgwYMWiwJYIc6t0A55hTbIKrRDXodjzlPoyN69e3P48OHLPx84cCCHDx/O3r17O6wKAAAAgEVGnkKHHj/C1BynAAAAAOPFyNOGHDly5PJkvgDA9XNuhXbIK7RBVqEd8joczVMAAAAAgAFctt+Q3bt3d10CAEwU51Zoh7xCG2QV2iGvw1mJkafvSTLbvwUAAAAAaMKyjzyttb49ydOWez8AAAAAAKNkztOGnDhxIidOnOi6DACYGM6t0A55hTbIKrRDXodjztOGnD9/vusSAGCiOLdCO+QV2iCr0A55HY7maUO2b9/edQkAMFGcW6Ed8gptkFVoh7wOR/O0IZs2beq6BACYKM6t0A55hTbIKrRDXodjzlMAAAAAgAE0Txty9uzZnD17tusyAGBiOLdCO+QV2iCr0A55HY7L9hsyMzOTJNmyZUvHlQDAZHBuhXbIK7RBVqEd8joczdOGbN68uesSAGCiOLdCO+QV2iCr0A55HY7maUNuuummrksAgIni3ArtkFdog6xCO+R1OOY8BQAAAAAYQPO0IfPz85mfn++6DACYGM6t0A55hTbIKrRDXoejedqQ6enpTE9Pd10GAEwM51Zoh7xCG2QV2iGvwzHnaUPWrl3bdQkAMFGcW6Ed8gptkFVoh7wOR/O0Ibt27eq6BACYKM6t0A55hTbIKrRDXofjsn0AAAAAgAE0TwEAAAAABtA8bcixY8dy7NixrssAgInh3ArtkFdog6xCO+R1OOY8bcjFixe7LgEAJopzK7RDXqENsgrtkNfhaJ425JZbbum6BACYKM6t0A55hTbIKrRDXoejedqQ9evXd10CAEwU51Zoh7xCG2QV2iGvwzHnKQAAAADAAJqnDTl9+nROnz7ddRkAMDGcW6Ed8gptkFVoh7wOR/O0IWfOnMmZM2e6LgMAJoZzK7RDXqENsgrtkNfhmPO0IVu3bu26BACYKM6t0A55hTbIKrRDXoejedqQbdu2dV0CAEwU51Zoh7xCG2QV2iGvw3HZPgAAAADAAJqnDZmbm8vc3FzXZQDAxHBuhXbIK7RBVqEd8joczdOGHD9+PMePH++6DACYGM6t0A55hTbIKrRDXodjztOGrFu3rusSAGCiOLdCO+QV2iCr0A55HY7maUN27NjRdQkAMFGcW6Ed8gptkFVoh7wOx2X7AAAAAAADaJ4CAAAAAAygedqQo0eP5ujRo12XAQATw7kV2iGv0AZZhXbI63DMedqQS5cudV0CAEwU51Zoh7xCG2QV2iGvw9E8bcjOnTu7LgEAJopzK7RDXqENsgrtkNfhaJ425IYb/LoAYJScW6Ed8gptkFVoh7wOZ6R/S6WUFyT5/iRfkGRLkoeS/E6Su2qtj4xyXwAAAAAAy2lkC0aVUr4uyZ8muSPJhiQPJ9mVZH+S+0spO0a1r9Xq1KlTOXXqVNdlAMDEcG6FdsgrtEFWoR3yOpyRNE9LKc9N8pYkC0m+O8m2WuvOJM9Icm96TdR3lFKMB74O586dy7lz57ouAwAmhnMrtENeoQ2yCu2Q1+GMqpl5V/+1Xldr/dnFO2utD5VSviLJ/UmeneRrk/zqiPa56kxNTXVdAgBMFOdWaIe8QhtkFdohr8O57pGnpZQ9Sb4oyUeS/PSVj9dazyd5ff/Hb7ne/a1Wjz76aO67777cfffdOXToUC5cuNB1ScASHn300cv/La8w3rZs2ZItW7Z0XQYwBHmFNsgqtENehzOKkae392/fUWudXWKbQ0nmkjy3lPK0WutHR7DfVeOBBx7InXfemZmZmcv3TU1N5eDBg9m7d2+HlQFXWszrov3798srAAAANGoUc57e1r9971Ib9JuqH0yvWat7cA0uXLjwhMZpkszMzOTOO+80og3GiLxCe2ZnZzM7u9R3v8A4kVdog6xCO+R1OKMYefqJ/duHrrLddJLnPG77JZVS7h9257XWJMmRI0eye/fuy/efOHEi58+fz/bt27Np06YkydmzZzMzM5PNmzfnpptuSpLMz89neno6a9euza5duy4//9ixY7l48WJuueWWrF+/Pkly+vTpnDlzJlu3bs22bduSJHNzczl+/HjWrVuXHTt2XH7+0aNHc+nSpezcuTM33ND7az516lTOnTuXqampy8OiZ2dnc/LkyWzcuDE333zz5ecfOXIkSfLXf/3XT2jELJqZmcmtt9467F8VjRiXf3uTmKflPqa3ve1t8gowhlb7+WlSjmnR7t27J+aYJvH35Jgc08mTJy9vPynHNIm/J8fkmKanpy8/b/E1JuGYlvo9Pf41r9Uomqfb+rdXuxR/8fFtT7oVH+fx/5iZXLfffnvXJTACx48f77oEAPo+7/M+r+sSGLENGzbkKU8ZxYVzwHLauHFj5ufnP+5LD2A8rVmzJk996lO7LmPsrVlYWLiuFyilvDPJS5L8m1rrHz7Jdvck+fok31Rr/ZXr2unHu74DGHOHDh3K/v37l3z8wIEDueOOO1awImAp8goAAABjbc21PmEUX91+pH+76SrbPa1/e3oE+1w19u3bl6mpqYGPTU1NZd++fStcEbAUeQUAAIDJMorm6SP9251X2W7x8UeedCs+zoYNG3Lw4MEnNGQWV+/esGFDR5UBV5JXAAAAmCyjmPP0ff3b5y61QSllY5JnJbmU5AMj2Oeqsnfv3hw+fDj33HNPHn744XzmZ35m9u3bpxEDY0heoS2DJqUHxpO8QhtkFdohr8MZxZynn5rkfyc5k2RHrXV2wDZfneTXk7yn1vq517XDJ5roOU8BAAAAgJFY+TlPa61/l+RdSbYm+d4rHy+lbEjyQ4ubX+/+AAAAAABWwigu20+S1yb5kyQ/WEo5l+SNtda5UsotSd6U3iX7H0py94j293jX3DFuVSnl/iSptX5O17UAT05eoQ2yCu2QV2iDrEI75HU4o1gwKrXWP0vyyv7r/XSSR0opR5NMJ3lZkmNJvrjW+tgo9gcAAAAAsNxG0jxNklrr3UlemOT3kzyW5Jb0mqdvSPLZtdajo9oXAAAAAMByG9Vl+0mSWuu7k7x7lK8JAAAAANCFkY08BQAAAACYJJqnAAAAAAADaJ4CAAAAAAygeQoAAAAAMIDmKQAAAADAAJqnAAAAAAADaJ4CAAAAAAywZmFhoesaAAAAAADGjpGnAAAAAAADaJ4CAAAAAAygeQoAAAAAMIDmKQAAAADAAJqnAAAAAAADaJ4CAAAAAAygeQoAAAAAMIDmKQAAAADAADd0XQBXV0p5QZLvT/IFSbYkeSjJ7yS5q9b6SJe1Af+klLI1yf4kX5nkmUkuJvnbJG9O8ku11ksdlgc8iVLKlyZ5U5KFJF9Za/3zjksC+kopO5N8T5KXJdmR3vn1fyX5pSS/Xmu90GF5QJJSypokX5Pkm5J8VpKtSU4l+ZMkb6y1/mmH5cGqVkr5jCS/mOTTk7ys1vqXA7Z5VpLXJnlJkk9McjLJHyT5sVrr0RUsdywZeTrmSilfl+RPk9yRZEOSh5PsSq9Bc38pZUeH5QF9pZRPSfL+JD+U5NYkjyS5Mcnzk9Qkf1hKWd9dhcBS+vl9a5Kbkzw9vQ9+wBgopXxhkg8k+bb03gOfTHIpvUEFb07y/lLKJ3dXIVBKWZfkd5P8WpIvSrI5yYkk29NrqL67lPLa7iqE1auU8vIkf5nk89Nrin7JgG1uT/K+JF+X3hcfH04vv9+c5K9KKc9eqXrHlebpGCulPDfJW9IbBfPdSbbVWncmeUaSe9N7A/mOUooRxNChUsraJL+dXib/OMnuflY3J/nXSY6n9w3ej3RWJDBQKeUp6TVgNiX5/f7dG7urCFhUSnlGeufXLUl+PMlNtdZd6X34+8IkH0zyaUle01WNQJLkB5J8aXpfbnxZkk3998JPS/Kd6X3h8WP9L0OAFVBKubGU8t+S/Gp6g3o+0H9o7RXb7UpyKMn6JD+VZKp/rn16/7n/Ir2BQJ+wUrWPI83T8XZXelMrvL7W+rO11rkkqbU+lOQr0rsc+NlJvra7EoEkL07yGel9Q3dHrfUfkqTWulBrvTfJN/a3+0/9Rg0wPr41vRFsv57ktzquBfh4r0+vcfrTtdbX1FrPJEmt9WO11vuSfG6S16U3chzozuJ73VfWWg/VWj+WJLXWC7XWN6TXkEmSV3ZSHaxOdyV5VZKjSV6Y5G1LbPfa9Ab9/Eqt9ftqrR9NklrrTJJXJLkvvUbqty93wePMh/gxVUrZk94lDx9J8tNXPl5rPZ/eG8ok+ZYVLA14oj3927fWWmcHPH5fktkkn5De5Q/AGCilPDO90Wyn0rskGBgTpZQtSb46ydkkPzpom1rrbK31R8ylCJ1bfH/7Z0s8vnj/zStQC9Dz7iQ/k+Q5tda/GLRBKWVjel9+fCy96ec+Tv+LkMUpN76lP7fxqqR5Or5u79++Y4lmTNIbWj2X5LmllKetSFXAIIeSHOj/GWQhvRNSkjy2IhUBT6r/5u9N6V2i/239b9eB8fFFSdYl+YNa69muiwGe1P392xcs8fji/e9dgVqAJP1R4N9Ta/3Ik2z2gvTOtX/ev8J5kL9Ib9Hypyf5VyMusxnmyhxft/VvlzzB1FpnSykfTPKcJHuz9Dd9wDKqtT6c5LueZJPnpXcpxIc0aGBsfH2SlyZ5e5Lf7LgW4Ik+s3/73v6UN/8uvYVn9iQ5neQ9SX5hcaocoFP/Ob15/99SSnllel96XCqlPDW9BWe+L8mx9EbBAeNjmL7TQinlvUn+ZX/7v1uJwsaNkafj6xP7t0t1/xdNX7E9MEb6H/h+ov/jj3dZC9BTStma3ge42SSvqrUudFwS8ESf0r89kd6XHL+R3pz/e9O7Qut7k3ywlPL1nVQHXNafOuPFSY4k+b0kp0sp/5DeFHT/pX/f59daT3VXJTCAvtOQNE/H17b+7Uevst3i49uedCugK69J8qL0VvG+p+NagJ7XJ/mkJD9Ua52+2sZAJ7b0b78rvUv4X5/kmelNtbE3yVuSbEhvpNtSlwoDK2dH/im3W5I8I73Vu5PevP+rtukCY0zfaUgu258cq3biXhhXpZQvT+/D3v9N8gqj26B7pZRnJ3l1kvenNxoGGE8b+7fPSfJ1tda3Pu6xDyR5RSnlTJLvSG9F4S9c4fqAvlLK/iQ/m95I029N8jtJHknvC4//kGR/kj8rpbzUAm/QtFXbd9I8HV+Lk/puusp2iwtFnV7GWoBrVEq5LcmvpXdZ8JfVWh/puCRY9fqLRP1celfevLrWOt9xScDSLvRvH7iicfp4P5rkVUleXEqZMq84rLxSyjOT/GSS80leWGv9m8c9/KEk31NK+UCSX0ny5lLKp/dX8Aa6p+80JJftj6/FRsvOq2y3+LjGDIyJUsrO9OZ2Wp/ka2qtD3RcEtDzkvRGp91Ta7XIIoy3xQ90S2a1/8Xk3/d/3LXsFQGDfHWSG5PcfUXj9PHuTvK36a3U/byVKgy4Kn2nIRl5Or7e17997lIblFI2JnlWkkvpXb4EdKyUsiW9+U1vTvKdtda3d1wS8E++rH+7r5TyfwY8vjhX25f3H//7JF9Ra70wYFtgeS1m9Goj1B4bcjtgeTyzf/vBpTbor9b9wSSfnt5cqH++AnUBVzdM32lNks+5YvtVx8jT8fWu/u3LSilLDaH+0vRGtr2v1np2RaoCllRKuSHJryd5dpJfiPkUYdz8QXrfmH9Skj0D/tzU325T/+fPiC+aoSuL8yJ+zlIb9AcSfEr/R4u/QTcWp8v4l1fZbnHk2sllrAW4Nn+WZD7J80spS2X4c9PL7/9LbwT5quQDwZiqtf5dKeVdSW5P8r1JXvf4x0spG5L80OLmK1kb8ET9b+TekOSLk9yb5NstEAXjpdb6jiRTSz1eSnl5kl9N8j9qrS9fscKAQQ6n90Htef1FZt45YJuS3pcdh80tDp05nOQ16S3i9jO11ic0R0spL05yW5JzSd67wvUBS6i1frSUck+SV6Q3j/grHv94KeUpSX6s/+ObVvPnWyNPx9tr07sk/wdLKd9dSlmfJKWUW5L8VnqX7H8ovTlkgG69qv/nQ0m+ykI0APDPV2udS/L6/o+/VUr5hlLKjUlvxGkp5buS/FSShVwxyABYUe9M7zL8m5LcV0q5vd9wSSllQynlFUl+u7/tT7piEsbOj6a3yPE3llJ+qpTytCQppWxL8t+TvDTJqSQHuiuxe2sWFlZt47gJpZR/n+Qt/R9n07vccEd6je9jSb6g1nq0o/KAJP2pNWaSbOjfLjX6ZSG9b+xW9YkHxpWRpzBe+ld1/GKS/9i/69H0RqPenN7UVfNJXl1rfVM3FQJJUkq5Ob2pcT6rf9fZ9Fblvjm998dJ8l+TfMdqHrkGXSqlvC7JDye5q9b6A1c89tIkb0+yLslckhNJPjm9xeD+McmLa61/taIFjxkjT8dcrfXuJC9MbwGax5Lckt6cTm9I8tkapzAWHkvy/v5/TyX5tCX+LE6SD4ynv4lLCmFs1FoXaq0lyb9Nb0qcjyZ5epKHk7w5yW0ap9C9WuuJJM9L8uok705yMb3Gy6kkb01ye63VlFbQrfekNyDvPVc+0J8a57Ykv5Helx870svvLyf5rNXeOE2MPAUAAAAAGMjIUwAAAACAATRPAQAAAAAG0DwFAAAAABhA8xQAAAAAYADNUwAAAACAATRPAQAAAAAG0DwFAAAAABhA8xQAAAAAYADNUwAAAACAATRPAQAAAAAG0DwFAAAAABhA8xQAAG1NsCkAAAA7SURBVAAAYADNUwAAAACAATRPAQAAAAAG0DwFAAAAABhA8xQAAAAAYADNUwAAAACAATRPAQAAAAAG+P8jEUnWUEa9aAAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "image/png": { + "height": 98, + "width": 679 + }, + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "figure, axes = ts.plot()\n", + "figure.savefig(\"test.pdf\", bbox_inches=\"tight\", format=\"pdf\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/helloworld.py b/examples/helloworld.py index 48b900c..e5d8e56 100644 --- a/examples/helloworld.py +++ b/examples/helloworld.py @@ -1,6 +1,5 @@ -import sys import glob - +import sys from datetime import datetime, timedelta import traces @@ -11,14 +10,14 @@ def parse_iso_datetime(value): return datetime.strptime(value, "%Y-%m-%dT%H:%M:%S") -def read_all(pattern='data/lightbulb-*.csv'): +def read_all(pattern="data/lightbulb-*.csv"): """Read all of the CSVs in a directory matching the filename pattern as TimeSeries. """ result = [] for filename in glob.iglob(pattern): - print('reading', filename, file=sys.stderr) + print("reading", filename, file=sys.stderr) ts = traces.TimeSeries.from_csv( filename, time_column=0, @@ -54,7 +53,7 @@ def read_all(pattern='data/lightbulb-*.csv'): # look at the typical number of lights on during business hours # (8am-6pm) for each day in january -for t in datetime_range(datetime(2016, 1, 1), datetime(2016, 2, 1), 'days'): +for t in datetime_range(datetime(2016, 1, 1), datetime(2016, 2, 1), "days"): biz_start = t + timedelta(hours=8) biz_end = t + timedelta(hours=18) histogram = total_watts.distribution(start=biz_start, end=biz_end) diff --git a/examples/stackystack.py b/examples/stackystack.py index 3783955..cf32b7d 100644 --- a/examples/stackystack.py +++ b/examples/stackystack.py @@ -1,7 +1,7 @@ -import traces -import random import datetime -from infinity import inf +import random + +import traces def average(values): @@ -15,13 +15,12 @@ def average(values): class Test(traces.TimeSeries): - def stack(self, duration, start_times, operation): ts_list = [] for start in start_times: end = start + duration ts = traces.TimeSeries() - for t0, dur, value in self.iterperiods(start, end): + for t0, _dur, value in self.iterperiods(start, end): offset = t0 - start if isinstance(offset, datetime.timedelta): offset = offset.total_seconds() @@ -33,7 +32,7 @@ def stack(self, duration, start_times, operation): def xmprint(ts): for t, v in ts: # print t.isoformat(), v - print(t, v) + print((t, v)) def generate_ts(n_days): @@ -55,7 +54,7 @@ def generate_ts(n_days): def hour_mask(n_days, hours): start_time = datetime.datetime(2016, 1, 1) - domain = TimeSeries(default=False) + domain = traces.TimeSeries(default=False) for day in range(n_days): start = start_time + datetime.timedelta(days=day, hours=hours) end = start + datetime.timedelta(hours=1) @@ -87,26 +86,28 @@ def hour_mask(n_days, hours): stack = ts.stack(datetime.timedelta(days=1), start_times, average) xmprint(stack) -print '' +print("") for hour in range(24): mask = hour_mask(n_days, hour) - print hour * 60 * 60, ts.distribution(mask=mask).mean() -print (hour + 1) * 60 * 60, ts.distribution(mask=mask).mean() + print(hour * 60 * 60, ts.distribution(mask=mask).mean()) +print((hour + 1) * 60 * 60, ts.distribution(mask=mask).mean()) -print '' +print("") unit = 60 * 60 start = 0 end = start + unit while end <= 24 * 60 * 60: value = stack.mean(start, end) - print start, value + print(start, value) start += unit end += unit -print start, value +print(start, value) -print '' +print("") -for t, v in sorted(stack.moving_average(60 * 60, 60 * 60, 0, 24 * 60 * 60).items()): - print t, v +for t, v in sorted( + stack.moving_average(60 * 60, 60 * 60, 0, 24 * 60 * 60).items() +): + print(t, v) diff --git a/examples/timing.py b/examples/timing.py index 760c977..5e68619 100644 --- a/examples/timing.py +++ b/examples/timing.py @@ -1,15 +1,15 @@ -import time -import pprint import collections -import sys import functools +import sys +import time TIMING_RESULTS = collections.defaultdict(list) -class timer(object): +class timer: def __call__(self, function): """Turn the object into a decorator""" + @functools.wraps(function) def wrapper(*arg, **kwargs): t1 = time.clock() @@ -17,8 +17,10 @@ def wrapper(*arg, **kwargs): t2 = time.clock() TIMING_RESULTS[function.__name__].append(t2 - t1) return result + return wrapper + def print_results(*args): args = sorted([f.__name__ for f in args]) focus = set(args) @@ -28,8 +30,8 @@ def print_results(*args): continue n = 0 sum_ = 0 - min_ = float('inf') - max_ = float('-inf') + min_ = float("inf") + max_ = float("-inf") for dt in timing_results: n += 1 sum_ += dt @@ -38,29 +40,28 @@ def print_results(*args): if dt > max_: max_ = dt avg = float(sum_) / n - msg = '{}: n={} avg={} min={} max={}'.format( - name, n, avg, min_, max_, - ) + msg = f"{name}: n={n} avg={avg} min={min_} max={max_}" result[name] = { - 'n': n, - 'avg': avg, - 'min': min_, - 'max': min_, + "n": n, + "avg": avg, + "min": min_, + "max": min_, } for i, name_a in enumerate(args): for j in range(i): name_b = args[j] - ratio = result[name_a]['min'] / result[name_b]['min'] + ratio = result[name_a]["min"] / result[name_b]["min"] if ratio <= 1: - msg = '%s is %.1fx faster than %s' % (name_a, 1 / ratio, name_b) + msg = f"{name_a} is {1 / ratio:.1f}x faster than {name_b}" else: - msg = '%s is %.1fx faster than %s' % (name_b, ratio, name_a) - print >> sys.stderr, msg - + msg = f"{name_b} is {ratio:.1f}x faster than {name_a}" + print(msg, file=sys.stderr) + return result - + + def timing_loop(n, mod=1000): for index, i in enumerate(range(n)): if not index % mod: - print >> sys.stderr, 'iteration %i' % index + print("iteration %i" % index, file=sys.stderr) yield i diff --git a/mkdocs.yml b/mkdocs.yml index 5ffc839..8373982 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,15 +1,54 @@ site_name: traces -repo_url: https://github.com/datascopeanalytics/traces/tree/master -theme: readthedocs -site_description: Tools for unevenly-spaced time series data +repo_url: https://github.com/stringertheory/traces +site_url: https://stringertheory.github.io/traces +site_description: A Python library for unevenly-spaced time series analysis site_author: Mike Stringer -site_favicon: http://datascopeanalytics.com/static/main/img/favicon.ico -copyright: -extra_javascript: - - http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML +edit_uri: edit/main/docs/ +repo_name: stringertheory/traces +copyright: Maintained by Mike. + +nav: + - Home: index.md + - Modules: modules.md +plugins: + - search + - mkdocstrings: + handlers: + python: + setup_commands: + - import sys + - sys.path.append('../') +theme: + name: material + feature: + tabs: true + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + primary: white + accent: deep orange + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: black + accent: deep orange + toggle: + icon: material/brightness-4 + name: Switch to light mode + icon: + repo: fontawesome/brands/github + +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/stringertheory/traces + - icon: fontawesome/brands/python + link: https://pypi.org/project/traces + markdown_extensions: - - smarty - - mdx_math -pages: -- Home: 'index.md' -- Installation: 'installation.md' + - toc: + permalink: true + - pymdownx.arithmatex: + generic: true diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..b1e3e8d --- /dev/null +++ b/poetry.lock @@ -0,0 +1,2580 @@ +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. + +[[package]] +name = "alabaster" +version = "0.7.13" +description = "A configurable sidebar-enabled Sphinx theme" +optional = false +python-versions = ">=3.6" +files = [ + {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"}, + {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, +] + +[[package]] +name = "alabaster" +version = "0.7.16" +description = "A light, configurable Sphinx theme" +optional = false +python-versions = ">=3.9" +files = [ + {file = "alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92"}, + {file = "alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65"}, +] + +[[package]] +name = "babel" +version = "2.14.0" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"}, + {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, +] + +[package.dependencies] +pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} + +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] + +[[package]] +name = "cachetools" +version = "5.3.2" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cachetools-5.3.2-py3-none-any.whl", hash = "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1"}, + {file = "cachetools-5.3.2.tar.gz", hash = "sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2"}, +] + +[[package]] +name = "certifi" +version = "2024.2.2" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, +] + +[[package]] +name = "cfgv" +version = "3.4.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + +[[package]] +name = "chardet" +version = "5.2.0" +description = "Universal encoding detector for Python 3" +optional = false +python-versions = ">=3.7" +files = [ + {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, + {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "commonmark" +version = "0.9.1" +description = "Python parser for the CommonMark Markdown spec" +optional = false +python-versions = "*" +files = [ + {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"}, + {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, +] + +[package.extras] +test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] + +[[package]] +name = "contourpy" +version = "1.1.1" +description = "Python library for calculating contours of 2D quadrilateral grids" +optional = false +python-versions = ">=3.8" +files = [ + {file = "contourpy-1.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:46e24f5412c948d81736509377e255f6040e94216bf1a9b5ea1eaa9d29f6ec1b"}, + {file = "contourpy-1.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e48694d6a9c5a26ee85b10130c77a011a4fedf50a7279fa0bdaf44bafb4299d"}, + {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a66045af6cf00e19d02191ab578a50cb93b2028c3eefed999793698e9ea768ae"}, + {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ebf42695f75ee1a952f98ce9775c873e4971732a87334b099dde90b6af6a916"}, + {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6aec19457617ef468ff091669cca01fa7ea557b12b59a7908b9474bb9674cf0"}, + {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:462c59914dc6d81e0b11f37e560b8a7c2dbab6aca4f38be31519d442d6cde1a1"}, + {file = "contourpy-1.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6d0a8efc258659edc5299f9ef32d8d81de8b53b45d67bf4bfa3067f31366764d"}, + {file = "contourpy-1.1.1-cp310-cp310-win32.whl", hash = "sha256:d6ab42f223e58b7dac1bb0af32194a7b9311065583cc75ff59dcf301afd8a431"}, + {file = "contourpy-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:549174b0713d49871c6dee90a4b499d3f12f5e5f69641cd23c50a4542e2ca1eb"}, + {file = "contourpy-1.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:407d864db716a067cc696d61fa1ef6637fedf03606e8417fe2aeed20a061e6b2"}, + {file = "contourpy-1.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe80c017973e6a4c367e037cb31601044dd55e6bfacd57370674867d15a899b"}, + {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e30aaf2b8a2bac57eb7e1650df1b3a4130e8d0c66fc2f861039d507a11760e1b"}, + {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3de23ca4f381c3770dee6d10ead6fff524d540c0f662e763ad1530bde5112532"}, + {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:566f0e41df06dfef2431defcfaa155f0acfa1ca4acbf8fd80895b1e7e2ada40e"}, + {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b04c2f0adaf255bf756cf08ebef1be132d3c7a06fe6f9877d55640c5e60c72c5"}, + {file = "contourpy-1.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d0c188ae66b772d9d61d43c6030500344c13e3f73a00d1dc241da896f379bb62"}, + {file = "contourpy-1.1.1-cp311-cp311-win32.whl", hash = "sha256:0683e1ae20dc038075d92e0e0148f09ffcefab120e57f6b4c9c0f477ec171f33"}, + {file = "contourpy-1.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:8636cd2fc5da0fb102a2504fa2c4bea3cbc149533b345d72cdf0e7a924decc45"}, + {file = "contourpy-1.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:560f1d68a33e89c62da5da4077ba98137a5e4d3a271b29f2f195d0fba2adcb6a"}, + {file = "contourpy-1.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:24216552104ae8f3b34120ef84825400b16eb6133af2e27a190fdc13529f023e"}, + {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56de98a2fb23025882a18b60c7f0ea2d2d70bbbcfcf878f9067234b1c4818442"}, + {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:07d6f11dfaf80a84c97f1a5ba50d129d9303c5b4206f776e94037332e298dda8"}, + {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1eaac5257a8f8a047248d60e8f9315c6cff58f7803971170d952555ef6344a7"}, + {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19557fa407e70f20bfaba7d55b4d97b14f9480856c4fb65812e8a05fe1c6f9bf"}, + {file = "contourpy-1.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:081f3c0880712e40effc5f4c3b08feca6d064cb8cfbb372ca548105b86fd6c3d"}, + {file = "contourpy-1.1.1-cp312-cp312-win32.whl", hash = "sha256:059c3d2a94b930f4dafe8105bcdc1b21de99b30b51b5bce74c753686de858cb6"}, + {file = "contourpy-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:f44d78b61740e4e8c71db1cf1fd56d9050a4747681c59ec1094750a658ceb970"}, + {file = "contourpy-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:70e5a10f8093d228bb2b552beeb318b8928b8a94763ef03b858ef3612b29395d"}, + {file = "contourpy-1.1.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8394e652925a18ef0091115e3cc191fef350ab6dc3cc417f06da66bf98071ae9"}, + {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5bd5680f844c3ff0008523a71949a3ff5e4953eb7701b28760805bc9bcff217"}, + {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66544f853bfa85c0d07a68f6c648b2ec81dafd30f272565c37ab47a33b220684"}, + {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0c02b75acfea5cab07585d25069207e478d12309557f90a61b5a3b4f77f46ce"}, + {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41339b24471c58dc1499e56783fedc1afa4bb018bcd035cfb0ee2ad2a7501ef8"}, + {file = "contourpy-1.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f29fb0b3f1217dfe9362ec55440d0743fe868497359f2cf93293f4b2701b8251"}, + {file = "contourpy-1.1.1-cp38-cp38-win32.whl", hash = "sha256:f9dc7f933975367251c1b34da882c4f0e0b2e24bb35dc906d2f598a40b72bfc7"}, + {file = "contourpy-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:498e53573e8b94b1caeb9e62d7c2d053c263ebb6aa259c81050766beb50ff8d9"}, + {file = "contourpy-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ba42e3810999a0ddd0439e6e5dbf6d034055cdc72b7c5c839f37a7c274cb4eba"}, + {file = "contourpy-1.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c06e4c6e234fcc65435223c7b2a90f286b7f1b2733058bdf1345d218cc59e34"}, + {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca6fab080484e419528e98624fb5c4282148b847e3602dc8dbe0cb0669469887"}, + {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93df44ab351119d14cd1e6b52a5063d3336f0754b72736cc63db59307dabb718"}, + {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eafbef886566dc1047d7b3d4b14db0d5b7deb99638d8e1be4e23a7c7ac59ff0f"}, + {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efe0fab26d598e1ec07d72cf03eaeeba8e42b4ecf6b9ccb5a356fde60ff08b85"}, + {file = "contourpy-1.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f08e469821a5e4751c97fcd34bcb586bc243c39c2e39321822060ba902eac49e"}, + {file = "contourpy-1.1.1-cp39-cp39-win32.whl", hash = "sha256:bfc8a5e9238232a45ebc5cb3bfee71f1167064c8d382cadd6076f0d51cff1da0"}, + {file = "contourpy-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:c84fdf3da00c2827d634de4fcf17e3e067490c4aea82833625c4c8e6cdea0887"}, + {file = "contourpy-1.1.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:229a25f68046c5cf8067d6d6351c8b99e40da11b04d8416bf8d2b1d75922521e"}, + {file = "contourpy-1.1.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a10dab5ea1bd4401c9483450b5b0ba5416be799bbd50fc7a6cc5e2a15e03e8a3"}, + {file = "contourpy-1.1.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4f9147051cb8fdb29a51dc2482d792b3b23e50f8f57e3720ca2e3d438b7adf23"}, + {file = "contourpy-1.1.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a75cc163a5f4531a256f2c523bd80db509a49fc23721b36dd1ef2f60ff41c3cb"}, + {file = "contourpy-1.1.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b53d5769aa1f2d4ea407c65f2d1d08002952fac1d9e9d307aa2e1023554a163"}, + {file = "contourpy-1.1.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11b836b7dbfb74e049c302bbf74b4b8f6cb9d0b6ca1bf86cfa8ba144aedadd9c"}, + {file = "contourpy-1.1.1.tar.gz", hash = "sha256:96ba37c2e24b7212a77da85004c38e7c4d155d3e72a45eeaf22c1f03f607e8ab"}, +] + +[package.dependencies] +numpy = {version = ">=1.16,<2.0", markers = "python_version <= \"3.11\""} + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.4.1)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "wurlitzer"] + +[[package]] +name = "contourpy" +version = "1.2.0" +description = "Python library for calculating contours of 2D quadrilateral grids" +optional = false +python-versions = ">=3.9" +files = [ + {file = "contourpy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8"}, + {file = "contourpy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab459a1cbbf18e8698399c595a01f6dcc5c138220ca3ea9e7e6126232d102bb4"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fdd887f17c2f4572ce548461e4f96396681212d858cae7bd52ba3310bc6f00f"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d16edfc3fc09968e09ddffada434b3bf989bf4911535e04eada58469873e28e"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c203f617abc0dde5792beb586f827021069fb6d403d7f4d5c2b543d87edceb9"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b69303ceb2e4d4f146bf82fda78891ef7bcd80c41bf16bfca3d0d7eb545448aa"}, + {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:884c3f9d42d7218304bc74a8a7693d172685c84bd7ab2bab1ee567b769696df9"}, + {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4a1b1208102be6e851f20066bf0e7a96b7d48a07c9b0cfe6d0d4545c2f6cadab"}, + {file = "contourpy-1.2.0-cp310-cp310-win32.whl", hash = "sha256:34b9071c040d6fe45d9826cbbe3727d20d83f1b6110d219b83eb0e2a01d79488"}, + {file = "contourpy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:bd2f1ae63998da104f16a8b788f685e55d65760cd1929518fd94cd682bf03e41"}, + {file = "contourpy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd10c26b4eadae44783c45ad6655220426f971c61d9b239e6f7b16d5cdaaa727"}, + {file = "contourpy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5c6b28956b7b232ae801406e529ad7b350d3f09a4fde958dfdf3c0520cdde0dd"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebeac59e9e1eb4b84940d076d9f9a6cec0064e241818bcb6e32124cc5c3e377a"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:139d8d2e1c1dd52d78682f505e980f592ba53c9f73bd6be102233e358b401063"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e9dc350fb4c58adc64df3e0703ab076f60aac06e67d48b3848c23647ae4310e"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18fc2b4ed8e4a8fe849d18dce4bd3c7ea637758c6343a1f2bae1e9bd4c9f4686"}, + {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:16a7380e943a6d52472096cb7ad5264ecee36ed60888e2a3d3814991a0107286"}, + {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8d8faf05be5ec8e02a4d86f616fc2a0322ff4a4ce26c0f09d9f7fb5330a35c95"}, + {file = "contourpy-1.2.0-cp311-cp311-win32.whl", hash = "sha256:67b7f17679fa62ec82b7e3e611c43a016b887bd64fb933b3ae8638583006c6d6"}, + {file = "contourpy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:99ad97258985328b4f207a5e777c1b44a83bfe7cf1f87b99f9c11d4ee477c4de"}, + {file = "contourpy-1.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:575bcaf957a25d1194903a10bc9f316c136c19f24e0985a2b9b5608bdf5dbfe0"}, + {file = "contourpy-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9e6c93b5b2dbcedad20a2f18ec22cae47da0d705d454308063421a3b290d9ea4"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:464b423bc2a009088f19bdf1f232299e8b6917963e2b7e1d277da5041f33a779"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68ce4788b7d93e47f84edd3f1f95acdcd142ae60bc0e5493bfd120683d2d4316"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d7d1f8871998cdff5d2ff6a087e5e1780139abe2838e85b0b46b7ae6cc25399"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e739530c662a8d6d42c37c2ed52a6f0932c2d4a3e8c1f90692ad0ce1274abe0"}, + {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:247b9d16535acaa766d03037d8e8fb20866d054d3c7fbf6fd1f993f11fc60ca0"}, + {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:461e3ae84cd90b30f8d533f07d87c00379644205b1d33a5ea03381edc4b69431"}, + {file = "contourpy-1.2.0-cp312-cp312-win32.whl", hash = "sha256:1c2559d6cffc94890b0529ea7eeecc20d6fadc1539273aa27faf503eb4656d8f"}, + {file = "contourpy-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:491b1917afdd8638a05b611a56d46587d5a632cabead889a5440f7c638bc6ed9"}, + {file = "contourpy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5fd1810973a375ca0e097dee059c407913ba35723b111df75671a1976efa04bc"}, + {file = "contourpy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:999c71939aad2780f003979b25ac5b8f2df651dac7b38fb8ce6c46ba5abe6ae9"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7caf9b241464c404613512d5594a6e2ff0cc9cb5615c9475cc1d9b514218ae8"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:266270c6f6608340f6c9836a0fb9b367be61dde0c9a9a18d5ece97774105ff3e"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbd50d0a0539ae2e96e537553aff6d02c10ed165ef40c65b0e27e744a0f10af8"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11f8d2554e52f459918f7b8e6aa20ec2a3bce35ce95c1f0ef4ba36fbda306df5"}, + {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ce96dd400486e80ac7d195b2d800b03e3e6a787e2a522bfb83755938465a819e"}, + {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6d3364b999c62f539cd403f8123ae426da946e142312a514162adb2addd8d808"}, + {file = "contourpy-1.2.0-cp39-cp39-win32.whl", hash = "sha256:1c88dfb9e0c77612febebb6ac69d44a8d81e3dc60f993215425b62c1161353f4"}, + {file = "contourpy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:78e6ad33cf2e2e80c5dfaaa0beec3d61face0fb650557100ee36db808bfa6843"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be16975d94c320432657ad2402f6760990cb640c161ae6da1363051805fa8108"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b95a225d4948b26a28c08307a60ac00fb8671b14f2047fc5476613252a129776"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d7e03c0f9a4f90dc18d4e77e9ef4ec7b7bbb437f7f675be8e530d65ae6ef956"}, + {file = "contourpy-1.2.0.tar.gz", hash = "sha256:171f311cb758de7da13fc53af221ae47a5877be5a0843a9fe150818c51ed276a"}, +] + +[package.dependencies] +numpy = ">=1.20,<2.0" + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.6.1)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] + +[[package]] +name = "coverage" +version = "7.4.1" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "coverage-7.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:077d366e724f24fc02dbfe9d946534357fda71af9764ff99d73c3c596001bbd7"}, + {file = "coverage-7.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0193657651f5399d433c92f8ae264aff31fc1d066deee4b831549526433f3f61"}, + {file = "coverage-7.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d17bbc946f52ca67adf72a5ee783cd7cd3477f8f8796f59b4974a9b59cacc9ee"}, + {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3277f5fa7483c927fe3a7b017b39351610265308f5267ac6d4c2b64cc1d8d25"}, + {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dceb61d40cbfcf45f51e59933c784a50846dc03211054bd76b421a713dcdf19"}, + {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6008adeca04a445ea6ef31b2cbaf1d01d02986047606f7da266629afee982630"}, + {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c61f66d93d712f6e03369b6a7769233bfda880b12f417eefdd4f16d1deb2fc4c"}, + {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9bb62fac84d5f2ff523304e59e5c439955fb3b7f44e3d7b2085184db74d733b"}, + {file = "coverage-7.4.1-cp310-cp310-win32.whl", hash = "sha256:f86f368e1c7ce897bf2457b9eb61169a44e2ef797099fb5728482b8d69f3f016"}, + {file = "coverage-7.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:869b5046d41abfea3e381dd143407b0d29b8282a904a19cb908fa24d090cc018"}, + {file = "coverage-7.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b8ffb498a83d7e0305968289441914154fb0ef5d8b3157df02a90c6695978295"}, + {file = "coverage-7.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3cacfaefe6089d477264001f90f55b7881ba615953414999c46cc9713ff93c8c"}, + {file = "coverage-7.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d6850e6e36e332d5511a48a251790ddc545e16e8beaf046c03985c69ccb2676"}, + {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18e961aa13b6d47f758cc5879383d27b5b3f3dcd9ce8cdbfdc2571fe86feb4dd"}, + {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfd1e1b9f0898817babf840b77ce9fe655ecbe8b1b327983df485b30df8cc011"}, + {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6b00e21f86598b6330f0019b40fb397e705135040dbedc2ca9a93c7441178e74"}, + {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:536d609c6963c50055bab766d9951b6c394759190d03311f3e9fcf194ca909e1"}, + {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7ac8f8eb153724f84885a1374999b7e45734bf93a87d8df1e7ce2146860edef6"}, + {file = "coverage-7.4.1-cp311-cp311-win32.whl", hash = "sha256:f3771b23bb3675a06f5d885c3630b1d01ea6cac9e84a01aaf5508706dba546c5"}, + {file = "coverage-7.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:9d2f9d4cc2a53b38cabc2d6d80f7f9b7e3da26b2f53d48f05876fef7956b6968"}, + {file = "coverage-7.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f68ef3660677e6624c8cace943e4765545f8191313a07288a53d3da188bd8581"}, + {file = "coverage-7.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23b27b8a698e749b61809fb637eb98ebf0e505710ec46a8aa6f1be7dc0dc43a6"}, + {file = "coverage-7.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e3424c554391dc9ef4a92ad28665756566a28fecf47308f91841f6c49288e66"}, + {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0860a348bf7004c812c8368d1fc7f77fe8e4c095d661a579196a9533778e156"}, + {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe558371c1bdf3b8fa03e097c523fb9645b8730399c14fe7721ee9c9e2a545d3"}, + {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3468cc8720402af37b6c6e7e2a9cdb9f6c16c728638a2ebc768ba1ef6f26c3a1"}, + {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:02f2edb575d62172aa28fe00efe821ae31f25dc3d589055b3fb64d51e52e4ab1"}, + {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ca6e61dc52f601d1d224526360cdeab0d0712ec104a2ce6cc5ccef6ed9a233bc"}, + {file = "coverage-7.4.1-cp312-cp312-win32.whl", hash = "sha256:ca7b26a5e456a843b9b6683eada193fc1f65c761b3a473941efe5a291f604c74"}, + {file = "coverage-7.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:85ccc5fa54c2ed64bd91ed3b4a627b9cce04646a659512a051fa82a92c04a448"}, + {file = "coverage-7.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8bdb0285a0202888d19ec6b6d23d5990410decb932b709f2b0dfe216d031d218"}, + {file = "coverage-7.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:918440dea04521f499721c039863ef95433314b1db00ff826a02580c1f503e45"}, + {file = "coverage-7.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:379d4c7abad5afbe9d88cc31ea8ca262296480a86af945b08214eb1a556a3e4d"}, + {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b094116f0b6155e36a304ff912f89bbb5067157aff5f94060ff20bbabdc8da06"}, + {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2f5968608b1fe2a1d00d01ad1017ee27efd99b3437e08b83ded9b7af3f6f766"}, + {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:10e88e7f41e6197ea0429ae18f21ff521d4f4490aa33048f6c6f94c6045a6a75"}, + {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a4a3907011d39dbc3e37bdc5df0a8c93853c369039b59efa33a7b6669de04c60"}, + {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6d224f0c4c9c98290a6990259073f496fcec1b5cc613eecbd22786d398ded3ad"}, + {file = "coverage-7.4.1-cp38-cp38-win32.whl", hash = "sha256:23f5881362dcb0e1a92b84b3c2809bdc90db892332daab81ad8f642d8ed55042"}, + {file = "coverage-7.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:a07f61fc452c43cd5328b392e52555f7d1952400a1ad09086c4a8addccbd138d"}, + {file = "coverage-7.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8e738a492b6221f8dcf281b67129510835461132b03024830ac0e554311a5c54"}, + {file = "coverage-7.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46342fed0fff72efcda77040b14728049200cbba1279e0bf1188f1f2078c1d70"}, + {file = "coverage-7.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9641e21670c68c7e57d2053ddf6c443e4f0a6e18e547e86af3fad0795414a628"}, + {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aeb2c2688ed93b027eb0d26aa188ada34acb22dceea256d76390eea135083950"}, + {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d12c923757de24e4e2110cf8832d83a886a4cf215c6e61ed506006872b43a6d1"}, + {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0491275c3b9971cdbd28a4595c2cb5838f08036bca31765bad5e17edf900b2c7"}, + {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8dfc5e195bbef80aabd81596ef52a1277ee7143fe419efc3c4d8ba2754671756"}, + {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1a78b656a4d12b0490ca72651fe4d9f5e07e3c6461063a9b6265ee45eb2bdd35"}, + {file = "coverage-7.4.1-cp39-cp39-win32.whl", hash = "sha256:f90515974b39f4dea2f27c0959688621b46d96d5a626cf9c53dbc653a895c05c"}, + {file = "coverage-7.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:64e723ca82a84053dd7bfcc986bdb34af8d9da83c521c19d6b472bc6880e191a"}, + {file = "coverage-7.4.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:32a8d985462e37cfdab611a6f95b09d7c091d07668fdc26e47a725ee575fe166"}, + {file = "coverage-7.4.1.tar.gz", hash = "sha256:1ed4b95480952b1a26d863e546fa5094564aa0065e1e5f0d4d0041f293251d04"}, +] + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "cycler" +version = "0.12.1" +description = "Composable style cycles" +optional = false +python-versions = ">=3.8" +files = [ + {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, + {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, +] + +[package.extras] +docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] +tests = ["pytest", "pytest-cov", "pytest-xdist"] + +[[package]] +name = "distlib" +version = "0.3.8" +description = "Distribution utilities" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, + {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, +] + +[[package]] +name = "docutils" +version = "0.19" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"}, + {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"}, +] + +[[package]] +name = "docutils" +version = "0.20.1" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, + {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "filelock" +version = "3.13.1" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +files = [ + {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, + {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +typing = ["typing-extensions (>=4.8)"] + +[[package]] +name = "fonttools" +version = "4.47.2" +description = "Tools to manipulate font files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fonttools-4.47.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3b629108351d25512d4ea1a8393a2dba325b7b7d7308116b605ea3f8e1be88df"}, + {file = "fonttools-4.47.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c19044256c44fe299d9a73456aabee4b4d06c6b930287be93b533b4737d70aa1"}, + {file = "fonttools-4.47.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8be28c036b9f186e8c7eaf8a11b42373e7e4949f9e9f370202b9da4c4c3f56c"}, + {file = "fonttools-4.47.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f83a4daef6d2a202acb9bf572958f91cfde5b10c8ee7fb1d09a4c81e5d851fd8"}, + {file = "fonttools-4.47.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a5a5318ba5365d992666ac4fe35365f93004109d18858a3e18ae46f67907670"}, + {file = "fonttools-4.47.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8f57ecd742545362a0f7186774b2d1c53423ed9ece67689c93a1055b236f638c"}, + {file = "fonttools-4.47.2-cp310-cp310-win32.whl", hash = "sha256:a1c154bb85dc9a4cf145250c88d112d88eb414bad81d4cb524d06258dea1bdc0"}, + {file = "fonttools-4.47.2-cp310-cp310-win_amd64.whl", hash = "sha256:3e2b95dce2ead58fb12524d0ca7d63a63459dd489e7e5838c3cd53557f8933e1"}, + {file = "fonttools-4.47.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:29495d6d109cdbabe73cfb6f419ce67080c3ef9ea1e08d5750240fd4b0c4763b"}, + {file = "fonttools-4.47.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0a1d313a415eaaba2b35d6cd33536560deeebd2ed758b9bfb89ab5d97dc5deac"}, + {file = "fonttools-4.47.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90f898cdd67f52f18049250a6474185ef6544c91f27a7bee70d87d77a8daf89c"}, + {file = "fonttools-4.47.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3480eeb52770ff75140fe7d9a2ec33fb67b07efea0ab5129c7e0c6a639c40c70"}, + {file = "fonttools-4.47.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0255dbc128fee75fb9be364806b940ed450dd6838672a150d501ee86523ac61e"}, + {file = "fonttools-4.47.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f791446ff297fd5f1e2247c188de53c1bfb9dd7f0549eba55b73a3c2087a2703"}, + {file = "fonttools-4.47.2-cp311-cp311-win32.whl", hash = "sha256:740947906590a878a4bde7dd748e85fefa4d470a268b964748403b3ab2aeed6c"}, + {file = "fonttools-4.47.2-cp311-cp311-win_amd64.whl", hash = "sha256:63fbed184979f09a65aa9c88b395ca539c94287ba3a364517698462e13e457c9"}, + {file = "fonttools-4.47.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4ec558c543609e71b2275c4894e93493f65d2f41c15fe1d089080c1d0bb4d635"}, + {file = "fonttools-4.47.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e040f905d542362e07e72e03612a6270c33d38281fd573160e1003e43718d68d"}, + {file = "fonttools-4.47.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dd58cc03016b281bd2c74c84cdaa6bd3ce54c5a7f47478b7657b930ac3ed8eb"}, + {file = "fonttools-4.47.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32ab2e9702dff0dd4510c7bb958f265a8d3dd5c0e2547e7b5f7a3df4979abb07"}, + {file = "fonttools-4.47.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a808f3c1d1df1f5bf39be869b6e0c263570cdafb5bdb2df66087733f566ea71"}, + {file = "fonttools-4.47.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ac71e2e201df041a2891067dc36256755b1229ae167edbdc419b16da78732c2f"}, + {file = "fonttools-4.47.2-cp312-cp312-win32.whl", hash = "sha256:69731e8bea0578b3c28fdb43dbf95b9386e2d49a399e9a4ad736b8e479b08085"}, + {file = "fonttools-4.47.2-cp312-cp312-win_amd64.whl", hash = "sha256:b3e1304e5f19ca861d86a72218ecce68f391646d85c851742d265787f55457a4"}, + {file = "fonttools-4.47.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:254d9a6f7be00212bf0c3159e0a420eb19c63793b2c05e049eb337f3023c5ecc"}, + {file = "fonttools-4.47.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eabae77a07c41ae0b35184894202305c3ad211a93b2eb53837c2a1143c8bc952"}, + {file = "fonttools-4.47.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a86a5ab2873ed2575d0fcdf1828143cfc6b977ac448e3dc616bb1e3d20efbafa"}, + {file = "fonttools-4.47.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13819db8445a0cec8c3ff5f243af6418ab19175072a9a92f6cc8ca7d1452754b"}, + {file = "fonttools-4.47.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4e743935139aa485fe3253fc33fe467eab6ea42583fa681223ea3f1a93dd01e6"}, + {file = "fonttools-4.47.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d49ce3ea7b7173faebc5664872243b40cf88814ca3eb135c4a3cdff66af71946"}, + {file = "fonttools-4.47.2-cp38-cp38-win32.whl", hash = "sha256:94208ea750e3f96e267f394d5588579bb64cc628e321dbb1d4243ffbc291b18b"}, + {file = "fonttools-4.47.2-cp38-cp38-win_amd64.whl", hash = "sha256:0f750037e02beb8b3569fbff701a572e62a685d2a0e840d75816592280e5feae"}, + {file = "fonttools-4.47.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3d71606c9321f6701642bd4746f99b6089e53d7e9817fc6b964e90d9c5f0ecc6"}, + {file = "fonttools-4.47.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:86e0427864c6c91cf77f16d1fb9bf1bbf7453e824589e8fb8461b6ee1144f506"}, + {file = "fonttools-4.47.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a00bd0e68e88987dcc047ea31c26d40a3c61185153b03457956a87e39d43c37"}, + {file = "fonttools-4.47.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5d77479fb885ef38a16a253a2f4096bc3d14e63a56d6246bfdb56365a12b20c"}, + {file = "fonttools-4.47.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5465df494f20a7d01712b072ae3ee9ad2887004701b95cb2cc6dcb9c2c97a899"}, + {file = "fonttools-4.47.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4c811d3c73b6abac275babb8aa439206288f56fdb2c6f8835e3d7b70de8937a7"}, + {file = "fonttools-4.47.2-cp39-cp39-win32.whl", hash = "sha256:5b60e3afa9635e3dfd3ace2757039593e3bd3cf128be0ddb7a1ff4ac45fa5a50"}, + {file = "fonttools-4.47.2-cp39-cp39-win_amd64.whl", hash = "sha256:7ee48bd9d6b7e8f66866c9090807e3a4a56cf43ffad48962725a190e0dd774c8"}, + {file = "fonttools-4.47.2-py3-none-any.whl", hash = "sha256:7eb7ad665258fba68fd22228a09f347469d95a97fb88198e133595947a20a184"}, + {file = "fonttools-4.47.2.tar.gz", hash = "sha256:7df26dd3650e98ca45f1e29883c96a0b9f5bb6af8d632a6a108bc744fa0bd9b3"}, +] + +[package.extras] +all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "pycairo", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"] +graphite = ["lz4 (>=1.7.4.2)"] +interpolatable = ["munkres", "pycairo", "scipy"] +lxml = ["lxml (>=4.0,<5)"] +pathops = ["skia-pathops (>=0.5.0)"] +plot = ["matplotlib"] +repacker = ["uharfbuzz (>=0.23.0)"] +symfont = ["sympy"] +type1 = ["xattr"] +ufo = ["fs (>=2.2.0,<3)"] +unicode = ["unicodedata2 (>=15.1.0)"] +woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] + +[[package]] +name = "ghp-import" +version = "2.1.0" +description = "Copy your docs directly to the gh-pages branch." +optional = false +python-versions = "*" +files = [ + {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, + {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, +] + +[package.dependencies] +python-dateutil = ">=2.8.1" + +[package.extras] +dev = ["flake8", "markdown", "twine", "wheel"] + +[[package]] +name = "identify" +version = "2.5.33" +description = "File identification library for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "identify-2.5.33-py2.py3-none-any.whl", hash = "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34"}, + {file = "identify-2.5.33.tar.gz", hash = "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d"}, +] + +[package.extras] +license = ["ukkonen"] + +[[package]] +name = "idna" +version = "3.6" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, +] + +[[package]] +name = "imagesize" +version = "1.4.1" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, + {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, +] + +[[package]] +name = "importlib-metadata" +version = "7.0.1" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-7.0.1-py3-none-any.whl", hash = "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e"}, + {file = "importlib_metadata-7.0.1.tar.gz", hash = "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + +[[package]] +name = "importlib-resources" +version = "6.1.1" +description = "Read resources from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_resources-6.1.1-py3-none-any.whl", hash = "sha256:e8bf90d8213b486f428c9c39714b920041cb02c184686a3dee24905aaa8105d6"}, + {file = "importlib_resources-6.1.1.tar.gz", hash = "sha256:3893a00122eafde6894c59914446a512f728a0c1a45f9bb9b63721b6bacf0b4a"}, +] + +[package.dependencies] +zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "zipp (>=3.17)"] + +[[package]] +name = "infinity" +version = "1.5" +description = "All-in-one infinity value for Python. Can be compared to any object." +optional = false +python-versions = "*" +files = [ + {file = "infinity-1.5.tar.gz", hash = "sha256:8daa7c15ce2100fdccfde212337e0cd5cf085869f54dc2634b6c30d61461ecda"}, +] + +[package.extras] +test = ["Pygments (>=1.2)", "flake8 (>=2.4.0)", "isort (>=4.2.2)", "pytest (>=2.2.3)", "six (>=1.4.1)"] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "jinja2" +version = "3.1.3" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "kiwisolver" +version = "1.4.5" +description = "A fast implementation of the Cassowary constraint solver" +optional = false +python-versions = ">=3.7" +files = [ + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win32.whl", hash = "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win_amd64.whl", hash = "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win32.whl", hash = "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win_amd64.whl", hash = "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win32.whl", hash = "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win_amd64.whl", hash = "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee"}, + {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, +] + +[[package]] +name = "livereload" +version = "2.6.3" +description = "Python LiveReload is an awesome tool for web developers" +optional = false +python-versions = "*" +files = [ + {file = "livereload-2.6.3-py2.py3-none-any.whl", hash = "sha256:ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4"}, + {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"}, +] + +[package.dependencies] +six = "*" +tornado = {version = "*", markers = "python_version > \"2.7\""} + +[[package]] +name = "markdown" +version = "3.5.2" +description = "Python implementation of John Gruber's Markdown." +optional = false +python-versions = ">=3.8" +files = [ + {file = "Markdown-3.5.2-py3-none-any.whl", hash = "sha256:d43323865d89fc0cb9b20c75fc8ad313af307cc087e84b657d9eec768eddeadd"}, + {file = "Markdown-3.5.2.tar.gz", hash = "sha256:e1ac7b3dc550ee80e602e71c1d168002f062e49f1b11e26a36264dafd4df2ef8"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] +testing = ["coverage", "pyyaml"] + +[[package]] +name = "markupsafe" +version = "2.1.5" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, +] + +[[package]] +name = "matplotlib" +version = "3.7.4" +description = "Python plotting package" +optional = false +python-versions = ">=3.8" +files = [ + {file = "matplotlib-3.7.4-cp310-cp310-macosx_10_12_universal2.whl", hash = "sha256:b71079239bd866bf56df023e5146de159cb0c7294e508830901f4d79e2d89385"}, + {file = "matplotlib-3.7.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:bf91a42f6274a64cb41189120b620c02e574535ff6671fa836cade7701b06fbd"}, + {file = "matplotlib-3.7.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f757e8b42841d6add0cb69b42497667f0d25a404dcd50bd923ec9904e38414c4"}, + {file = "matplotlib-3.7.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4dfee00aa4bd291e08bb9461831c26ce0da85ca9781bb8794f2025c6e925281"}, + {file = "matplotlib-3.7.4-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3640f33632beb3993b698b1be9d1c262b742761d6101f3c27b87b2185d25c875"}, + {file = "matplotlib-3.7.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff539c4a17ecdf076ed808ee271ffae4a30dcb7e157b99ccae2c837262c07db6"}, + {file = "matplotlib-3.7.4-cp310-cp310-win32.whl", hash = "sha256:24b8f28af3e766195c09b780b15aa9f6710192b415ae7866b9c03dee7ec86370"}, + {file = "matplotlib-3.7.4-cp310-cp310-win_amd64.whl", hash = "sha256:3fa193286712c3b6c3cfa5fe8a6bb563f8c52cc750006c782296e0807ce5e799"}, + {file = "matplotlib-3.7.4-cp311-cp311-macosx_10_12_universal2.whl", hash = "sha256:b167f54cb4654b210c9624ec7b54e2b3b8de68c93a14668937e7e53df60770ec"}, + {file = "matplotlib-3.7.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7dfe6821f1944cb35603ff22e21510941bbcce7ccf96095beffaac890d39ce77"}, + {file = "matplotlib-3.7.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3c557d9165320dff3c5f2bb99bfa0b6813d3e626423ff71c40d6bc23b83c3339"}, + {file = "matplotlib-3.7.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08372696b3bb45c563472a552a705bfa0942f0a8ffe084db8a4e8f9153fbdf9d"}, + {file = "matplotlib-3.7.4-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81e1a7ac818000e8ac3ca696c3fdc501bc2d3adc89005e7b4e22ee5e9d51de98"}, + {file = "matplotlib-3.7.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:390920a3949906bc4b0216198d378f2a640c36c622e3584dd0c79a7c59ae9f50"}, + {file = "matplotlib-3.7.4-cp311-cp311-win32.whl", hash = "sha256:62e094d8da26294634da9e7f1856beee3978752b1b530c8e1763d2faed60cc10"}, + {file = "matplotlib-3.7.4-cp311-cp311-win_amd64.whl", hash = "sha256:f8fc2df756105784e650605e024d36dc2d048d68e5c1b26df97ee25d1bd41f9f"}, + {file = "matplotlib-3.7.4-cp312-cp312-macosx_10_12_universal2.whl", hash = "sha256:568574756127791903604e315c11aef9f255151e4cfe20ec603a70f9dda8e259"}, + {file = "matplotlib-3.7.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7d479aac338195e2199a8cfc03c4f2f55914e6a120177edae79e0340a6406457"}, + {file = "matplotlib-3.7.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:32183d4be84189a4c52b4b8861434d427d9118db2cec32986f98ed6c02dcfbb6"}, + {file = "matplotlib-3.7.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0037d066cca1f4bda626c507cddeb6f7da8283bc6a214da2db13ff2162933c52"}, + {file = "matplotlib-3.7.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44856632ebce88abd8efdc0a0dceec600418dcac06b72ae77af0019d260aa243"}, + {file = "matplotlib-3.7.4-cp312-cp312-win_amd64.whl", hash = "sha256:632fc938c22117d4241411191cfb88ac264a4c0a9ac702244641ddf30f0d739c"}, + {file = "matplotlib-3.7.4-cp38-cp38-macosx_10_12_universal2.whl", hash = "sha256:ce163be048613b9d1962273708cc97e09ca05d37312e670d166cf332b80bbaff"}, + {file = "matplotlib-3.7.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:e680f49bb8052ba3b2698e370155d2b4afb49f9af1cc611a26579d5981e2852a"}, + {file = "matplotlib-3.7.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0604880e4327114054199108b7390f987f4f40ee5ce728985836889e11a780ba"}, + {file = "matplotlib-3.7.4-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1e6abcde6fc52475f9d6a12b9f1792aee171ce7818ef6df5d61cb0b82816e6e8"}, + {file = "matplotlib-3.7.4-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f59a70e2ec3212033ef6633ed07682da03f5249379722512a3a2a26a7d9a738e"}, + {file = "matplotlib-3.7.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a9981b2a2dd9da06eca4ab5855d09b54b8ce7377c3e0e3957767b83219d652d"}, + {file = "matplotlib-3.7.4-cp38-cp38-win32.whl", hash = "sha256:83859ac26839660ecd164ee8311272074250b915ac300f9b2eccc84410f8953b"}, + {file = "matplotlib-3.7.4-cp38-cp38-win_amd64.whl", hash = "sha256:7a7709796ac59fe8debde68272388be6ed449c8971362eb5b60d280eac8dadde"}, + {file = "matplotlib-3.7.4-cp39-cp39-macosx_10_12_universal2.whl", hash = "sha256:b1d70bc1ea1bf110bec64f4578de3e14947909a8887df4c1fd44492eca487955"}, + {file = "matplotlib-3.7.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c83f49e795a5de6c168876eea723f5b88355202f9603c55977f5356213aa8280"}, + {file = "matplotlib-3.7.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5c9133f230945fe10652eb33e43642e933896194ef6a4f8d5e79bb722bdb2000"}, + {file = "matplotlib-3.7.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:798ff59022eeb276380ce9a73ba35d13c3d1499ab9b73d194fd07f1b0a41c304"}, + {file = "matplotlib-3.7.4-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1707b20b25e90538c2ce8d4409e30f0ef1df4017cc65ad0439633492a973635b"}, + {file = "matplotlib-3.7.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e6227ca8492baeef873cdd8e169a318efb5c3a25ce94e69727e7f964995b0b1"}, + {file = "matplotlib-3.7.4-cp39-cp39-win32.whl", hash = "sha256:5661c8639aded7d1bbf781373a359011cb1dd09199dee49043e9e68dd16f07ba"}, + {file = "matplotlib-3.7.4-cp39-cp39-win_amd64.whl", hash = "sha256:55eec941a4743f0bd3e5b8ee180e36b7ea8e62f867bf2613937c9f01b9ac06a2"}, + {file = "matplotlib-3.7.4-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ab16868714e5cc90ec8f7ff5d83d23bcd6559224d8e9cb5227c9f58748889fe8"}, + {file = "matplotlib-3.7.4-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c698b33f9a3f0b127a8e614c8fb4087563bb3caa9c9d95298722fa2400cdd3f"}, + {file = "matplotlib-3.7.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be3493bbcb4d255cb71de1f9050ac71682fce21a56089eadbcc8e21784cb12ee"}, + {file = "matplotlib-3.7.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:f8c725d1dd2901b2e7ec6cd64165e00da2978cc23d4143cb9ef745bec88e6b04"}, + {file = "matplotlib-3.7.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:286332f8f45f8ffde2d2119b9fdd42153dccd5025fa9f451b4a3b5c086e26da5"}, + {file = "matplotlib-3.7.4-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:116ef0b43aa00ff69260b4cce39c571e4b8c6f893795b708303fa27d9b9d7548"}, + {file = "matplotlib-3.7.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c90590d4b46458677d80bc3218f3f1ac11fc122baa9134e0cb5b3e8fc3714052"}, + {file = "matplotlib-3.7.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:de7c07069687be64fd9d119da3122ba13a8d399eccd3f844815f0dc78a870b2c"}, + {file = "matplotlib-3.7.4.tar.gz", hash = "sha256:7cd4fef8187d1dd0d9dcfdbaa06ac326d396fb8c71c647129f0bf56835d77026"}, +] + +[package.dependencies] +contourpy = ">=1.0.1" +cycler = ">=0.10" +fonttools = ">=4.22.0" +importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} +kiwisolver = ">=1.0.1" +numpy = ">=1.20,<2" +packaging = ">=20.0" +pillow = ">=6.2.0" +pyparsing = ">=2.3.1" +python-dateutil = ">=2.7" + +[[package]] +name = "matplotlib" +version = "3.8.2" +description = "Python plotting package" +optional = false +python-versions = ">=3.9" +files = [ + {file = "matplotlib-3.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:09796f89fb71a0c0e1e2f4bdaf63fb2cefc84446bb963ecdeb40dfee7dfa98c7"}, + {file = "matplotlib-3.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f9c6976748a25e8b9be51ea028df49b8e561eed7809146da7a47dbecebab367"}, + {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b78e4f2cedf303869b782071b55fdde5987fda3038e9d09e58c91cc261b5ad18"}, + {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e208f46cf6576a7624195aa047cb344a7f802e113bb1a06cfd4bee431de5e31"}, + {file = "matplotlib-3.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:46a569130ff53798ea5f50afce7406e91fdc471ca1e0e26ba976a8c734c9427a"}, + {file = "matplotlib-3.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:830f00640c965c5b7f6bc32f0d4ce0c36dfe0379f7dd65b07a00c801713ec40a"}, + {file = "matplotlib-3.8.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d86593ccf546223eb75a39b44c32788e6f6440d13cfc4750c1c15d0fcb850b63"}, + {file = "matplotlib-3.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a5430836811b7652991939012f43d2808a2db9b64ee240387e8c43e2e5578c8"}, + {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9576723858a78751d5aacd2497b8aef29ffea6d1c95981505877f7ac28215c6"}, + {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ba9cbd8ac6cf422f3102622b20f8552d601bf8837e49a3afed188d560152788"}, + {file = "matplotlib-3.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:03f9d160a29e0b65c0790bb07f4f45d6a181b1ac33eb1bb0dd225986450148f0"}, + {file = "matplotlib-3.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:3773002da767f0a9323ba1a9b9b5d00d6257dbd2a93107233167cfb581f64717"}, + {file = "matplotlib-3.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4c318c1e95e2f5926fba326f68177dee364aa791d6df022ceb91b8221bd0a627"}, + {file = "matplotlib-3.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:091275d18d942cf1ee9609c830a1bc36610607d8223b1b981c37d5c9fc3e46a4"}, + {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b0f3b8ea0e99e233a4bcc44590f01604840d833c280ebb8fe5554fd3e6cfe8d"}, + {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7b1704a530395aaf73912be741c04d181f82ca78084fbd80bc737be04848331"}, + {file = "matplotlib-3.8.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:533b0e3b0c6768eef8cbe4b583731ce25a91ab54a22f830db2b031e83cca9213"}, + {file = "matplotlib-3.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:0f4fc5d72b75e2c18e55eb32292659cf731d9d5b312a6eb036506304f4675630"}, + {file = "matplotlib-3.8.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:deaed9ad4da0b1aea77fe0aa0cebb9ef611c70b3177be936a95e5d01fa05094f"}, + {file = "matplotlib-3.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:172f4d0fbac3383d39164c6caafd3255ce6fa58f08fc392513a0b1d3b89c4f89"}, + {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7d36c2209d9136cd8e02fab1c0ddc185ce79bc914c45054a9f514e44c787917"}, + {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5864bdd7da445e4e5e011b199bb67168cdad10b501750367c496420f2ad00843"}, + {file = "matplotlib-3.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ef8345b48e95cee45ff25192ed1f4857273117917a4dcd48e3905619bcd9c9b8"}, + {file = "matplotlib-3.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:7c48d9e221b637c017232e3760ed30b4e8d5dfd081daf327e829bf2a72c731b4"}, + {file = "matplotlib-3.8.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:aa11b3c6928a1e496c1a79917d51d4cd5d04f8a2e75f21df4949eeefdf697f4b"}, + {file = "matplotlib-3.8.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1095fecf99eeb7384dabad4bf44b965f929a5f6079654b681193edf7169ec20"}, + {file = "matplotlib-3.8.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:bddfb1db89bfaa855912261c805bd0e10218923cc262b9159a49c29a7a1c1afa"}, + {file = "matplotlib-3.8.2.tar.gz", hash = "sha256:01a978b871b881ee76017152f1f1a0cbf6bd5f7b8ff8c96df0df1bd57d8755a1"}, +] + +[package.dependencies] +contourpy = ">=1.0.1" +cycler = ">=0.10" +fonttools = ">=4.22.0" +importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} +kiwisolver = ">=1.3.1" +numpy = ">=1.21,<2" +packaging = ">=20.0" +pillow = ">=8" +pyparsing = ">=2.3.1" +python-dateutil = ">=2.7" + +[[package]] +name = "mergedeep" +version = "1.3.4" +description = "A deep merge function for 🐍." +optional = false +python-versions = ">=3.6" +files = [ + {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, + {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, +] + +[[package]] +name = "mkdocs" +version = "1.5.3" +description = "Project documentation with Markdown." +optional = false +python-versions = ">=3.7" +files = [ + {file = "mkdocs-1.5.3-py3-none-any.whl", hash = "sha256:3b3a78e736b31158d64dbb2f8ba29bd46a379d0c6e324c2246c3bc3d2189cfc1"}, + {file = "mkdocs-1.5.3.tar.gz", hash = "sha256:eb7c99214dcb945313ba30426c2451b735992c73c2e10838f76d09e39ff4d0e2"}, +] + +[package.dependencies] +click = ">=7.0" +colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} +ghp-import = ">=1.0" +importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} +jinja2 = ">=2.11.1" +markdown = ">=3.2.1" +markupsafe = ">=2.0.1" +mergedeep = ">=1.3.4" +packaging = ">=20.5" +pathspec = ">=0.11.1" +platformdirs = ">=2.2.0" +pyyaml = ">=5.1" +pyyaml-env-tag = ">=0.1" +watchdog = ">=2.0" + +[package.extras] +i18n = ["babel (>=2.9.0)"] +min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pathspec (==0.11.1)", "platformdirs (==2.2.0)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"] + +[[package]] +name = "mkdocs-autorefs" +version = "0.5.0" +description = "Automatically link across pages in MkDocs." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_autorefs-0.5.0-py3-none-any.whl", hash = "sha256:7930fcb8ac1249f10e683967aeaddc0af49d90702af111a5e390e8b20b3d97ff"}, + {file = "mkdocs_autorefs-0.5.0.tar.gz", hash = "sha256:9a5054a94c08d28855cfab967ada10ed5be76e2bfad642302a610b252c3274c0"}, +] + +[package.dependencies] +Markdown = ">=3.3" +mkdocs = ">=1.1" + +[[package]] +name = "mkdocs-material" +version = "9.5.7" +description = "Documentation that simply works" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_material-9.5.7-py3-none-any.whl", hash = "sha256:0be8ce8bcfebb52bae9b00cf9b851df45b8a92d629afcfd7f2c09b2dfa155ea3"}, + {file = "mkdocs_material-9.5.7.tar.gz", hash = "sha256:16110292575d88a338d2961f3cb665cf12943ff8829e551a9b364f24019e46af"}, +] + +[package.dependencies] +babel = ">=2.10,<3.0" +colorama = ">=0.4,<1.0" +jinja2 = ">=3.0,<4.0" +markdown = ">=3.2,<4.0" +mkdocs = ">=1.5.3,<1.6.0" +mkdocs-material-extensions = ">=1.3,<2.0" +paginate = ">=0.5,<1.0" +pygments = ">=2.16,<3.0" +pymdown-extensions = ">=10.2,<11.0" +regex = ">=2022.4" +requests = ">=2.26,<3.0" + +[package.extras] +git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2,<2.0)"] +imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<11.0)"] +recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"] + +[[package]] +name = "mkdocs-material-extensions" +version = "1.3.1" +description = "Extension pack for Python Markdown and MkDocs Material." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"}, + {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"}, +] + +[[package]] +name = "mkdocstrings" +version = "0.23.0" +description = "Automatic documentation from sources, for MkDocs." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocstrings-0.23.0-py3-none-any.whl", hash = "sha256:051fa4014dfcd9ed90254ae91de2dbb4f24e166347dae7be9a997fe16316c65e"}, + {file = "mkdocstrings-0.23.0.tar.gz", hash = "sha256:d9c6a37ffbe7c14a7a54ef1258c70b8d394e6a33a1c80832bce40b9567138d1c"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} +Jinja2 = ">=2.11.1" +Markdown = ">=3.3" +MarkupSafe = ">=1.1" +mkdocs = ">=1.2" +mkdocs-autorefs = ">=0.3.1" +pymdown-extensions = ">=6.3" +typing-extensions = {version = ">=4.1", markers = "python_version < \"3.10\""} + +[package.extras] +crystal = ["mkdocstrings-crystal (>=0.3.4)"] +python = ["mkdocstrings-python (>=0.5.2)"] +python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"] + +[[package]] +name = "mypy" +version = "1.8.0" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3"}, + {file = "mypy-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4"}, + {file = "mypy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d"}, + {file = "mypy-1.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9"}, + {file = "mypy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410"}, + {file = "mypy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae"}, + {file = "mypy-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3"}, + {file = "mypy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817"}, + {file = "mypy-1.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d"}, + {file = "mypy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835"}, + {file = "mypy-1.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd"}, + {file = "mypy-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55"}, + {file = "mypy-1.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218"}, + {file = "mypy-1.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3"}, + {file = "mypy-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e"}, + {file = "mypy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6"}, + {file = "mypy-1.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66"}, + {file = "mypy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6"}, + {file = "mypy-1.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d"}, + {file = "mypy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02"}, + {file = "mypy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8"}, + {file = "mypy-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259"}, + {file = "mypy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b"}, + {file = "mypy-1.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592"}, + {file = "mypy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a"}, + {file = "mypy-1.8.0-py3-none-any.whl", hash = "sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d"}, + {file = "mypy-1.8.0.tar.gz", hash = "sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +mypyc = ["setuptools (>=50)"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "nodeenv" +version = "1.8.0" +description = "Node.js virtual environment builder" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +files = [ + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, +] + +[package.dependencies] +setuptools = "*" + +[[package]] +name = "numpy" +version = "1.24.4" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"}, + {file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"}, + {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"}, + {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"}, + {file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"}, + {file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"}, + {file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"}, + {file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"}, + {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"}, + {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"}, + {file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"}, + {file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"}, + {file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"}, + {file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"}, + {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"}, + {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"}, + {file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"}, + {file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"}, + {file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"}, + {file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"}, + {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"}, + {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"}, + {file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"}, + {file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"}, + {file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"}, +] + +[[package]] +name = "numpy" +version = "1.26.3" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-1.26.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:806dd64230dbbfaca8a27faa64e2f414bf1c6622ab78cc4264f7f5f028fee3bf"}, + {file = "numpy-1.26.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02f98011ba4ab17f46f80f7f8f1c291ee7d855fcef0a5a98db80767a468c85cd"}, + {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d45b3ec2faed4baca41c76617fcdcfa4f684ff7a151ce6fc78ad3b6e85af0a6"}, + {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdd2b45bf079d9ad90377048e2747a0c82351989a2165821f0c96831b4a2a54b"}, + {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:211ddd1e94817ed2d175b60b6374120244a4dd2287f4ece45d49228b4d529178"}, + {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b1240f767f69d7c4c8a29adde2310b871153df9b26b5cb2b54a561ac85146485"}, + {file = "numpy-1.26.3-cp310-cp310-win32.whl", hash = "sha256:21a9484e75ad018974a2fdaa216524d64ed4212e418e0a551a2d83403b0531d3"}, + {file = "numpy-1.26.3-cp310-cp310-win_amd64.whl", hash = "sha256:9e1591f6ae98bcfac2a4bbf9221c0b92ab49762228f38287f6eeb5f3f55905ce"}, + {file = "numpy-1.26.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b831295e5472954104ecb46cd98c08b98b49c69fdb7040483aff799a755a7374"}, + {file = "numpy-1.26.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9e87562b91f68dd8b1c39149d0323b42e0082db7ddb8e934ab4c292094d575d6"}, + {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c66d6fec467e8c0f975818c1796d25c53521124b7cfb760114be0abad53a0a2"}, + {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f25e2811a9c932e43943a2615e65fc487a0b6b49218899e62e426e7f0a57eeda"}, + {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:af36e0aa45e25c9f57bf684b1175e59ea05d9a7d3e8e87b7ae1a1da246f2767e"}, + {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:51c7f1b344f302067b02e0f5b5d2daa9ed4a721cf49f070280ac202738ea7f00"}, + {file = "numpy-1.26.3-cp311-cp311-win32.whl", hash = "sha256:7ca4f24341df071877849eb2034948459ce3a07915c2734f1abb4018d9c49d7b"}, + {file = "numpy-1.26.3-cp311-cp311-win_amd64.whl", hash = "sha256:39763aee6dfdd4878032361b30b2b12593fb445ddb66bbac802e2113eb8a6ac4"}, + {file = "numpy-1.26.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a7081fd19a6d573e1a05e600c82a1c421011db7935ed0d5c483e9dd96b99cf13"}, + {file = "numpy-1.26.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12c70ac274b32bc00c7f61b515126c9205323703abb99cd41836e8125ea0043e"}, + {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f784e13e598e9594750b2ef6729bcd5a47f6cfe4a12cca13def35e06d8163e3"}, + {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f24750ef94d56ce6e33e4019a8a4d68cfdb1ef661a52cdaee628a56d2437419"}, + {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:77810ef29e0fb1d289d225cabb9ee6cf4d11978a00bb99f7f8ec2132a84e0166"}, + {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8ed07a90f5450d99dad60d3799f9c03c6566709bd53b497eb9ccad9a55867f36"}, + {file = "numpy-1.26.3-cp312-cp312-win32.whl", hash = "sha256:f73497e8c38295aaa4741bdfa4fda1a5aedda5473074369eca10626835445511"}, + {file = "numpy-1.26.3-cp312-cp312-win_amd64.whl", hash = "sha256:da4b0c6c699a0ad73c810736303f7fbae483bcb012e38d7eb06a5e3b432c981b"}, + {file = "numpy-1.26.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1666f634cb3c80ccbd77ec97bc17337718f56d6658acf5d3b906ca03e90ce87f"}, + {file = "numpy-1.26.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18c3319a7d39b2c6a9e3bb75aab2304ab79a811ac0168a671a62e6346c29b03f"}, + {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b7e807d6888da0db6e7e75838444d62495e2b588b99e90dd80c3459594e857b"}, + {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4d362e17bcb0011738c2d83e0a65ea8ce627057b2fdda37678f4374a382a137"}, + {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b8c275f0ae90069496068c714387b4a0eba5d531aace269559ff2b43655edd58"}, + {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cc0743f0302b94f397a4a65a660d4cd24267439eb16493fb3caad2e4389bccbb"}, + {file = "numpy-1.26.3-cp39-cp39-win32.whl", hash = "sha256:9bc6d1a7f8cedd519c4b7b1156d98e051b726bf160715b769106661d567b3f03"}, + {file = "numpy-1.26.3-cp39-cp39-win_amd64.whl", hash = "sha256:867e3644e208c8922a3be26fc6bbf112a035f50f0a86497f98f228c50c607bb2"}, + {file = "numpy-1.26.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3c67423b3703f8fbd90f5adaa37f85b5794d3366948efe9a5190a5f3a83fc34e"}, + {file = "numpy-1.26.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46f47ee566d98849323f01b349d58f2557f02167ee301e5e28809a8c0e27a2d0"}, + {file = "numpy-1.26.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a8474703bffc65ca15853d5fd4d06b18138ae90c17c8d12169968e998e448bb5"}, + {file = "numpy-1.26.3.tar.gz", hash = "sha256:697df43e2b6310ecc9d95f05d5ef20eacc09c7c4ecc9da3f235d39e71b7da1e4"}, +] + +[[package]] +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "paginate" +version = "0.5.6" +description = "Divides large result sets into pages for easier browsing" +optional = false +python-versions = "*" +files = [ + {file = "paginate-0.5.6.tar.gz", hash = "sha256:5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d"}, +] + +[[package]] +name = "pandas" +version = "1.5.3" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pandas-1.5.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3749077d86e3a2f0ed51367f30bf5b82e131cc0f14260c4d3e499186fccc4406"}, + {file = "pandas-1.5.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:972d8a45395f2a2d26733eb8d0f629b2f90bebe8e8eddbb8829b180c09639572"}, + {file = "pandas-1.5.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:50869a35cbb0f2e0cd5ec04b191e7b12ed688874bd05dd777c19b28cbea90996"}, + {file = "pandas-1.5.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3ac844a0fe00bfaeb2c9b51ab1424e5c8744f89860b138434a363b1f620f354"}, + {file = "pandas-1.5.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a0a56cef15fd1586726dace5616db75ebcfec9179a3a55e78f72c5639fa2a23"}, + {file = "pandas-1.5.3-cp310-cp310-win_amd64.whl", hash = "sha256:478ff646ca42b20376e4ed3fa2e8d7341e8a63105586efe54fa2508ee087f328"}, + {file = "pandas-1.5.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6973549c01ca91ec96199e940495219c887ea815b2083722821f1d7abfa2b4dc"}, + {file = "pandas-1.5.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c39a8da13cede5adcd3be1182883aea1c925476f4e84b2807a46e2775306305d"}, + {file = "pandas-1.5.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f76d097d12c82a535fda9dfe5e8dd4127952b45fea9b0276cb30cca5ea313fbc"}, + {file = "pandas-1.5.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e474390e60ed609cec869b0da796ad94f420bb057d86784191eefc62b65819ae"}, + {file = "pandas-1.5.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f2b952406a1588ad4cad5b3f55f520e82e902388a6d5a4a91baa8d38d23c7f6"}, + {file = "pandas-1.5.3-cp311-cp311-win_amd64.whl", hash = "sha256:bc4c368f42b551bf72fac35c5128963a171b40dce866fb066540eeaf46faa003"}, + {file = "pandas-1.5.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14e45300521902689a81f3f41386dc86f19b8ba8dd5ac5a3c7010ef8d2932813"}, + {file = "pandas-1.5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9842b6f4b8479e41968eced654487258ed81df7d1c9b7b870ceea24ed9459b31"}, + {file = "pandas-1.5.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:26d9c71772c7afb9d5046e6e9cf42d83dd147b5cf5bcb9d97252077118543792"}, + {file = "pandas-1.5.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fbcb19d6fceb9e946b3e23258757c7b225ba450990d9ed63ccceeb8cae609f7"}, + {file = "pandas-1.5.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:565fa34a5434d38e9d250af3c12ff931abaf88050551d9fbcdfafca50d62babf"}, + {file = "pandas-1.5.3-cp38-cp38-win32.whl", hash = "sha256:87bd9c03da1ac870a6d2c8902a0e1fd4267ca00f13bc494c9e5a9020920e1d51"}, + {file = "pandas-1.5.3-cp38-cp38-win_amd64.whl", hash = "sha256:41179ce559943d83a9b4bbacb736b04c928b095b5f25dd2b7389eda08f46f373"}, + {file = "pandas-1.5.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c74a62747864ed568f5a82a49a23a8d7fe171d0c69038b38cedf0976831296fa"}, + {file = "pandas-1.5.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c4c00e0b0597c8e4f59e8d461f797e5d70b4d025880516a8261b2817c47759ee"}, + {file = "pandas-1.5.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a50d9a4336a9621cab7b8eb3fb11adb82de58f9b91d84c2cd526576b881a0c5a"}, + {file = "pandas-1.5.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd05f7783b3274aa206a1af06f0ceed3f9b412cf665b7247eacd83be41cf7bf0"}, + {file = "pandas-1.5.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f69c4029613de47816b1bb30ff5ac778686688751a5e9c99ad8c7031f6508e5"}, + {file = "pandas-1.5.3-cp39-cp39-win32.whl", hash = "sha256:7cec0bee9f294e5de5bbfc14d0573f65526071029d036b753ee6507d2a21480a"}, + {file = "pandas-1.5.3-cp39-cp39-win_amd64.whl", hash = "sha256:dfd681c5dc216037e0b0a2c821f5ed99ba9f03ebcf119c7dac0e9a7b960b9ec9"}, + {file = "pandas-1.5.3.tar.gz", hash = "sha256:74a3fd7e5a7ec052f183273dc7b0acd3a863edf7520f5d3a1765c04ffdb3b0b1"}, +] + +[package.dependencies] +numpy = {version = ">=1.20.3", markers = "python_version < \"3.10\""} +python-dateutil = ">=2.8.1" +pytz = ">=2020.1" + +[package.extras] +test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"] + +[[package]] +name = "pandas" +version = "2.2.0" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pandas-2.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8108ee1712bb4fa2c16981fba7e68b3f6ea330277f5ca34fa8d557e986a11670"}, + {file = "pandas-2.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:736da9ad4033aeab51d067fc3bd69a0ba36f5a60f66a527b3d72e2030e63280a"}, + {file = "pandas-2.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38e0b4fc3ddceb56ec8a287313bc22abe17ab0eb184069f08fc6a9352a769b18"}, + {file = "pandas-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20404d2adefe92aed3b38da41d0847a143a09be982a31b85bc7dd565bdba0f4e"}, + {file = "pandas-2.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ea3ee3f125032bfcade3a4cf85131ed064b4f8dd23e5ce6fa16473e48ebcaf5"}, + {file = "pandas-2.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f9670b3ac00a387620489dfc1bca66db47a787f4e55911f1293063a78b108df1"}, + {file = "pandas-2.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a946f210383c7e6d16312d30b238fd508d80d927014f3b33fb5b15c2f895430"}, + {file = "pandas-2.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a1b438fa26b208005c997e78672f1aa8138f67002e833312e6230f3e57fa87d5"}, + {file = "pandas-2.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8ce2fbc8d9bf303ce54a476116165220a1fedf15985b09656b4b4275300e920b"}, + {file = "pandas-2.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2707514a7bec41a4ab81f2ccce8b382961a29fbe9492eab1305bb075b2b1ff4f"}, + {file = "pandas-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85793cbdc2d5bc32620dc8ffa715423f0c680dacacf55056ba13454a5be5de88"}, + {file = "pandas-2.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cfd6c2491dc821b10c716ad6776e7ab311f7df5d16038d0b7458bc0b67dc10f3"}, + {file = "pandas-2.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a146b9dcacc3123aa2b399df1a284de5f46287a4ab4fbfc237eac98a92ebcb71"}, + {file = "pandas-2.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbc1b53c0e1fdf16388c33c3cca160f798d38aea2978004dd3f4d3dec56454c9"}, + {file = "pandas-2.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a41d06f308a024981dcaa6c41f2f2be46a6b186b902c94c2674e8cb5c42985bc"}, + {file = "pandas-2.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:159205c99d7a5ce89ecfc37cb08ed179de7783737cea403b295b5eda8e9c56d1"}, + {file = "pandas-2.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1e1f3861ea9132b32f2133788f3b14911b68102d562715d71bd0013bc45440"}, + {file = "pandas-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:761cb99b42a69005dec2b08854fb1d4888fdf7b05db23a8c5a099e4b886a2106"}, + {file = "pandas-2.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a20628faaf444da122b2a64b1e5360cde100ee6283ae8effa0d8745153809a2e"}, + {file = "pandas-2.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f5be5d03ea2073627e7111f61b9f1f0d9625dc3c4d8dda72cc827b0c58a1d042"}, + {file = "pandas-2.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:a626795722d893ed6aacb64d2401d017ddc8a2341b49e0384ab9bf7112bdec30"}, + {file = "pandas-2.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9f66419d4a41132eb7e9a73dcec9486cf5019f52d90dd35547af11bc58f8637d"}, + {file = "pandas-2.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:57abcaeda83fb80d447f28ab0cc7b32b13978f6f733875ebd1ed14f8fbc0f4ab"}, + {file = "pandas-2.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e60f1f7dba3c2d5ca159e18c46a34e7ca7247a73b5dd1a22b6d59707ed6b899a"}, + {file = "pandas-2.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb61dc8567b798b969bcc1fc964788f5a68214d333cade8319c7ab33e2b5d88a"}, + {file = "pandas-2.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:52826b5f4ed658fa2b729264d63f6732b8b29949c7fd234510d57c61dbeadfcd"}, + {file = "pandas-2.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bde2bc699dbd80d7bc7f9cab1e23a95c4375de615860ca089f34e7c64f4a8de7"}, + {file = "pandas-2.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:3de918a754bbf2da2381e8a3dcc45eede8cd7775b047b923f9006d5f876802ae"}, + {file = "pandas-2.2.0.tar.gz", hash = "sha256:30b83f7c3eb217fb4d1b494a57a2fda5444f17834f5df2de6b2ffff68dc3c8e2"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.22.4,<2", markers = "python_version < \"3.11\""}, + {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0,<2", markers = "python_version >= \"3.12\""}, +] +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.7" + +[package.extras] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] +aws = ["s3fs (>=2022.11.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] +compression = ["zstandard (>=0.19.0)"] +computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] +feather = ["pyarrow (>=10.0.1)"] +fss = ["fsspec (>=2022.11.0)"] +gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] +hdf5 = ["tables (>=3.8.0)"] +html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] +mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=10.0.1)"] +performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] +plot = ["matplotlib (>=3.6.3)"] +postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +spss = ["pyreadstat (>=1.2.0)"] +sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.9.2)"] + +[[package]] +name = "pathspec" +version = "0.12.1" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, +] + +[[package]] +name = "pillow" +version = "10.2.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pillow-10.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:7823bdd049099efa16e4246bdf15e5a13dbb18a51b68fa06d6c1d4d8b99a796e"}, + {file = "pillow-10.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:83b2021f2ade7d1ed556bc50a399127d7fb245e725aa0113ebd05cfe88aaf588"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fad5ff2f13d69b7e74ce5b4ecd12cc0ec530fcee76356cac6742785ff71c452"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da2b52b37dad6d9ec64e653637a096905b258d2fc2b984c41ae7d08b938a67e4"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:47c0995fc4e7f79b5cfcab1fc437ff2890b770440f7696a3ba065ee0fd496563"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:322bdf3c9b556e9ffb18f93462e5f749d3444ce081290352c6070d014c93feb2"}, + {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:51f1a1bffc50e2e9492e87d8e09a17c5eea8409cda8d3f277eb6edc82813c17c"}, + {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69ffdd6120a4737710a9eee73e1d2e37db89b620f702754b8f6e62594471dee0"}, + {file = "pillow-10.2.0-cp310-cp310-win32.whl", hash = "sha256:c6dafac9e0f2b3c78df97e79af707cdc5ef8e88208d686a4847bab8266870023"}, + {file = "pillow-10.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:aebb6044806f2e16ecc07b2a2637ee1ef67a11840a66752751714a0d924adf72"}, + {file = "pillow-10.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:7049e301399273a0136ff39b84c3678e314f2158f50f517bc50285fb5ec847ad"}, + {file = "pillow-10.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35bb52c37f256f662abdfa49d2dfa6ce5d93281d323a9af377a120e89a9eafb5"}, + {file = "pillow-10.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c23f307202661071d94b5e384e1e1dc7dfb972a28a2310e4ee16103e66ddb67"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773efe0603db30c281521a7c0214cad7836c03b8ccff897beae9b47c0b657d61"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11fa2e5984b949b0dd6d7a94d967743d87c577ff0b83392f17cb3990d0d2fd6e"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:716d30ed977be8b37d3ef185fecb9e5a1d62d110dfbdcd1e2a122ab46fddb03f"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a086c2af425c5f62a65e12fbf385f7c9fcb8f107d0849dba5839461a129cf311"}, + {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c8de2789052ed501dd829e9cae8d3dcce7acb4777ea4a479c14521c942d395b1"}, + {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:609448742444d9290fd687940ac0b57fb35e6fd92bdb65386e08e99af60bf757"}, + {file = "pillow-10.2.0-cp311-cp311-win32.whl", hash = "sha256:823ef7a27cf86df6597fa0671066c1b596f69eba53efa3d1e1cb8b30f3533068"}, + {file = "pillow-10.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:1da3b2703afd040cf65ec97efea81cfba59cdbed9c11d8efc5ab09df9509fc56"}, + {file = "pillow-10.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:edca80cbfb2b68d7b56930b84a0e45ae1694aeba0541f798e908a49d66b837f1"}, + {file = "pillow-10.2.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:1b5e1b74d1bd1b78bc3477528919414874748dd363e6272efd5abf7654e68bef"}, + {file = "pillow-10.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0eae2073305f451d8ecacb5474997c08569fb4eb4ac231ffa4ad7d342fdc25ac"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7c2286c23cd350b80d2fc9d424fc797575fb16f854b831d16fd47ceec078f2c"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e23412b5c41e58cec602f1135c57dfcf15482013ce6e5f093a86db69646a5aa"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:52a50aa3fb3acb9cf7213573ef55d31d6eca37f5709c69e6858fe3bc04a5c2a2"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:127cee571038f252a552760076407f9cff79761c3d436a12af6000cd182a9d04"}, + {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8d12251f02d69d8310b046e82572ed486685c38f02176bd08baf216746eb947f"}, + {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54f1852cd531aa981bc0965b7d609f5f6cc8ce8c41b1139f6ed6b3c54ab82bfb"}, + {file = "pillow-10.2.0-cp312-cp312-win32.whl", hash = "sha256:257d8788df5ca62c980314053197f4d46eefedf4e6175bc9412f14412ec4ea2f"}, + {file = "pillow-10.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:154e939c5f0053a383de4fd3d3da48d9427a7e985f58af8e94d0b3c9fcfcf4f9"}, + {file = "pillow-10.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:f379abd2f1e3dddb2b61bc67977a6b5a0a3f7485538bcc6f39ec76163891ee48"}, + {file = "pillow-10.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8373c6c251f7ef8bda6675dd6d2b3a0fcc31edf1201266b5cf608b62a37407f9"}, + {file = "pillow-10.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:870ea1ada0899fd0b79643990809323b389d4d1d46c192f97342eeb6ee0b8483"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4b6b1e20608493548b1f32bce8cca185bf0480983890403d3b8753e44077129"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3031709084b6e7852d00479fd1d310b07d0ba82765f973b543c8af5061cf990e"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:3ff074fc97dd4e80543a3e91f69d58889baf2002b6be64347ea8cf5533188213"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:cb4c38abeef13c61d6916f264d4845fab99d7b711be96c326b84df9e3e0ff62d"}, + {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b1b3020d90c2d8e1dae29cf3ce54f8094f7938460fb5ce8bc5c01450b01fbaf6"}, + {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:170aeb00224ab3dc54230c797f8404507240dd868cf52066f66a41b33169bdbe"}, + {file = "pillow-10.2.0-cp38-cp38-win32.whl", hash = "sha256:c4225f5220f46b2fde568c74fca27ae9771536c2e29d7c04f4fb62c83275ac4e"}, + {file = "pillow-10.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:0689b5a8c5288bc0504d9fcee48f61a6a586b9b98514d7d29b840143d6734f39"}, + {file = "pillow-10.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:b792a349405fbc0163190fde0dc7b3fef3c9268292586cf5645598b48e63dc67"}, + {file = "pillow-10.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c570f24be1e468e3f0ce7ef56a89a60f0e05b30a3669a459e419c6eac2c35364"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8ecd059fdaf60c1963c58ceb8997b32e9dc1b911f5da5307aab614f1ce5c2fb"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c365fd1703040de1ec284b176d6af5abe21b427cb3a5ff68e0759e1e313a5e7e"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:70c61d4c475835a19b3a5aa42492409878bbca7438554a1f89d20d58a7c75c01"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b6f491cdf80ae540738859d9766783e3b3c8e5bd37f5dfa0b76abdecc5081f13"}, + {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d189550615b4948f45252d7f005e53c2040cea1af5b60d6f79491a6e147eef7"}, + {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:49d9ba1ed0ef3e061088cd1e7538a0759aab559e2e0a80a36f9fd9d8c0c21591"}, + {file = "pillow-10.2.0-cp39-cp39-win32.whl", hash = "sha256:babf5acfede515f176833ed6028754cbcd0d206f7f614ea3447d67c33be12516"}, + {file = "pillow-10.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:0304004f8067386b477d20a518b50f3fa658a28d44e4116970abfcd94fac34a8"}, + {file = "pillow-10.2.0-cp39-cp39-win_arm64.whl", hash = "sha256:0fb3e7fc88a14eacd303e90481ad983fd5b69c761e9e6ef94c983f91025da869"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:322209c642aabdd6207517e9739c704dc9f9db943015535783239022002f054a"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eedd52442c0a5ff4f887fab0c1c0bb164d8635b32c894bc1faf4c618dd89df2"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb28c753fd5eb3dd859b4ee95de66cc62af91bcff5db5f2571d32a520baf1f04"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:33870dc4653c5017bf4c8873e5488d8f8d5f8935e2f1fb9a2208c47cdd66efd2"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3c31822339516fb3c82d03f30e22b1d038da87ef27b6a78c9549888f8ceda39a"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a2b56ba36e05f973d450582fb015594aaa78834fefe8dfb8fcd79b93e64ba4c6"}, + {file = "pillow-10.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d8e6aeb9201e655354b3ad049cb77d19813ad4ece0df1249d3c793de3774f8c7"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:2247178effb34a77c11c0e8ac355c7a741ceca0a732b27bf11e747bbc950722f"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15587643b9e5eb26c48e49a7b33659790d28f190fc514a322d55da2fb5c2950e"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753cd8f2086b2b80180d9b3010dd4ed147efc167c90d3bf593fe2af21265e5a5"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7c8f97e8e7a9009bcacbe3766a36175056c12f9a44e6e6f2d5caad06dcfbf03b"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d1b35bcd6c5543b9cb547dee3150c93008f8dd0f1fef78fc0cd2b141c5baf58a"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe4c15f6c9285dc54ce6553a3ce908ed37c8f3825b5a51a15c91442bb955b868"}, + {file = "pillow-10.2.0.tar.gz", hash = "sha256:e87f0b2c78157e12d7686b27d63c070fd65d994e8ddae6f328e0dcf4a0cd007e"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +typing = ["typing-extensions"] +xmp = ["defusedxml"] + +[[package]] +name = "platformdirs" +version = "4.2.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, + {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] + +[[package]] +name = "pluggy" +version = "1.4.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pre-commit" +version = "2.21.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pre_commit-2.21.0-py2.py3-none-any.whl", hash = "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad"}, + {file = "pre_commit-2.21.0.tar.gz", hash = "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + +[[package]] +name = "pre-commit" +version = "3.6.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.9" +files = [ + {file = "pre_commit-3.6.0-py2.py3-none-any.whl", hash = "sha256:c255039ef399049a5544b6ce13d135caba8f2c28c3b4033277a788f434308376"}, + {file = "pre_commit-3.6.0.tar.gz", hash = "sha256:d30bad9abf165f7785c15a21a1f46da7d0677cb00ee7ff4c579fd38922efe15d"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + +[[package]] +name = "pyarrow" +version = "15.0.0" +description = "Python library for Apache Arrow" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyarrow-15.0.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:0a524532fd6dd482edaa563b686d754c70417c2f72742a8c990b322d4c03a15d"}, + {file = "pyarrow-15.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:60a6bdb314affa9c2e0d5dddf3d9cbb9ef4a8dddaa68669975287d47ece67642"}, + {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66958fd1771a4d4b754cd385835e66a3ef6b12611e001d4e5edfcef5f30391e2"}, + {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f500956a49aadd907eaa21d4fff75f73954605eaa41f61cb94fb008cf2e00c6"}, + {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6f87d9c4f09e049c2cade559643424da84c43a35068f2a1c4653dc5b1408a929"}, + {file = "pyarrow-15.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:85239b9f93278e130d86c0e6bb455dcb66fc3fd891398b9d45ace8799a871a1e"}, + {file = "pyarrow-15.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:5b8d43e31ca16aa6e12402fcb1e14352d0d809de70edd185c7650fe80e0769e3"}, + {file = "pyarrow-15.0.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:fa7cd198280dbd0c988df525e50e35b5d16873e2cdae2aaaa6363cdb64e3eec5"}, + {file = "pyarrow-15.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8780b1a29d3c8b21ba6b191305a2a607de2e30dab399776ff0aa09131e266340"}, + {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe0ec198ccc680f6c92723fadcb97b74f07c45ff3fdec9dd765deb04955ccf19"}, + {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:036a7209c235588c2f07477fe75c07e6caced9b7b61bb897c8d4e52c4b5f9555"}, + {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:2bd8a0e5296797faf9a3294e9fa2dc67aa7f10ae2207920dbebb785c77e9dbe5"}, + {file = "pyarrow-15.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:e8ebed6053dbe76883a822d4e8da36860f479d55a762bd9e70d8494aed87113e"}, + {file = "pyarrow-15.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:17d53a9d1b2b5bd7d5e4cd84d018e2a45bc9baaa68f7e6e3ebed45649900ba99"}, + {file = "pyarrow-15.0.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:9950a9c9df24090d3d558b43b97753b8f5867fb8e521f29876aa021c52fda351"}, + {file = "pyarrow-15.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:003d680b5e422d0204e7287bb3fa775b332b3fce2996aa69e9adea23f5c8f970"}, + {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f75fce89dad10c95f4bf590b765e3ae98bcc5ba9f6ce75adb828a334e26a3d40"}, + {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca9cb0039923bec49b4fe23803807e4ef39576a2bec59c32b11296464623dc2"}, + {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:9ed5a78ed29d171d0acc26a305a4b7f83c122d54ff5270810ac23c75813585e4"}, + {file = "pyarrow-15.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:6eda9e117f0402dfcd3cd6ec9bfee89ac5071c48fc83a84f3075b60efa96747f"}, + {file = "pyarrow-15.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:9a3a6180c0e8f2727e6f1b1c87c72d3254cac909e609f35f22532e4115461177"}, + {file = "pyarrow-15.0.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:19a8918045993349b207de72d4576af0191beef03ea655d8bdb13762f0cd6eac"}, + {file = "pyarrow-15.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d0ec076b32bacb6666e8813a22e6e5a7ef1314c8069d4ff345efa6246bc38593"}, + {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5db1769e5d0a77eb92344c7382d6543bea1164cca3704f84aa44e26c67e320fb"}, + {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2617e3bf9df2a00020dd1c1c6dce5cc343d979efe10bc401c0632b0eef6ef5b"}, + {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:d31c1d45060180131caf10f0f698e3a782db333a422038bf7fe01dace18b3a31"}, + {file = "pyarrow-15.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:c8c287d1d479de8269398b34282e206844abb3208224dbdd7166d580804674b7"}, + {file = "pyarrow-15.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:07eb7f07dc9ecbb8dace0f58f009d3a29ee58682fcdc91337dfeb51ea618a75b"}, + {file = "pyarrow-15.0.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:47af7036f64fce990bb8a5948c04722e4e3ea3e13b1007ef52dfe0aa8f23cf7f"}, + {file = "pyarrow-15.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93768ccfff85cf044c418bfeeafce9a8bb0cee091bd8fd19011aff91e58de540"}, + {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6ee87fd6892700960d90abb7b17a72a5abb3b64ee0fe8db6c782bcc2d0dc0b4"}, + {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:001fca027738c5f6be0b7a3159cc7ba16a5c52486db18160909a0831b063c4e4"}, + {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:d1c48648f64aec09accf44140dccb92f4f94394b8d79976c426a5b79b11d4fa7"}, + {file = "pyarrow-15.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:972a0141be402bb18e3201448c8ae62958c9c7923dfaa3b3d4530c835ac81aed"}, + {file = "pyarrow-15.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:f01fc5cf49081426429127aa2d427d9d98e1cb94a32cb961d583a70b7c4504e6"}, + {file = "pyarrow-15.0.0.tar.gz", hash = "sha256:876858f549d540898f927eba4ef77cd549ad8d24baa3207cf1b72e5788b50e83"}, +] + +[package.dependencies] +numpy = ">=1.16.6,<2" + +[[package]] +name = "pygments" +version = "2.17.2" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, + {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, +] + +[package.extras] +plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pymdown-extensions" +version = "10.7" +description = "Extension pack for Python Markdown." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pymdown_extensions-10.7-py3-none-any.whl", hash = "sha256:6ca215bc57bc12bf32b414887a68b810637d039124ed9b2e5bd3325cbb2c050c"}, + {file = "pymdown_extensions-10.7.tar.gz", hash = "sha256:c0d64d5cf62566f59e6b2b690a4095c931107c250a8c8e1351c1de5f6b036deb"}, +] + +[package.dependencies] +markdown = ">=3.5" +pyyaml = "*" + +[package.extras] +extra = ["pygments (>=2.12)"] + +[[package]] +name = "pyparsing" +version = "3.1.1" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb"}, + {file = "pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[package]] +name = "pyproject-api" +version = "1.6.1" +description = "API to interact with the python pyproject.toml based projects" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyproject_api-1.6.1-py3-none-any.whl", hash = "sha256:4c0116d60476b0786c88692cf4e325a9814965e2469c5998b830bba16b183675"}, + {file = "pyproject_api-1.6.1.tar.gz", hash = "sha256:1817dc018adc0d1ff9ca1ed8c60e1623d5aaca40814b953af14a9cf9a5cae538"}, +] + +[package.dependencies] +packaging = ">=23.1" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +docs = ["furo (>=2023.8.19)", "sphinx (<7.2)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "setuptools (>=68.1.2)", "wheel (>=0.41.2)"] + +[[package]] +name = "pytest" +version = "7.4.4" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "4.1.0" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, + {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, +] + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] + +[[package]] +name = "pytest-mpl" +version = "0.16.1" +description = "pytest plugin to help with testing figures output from Matplotlib" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pytest-mpl-0.16.1.tar.gz", hash = "sha256:2d571681124e8ff5f4e2b9c0d047d37d0499d6b6d8f2f49a1b50cdd993104469"}, + {file = "pytest_mpl-0.16.1-py3-none-any.whl", hash = "sha256:a830e6bcd218b7cdf968034095855527d8191da00c37770138eb72b9534aa228"}, +] + +[package.dependencies] +Jinja2 = "*" +matplotlib = "*" +packaging = "*" +Pillow = "*" +pytest = "*" + +[package.extras] +test = ["pytest-cov"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytz" +version = "2024.1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "pyyaml-env-tag" +version = "0.1" +description = "A custom YAML tag for referencing environment variables in YAML files. " +optional = false +python-versions = ">=3.6" +files = [ + {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"}, + {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"}, +] + +[package.dependencies] +pyyaml = "*" + +[[package]] +name = "recommonmark" +version = "0.7.1" +description = "A docutils-compatibility bridge to CommonMark, enabling you to write CommonMark inside of Docutils & Sphinx projects." +optional = false +python-versions = "*" +files = [ + {file = "recommonmark-0.7.1-py2.py3-none-any.whl", hash = "sha256:1b1db69af0231efce3fa21b94ff627ea33dee7079a01dd0a7f8482c3da148b3f"}, + {file = "recommonmark-0.7.1.tar.gz", hash = "sha256:bdb4db649f2222dcd8d2d844f0006b958d627f732415d399791ee436a3686d67"}, +] + +[package.dependencies] +commonmark = ">=0.8.1" +docutils = ">=0.11" +sphinx = ">=1.3.1" + +[[package]] +name = "regex" +version = "2023.12.25" +description = "Alternative regular expression module, to replace re." +optional = false +python-versions = ">=3.7" +files = [ + {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"}, + {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"}, + {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"}, + {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"}, + {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"}, + {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"}, + {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"}, + {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"}, + {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"}, + {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"}, + {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"}, + {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"}, + {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"}, + {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"}, + {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"}, + {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"}, + {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"}, + {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"}, + {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"}, + {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"}, + {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"}, + {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"}, + {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"}, + {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"}, + {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"}, + {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"}, + {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"}, + {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"}, + {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"}, +] + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "scipy" +version = "1.10.1" +description = "Fundamental algorithms for scientific computing in Python" +optional = false +python-versions = "<3.12,>=3.8" +files = [ + {file = "scipy-1.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7354fd7527a4b0377ce55f286805b34e8c54b91be865bac273f527e1b839019"}, + {file = "scipy-1.10.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:4b3f429188c66603a1a5c549fb414e4d3bdc2a24792e061ffbd607d3d75fd84e"}, + {file = "scipy-1.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1553b5dcddd64ba9a0d95355e63fe6c3fc303a8fd77c7bc91e77d61363f7433f"}, + {file = "scipy-1.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c0ff64b06b10e35215abce517252b375e580a6125fd5fdf6421b98efbefb2d2"}, + {file = "scipy-1.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:fae8a7b898c42dffe3f7361c40d5952b6bf32d10c4569098d276b4c547905ee1"}, + {file = "scipy-1.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0f1564ea217e82c1bbe75ddf7285ba0709ecd503f048cb1236ae9995f64217bd"}, + {file = "scipy-1.10.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:d925fa1c81b772882aa55bcc10bf88324dadb66ff85d548c71515f6689c6dac5"}, + {file = "scipy-1.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaea0a6be54462ec027de54fca511540980d1e9eea68b2d5c1dbfe084797be35"}, + {file = "scipy-1.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15a35c4242ec5f292c3dd364a7c71a61be87a3d4ddcc693372813c0b73c9af1d"}, + {file = "scipy-1.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:43b8e0bcb877faf0abfb613d51026cd5cc78918e9530e375727bf0625c82788f"}, + {file = "scipy-1.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5678f88c68ea866ed9ebe3a989091088553ba12c6090244fdae3e467b1139c35"}, + {file = "scipy-1.10.1-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:39becb03541f9e58243f4197584286e339029e8908c46f7221abeea4b749fa88"}, + {file = "scipy-1.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bce5869c8d68cf383ce240e44c1d9ae7c06078a9396df68ce88a1230f93a30c1"}, + {file = "scipy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07c3457ce0b3ad5124f98a86533106b643dd811dd61b548e78cf4c8786652f6f"}, + {file = "scipy-1.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:049a8bbf0ad95277ffba9b3b7d23e5369cc39e66406d60422c8cfef40ccc8415"}, + {file = "scipy-1.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cd9f1027ff30d90618914a64ca9b1a77a431159df0e2a195d8a9e8a04c78abf9"}, + {file = "scipy-1.10.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:79c8e5a6c6ffaf3a2262ef1be1e108a035cf4f05c14df56057b64acc5bebffb6"}, + {file = "scipy-1.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51af417a000d2dbe1ec6c372dfe688e041a7084da4fdd350aeb139bd3fb55353"}, + {file = "scipy-1.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b4735d6c28aad3cdcf52117e0e91d6b39acd4272f3f5cd9907c24ee931ad601"}, + {file = "scipy-1.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ff7f37b1bf4417baca958d254e8e2875d0cc23aaadbe65b3d5b3077b0eb23ea"}, + {file = "scipy-1.10.1.tar.gz", hash = "sha256:2cf9dfb80a7b4589ba4c40ce7588986d6d5cebc5457cad2c2880f6bc2d42f3a5"}, +] + +[package.dependencies] +numpy = ">=1.19.5,<1.27.0" + +[package.extras] +dev = ["click", "doit (>=0.36.0)", "flake8", "mypy", "pycodestyle", "pydevtool", "rich-click", "typing_extensions"] +doc = ["matplotlib (>2)", "numpydoc", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] +test = ["asv", "gmpy2", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] + +[[package]] +name = "scipy" +version = "1.12.0" +description = "Fundamental algorithms for scientific computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "scipy-1.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:78e4402e140879387187f7f25d91cc592b3501a2e51dfb320f48dfb73565f10b"}, + {file = "scipy-1.12.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:f5f00ebaf8de24d14b8449981a2842d404152774c1a1d880c901bf454cb8e2a1"}, + {file = "scipy-1.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e53958531a7c695ff66c2e7bb7b79560ffdc562e2051644c5576c39ff8efb563"}, + {file = "scipy-1.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e32847e08da8d895ce09d108a494d9eb78974cf6de23063f93306a3e419960c"}, + {file = "scipy-1.12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4c1020cad92772bf44b8e4cdabc1df5d87376cb219742549ef69fc9fd86282dd"}, + {file = "scipy-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:75ea2a144096b5e39402e2ff53a36fecfd3b960d786b7efd3c180e29c39e53f2"}, + {file = "scipy-1.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:408c68423f9de16cb9e602528be4ce0d6312b05001f3de61fe9ec8b1263cad08"}, + {file = "scipy-1.12.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:5adfad5dbf0163397beb4aca679187d24aec085343755fcdbdeb32b3679f254c"}, + {file = "scipy-1.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3003652496f6e7c387b1cf63f4bb720951cfa18907e998ea551e6de51a04467"}, + {file = "scipy-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b8066bce124ee5531d12a74b617d9ac0ea59245246410e19bca549656d9a40a"}, + {file = "scipy-1.12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8bee4993817e204d761dba10dbab0774ba5a8612e57e81319ea04d84945375ba"}, + {file = "scipy-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:a24024d45ce9a675c1fb8494e8e5244efea1c7a09c60beb1eeb80373d0fecc70"}, + {file = "scipy-1.12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e7e76cc48638228212c747ada851ef355c2bb5e7f939e10952bc504c11f4e372"}, + {file = "scipy-1.12.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:f7ce148dffcd64ade37b2df9315541f9adad6efcaa86866ee7dd5db0c8f041c3"}, + {file = "scipy-1.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c39f92041f490422924dfdb782527a4abddf4707616e07b021de33467f917bc"}, + {file = "scipy-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7ebda398f86e56178c2fa94cad15bf457a218a54a35c2a7b4490b9f9cb2676c"}, + {file = "scipy-1.12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:95e5c750d55cf518c398a8240571b0e0782c2d5a703250872f36eaf737751338"}, + {file = "scipy-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:e646d8571804a304e1da01040d21577685ce8e2db08ac58e543eaca063453e1c"}, + {file = "scipy-1.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:913d6e7956c3a671de3b05ccb66b11bc293f56bfdef040583a7221d9e22a2e35"}, + {file = "scipy-1.12.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba1b0c7256ad75401c73e4b3cf09d1f176e9bd4248f0d3112170fb2ec4db067"}, + {file = "scipy-1.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:730badef9b827b368f351eacae2e82da414e13cf8bd5051b4bdfd720271a5371"}, + {file = "scipy-1.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6546dc2c11a9df6926afcbdd8a3edec28566e4e785b915e849348c6dd9f3f490"}, + {file = "scipy-1.12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:196ebad3a4882081f62a5bf4aeb7326aa34b110e533aab23e4374fcccb0890dc"}, + {file = "scipy-1.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:b360f1b6b2f742781299514e99ff560d1fe9bd1bff2712894b52abe528d1fd1e"}, + {file = "scipy-1.12.0.tar.gz", hash = "sha256:4bf5abab8a36d20193c698b0f1fc282c1d083c94723902c447e5d2f1780936a3"}, +] + +[package.dependencies] +numpy = ">=1.22.4,<1.29.0" + +[package.extras] +dev = ["click", "cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"] +doc = ["jupytext", "matplotlib (>2)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] +test = ["asv", "gmpy2", "hypothesis", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] + +[[package]] +name = "setuptools" +version = "69.0.3" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"}, + {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +optional = false +python-versions = "*" +files = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] + +[[package]] +name = "sortedcontainers" +version = "2.4.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +optional = false +python-versions = "*" +files = [ + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, +] + +[[package]] +name = "sphinx" +version = "6.2.1" +description = "Python documentation generator" +optional = false +python-versions = ">=3.8" +files = [ + {file = "Sphinx-6.2.1.tar.gz", hash = "sha256:6d56a34697bb749ffa0152feafc4b19836c755d90a7c59b72bc7dfd371b9cc6b"}, + {file = "sphinx-6.2.1-py3-none-any.whl", hash = "sha256:97787ff1fa3256a3eef9eda523a63dbf299f7b47e053cfcf684a1c2a8380c912"}, +] + +[package.dependencies] +alabaster = ">=0.7,<0.8" +babel = ">=2.9" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +docutils = ">=0.18.1,<0.20" +imagesize = ">=1.3" +importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""} +Jinja2 = ">=3.0" +packaging = ">=21.0" +Pygments = ">=2.13" +requests = ">=2.25.0" +snowballstemmer = ">=2.0" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.5" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] +test = ["cython", "filelock", "html5lib", "pytest (>=4.6)"] + +[[package]] +name = "sphinx" +version = "7.2.6" +description = "Python documentation generator" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinx-7.2.6-py3-none-any.whl", hash = "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560"}, + {file = "sphinx-7.2.6.tar.gz", hash = "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5"}, +] + +[package.dependencies] +alabaster = ">=0.7,<0.8" +babel = ">=2.9" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +docutils = ">=0.18.1,<0.21" +imagesize = ">=1.3" +importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""} +Jinja2 = ">=3.0" +packaging = ">=21.0" +Pygments = ">=2.14" +requests = ">=2.25.0" +snowballstemmer = ">=2.0" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.9" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] +test = ["cython (>=3.0)", "filelock", "html5lib", "pytest (>=4.6)", "setuptools (>=67.0)"] + +[[package]] +name = "sphinx-autobuild" +version = "2021.3.14" +description = "Rebuild Sphinx documentation on changes, with live-reload in the browser." +optional = false +python-versions = ">=3.6" +files = [ + {file = "sphinx-autobuild-2021.3.14.tar.gz", hash = "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"}, + {file = "sphinx_autobuild-2021.3.14-py3-none-any.whl", hash = "sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac"}, +] + +[package.dependencies] +colorama = "*" +livereload = "*" +sphinx = "*" + +[package.extras] +test = ["pytest", "pytest-cov"] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "1.0.4" +description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"}, + {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "1.0.8" +description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_applehelp-1.0.8-py3-none-any.whl", hash = "sha256:cb61eb0ec1b61f349e5cc36b2028e9e7ca765be05e49641c97241274753067b4"}, + {file = "sphinxcontrib_applehelp-1.0.8.tar.gz", hash = "sha256:c40a4f96f3776c4393d933412053962fac2b84f4c99a7982ba42e09576a70619"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "1.0.2" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, + {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "1.0.6" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_devhelp-1.0.6-py3-none-any.whl", hash = "sha256:6485d09629944511c893fa11355bda18b742b83a2b181f9a009f7e500595c90f"}, + {file = "sphinxcontrib_devhelp-1.0.6.tar.gz", hash = "sha256:9893fd3f90506bc4b97bdb977ceb8fbd823989f4316b28c3841ec128544372d3"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.0.1" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"}, + {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["html5lib", "pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.0.5" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_htmlhelp-2.0.5-py3-none-any.whl", hash = "sha256:393f04f112b4d2f53d93448d4bce35842f62b307ccdc549ec1585e950bc35e04"}, + {file = "sphinxcontrib_htmlhelp-2.0.5.tar.gz", hash = "sha256:0dc87637d5de53dd5eec3a6a01753b1ccf99494bd756aafecd74b4fa9e729015"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] +test = ["html5lib", "pytest"] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] + +[package.extras] +test = ["flake8", "mypy", "pytest"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "1.0.3" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, + {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "1.0.7" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_qthelp-1.0.7-py3-none-any.whl", hash = "sha256:e2ae3b5c492d58fcbd73281fbd27e34b8393ec34a073c792642cd8e529288182"}, + {file = "sphinxcontrib_qthelp-1.0.7.tar.gz", hash = "sha256:053dedc38823a80a7209a80860b16b722e9e0209e32fea98c90e4e6624588ed6"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "1.1.5" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, + {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "1.1.10" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_serializinghtml-1.1.10-py3-none-any.whl", hash = "sha256:326369b8df80a7d2d8d7f99aa5ac577f51ea51556ed974e7716cfd4fca3f6cb7"}, + {file = "sphinxcontrib_serializinghtml-1.1.10.tar.gz", hash = "sha256:93f3f5dc458b91b192fe10c397e324f262cf163d79f3282c158e8436a2c4511f"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "tornado" +version = "6.4" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +optional = false +python-versions = ">= 3.8" +files = [ + {file = "tornado-6.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0"}, + {file = "tornado-6.4-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f"}, + {file = "tornado-6.4-cp38-abi3-win32.whl", hash = "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052"}, + {file = "tornado-6.4-cp38-abi3-win_amd64.whl", hash = "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63"}, + {file = "tornado-6.4.tar.gz", hash = "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee"}, +] + +[[package]] +name = "tox" +version = "4.12.1" +description = "tox is a generic virtualenv management and test command line tool" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tox-4.12.1-py3-none-any.whl", hash = "sha256:c07ea797880a44f3c4f200ad88ad92b446b83079d4ccef89585df64cc574375c"}, + {file = "tox-4.12.1.tar.gz", hash = "sha256:61aafbeff1bd8a5af84e54ef6e8402f53c6a6066d0782336171ddfbf5362122e"}, +] + +[package.dependencies] +cachetools = ">=5.3.2" +chardet = ">=5.2" +colorama = ">=0.4.6" +filelock = ">=3.13.1" +packaging = ">=23.2" +platformdirs = ">=4.1" +pluggy = ">=1.3" +pyproject-api = ">=1.6.1" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} +virtualenv = ">=20.25" + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-argparse-cli (>=1.11.1)", "sphinx-autodoc-typehints (>=1.25.2)", "sphinx-copybutton (>=0.5.2)", "sphinx-inline-tabs (>=2023.4.21)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.11)"] +testing = ["build[virtualenv] (>=1.0.3)", "covdefaults (>=2.3)", "detect-test-pollution (>=1.2)", "devpi-process (>=1)", "diff-cover (>=8.0.2)", "distlib (>=0.3.8)", "flaky (>=3.7)", "hatch-vcs (>=0.4)", "hatchling (>=1.21)", "psutil (>=5.9.7)", "pytest (>=7.4.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-xdist (>=3.5)", "re-assert (>=1.1)", "time-machine (>=2.13)", "wheel (>=0.42)"] + +[[package]] +name = "typing-extensions" +version = "4.9.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, + {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, +] + +[[package]] +name = "tzdata" +version = "2023.4" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2023.4-py2.py3-none-any.whl", hash = "sha256:aa3ace4329eeacda5b7beb7ea08ece826c28d761cda36e747cfbf97996d39bf3"}, + {file = "tzdata-2023.4.tar.gz", hash = "sha256:dd54c94f294765522c77399649b4fefd95522479a664a0cec87f41bebc6148c9"}, +] + +[[package]] +name = "urllib3" +version = "2.2.0" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.0-py3-none-any.whl", hash = "sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224"}, + {file = "urllib3-2.2.0.tar.gz", hash = "sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "virtualenv" +version = "20.25.0" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.7" +files = [ + {file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"}, + {file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<5" + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] + +[[package]] +name = "watchdog" +version = "3.0.0" +description = "Filesystem events monitoring" +optional = false +python-versions = ">=3.7" +files = [ + {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:336adfc6f5cc4e037d52db31194f7581ff744b67382eb6021c868322e32eef41"}, + {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a70a8dcde91be523c35b2bf96196edc5730edb347e374c7de7cd20c43ed95397"}, + {file = "watchdog-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:adfdeab2da79ea2f76f87eb42a3ab1966a5313e5a69a0213a3cc06ef692b0e96"}, + {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b57a1e730af3156d13b7fdddfc23dea6487fceca29fc75c5a868beed29177ae"}, + {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7ade88d0d778b1b222adebcc0927428f883db07017618a5e684fd03b83342bd9"}, + {file = "watchdog-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7e447d172af52ad204d19982739aa2346245cc5ba6f579d16dac4bfec226d2e7"}, + {file = "watchdog-3.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9fac43a7466eb73e64a9940ac9ed6369baa39b3bf221ae23493a9ec4d0022674"}, + {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8ae9cda41fa114e28faf86cb137d751a17ffd0316d1c34ccf2235e8a84365c7f"}, + {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:25f70b4aa53bd743729c7475d7ec41093a580528b100e9a8c5b5efe8899592fc"}, + {file = "watchdog-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4f94069eb16657d2c6faada4624c39464f65c05606af50bb7902e036e3219be3"}, + {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c5f84b5194c24dd573fa6472685b2a27cc5a17fe5f7b6fd40345378ca6812e3"}, + {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3aa7f6a12e831ddfe78cdd4f8996af9cf334fd6346531b16cec61c3b3c0d8da0"}, + {file = "watchdog-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:233b5817932685d39a7896b1090353fc8efc1ef99c9c054e46c8002561252fb8"}, + {file = "watchdog-3.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:13bbbb462ee42ec3c5723e1205be8ced776f05b100e4737518c67c8325cf6100"}, + {file = "watchdog-3.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8f3ceecd20d71067c7fd4c9e832d4e22584318983cabc013dbf3f70ea95de346"}, + {file = "watchdog-3.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c9d8c8ec7efb887333cf71e328e39cffbf771d8f8f95d308ea4125bf5f90ba64"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:0e06ab8858a76e1219e68c7573dfeba9dd1c0219476c5a44d5333b01d7e1743a"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:c07253088265c363d1ddf4b3cdb808d59a0468ecd017770ed716991620b8f77a"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:5113334cf8cf0ac8cd45e1f8309a603291b614191c9add34d33075727a967709"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:51f90f73b4697bac9c9a78394c3acbbd331ccd3655c11be1a15ae6fe289a8c83"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:ba07e92756c97e3aca0912b5cbc4e5ad802f4557212788e72a72a47ff376950d"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33"}, + {file = "watchdog-3.0.0-py3-none-win32.whl", hash = "sha256:3ed7c71a9dccfe838c2f0b6314ed0d9b22e77d268c67e015450a29036a81f60f"}, + {file = "watchdog-3.0.0-py3-none-win_amd64.whl", hash = "sha256:4c9956d27be0bb08fc5f30d9d0179a855436e655f046d288e2bcc11adfae893c"}, + {file = "watchdog-3.0.0-py3-none-win_ia64.whl", hash = "sha256:5d9f3a10e02d7371cd929b5d8f11e87d4bad890212ed3901f9b4d68767bee759"}, + {file = "watchdog-3.0.0.tar.gz", hash = "sha256:4d98a320595da7a7c5a18fc48cb633c2e73cda78f93cac2ef42d42bf609a33f9"}, +] + +[package.extras] +watchmedo = ["PyYAML (>=3.10)"] + +[[package]] +name = "zipp" +version = "3.17.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + +[metadata] +lock-version = "2.0" +python-versions = ">=3.8,<4.0" +content-hash = "743b745ca0e0935fd2572dbfa9252969fe50f74c7240b72e7fec5f3f3e55bba0" diff --git a/poetry.toml b/poetry.toml new file mode 100644 index 0000000..ab1033b --- /dev/null +++ b/poetry.toml @@ -0,0 +1,2 @@ +[virtualenvs] +in-project = true diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..4f1b1f0 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,134 @@ +[tool.poetry] +name = "traces" +version = "0.0.1" +description = "A Python library for unevenly-spaced time series analysis" +authors = ["Mike Stringer "] +repository = "https://github.com/stringertheory/traces" +documentation = "https://stringertheory.github.io/traces/" +readme = "README.md" +packages = [ + {include = "traces"} +] + +[tool.poetry.dependencies] +python = ">=3.8,<4.0" +infinity = "^1.5" +sortedcontainers = "^2.4.0" + +[tool.poetry.group.dev.dependencies] +pytest = "^7.2.0" +pytest-cov = "^4.0.0" +mypy = "^1.5.1" +pre-commit = [ + {version = "^3.4.0", python = ">=3.9"}, + {version = "^2.20.0", python = ">=3.7,<3.9"} +] +tox = "^4.11.1" +numpy = [ + {version = "^1.26.3", python = ">=3.9"}, + {version = "^1.19.5", python = ">=3.7,<3.9"} +] +pandas = [ + {version = "^2.2.0", python = ">=3.9"}, + {version = "^1.3.5", python = ">=3.7,<3.9"} +] +scipy = [ + {version = "^1.12.0", python = ">=3.9"}, + {version = "^1.7.2", python = ">=3.7,<3.9"} +] +matplotlib = [ + {version = "^3.8.2", python = ">=3.9"}, + {version = "^3.5", python = ">=3.7,<3.9"} +] +pytest-mpl = "^0.16.1" +pyarrow = "^15.0.0" + +[tool.poetry.group.docs.dependencies] +mkdocs = "^1.4.2" +mkdocs-material = "^9.2.7" +mkdocstrings = "^0.23.0" +sphinx = [ + {version = "^7.2.6", python = ">=3.9"}, + {version = "^6.0", python = ">=3.8,<3.9"}, +] +sphinx-autobuild = "^2021.3.14" +recommonmark = "^0.7.1" + + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" + +[tool.mypy] +files = ["traces"] +disallow_untyped_defs = "True" +disallow_any_unimported = "True" +no_implicit_optional = "True" +check_untyped_defs = "True" +warn_return_any = "True" +warn_unused_ignores = "True" +show_error_codes = "True" + +[tool.pytest.ini_options] +testpaths = ["tests"] + +[tool.ruff] +target-version = "py37" +line-length = 80 +fix = true +select = [ + # flake8-2020 + "YTT", + # flake8-bandit + "S", + # flake8-bugbear + "B", + # flake8-builtins + "A", + # flake8-comprehensions + "C4", + # flake8-debugger + "T10", + # flake8-simplify + "SIM", + # isort + "I", + # mccabe + "C90", + # pycodestyle + "E", "W", + # pyflakes + "F", + # pygrep-hooks + "PGH", + # pyupgrade + "UP", + # ruff + "RUF", + # tryceratops + "TRY", +] +ignore = [ + # LineTooLong + "E501", + # DoNotAssignLambda + "E731", + # Non-cryptographic random usage + "S311", + # Class attribute shadowing a Python builtin + "A003", +] + +[tool.ruff.format] +preview = true + +[tool.coverage.report] +skip_empty = true + +[tool.coverage.run] +branch = true +source = ["traces"] + +[tool.ruff.per-file-ignores] +"tests/*" = ["S101"] +"__init__.py" = ["F401"] diff --git a/requirements/python-test.txt b/requirements/python-test.txt index e9f1f10..e317855 100644 --- a/requirements/python-test.txt +++ b/requirements/python-test.txt @@ -3,6 +3,7 @@ # testing pycodestyle coveralls +codecov nose pytest pytest-mpl diff --git a/setup.cfg b/setup.cfg index ad07026..a389edb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,4 +20,3 @@ universal = 1 [flake8] exclude = docs - diff --git a/setup.py b/setup.py deleted file mode 100644 index d4f1efd..0000000 --- a/setup.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -import os -from setuptools import setup - - -def read_init(key): - """Parse the package __init__ file to find a variable so that it's not - in multiple places. - - """ - filename = os.path.join("traces", "__init__.py") - result = None - with open(filename) as stream: - for line in stream: - if key in line: - result = line.split('=')[-1].strip().replace("'", "") - - # throw error if version isn't in __init__ file - if result is None: - raise ValueError('must define %s in %s' % (key, filename)) - - return result - - -def read_author(): - return read_init('author') - - -def read_author_email(): - return read_init('email') - - -def read_dependencies(filename): - """Read in the dependencies from the virtualenv requirements file. - - """ - dependencies = [] - filepath = os.path.join('requirements', filename) - with open(filepath, 'r') as stream: - for line in stream: - package = line.strip().split('#')[0].strip() - if package and package.split(' ')[0] != '-r': - dependencies.append(package) - return dependencies - - -with open("README.md", "r") as fh: - long_description = fh.read() - -setup( - name='traces', - version='0.6.0', - description="A library for unevenly-spaced time series analysis.", - long_description=long_description, - long_description_content_type="text/markdown", - author=read_author(), - author_email=read_author_email(), - url='https://github.com/datascopeanalytics/traces', - packages=['traces'], - package_dir={'traces': 'traces'}, - include_package_data=True, - install_requires=read_dependencies('python.txt'), - extras_require={ - 'test': read_dependencies('python-test.txt'), - 'doc': read_dependencies('python-doc.txt'), - 'dev': read_dependencies('python-dev.txt'), - 'pandas': ['pandas'], - }, - license="MIT license", - zip_safe=False, - keywords='traces', - classifiers=[ - 'Development Status :: 4 - Beta', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: MIT License', - 'Natural Language :: English', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - ], - test_suite='nose.collector', -) diff --git a/tests/.coveragerc b/tests/.coveragerc index 40b3f80..a852abd 100644 --- a/tests/.coveragerc +++ b/tests/.coveragerc @@ -1,3 +1,3 @@ # .coveragerc [report] -show_missing = True \ No newline at end of file +show_missing = True diff --git a/tests/__init__.py b/tests/__init__.py index 40a96af..e69de29 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/tests/test_compact.py b/tests/test_compact.py index 7782d0c..8e07e11 100644 --- a/tests/test_compact.py +++ b/tests/test_compact.py @@ -1,13 +1,11 @@ -import traces - import random +import traces + def test_compact(): - # since this is random, do it a bunch of times - for n_trial in range(100): - + for _n_trial in range(100): # make two time series, one compact and one not test_ts = traces.TimeSeries() compact_ts = traces.TimeSeries() diff --git a/tests/test_distribution.py b/tests/test_distribution.py index 3693ae9..8ac8c44 100644 --- a/tests/test_distribution.py +++ b/tests/test_distribution.py @@ -1,10 +1,11 @@ import datetime -import nose -from traces import TimeSeries, Histogram +import pytest + +from traces import Histogram, TimeSeries -def test_distribution(): +def test_distribution(): start = datetime.datetime(2015, 3, 1) # v. simple @@ -17,7 +18,9 @@ def test_distribution(): # not normalized distribution = a.distribution( - start=start, end=end, normalized=False, + start=start, + end=end, + normalized=False, ) assert distribution[0] == 24 * 60 * 60 * 2 # two days assert distribution[1] == 24 * 60 * 60 * 2 @@ -29,7 +32,6 @@ def test_distribution(): def test_default_values(): - # v. simple a = TimeSeries() a.set(datetime.datetime(2015, 3, 1), 1) @@ -47,7 +49,6 @@ def test_default_values(): def test_mask(): - start = datetime.datetime(2015, 3, 1) # v. simple @@ -64,21 +65,25 @@ def test_mask(): # not normalized distribution = a.distribution( - start=start, end=end, normalized=False, mask=mask, + start=start, + end=end, + normalized=False, + mask=mask, ) assert distribution[0] == 24 * 60 * 60 # one day assert distribution[1] == 24 * 60 * 60 # normalized distribution = a.distribution( - start=start, end=end, mask=mask, + start=start, + end=end, + mask=mask, ) assert distribution[0] == 0.5 assert distribution[1] == 0.5 def test_integer_times(): - # v. simple a = TimeSeries() a[0] = 1 @@ -94,17 +99,16 @@ def test_integer_times(): def test_distribution_set(): time_series = TimeSeries() - time_series[1.2] = {'broccoli'} - time_series[1.4] = {'broccoli', 'orange'} - time_series[1.7] = {'broccoli', 'orange', 'banana'} - time_series[2.2] = {'orange', 'banana'} - time_series[3.5] = {'orange', 'banana', 'beets'} + time_series[1.2] = {"broccoli"} + time_series[1.4] = {"broccoli", "orange"} + time_series[1.7] = {"broccoli", "orange", "banana"} + time_series[2.2] = {"orange", "banana"} + time_series[3.5] = {"orange", "banana", "beets"} # TODO: How to convert the set into multiple ts? def test_distribution_empty(): - ts = TimeSeries() mask = TimeSeries(default=0) @@ -113,7 +117,7 @@ def test_distribution_empty(): # distribution with default args and no default value on empty # TimeSeries doesn't know what to do - nose.tools.assert_raises(KeyError, ts.distribution) + pytest.raises(KeyError, ts.distribution) # distribution with start and end, but no default value on empty # TimeSeries doesn't know what to do @@ -121,13 +125,12 @@ def test_distribution_empty(): # no matter what is passed in to distribution, if the default # value is not set on an empty TimeSeries this should be an error - ts.distribution(mask=mask) == Histogram.from_dict({None: 1.0}) - # nose.tools.assert_raises(KeyError, ts.distribution, mask=mask) + assert ts.distribution(mask=mask) == Histogram.from_dict({None: 1.0}) ts = TimeSeries(default=0) # no mask or start/end on empty TimeSeries, don't know what to do - nose.tools.assert_raises(KeyError, ts.distribution) + pytest.raises(KeyError, ts.distribution) # start and end or mask given, is fine distribution = ts.distribution(0, 10) @@ -139,10 +142,10 @@ def test_distribution_empty(): # empty mask mask = TimeSeries(default=0) - with nose.tools.assert_raises(ValueError): + with pytest.raises(ValueError): ts.distribution(mask=mask) - with nose.tools.assert_raises(ValueError): + with pytest.raises(ValueError): ts.distribution(start=0, end=2, mask=mask) @@ -153,5 +156,5 @@ def test_none_handling(): ts[3] = (2, 0) # print(ts.distribution(normalized=False)) - assert(ts.distribution()[(0, 1)] == 0.5) - assert(ts.distribution()[(None, 0)] == 0.5) + assert ts.distribution()[(0, 1)] == 0.5 + assert ts.distribution()[(None, 0)] == 0.5 diff --git a/tests/test_docs.py b/tests/test_docs.py index 7be7acb..38831d9 100644 --- a/tests/test_docs.py +++ b/tests/test_docs.py @@ -1,20 +1,21 @@ -import traces from datetime import datetime +import traces + def test_quickstart(): time_series = traces.TimeSeries() - time_series[datetime(2042, 2, 1, 6, 0, 0)] = 0 # 6:00:00am - time_series[datetime(2042, 2, 1, 7, 45, 56)] = 1 # 7:45:56am - time_series[datetime(2042, 2, 1, 8, 51, 42)] = 0 # 8:51:42am - time_series[datetime(2042, 2, 1, 12, 3, 56)] = 1 # 12:03:56am - time_series[datetime(2042, 2, 1, 12, 7, 13)] = 0 # 12:07:13am + time_series[datetime(2042, 2, 1, 6, 0, 0)] = 0 # 6:00:00am + time_series[datetime(2042, 2, 1, 7, 45, 56)] = 1 # 7:45:56am + time_series[datetime(2042, 2, 1, 8, 51, 42)] = 0 # 8:51:42am + time_series[datetime(2042, 2, 1, 12, 3, 56)] = 1 # 12:03:56am + time_series[datetime(2042, 2, 1, 12, 7, 13)] = 0 # 12:07:13am - assert time_series[datetime(2042, 2, 1, 11, 0, 0)] == 0 + assert time_series[datetime(2042, 2, 1, 11, 0, 0)] == 0 distribution = time_series.distribution( - start=datetime(2042, 2, 1, 6, 0, 0), # 6:00am - end=datetime(2042, 2, 1, 13, 0, 0) # 1:00pm + start=datetime(2042, 2, 1, 6, 0, 0), # 6:00am + end=datetime(2042, 2, 1, 13, 0, 0), # 1:00pm ) assert distribution[1] == 0.16440476190476191 @@ -22,13 +23,13 @@ def test_quickstart(): def test_reference(): cart = traces.TimeSeries() - cart[1.2] = {'broccoli'} - cart[1.7] = {'broccoli', 'apple'} - cart[2.2] = {'apple'} - cart[3.5] = {'apple', 'beets'} + cart[1.2] = {"broccoli"} + cart[1.7] = {"broccoli", "apple"} + cart[2.2] = {"apple"} + cart[3.5] = {"apple", "beets"} - assert cart[2] == {'broccoli', 'apple'} + assert cart[2] == {"broccoli", "apple"} assert cart[-1] is None cart = traces.TimeSeries(default=set()) - assert cart[-1] == set([]) + assert cart[-1] == set() diff --git a/tests/test_eventseries.py b/tests/test_eventseries.py new file mode 100644 index 0000000..20f20c3 --- /dev/null +++ b/tests/test_eventseries.py @@ -0,0 +1,158 @@ +import pandas as pd + +from traces import EventSeries, TimeSeries + + +def test_init_data(): + es = EventSeries([0, 0, 6, 8.7, 10]) + + assert es[0] == 0 + assert es[1] == 0 + assert es[2] == 6 + assert es[3] == 8.7 + assert es[4] == 10 + + +def test_cumsum(): + # Test with basic timestamp data + data = [ + "2018-10-15T16:45:01", + "2019-04-16T13:08:26", + "2019-02-22T12:05:08", + "2019-04-16T13:09:06", + "2019-04-16T13:09:13", + "2019-04-16T13:09:28", + "2019-04-16T13:09:29", + "2019-04-16T13:10:20", + "2019-04-16T13:10:30", + "2019-03-08T16:46:48", + "2019-04-16T13:09:29", + "2019-04-16T13:10:20", + ] + es = EventSeries(pd.to_datetime(data)) + + ref = { + pd.Timestamp("2018-10-15 16:45:01"): 1, + pd.Timestamp("2019-02-22 12:05:08"): 2, + pd.Timestamp("2019-03-08 16:46:48"): 3, + pd.Timestamp("2019-04-16 13:08:26"): 4, + pd.Timestamp("2019-04-16 13:09:06"): 5, + pd.Timestamp("2019-04-16 13:09:13"): 6, + pd.Timestamp("2019-04-16 13:09:28"): 7, + pd.Timestamp("2019-04-16 13:09:29"): 9, + pd.Timestamp("2019-04-16 13:10:20"): 11, + pd.Timestamp("2019-04-16 13:10:30"): 12, + } + + reference = TimeSeries(ref, default=0) + + assert es.cumsum() == reference + + # check default is 0 + assert es.cumsum()[pd.Timestamp("2015-01-01")] == 0 + + # Test Empty Series + es = EventSeries() + assert es.cumsum() == TimeSeries(default=0) + + +def test_events_between(): + data = [ + "2018-10-15T16:45:01", + "2019-04-16T13:08:26", + "2019-02-22T12:05:08", + "2019-04-16T13:09:06", + "2019-04-16T13:09:13", + "2019-04-16T13:09:28", + "2019-04-16T13:09:29", + "2019-04-16T13:10:20", + "2019-04-16T13:10:30", + "2019-03-08T16:46:48", + "2019-04-16T13:09:29", + "2019-04-16T13:10:20", + ] + es = EventSeries(pd.to_datetime(data)) + + assert ( + es.events_between( + pd.Timestamp("2018-01-01"), pd.Timestamp("2020-01-01") + ) + == 12 + ) + assert ( + es.events_between( + pd.Timestamp("2018-01-01"), pd.Timestamp("2019-01-01") + ) + == 1 + ) + assert ( + es.events_between( + pd.Timestamp("2020-01-01"), pd.Timestamp("2020-02-01") + ) + == 0 + ) + assert ( + es.events_between( + pd.Timestamp("2016-01-01"), pd.Timestamp("2017-02-01") + ) + == 0 + ) + + # Test closed boundaries on end points + # left + assert ( + es.events_between( + pd.Timestamp("2018-10-15 16:45:01"), + pd.Timestamp("2019-04-15 12:00:00"), + ) + == 3 + ) + # right + assert ( + es.events_between( + pd.Timestamp("2019-02-28 12:00:00"), + pd.Timestamp("2019-04-16 13:10:20"), + ) + == 9 + ) + # both + assert ( + es.events_between( + pd.Timestamp("2019-02-22 12:05:08"), + pd.Timestamp("2019-04-16 13:10:20"), + ) + == 10 + ) + + +def test_count_active(): + es_open = EventSeries( + ["08:00", "09:00", "13:00", "07:00", "06:30", "13:00"] + ) + es_closed = EventSeries(["08:00", "08:30", "12:00", "12:00", "12:00"]) + ts = EventSeries.count_active(es_open, es_closed) + + assert ts["06:30"] == 1 + assert ts["07:00"] == 2 + assert ts["08:00"] == 2 + assert ts["12:00"] == -1 + assert ts["13:00"] == 1 + + +def test_time_lag(): + data = [ + "2019-02-01", + "2019-02-28", + "2019-02-22", + "2019-02-16", + "2019-02-26", + "2019-02-16", + ] + es = EventSeries(pd.to_datetime(data)) + + time_lag = es.time_lag() + assert time_lag[0] == pd.Timedelta(days=15) + assert time_lag[1] == pd.Timedelta(days=0) + + # Make sure we got the right shape + assert time_lag.shape[0] == len(data) - 1 diff --git a/tests/test_histogram.py b/tests/test_histogram.py index e72a2e9..a17d14a 100644 --- a/tests/test_histogram.py +++ b/tests/test_histogram.py @@ -1,13 +1,13 @@ -import nose +import contextlib -import traces - -from scipy import stats import numpy +import pytest +from scipy import stats +import traces -def test_quantiles(): +def test_quantiles(): data = [15, 15, 20, 20, 20, 35, 35, 40, 40, 50, 50] histogram = traces.Histogram(data) @@ -15,15 +15,15 @@ def test_quantiles(): alpha = 0.5 q_list = [0.05, 0.25, 0.5, 0.75, 0.95] q_values = histogram.quantiles(q_list, alpha=alpha, smallest_count=1) - reference = \ - stats.mstats.mquantiles(data, prob=q_list, alphap=0.5, betap=0.5) + reference = stats.mstats.mquantiles( + data, prob=q_list, alphap=0.5, betap=0.5 + ) for i, j in zip(q_values, reference): assert i == j def test_normalize(): - data = [15, 15, 20, 20, 20, 35, 35, 40, 40, 50, 50] histogram = traces.Histogram(data) normalized = histogram.normalized() @@ -32,7 +32,6 @@ def test_normalize(): def _test_statistics(normalized): - data_list = [ [1, 2, 3, 5, 6, 7], [1, 2, 3, 5, 6], @@ -42,7 +41,6 @@ def _test_statistics(normalized): ] for data in data_list: - histogram = traces.Histogram(data) if normalized: histogram = histogram.normalized() @@ -50,34 +48,29 @@ def _test_statistics(normalized): else: n = len(data) - nose.tools.assert_almost_equal(histogram.total(), n) - nose.tools.assert_almost_equal(histogram.mean(), numpy.mean(data)) - nose.tools.assert_almost_equal(histogram.variance(), numpy.var(data)) - nose.tools.assert_almost_equal( - histogram.standard_deviation(), - numpy.std(data), - ) - nose.tools.assert_almost_equal(histogram.max(), numpy.max(data)) - nose.tools.assert_almost_equal(histogram.min(), numpy.min(data)) - nose.tools.assert_almost_equal( - histogram.quantile(0.5), - numpy.median(data), - ) + assert histogram.total() == pytest.approx(n) + assert histogram.mean() == pytest.approx(numpy.mean(data)) + assert histogram.variance() == pytest.approx(numpy.var(data)) + assert histogram.standard_deviation() == pytest.approx(numpy.std(data)) + assert histogram.max() == pytest.approx(numpy.max(data)) + assert histogram.min() == pytest.approx(numpy.min(data)) + assert histogram.quantile(0.5) == pytest.approx(numpy.median(data)) q_list = [0.001, 0.01, 0.05, 0.25, 0.5, 0.75, 0.95, 0.99, 0.999] # linear interpolation result = histogram.quantiles(q_list) reference = stats.mstats.mquantiles( - data, prob=q_list, alphap=0.5, betap=0.5, + data, + prob=q_list, + alphap=0.5, + betap=0.5, ) for i, j in zip(result, reference): - nose.tools.assert_almost_equal(i, j) + assert i == pytest.approx(j) # make sure ot throw an error for bad quantile values - try: + with contextlib.suppress(ValueError): histogram.quantile(-1) - except ValueError: - pass def test_statistics(): @@ -89,7 +82,6 @@ def test_normalized_statistics(): def test_quantile_interpolation(): - data = [1, 1, 1, 2, 3, 5, 6, 7] histogram = traces.Histogram(data) normalized = histogram.normalized() @@ -100,32 +92,37 @@ def test_quantile_interpolation(): result = histogram.quantiles(q_list, alpha=0, smallest_count=1) answer = [1.0, 1.0, 1.0, 1.0, 2.5, 5.5, 7.0, 7.0, 7.0] for i, j in zip(result, answer): - nose.tools.assert_almost_equal(i, j) + assert i == pytest.approx(j) # same thing with normalized result = normalized.quantiles( - q_list, alpha=0, smallest_count=1.0 / len(data)) + q_list, alpha=0, smallest_count=1.0 / len(data) + ) for i, j in zip(result, answer): - nose.tools.assert_almost_equal(i, j) + assert i == pytest.approx(j) # now do the linear interpolation method result = histogram.quantiles(q_list, alpha=0.5, smallest_count=1) answer = stats.mstats.mquantiles( - data, prob=q_list, alphap=0.5, betap=0.5, + data, + prob=q_list, + alphap=0.5, + betap=0.5, ) for i, j in zip(result, answer): - nose.tools.assert_almost_equal(i, j) + assert i == pytest.approx(j) # same thing with normalized result = normalized.quantiles( - q_list, alpha=0.5, smallest_count=1.0 / len(data), + q_list, + alpha=0.5, + smallest_count=1.0 / len(data), ) for i, j in zip(result, answer): - nose.tools.assert_almost_equal(i, j) + assert i == pytest.approx(j) def test_addition(): - hist_a = traces.Histogram([1, 1, 1, 2, 3, 5]) hist_b = traces.Histogram([0, 0, 1, 2, 2]) @@ -134,7 +131,6 @@ def test_addition(): def test_minmax_with_zeros(): - histogram = traces.Histogram() histogram[0] += 0 @@ -142,29 +138,28 @@ def test_minmax_with_zeros(): histogram[2] += 1 histogram[3] += 0 - nose.tools.eq_(histogram.min(), 1) - nose.tools.eq_(histogram.max(), 2) + assert histogram.min() == 1 + assert histogram.max() == 2 def test_histogram_stats_with_nones(): - histogram = traces.Histogram() - nose.tools.eq_(histogram.mean(), None) - nose.tools.eq_(histogram.variance(), None) - nose.tools.eq_(histogram.standard_deviation(), None) - nose.tools.eq_(histogram.min(), None) - nose.tools.eq_(histogram.max(), None) - nose.tools.eq_(histogram.median(), None) + assert histogram.mean() is None + assert histogram.variance() is None + assert histogram.standard_deviation() is None + assert histogram.min() is None + assert histogram.max() is None + assert histogram.median() is None histogram = traces.Histogram.from_dict({None: 1}, key=hash) - nose.tools.eq_(histogram.mean(), None) - nose.tools.eq_(histogram.variance(), None) - nose.tools.eq_(histogram.standard_deviation(), None) - nose.tools.eq_(histogram.min(), None) - nose.tools.eq_(histogram.max(), None) - nose.tools.eq_(histogram.median(), None) + assert histogram.mean() is None + assert histogram.variance() is None + assert histogram.standard_deviation() is None + assert histogram.min() is None + assert histogram.max() is None + assert histogram.median() is None ts = traces.TimeSeries() ts[0] = None @@ -175,4 +170,4 @@ def test_histogram_stats_with_nones(): ts[10] = None histogram = ts.distribution(start=0, end=10) - nose.tools.eq_(histogram.mean(), 6) + assert histogram.mean() == 6 diff --git a/tests/test_iterators.py b/tests/test_iterators.py index 8fa6c0e..d3a2c0b 100644 --- a/tests/test_iterators.py +++ b/tests/test_iterators.py @@ -1,16 +1,13 @@ import datetime -import random -import sys import pprint +import random -from infinity import inf -import nose +import pytest from traces import TimeSeries def test_iterintervals(): - ts = TimeSeries() ts.set(datetime.datetime(2015, 3, 1), 1) ts.set(datetime.datetime(2015, 3, 2), 0) @@ -19,16 +16,15 @@ def test_iterintervals(): answer = [(1, 0), (0, 1), (1, 2)] result = [] - for (t0, v0), (t1, v1) in ts.iterintervals(): + for (_t0, v0), (_t1, v1) in ts.iterintervals(): result.append((v0, v1)) assert answer == result def test_iterperiods(): - # timeseries with no points raises a KeyError ts = TimeSeries() - with nose.tools.assert_raises(KeyError): + with pytest.raises(KeyError): next(ts.iterperiods()) ts.set(datetime.datetime(2015, 3, 1), 1) @@ -39,11 +35,11 @@ def test_iterperiods(): answer = [ (datetime.datetime(2015, 3, 1), datetime.datetime(2015, 3, 2), 1), (datetime.datetime(2015, 3, 2), datetime.datetime(2015, 3, 3), 0), - (datetime.datetime(2015, 3, 3), datetime.datetime(2015, 3, 4), 1)] + (datetime.datetime(2015, 3, 3), datetime.datetime(2015, 3, 4), 1), + ] result = [] - for (t0, t1, v0) in ts.iterperiods( - start=datetime.datetime(2015, 3, 1), - end=datetime.datetime(2015, 3, 4) + for t0, t1, v0 in ts.iterperiods( + start=datetime.datetime(2015, 3, 1), end=datetime.datetime(2015, 3, 4) ): result.append((t0, t1, v0)) assert answer == result @@ -53,32 +49,31 @@ def test_iterperiods(): (datetime.datetime(2015, 3, 3), datetime.datetime(2015, 3, 4), 1), ] result = [] - for (t0, t1, v0) in ts.iterperiods( - start=datetime.datetime(2015, 3, 1), - end=datetime.datetime(2015, 3, 4), - value=1, + for t0, t1, v0 in ts.iterperiods( + start=datetime.datetime(2015, 3, 1), + end=datetime.datetime(2015, 3, 4), + value=1, ): result.append((t0, t1, v0)) assert answer == result - def filter(t0, t1, value): - return True if not value else False + def filter_function(t0, t1, value): + return bool(not value) answer = [ (datetime.datetime(2015, 3, 2), datetime.datetime(2015, 3, 3), 0), ] result = [] - for (t0, t1, v0) in ts.iterperiods( - start=datetime.datetime(2015, 3, 1), - end=datetime.datetime(2015, 3, 4), - value=filter, + for t0, t1, v0 in ts.iterperiods( + start=datetime.datetime(2015, 3, 1), + end=datetime.datetime(2015, 3, 4), + value=filter_function, ): result.append((t0, t1, v0)) assert answer == result def test_slice(): - ts = TimeSeries(default=1) ts[0] = 1 ts[1] = 5 @@ -90,14 +85,14 @@ def test_slice(): assert list(ts.slice(-1, 1).items()) == [(-1, 1), (0, 1), (1, 5)] assert list(ts.slice(-1, 0.5).items()) == [(-1, 1), (0, 1), (0.5, 1)] - nose.tools.assert_raises(ValueError, ts.slice, 2.5, 0) + pytest.raises(ValueError, ts.slice, 2.5, 0) def make_random_timeseries(): length = random.randint(1, 10) result = TimeSeries() t = 0 - for i in range(length): + for _i in range(length): t += random.randint(0, 5) x = random.randint(0, 5) result[t] = x @@ -105,26 +100,23 @@ def make_random_timeseries(): def test_merge(): - # since this is random, do it a bunch of times - for n_trial in range(1000): - + for _n_trial in range(1000): # make a list of TimeSeries that is anywhere from 0 to 5 # long. Each TimeSeries is of random length between 0 and 20, # with random time points and random values. ts_list = [] - for i in range(random.randint(1, 5)): + for _i in range(random.randint(1, 5)): ts_list.append(make_random_timeseries()) method_a = list(TimeSeries.merge(ts_list, compact=False)) method_b = list(TimeSeries.iter_merge(ts_list)) - msg = '%s != %s' % (pprint.pformat(method_a), pprint.pformat(method_b)) + msg = f"{pprint.pformat(method_a)} != {pprint.pformat(method_b)}" assert method_a == method_b, msg def test_single_merges(): - # a single empty time series ts = TimeSeries() assert TimeSeries.merge([ts]) == TimeSeries(default=[None]) @@ -132,8 +124,7 @@ def test_single_merges(): # multiple empty time series ts_a = TimeSeries() ts_b = TimeSeries() - assert TimeSeries.merge([ts_a, ts_b]) == \ - TimeSeries(default=[None, None]) + assert TimeSeries.merge([ts_a, ts_b]) == TimeSeries(default=[None, None]) # test a single time series with only one measurement ts = TimeSeries() diff --git a/tests/test_methods.py b/tests/test_methods.py index 711223f..f80ef3d 100644 --- a/tests/test_methods.py +++ b/tests/test_methods.py @@ -1,9 +1,10 @@ import datetime -import nose -import traces -import pandas as pd + import numpy as np +import pandas as pd +import pytest +import traces key_list = [ datetime.datetime(2012, 1, 7), @@ -14,21 +15,21 @@ numeric_types = { int: [1, 2, 3, 0], float: [1.0, 2.0, 3.0, 0.0], - bool: [True, False, True, False] + bool: [True, False, True, False], } non_numeric_hashable_types = { - str: ['a', 'b', 'c', ''], - tuple: [('a', 1), ('b', 2), ('c', 3), ()], + str: ["a", "b", "c", ""], + tuple: [("a", 1), ("b", 2), ("c", 3), ()], } unhashable_types = { list: [[1, 1], [2, 2], [3, 3], []], - dict: [{'a': 1}, {'b': 2}, {'c': 3}, {}], + dict: [{"a": 1}, {"b": 2}, {"c": 3}, {}], set: [{1}, {1, 2}, {1, 2, 3}, set()], } all_types = dict( - list(numeric_types.items()) + - list(non_numeric_hashable_types.items()) + - list(unhashable_types.items()) + list(numeric_types.items()) + + list(non_numeric_hashable_types.items()) + + list(unhashable_types.items()) ) @@ -46,7 +47,6 @@ def frange(x, y, jump): def test_mean(): - # numeric hashable types should work for type_, value_list in numeric_types.items(): ts = _make_ts(type_, key_list, value_list) @@ -58,51 +58,43 @@ def test_mean(): for type_, value_list in non_numeric_hashable_types.items(): ts = _make_ts(type_, key_list, value_list) ts.distribution(key_list[0], key_list[-1]) - nose.tools.assert_raises(TypeError, ts.mean, key_list[0], key_list[1]) + pytest.raises(TypeError, ts.mean, key_list[0], key_list[1]) # non-numeric unhashable types should raise error on distribution # and mean for type_, value_list in unhashable_types.items(): ts = _make_ts(type_, key_list, value_list) - nose.tools.assert_raises(TypeError, ts.distribution, - key_list[0], key_list[1]) - nose.tools.assert_raises(TypeError, ts.mean, - key_list[0], key_list[1]) + pytest.raises(TypeError, ts.distribution, key_list[0], key_list[1]) + pytest.raises(TypeError, ts.mean, key_list[0], key_list[1]) def test_mean_interpolate(): - ts = traces.TimeSeries() ts[0] = 0 ts[1] = 0 ts[3] = 20 - nose.tools.assert_almost_equal( - ts.mean(0, 2, interpolate='linear'), - 2.5, - ) - assert ts.mean(0, 2, interpolate='linear') == 2.5 + assert ts.mean(0, 2, interpolate="linear") == pytest.approx(2.5) + assert ts.mean(0, 2, interpolate="linear") == 2.5 mask = traces.TimeSeries(default=False) mask[0] = True mask[0.5] = False mask[1] = True mask[3] = False - nose.tools.assert_almost_equal( - ts.mean(0, 2, mask=mask, interpolate='linear'), - 10/3.0, - ) - nose.tools.assert_almost_equal( - ts.mean(0, 3, mask=mask, interpolate='linear'), - 8.0, + + assert ts.mean(0, 2, mask=mask, interpolate="linear") == pytest.approx( + 10 / 3.0 ) + assert ts.mean(0, 3, mask=mask, interpolate="linear") == pytest.approx(8.0) + def test_sample(): time_list = [ datetime.datetime(2016, 1, 1, 1, 1, 2), datetime.datetime(2016, 1, 1, 1, 1, 3), datetime.datetime(2016, 1, 1, 1, 1, 8), - datetime.datetime(2016, 1, 1, 1, 1, 10) + datetime.datetime(2016, 1, 1, 1, 1, 10), ] ts = _make_ts(int, time_list, [1, 2, 3, 0]) @@ -111,37 +103,39 @@ def curr_time(i): # Check first arguments assert dict(ts.sample(1, time_list[0], time_list[-1])) == { - curr_time(i): ts[curr_time(i)] for i in range(2, 11)} + curr_time(i): ts[curr_time(i)] for i in range(2, 11) + } assert dict(ts.sample(2, time_list[0], time_list[-1])) == { - curr_time(i): ts[curr_time(i)] for i in range(2, 11, 2)} + curr_time(i): ts[curr_time(i)] for i in range(2, 11, 2) + } - nose.tools.assert_raises( - ValueError, ts.sample, -1, time_list[0], time_list[-1]) - nose.tools.assert_raises(ValueError, ts.sample, - 20, time_list[0], time_list[-1]) + pytest.raises(ValueError, ts.sample, -1, time_list[0], time_list[-1]) + pytest.raises(ValueError, ts.sample, 20, time_list[0], time_list[-1]) # Check second and third arguments - nose.tools.assert_raises(ValueError, ts.sample, - 1, time_list[3], time_list[0]) + pytest.raises(ValueError, ts.sample, 1, time_list[3], time_list[0]) assert dict(ts.sample(1, curr_time(5), curr_time(10))) == { - curr_time(i): ts[curr_time(i)] for i in range(5, 11)} + curr_time(i): ts[curr_time(i)] for i in range(5, 11) + } assert dict(ts.sample(1, curr_time(2), curr_time(5))) == { - curr_time(i): ts[curr_time(i)] for i in range(2, 6)} + curr_time(i): ts[curr_time(i)] for i in range(2, 6) + } assert dict(ts.sample(1, curr_time(0), curr_time(13))) == { - curr_time(i): ts[curr_time(i)] for i in range(0, 14)} + curr_time(i): ts[curr_time(i)] for i in range(0, 14) + } # Check using int ts = traces.TimeSeries([[1, 2], [2, 3], [6, 1], [8, 4]]) - assert dict(ts.sample(1, 1, 8)) == { - i: ts[i] for i in range(1, 9)} + assert dict(ts.sample(1, 1, 8)) == {i: ts[i] for i in range(1, 9)} assert dict(ts.sample(0.5, 1, 8)) == { - 1 + i / 2.: ts[1 + i / 2.] for i in range(0, 15)} - nose.tools.assert_raises(ValueError, ts.sample, 0.5, -traces.inf, 8) - nose.tools.assert_raises(ValueError, ts.sample, 0.5, 1, traces.inf) + 1 + i / 2.0: ts[1 + i / 2.0] for i in range(0, 15) + } + pytest.raises(ValueError, ts.sample, 0.5, -traces.inf, 8) + pytest.raises(ValueError, ts.sample, 0.5, 1, traces.inf) # Test pandas compatibility pd_ts = pd.Series(dict(ts.sample(1, 1, 8))) @@ -154,7 +148,7 @@ def test_moving_average(): datetime.datetime(2016, 1, 1, 1, 1, 2), datetime.datetime(2016, 1, 1, 1, 1, 3), datetime.datetime(2016, 1, 1, 1, 1, 8), - datetime.datetime(2016, 1, 1, 1, 1, 10) + datetime.datetime(2016, 1, 1, 1, 1, 10), ] ts = _make_ts(int, time_list, [1, 2, 3, 0]) @@ -168,10 +162,10 @@ def build_answer(step, interval): try: answer[t] = ts.mean(t - step, t + step) except TypeError as e: - if 'NoneType' in str(e): + if "NoneType" in str(e): answer[t] = None else: - raise e + raise return answer # Check first arguments @@ -180,63 +174,51 @@ def build_answer(step, interval): sampling_period=1, window_size=2, start=time_list[0], - end=time_list[-1] - )) + end=time_list[-1], + ) + ) assert output == build_answer(datetime.timedelta(seconds=1), (2, 11)) output = dict(ts.moving_average(1, 0.2, time_list[0], time_list[-1])) - assert output == build_answer( - datetime.timedelta(seconds=0.1), (2, 11) - ) + assert output == build_answer(datetime.timedelta(seconds=0.1), (2, 11)) - nose.tools.assert_raises( - ValueError, ts.moving_average, 1, -1, time_list[0], time_list[-1]) + pytest.raises( + ValueError, ts.moving_average, 1, -1, time_list[0], time_list[-1] + ) # Check second arguments output = dict(ts.moving_average(2, 1, time_list[0], time_list[-1])) - assert output == build_answer( - datetime.timedelta(seconds=.5), (2, 11, 2)) + assert output == build_answer(datetime.timedelta(seconds=0.5), (2, 11, 2)) - nose.tools.assert_raises( - ValueError, - ts.moving_average, - -1, 1, time_list[0], time_list[-1] + pytest.raises( + ValueError, ts.moving_average, -1, 1, time_list[0], time_list[-1] ) - nose.tools.assert_raises( - ValueError, - ts.moving_average, - 20, 1, time_list[0], time_list[-1] + pytest.raises( + ValueError, ts.moving_average, 20, 1, time_list[0], time_list[-1] ) # Check third and fourth arguments - nose.tools.assert_raises( - ValueError, - ts.moving_average, - 1, 1, time_list[3], time_list[0] + pytest.raises( + ValueError, ts.moving_average, 1, 1, time_list[3], time_list[0] ) output = dict(ts.moving_average(1, 2, curr_time(5), curr_time(10))) - assert output == build_answer( - datetime.timedelta(seconds=1), (5, 11) - ) + assert output == build_answer(datetime.timedelta(seconds=1), (5, 11)) output = dict(ts.moving_average(1, 2, curr_time(2), curr_time(5))) - assert output == build_answer( - datetime.timedelta(seconds=1), (2, 6) - ) + assert output == build_answer(datetime.timedelta(seconds=1), (2, 6)) output = dict(ts.moving_average(1, 2, curr_time(0), curr_time(13))) - assert output == build_answer( - datetime.timedelta(seconds=1), (0, 14) - ) + assert output == build_answer(datetime.timedelta(seconds=1), (0, 14)) # Check using int ts = traces.TimeSeries([[1, 2], [2, 3], [6, 1], [8, 4]]) assert dict(ts.moving_average(1, 2, 2, 8)) == { - i: ts.mean(i - 1, i + 1) for i in range(2, 9)} + i: ts.mean(i - 1, i + 1) for i in range(2, 9) + } assert dict(ts.moving_average(0.5, 2, 2, 8)) == { - 1 + i / 2.: ts.mean(1 + i / 2. - 1, 1 + i / 2. + 1) + 1 + i / 2.0: ts.mean(1 + i / 2.0 - 1, 1 + i / 2.0 + 1) for i in range(2, 15) } @@ -244,22 +226,20 @@ def build_answer(step, interval): pd_ts = pd.Series(dict(ts.moving_average(1, 2, 0, 8))) assert all(pd_ts.index[i] == i for i in range(1, 9)) assert np.isnan(pd_ts.values[0]) - assert all(pd_ts.values[i] == ts.mean(i - 1, i + 1) - for i in range(2, 9)) + assert all(pd_ts.values[i] == ts.mean(i - 1, i + 1) for i in range(2, 9)) # Test using timedelta as sampling_period ts = _make_ts(int, time_list, [1, 2, 3, 0]) sampling_period = datetime.timedelta(seconds=1) output = dict(ts.moving_average(sampling_period)) - answer = build_answer(datetime.timedelta(seconds=1), (2, 11)) + build_answer(datetime.timedelta(seconds=1), (2, 11)) assert output == build_answer(datetime.timedelta(seconds=1), (2, 11)) def test_to_bool(): - answer = {} for type_, value_list in all_types.items(): - answer[type_] = [True if i else False for i in value_list] + answer[type_] = [bool(i) for i in value_list] # numeric hashable types should work for type_, value_list in all_types.items(): @@ -270,7 +250,6 @@ def test_to_bool(): def test_get_item_by_index(): - ts = traces.TimeSeries(default=0) ts[0] = 1 ts[2] = 3 @@ -291,23 +270,23 @@ def test_bin(): end = datetime.datetime(2019, 2, 3, 8, 45, 10) # make a timeseries - span = end-start + span = end - start ts = traces.TimeSeries() - ts[start-span/2] = 2 + ts[start - span / 2] = 2 ts[start] = 12 - ts[start+span/3] = 5 - ts[end - span/4] = 14 - ts[end+span] = None - # nose.tools.assert_raises(KeyError, ts.bin, 'days') + ts[start + span / 3] = 5 + ts[end - span / 4] = 14 + ts[end + span] = None + # pytest.raises(KeyError, ts.bin, 'days') # make a mask mask = traces.TimeSeries(default=False) mask[start] = True mask[end] = False - mask[start + 3*span/10] = False - mask[start + 5*span/10] = True + mask[start + 3 * span / 10] = False + mask[start + 5 * span / 10] = True - binned = ts.bin('weeks', mask=mask) + binned = ts.bin("weeks", mask=mask) first = binned.peekitem(0) last = binned.peekitem() @@ -322,7 +301,6 @@ def test_rebin(): def test_npoints(): - ts = traces.TimeSeries() ts[0] = 4 ts[1] = 2 @@ -330,33 +308,40 @@ def test_npoints(): ts[5] = 2 ts[8] = 4 - nose.tools.eq_(ts.n_points(), 5) - nose.tools.eq_( - ts.n_points(start=0, end=8, include_start=False, include_end=False), 3) - nose.tools.eq_( - ts.n_points(start=0, end=8, include_start=False, include_end=True), 4) - nose.tools.eq_( - ts.n_points(start=0, end=8, include_start=True, include_end=False), 4) - nose.tools.eq_( - ts.n_points(start=0, end=8, include_start=True, include_end=True), 5) - nose.tools.eq_( - ts.n_points(start=1, end=8, include_start=False, include_end=False), 2) - nose.tools.eq_( - ts.n_points(start=1, end=8, include_start=False, include_end=True), 3) - nose.tools.eq_( - ts.n_points(start=1, end=8, include_start=True, include_end=False), 3) - nose.tools.eq_( - ts.n_points(start=1, end=8, include_start=True, include_end=True), 4) + assert ts.n_points() == 5 + assert ( + ts.n_points(start=0, end=8, include_start=False, include_end=False) == 3 + ) + assert ( + ts.n_points(start=0, end=8, include_start=False, include_end=True) == 4 + ) + assert ( + ts.n_points(start=0, end=8, include_start=True, include_end=False) == 4 + ) + assert ( + ts.n_points(start=0, end=8, include_start=True, include_end=True) == 5 + ) + assert ( + ts.n_points(start=1, end=8, include_start=False, include_end=False) == 2 + ) + assert ( + ts.n_points(start=1, end=8, include_start=False, include_end=True) == 3 + ) + assert ( + ts.n_points(start=1, end=8, include_start=True, include_end=False) == 3 + ) + assert ( + ts.n_points(start=1, end=8, include_start=True, include_end=True) == 4 + ) ts = traces.TimeSeries() - nose.tools.eq_(ts.n_points(), 0) - nose.tools.eq_(ts.n_points(include_start=False), 0) - nose.tools.eq_(ts.n_points(include_end=False), 0) + assert ts.n_points() == 0 + assert ts.n_points(include_start=False) == 0 + assert ts.n_points(include_end=False) == 0 def test_radd(): - ts1 = traces.TimeSeries(default=0) ts1[0] = 1 ts1[2] = 0 @@ -371,9 +356,22 @@ def test_radd(): ts3 = ts1 + ts2 - nose.tools.eq_( - list(ts3.items()), - [(-1, 1), (0, 2), (2, 0), (3, 2), (4, 0)] - ) + assert list(ts3.items()) == [(-1, 1), (0, 2), (2, 0), (3, 2), (4, 0)] + + pytest.raises(TypeError, ts3.__radd__, 1) + + +def test_repr(): + import datetime + + import traces + + ts = traces.TimeSeries() + t = datetime.date(2000, 1, 1) + for i in range(1000): + ts[t] = i + t += datetime.timedelta(days=i) + + assert "<..." not in repr(ts) - nose.tools.assert_raises(TypeError, ts3.__radd__, 1) + assert "<..." in str(ts) diff --git a/tests/test_missing.py b/tests/test_missing.py index 8bd0c81..a019d26 100644 --- a/tests/test_missing.py +++ b/tests/test_missing.py @@ -1,23 +1,19 @@ -import nose import traces -import unittest # @unittest.skip("not fully fleshed out yet") def test_missing(): """example code for dealing with missing datapoints""" - router_a = traces.TimeSeries([ - (-10, 0), (-7, 1), (-5, None), (0, 3), (1, 3), (5, None) - ]) + router_a = traces.TimeSeries( + [(-10, 0), (-7, 1), (-5, None), (0, 3), (1, 3), (5, None)] + ) assert router_a[-6] == 1 assert router_a[-15] is None assert not router_a[15] - router_b = traces.TimeSeries([ - (-8, 0), (-5, 0), (-2, 1), (5, 3) - ], default=0) + router_b = traces.TimeSeries([(-8, 0), (-5, 0), (-2, 1), (5, 3)], default=0) assert router_b[7] == 3 @@ -26,7 +22,7 @@ def test_missing(): for timestamp in [-10, -1, 10]: if timestamp < router_b.first_key(): router_b.default = None - for start, end, value in router_b.iterperiods(): + for start, end, _value in router_b.iterperiods(): if timestamp >= start and timestamp < end: router_b[timestamp] = None if timestamp >= router_b.last_key(): @@ -42,8 +38,7 @@ def test_missing(): # the default here should be the element returned by `count_merge([])` clients = traces.TimeSeries.merge( - router_list, - operation=traces.operations.strict_sum + router_list, operation=traces.operations.strict_sum ) assert clients[-15] is None assert clients[-6] == 1 @@ -57,8 +52,7 @@ def test_missing(): assert system_uptime[-1] is False clients = traces.TimeSeries.merge( - router_list, - operation=traces.operations.ignorant_sum + router_list, operation=traces.operations.ignorant_sum ) assert clients[-15] == 0 assert clients[-6] == 1 diff --git a/tests/test_operations.py b/tests/test_operations.py index 3a962bf..471f8d4 100644 --- a/tests/test_operations.py +++ b/tests/test_operations.py @@ -1,7 +1,9 @@ import datetime -import nose + +import pytest + from traces import TimeSeries -from traces.decorators import ignorant, strict +from traces.decorators import ignorant def test_scalar_ops(): @@ -40,7 +42,6 @@ def test_scalar_ops(): def test_sum(): - a = TimeSeries() a.set(datetime.datetime(2015, 3, 1), 1) a.set(datetime.datetime(2015, 3, 2), 0) @@ -83,171 +84,19 @@ def test_sum(): assert 0 + a + b == a + b -def example_dictlike(): - - # test overwriting keys - ts = TimeSeries() - ts[datetime.datetime(2010, 1, 1)] = 5 - ts[datetime.datetime(2010, 1, 2)] = 4 - ts[datetime.datetime(2010, 1, 3)] = 3 - ts[datetime.datetime(2010, 1, 7)] = 2 - ts[datetime.datetime(2010, 1, 4)] = 1 - ts[datetime.datetime(2010, 1, 4)] = 10 - ts[datetime.datetime(2010, 1, 4)] = 5 - ts[datetime.datetime(2010, 1, 1)] = 1 - ts[datetime.datetime(2010, 1, 7)] = 1.2 - ts[datetime.datetime(2010, 1, 8)] = 1.3 - ts[datetime.datetime(2010, 1, 12)] = 1.3 - - # do some wackiness with a bunch of points - dt = datetime.datetime(2010, 1, 12) - for i in range(1000): - dt += datetime.timedelta(hours=random.random()) - ts[dt] = math.sin(i / float(math.pi)) - - dt -= datetime.timedelta(hours=500) - dt -= datetime.timedelta(minutes=30) - for i in range(1000): - dt += datetime.timedelta(hours=random.random()) - ts[dt] = math.cos(i / float(math.pi)) - - # output the time series - for i, j in ts: - print(i.isoformat(), j) - - -def example_mean(): - - ts = TimeSeries() - ts[datetime.datetime(2010, 1, 1)] = 0 - ts[datetime.datetime(2010, 1, 3, 10)] = 1 - ts[datetime.datetime(2010, 1, 5)] = 0 - ts[datetime.datetime(2010, 1, 8)] = 1 - ts[datetime.datetime(2010, 1, 17)] = 0 - ts[datetime.datetime(2010, 1, 19)] = 1 - ts[datetime.datetime(2010, 1, 23)] = 0 - ts[datetime.datetime(2010, 1, 26)] = 1 - ts[datetime.datetime(2010, 1, 28)] = 0 - ts[datetime.datetime(2010, 1, 31)] = 1 - ts[datetime.datetime(2010, 2, 5)] = 0 - - for time, value in ts: - print(time.isoformat(), 0.1 * value + 1.1) - - print('') - - timestep = {'hours': 25} - start = datetime.datetime(2010, 1, 1) - while start <= datetime.datetime(2010, 2, 5): - end = start + datetime.timedelta(**timestep) - print(start.isoformat(), ts.mean(start, end)) - start = end - - print('') - - start = datetime.datetime(2010, 1, 1) - while start <= datetime.datetime(2010, 2, 5): - end = start + datetime.timedelta(**timestep) - print(start.isoformat(), -0.2) - print(start.isoformat(), 1.2) - start = end - - -def example_arrow(): - - ts = TimeSeries() - ts[arrow.Arrow(2010, 1, 1)] = 0 - ts[arrow.Arrow(2010, 1, 3, 10)] = 1 - ts[arrow.Arrow(2010, 1, 5)] = 0 - ts[arrow.Arrow(2010, 1, 8)] = 1 - ts[arrow.Arrow(2010, 1, 17)] = 0 - ts[arrow.Arrow(2010, 1, 19)] = 1 - ts[arrow.Arrow(2010, 1, 23)] = 0 - ts[arrow.Arrow(2010, 1, 26)] = 1 - ts[arrow.Arrow(2010, 1, 28)] = 0 - ts[arrow.Arrow(2010, 1, 31)] = 1 - ts[arrow.Arrow(2010, 2, 5)] = 0 - - for time, value in ts: - print(time.naive.isoformat(), 0.1 * value + 1.1) - - print('') - - start = arrow.Arrow(2010, 1, 1) - end = arrow.Arrow(2010, 2, 5) - unit = {'hours': 25} - for start, end in span_range(start, end, unit): - print(start.naive.isoformat(), ts.mean(start, end)) - - print('') - - for start, end in span_range(start, end, unit): - print(start.naive.isoformat(), -0.2) - print(start.naive.isoformat(), 1.2) - - -def example_sum(): - - a = TimeSeries() - a.set(datetime.datetime(2015, 3, 1), 1) - a.set(datetime.datetime(2015, 3, 2), 0) - a.set(datetime.datetime(2015, 3, 3), 1) - a.set(datetime.datetime(2015, 3, 5), 0) - a.set(datetime.datetime(2015, 3, 6), 0) - - b = TimeSeries() - b.set(datetime.datetime(2015, 3, 1), 0) - b.set(datetime.datetime(2015, 3, 2, 12), 1) - b.set(datetime.datetime(2015, 3, 3, 13, 13), 0) - b.set(datetime.datetime(2015, 3, 4), 1) - b.set(datetime.datetime(2015, 3, 5), 0) - b.set(datetime.datetime(2015, 3, 5, 12), 1) - b.set(datetime.datetime(2015, 3, 5, 19), 0) - - c = TimeSeries() - c.set(datetime.datetime(2015, 3, 1, 17), 0) - c.set(datetime.datetime(2015, 3, 1, 21), 1) - c.set(datetime.datetime(2015, 3, 2, 13, 13), 0) - c.set(datetime.datetime(2015, 3, 4, 18), 1) - c.set(datetime.datetime(2015, 3, 5, 4), 0) - - # output the three time series - for i, ts in enumerate([a, b, c]): - - for (t0, v0), (t1, v1) in ts.iterintervals(1): - print(t0.isoformat(), i) - print(t1.isoformat(), i) - - print('') - - for (t0, v0), (t1, v1) in ts.iterintervals(0): - print(t0.isoformat(), i) - print(t1.isoformat(), i) - - print('') - - # output the sum - # for dt, i in sum([a, b, c]): - # print dt.isoformat(), i - # print '' - for dt, i in TimeSeries.merge([a, b, c], operation=sum): - print(dt.isoformat(), i) - - def test_interpolation(): - ts = TimeSeries(data=[(0, 0), (1, 2)]) - assert ts.get(0, interpolate='linear') == 0 - assert ts.get(0.25, interpolate='linear') == 0.5 - assert ts.get(0.5, interpolate='linear') == 1.0 - assert ts.get(0.75, interpolate='linear') == 1.5 - assert ts.get(1, interpolate='linear') == 2 + assert ts.get(0, interpolate="linear") == 0 + assert ts.get(0.25, interpolate="linear") == 0.5 + assert ts.get(0.5, interpolate="linear") == 1.0 + assert ts.get(0.75, interpolate="linear") == 1.5 + assert ts.get(1, interpolate="linear") == 2 - assert ts.get(-1, interpolate='linear') is None - assert ts.get(2, interpolate='linear') == 2 + assert ts.get(-1, interpolate="linear") is None + assert ts.get(2, interpolate="linear") == 2 - nose.tools.assert_raises(ValueError, ts.get, 0.5, 'spline') + pytest.raises(ValueError, ts.get, 0.5, "spline") def test_default(): @@ -263,9 +112,8 @@ def test_default(): def test_difference(): - a = TimeSeries(data=[(0, 0), (2, 2)], default=0) b = TimeSeries(data=[(1, 1), (3, 2)], default=0) c = a - b - nose.tools.eq_(list(c.items()), [(0, 0), (1, -1), (2, 1), (3, 0)]) + assert list(c.items()) == [(0, 0), (1, -1), (2, 1), (3, 0)] diff --git a/tests/test_plot.py b/tests/test_plot.py index 735de6d..b2e6697 100644 --- a/tests/test_plot.py +++ b/tests/test_plot.py @@ -1,20 +1,21 @@ -import traces import pytest +import traces + + @pytest.mark.mpl_image_compare( - savefig_kwargs={'bbox_inches': 'tight', 'dpi': 300}, + savefig_kwargs={"bbox_inches": "tight", "dpi": 300}, remove_text=True, - style='ggplot', + style="ggplot", tolerance=20, ) def test_plot(): - ts = traces.TimeSeries() ts[0] = 0 ts[1] = 2 ts[3] = 1 ts[5] = 0 - + figure, axes = ts.plot() return figure @@ -25,21 +26,18 @@ def test_optional_import(): def test_invalid_call(): - ts = traces.TimeSeries() ts[0] = 0 ts[1] = 1 - - ts.plot(interpolate='previous') - ts.plot(interpolate='linear') + + ts.plot(interpolate="previous") + ts.plot(interpolate="linear") with pytest.raises(ValueError): - ts.plot(interpolate='yomama') + ts.plot(interpolate="yomama") def test_empty(): - ts = traces.TimeSeries() - + ts.plot() - diff --git a/tests/test_something.py b/tests/test_something.py index 0ae74c1..53a5295 100644 --- a/tests/test_something.py +++ b/tests/test_something.py @@ -1,8 +1,9 @@ +import contextlib + import traces def test_compact(): - # make a v. simple time series ts = traces.TimeSeries() ts[0] = 42 @@ -24,7 +25,6 @@ def test_compact(): def test_remove(): - # v. simple time series ts = traces.TimeSeries() ts[0] = 42 @@ -32,10 +32,8 @@ def test_remove(): # asser that trying to delete a non-existent entry raises a # KeyError - try: + with contextlib.suppress(KeyError): del ts[2] - except KeyError: - pass # now delete the measurement at t=1 del ts[1] @@ -47,7 +45,6 @@ def test_remove(): def test_last_item(): - # v. simple time series ts = traces.TimeSeries() ts[0] = 42 diff --git a/tests/test_traces.py b/tests/test_traces.py index 3372819..64c33ff 100644 --- a/tests/test_traces.py +++ b/tests/test_traces.py @@ -1,10 +1,11 @@ -from datetime import datetime +import csv +import os import pickle -import nose +from datetime import datetime + +import pytest from traces import TimeSeries -import csv -import os def test_init_data(): @@ -41,7 +42,6 @@ def test_init_data(): def test_get(): ts = TimeSeries() - # nose.tools.assert_raises(KeyError, ts.get, 0) assert ts[0] is None ts[1.2] = 1 @@ -54,9 +54,7 @@ def test_get(): def test_exists(): - ts = TimeSeries([ - (-5, 0), (0, 23), (5, None) - ]) + ts = TimeSeries([(-5, 0), (0, 23), (5, None)]) ts_exists = ts.exists() assert ts_exists[-10] is False @@ -110,25 +108,33 @@ def test_set_interval(): tsc = TimeSeries(ts) ts.set_interval(3, 4, 4) - assert list(ts.items()) == [(1.2, 1), (2, 5), - (3, 4), (4, 4), (5, 0), (6, 2)] + assert list(ts.items()) == [ + (1.2, 1), + (2, 5), + (3, 4), + (4, 4), + (5, 0), + (6, 2), + ] tsc.set_interval(3, 4, 4, compact=True) assert list(tsc.items()) == [(1.2, 1), (2, 5), (3, 4), (5, 0), (6, 2)] tsd = TimeSeries() - nose.tools.assert_raises(ValueError, tsd.set_interval, 4, 4, 4) + pytest.raises(ValueError, tsd.set_interval, 4, 4, 4) def test_set_interval_datetime(): ts = TimeSeries(default=400) ts[datetime(2012, 1, 4, 12)] = 5 ts[datetime(2012, 1, 9, 18)] = 10 - ts[datetime(2012, 1, 8):datetime(2012, 1, 10)] = 100 + ts[datetime(2012, 1, 8) : datetime(2012, 1, 10)] = 100 - assert list(ts.items()) == [(datetime(2012, 1, 4, 12, 0), 5), - (datetime(2012, 1, 8, 0, 0), 100), - (datetime(2012, 1, 10, 0, 0), 10)] + assert list(ts.items()) == [ + (datetime(2012, 1, 4, 12, 0), 5), + (datetime(2012, 1, 8, 0, 0), 100), + (datetime(2012, 1, 10, 0, 0), 10), + ] def test_remove_points_from_interval(): @@ -163,7 +169,7 @@ def test_pickle(): ts[1] = True ts[2] = False dump_string = pickle.dumps(ts) - unpickled = pickle.loads(dump_string) + unpickled = pickle.loads(dump_string) # noqa: S301 assert unpickled == ts unpickled[3] = unpickled[1] @@ -180,16 +186,16 @@ def value_parse(value): except ValueError: return None - filename = 'sample.csv' - with open(filename, 'w') as csvfile: + filename = "sample.csv" + with open(filename, "w") as csvfile: writer = csv.writer(csvfile) - writer.writerow(['hour', 'value']) - writer.writerow(['10', '15']) - writer.writerow(['11', '34']) - writer.writerow(['12', '19']) - writer.writerow(['13', 'nan']) - writer.writerow(['14', '18']) - writer.writerow(['15', 'nan']) + writer.writerow(["hour", "value"]) + writer.writerow(["10", "15"]) + writer.writerow(["11", "34"]) + writer.writerow(["12", "19"]) + writer.writerow(["13", "nan"]) + writer.writerow(["14", "18"]) + writer.writerow(["15", "nan"]) ts = TimeSeries.from_csv( filename, @@ -197,7 +203,7 @@ def value_parse(value): time_transform=time_parse, value_column=1, value_transform=value_parse, - default=None + default=None, ) os.remove(filename) @@ -206,22 +212,22 @@ def value_parse(value): assert ts[13.5] is None histogram = ts.distribution() - nose.tools.assert_almost_equal(histogram.mean(), (15 + 34 + 19 + 18) / 4.0) + assert histogram.mean() == pytest.approx((15 + 34 + 19 + 18) / 4.0) - filename = 'sample.csv' - with open(filename, 'w') as csvfile: + filename = "sample.csv" + with open(filename, "w") as csvfile: writer = csv.writer(csvfile) - writer.writerow(['hour', 'value']) - writer.writerow(['2000-01-01 10:00:00', '15']) - writer.writerow(['2000-01-01 11:00:00', '34']) - writer.writerow(['2000-01-01 12:00:00', '19']) - writer.writerow(['2000-01-01 13:00:00', 'nan']) - writer.writerow(['2000-01-01 14:00:00', '18']) - writer.writerow(['2000-01-01 15:00:00', 'nan']) + writer.writerow(["hour", "value"]) + writer.writerow(["2000-01-01 10:00:00", "15"]) + writer.writerow(["2000-01-01 11:00:00", "34"]) + writer.writerow(["2000-01-01 12:00:00", "19"]) + writer.writerow(["2000-01-01 13:00:00", "nan"]) + writer.writerow(["2000-01-01 14:00:00", "18"]) + writer.writerow(["2000-01-01 15:00:00", "nan"]) ts = TimeSeries.from_csv(filename) os.remove(filename) assert ts[datetime(2000, 1, 1, 9)] is None - assert ts[datetime(2000, 1, 1, 10, 30)] == '15' - assert ts[datetime(2000, 1, 1, 20)] == 'nan' + assert ts[datetime(2000, 1, 1, 10, 30)] == "15" + assert ts[datetime(2000, 1, 1, 20)] == "nan" diff --git a/tests/test_utils.py b/tests/test_utils.py index 358e52c..57d107d 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,39 +1,35 @@ -from datetime import timedelta, datetime, date -import nose +from datetime import date, datetime, timedelta + +import pytest from infinity import inf import traces.utils as utils - timedelta_list = [ timedelta(hours=1), timedelta(minutes=2), timedelta(seconds=5), - timedelta(milliseconds=5) + timedelta(milliseconds=5), ] -numeric_types = { - int: [1, 2, 3, 0], - float: [1.0, 2.0, 3.0, 0.0] -} +numeric_types = {int: [1, 2, 3, 0], float: [1.0, 2.0, 3.0, 0.0]} -non_numeric_types = [ - [2], {'a': 4}, (2, 4), 'df', 'a' -] +non_numeric_types = [[2], {"a": 4}, (2, 4), "df", "a"] def test_duration_to_number(): for tdelta in timedelta_list: assert utils.duration_to_number(tdelta) == tdelta.total_seconds() - nose.tools.assert_raises( - NotImplementedError, utils.duration_to_number, tdelta, 'hours') + pytest.raises( + NotImplementedError, utils.duration_to_number, tdelta, "hours" + ) for _type, item in numeric_types.items(): for num in item: assert utils.duration_to_number(num) == num for item in non_numeric_types: - nose.tools.assert_raises(TypeError, utils.duration_to_number, item) + pytest.raises(TypeError, utils.duration_to_number, item) def test_convert_args_to_list(): @@ -51,7 +47,7 @@ def test_convert_args_to_list(): [[[1, 2], [4, 5], [6, 7]]], [[(1, 2), (4, 5), (6, 7)]], [([1, 2], [4, 5], [6, 7])], - [((1, 2), (4, 5), (6, 7))] + [((1, 2), (4, 5), (6, 7))], ] iterable_inputs_answers = [ @@ -68,94 +64,102 @@ def test_convert_args_to_list(): [[1, 2], [4, 5], [6, 7]], [[1, 2], [4, 5], [6, 7]], [[1, 2], [4, 5], [6, 7]], - [[1, 2], [4, 5], [6, 7]] + [[1, 2], [4, 5], [6, 7]], ] for inputs, answers in zip(iterable_inputs, iterable_inputs_answers): assert utils.convert_args_to_list(inputs) == answers - nose.tools.assert_raises(TypeError, utils.convert_args_to_list, [2, 3, 4]) - nose.tools.assert_raises(TypeError, utils.convert_args_to_list, [2]) + pytest.raises(TypeError, utils.convert_args_to_list, [2, 3, 4]) + pytest.raises(TypeError, utils.convert_args_to_list, [2]) def test_datetime_range(): # test default options - dt_range = list(utils.datetime_range( - datetime(2016, 1, 1), datetime(2016, 2, 1), 'days')) + dt_range = list( + utils.datetime_range(datetime(2016, 1, 1), datetime(2016, 2, 1), "days") + ) assert dt_range[0] == datetime(2016, 1, 1) assert dt_range[-1] == datetime(2016, 1, 31) assert dt_range[10] == datetime(2016, 1, 11) # test non-default options - dt_range = list(utils.datetime_range( - datetime(2016, 1, 2), - datetime(2016, 2, 1), - 'days', n_units=2, inclusive_end=True)) + dt_range = list( + utils.datetime_range( + datetime(2016, 1, 2), + datetime(2016, 2, 1), + "days", + n_units=2, + inclusive_end=True, + ) + ) assert dt_range[0] == datetime(2016, 1, 2) assert dt_range[-1] == datetime(2016, 2, 1) assert dt_range[10] == datetime(2016, 1, 22) # test units - dt_range = list(utils.datetime_range( - datetime(2016, 1, 1), datetime(2016, 2, 1), 'hours')) + dt_range = list( + utils.datetime_range( + datetime(2016, 1, 1), datetime(2016, 2, 1), "hours" + ) + ) assert dt_range[1] - dt_range[0] == timedelta(hours=1) - dt_range = list(utils.datetime_range( - datetime(2016, 1, 1), - datetime(2016, 2, 1), - 'minutes', - n_units=10, - )) + dt_range = list( + utils.datetime_range( + datetime(2016, 1, 1), + datetime(2016, 2, 1), + "minutes", + n_units=10, + ) + ) assert dt_range[1] - dt_range[0] == timedelta(minutes=10) # test end < start - dt_range = list(utils.datetime_range( - datetime(2016, 2, 1), datetime(2016, 1, 1), 'days' - )) + dt_range = list( + utils.datetime_range(datetime(2016, 2, 1), datetime(2016, 1, 1), "days") + ) assert dt_range == [] def test_datetime_floor(): # the date here is May 6th, 2016 (week 18) - nose.tools.eq_( - utils.datetime_floor(date(2016, 5, 6), 'years'), - datetime(2016, 1, 1) + assert utils.datetime_floor(date(2016, 5, 6), "years") == datetime( + 2016, 1, 1 ) - nose.tools.eq_(utils.datetime_floor(inf), inf) + + assert utils.datetime_floor(inf) == inf test_dt = datetime(2016, 5, 6, 11, 45, 6) - nose.tools.eq_( - utils.datetime_floor(test_dt, 'months', n_units=3), - datetime(2016, 4, 1) + assert utils.datetime_floor(test_dt, "months", n_units=3) == datetime( + 2016, 4, 1 ) - nose.tools.eq_( - utils.datetime_floor(test_dt, 'weeks', n_units=3), - datetime(2016, 4, 18) - ) - nose.tools.eq_( - utils.datetime_floor(test_dt, 'hours', n_units=10), - datetime(2016, 5, 6, 10) + + assert utils.datetime_floor(test_dt, "weeks", n_units=3) == datetime( + 2016, 4, 18 ) - nose.tools.eq_( - utils.datetime_floor(test_dt, 'minutes', n_units=15), - datetime(2016, 5, 6, 11, 45) + + assert utils.datetime_floor(test_dt, "hours", n_units=10) == datetime( + 2016, 5, 6, 10 ) - nose.tools.eq_( - utils.datetime_floor(test_dt, 'seconds', n_units=30), - datetime(2016, 5, 6, 11, 45) + + assert utils.datetime_floor(test_dt, "minutes", n_units=15) == datetime( + 2016, 5, 6, 11, 45 ) - nose.tools.assert_raises( - ValueError, utils.datetime_floor, "2016-6-7" + + assert utils.datetime_floor(test_dt, "seconds", n_units=30) == datetime( + 2016, 5, 6, 11, 45 ) - nose.tools.assert_raises( - ValueError, utils.datetime_floor, - test_dt, 'sleconds', n_units=3 + + pytest.raises(ValueError, utils.datetime_floor, "2016-6-7") + pytest.raises( + ValueError, utils.datetime_floor, test_dt, "sleconds", n_units=3 ) def test_weekday_number(): assert utils.weekday_number(5) == 5 - nose.tools.assert_raises(ValueError, utils.weekday_number, 7) + pytest.raises(ValueError, utils.weekday_number, 7) print(utils.weekday_number("Tuesday")) assert utils.weekday_number("Tuesday") == 1 - nose.tools.assert_raises(ValueError, utils.weekday_number, 'Mooday') + pytest.raises(ValueError, utils.weekday_number, "Mooday") diff --git a/tox.ini b/tox.ini index 5630c12..8e1de18 100644 --- a/tox.ini +++ b/tox.ini @@ -1,20 +1,19 @@ [tox] -envlist = py36, py37, py38, pycodestyle skipsdist = true +envlist = py38, py39, py310, py311, py312 -[testenv:pycodestyle] -basepython=python -deps=pycodestyle -commands=pycodestyle traces +[gh-actions] +python = + 3.8: py38 + 3.9: py39 + 3.10: py310 + 3.11: py311 + 3.12: py312 [testenv] -setenv = - PYTHONPATH = {toxinidir}:{toxinidir}/traces -deps = - -r{toxinidir}/requirements/python-test.txt -commands = python setup.py test - -; If you want to make tox run the tests with the same versions, create a -; requirements.txt with the pinned versions and uncomment the following lines: -; deps = -; -r{toxinidir}/requirements.txt +passenv = PYTHON_VERSION +allowlist_externals = poetry +commands = + poetry install -v + pytest --doctest-modules tests --cov --cov-config=pyproject.toml --cov-report=xml + # mypy diff --git a/traces/__init__.py b/traces/__init__.py index 0195f1f..86823e3 100644 --- a/traces/__init__.py +++ b/traces/__init__.py @@ -1,12 +1,12 @@ -# -*- coding: utf-8 -*- - from infinity import inf + from traces import decorators, operations +from .eventseries import EventSeries from .histogram import Histogram from .timeseries import TimeSeries from .utils import datetime_range -__author__ = 'Mike Stringer' -__email__ = 'mike.stringer@datascopeanalytics.com' -__version__ = '0.6.0' +__author__ = "Mike Stringer" +__email__ = "mike.stringer@datascopeanalytics.com" +__version__ = "0.6.0" diff --git a/traces/eventseries.py b/traces/eventseries.py new file mode 100644 index 0000000..9efaaeb --- /dev/null +++ b/traces/eventseries.py @@ -0,0 +1,56 @@ +import collections + +import numpy as np +import sortedcontainers + + +class EventSeries(sortedcontainers.SortedList): + def __init__(self, data=None): + super().__init__(data) + + def cumsum(self): + """ + Returns a TimeSeries with each unique time in the EventSeries as an + index point and with the cumulative number of events that have occured + since the earliest time in the EventSeries as the value + """ + from traces import TimeSeries + + # Multiple events can happen at the same time so we need to hash them + # as counts + c = collections.Counter(self) + # Then we want to sort them and calculate the cumsum + c = sortedcontainers.SortedDict(c) + keys = c.keys() + values = np.cumsum(list(c.values())) + + return TimeSeries(zip(keys, values), default=0) + + def events_between(self, start, end): + """ + Returns the number of events that occured between `start and `end. + Calculates on a closed interval, so start and end are included in the + range + """ + start_idx = self.bisect_left(start) + end_idx = self.bisect_right(end) + return end_idx - start_idx + + def time_lag(self): + """ + Returns a `np.array` of inter event arrival times. This will only work + for EventSeries of a type that have a minus operation implemented. + """ + return np.array(self[1:]) - np.array(self[0:-1]) + + @staticmethod + def count_active(es_open, es_closed): + """ + Calculates the running difference from two event series + `es_open` is an EventSeries that adds to the cumulative sum and + `es_closed` is an EventSeries of subtracts from it + + Returns a TimeSeries of the number of open cases at any given time, + assuming 0 open cases at the earliest time in either EventSeries + """ + return es_open.cumsum() - es_closed.cumsum() diff --git a/traces/histogram.py b/traces/histogram.py index 1fedfc2..42bce05 100644 --- a/traces/histogram.py +++ b/traces/histogram.py @@ -21,50 +21,44 @@ def from_dict(cls, in_dict, *args, **kwargs): def __init__(self, data=(), **kwargs): if "key" in kwargs: - super(Histogram, self).__init__(kwargs["key"]) + super().__init__(kwargs["key"]) else: - super(Histogram, self).__init__() + super().__init__() for datum in data: self[datum] += 1 def __getitem__(self, key): try: - result = super(Histogram, self).__getitem__(key) + result = super().__getitem__(key) except KeyError: result = 0 except TypeError as error: - if "unorderable" in str(error): - raise UnorderableElements(error) + raise UnorderableElements(error) from error if "unhashable" in str(error): - msg = "Can't make histogram of unhashable type ({})".format( - type(key) - ) - raise UnhashableType(msg) + msg = f"Can't make histogram of unhashable type ({type(key)})" + raise UnhashableType(msg) from error - raise error + raise return result def __setitem__(self, key, value): try: - result = super(Histogram, self).__setitem__(key, value) + result = super().__setitem__(key, value) except TypeError as error: - if "unorderable" in str(error): - raise UnorderableElements(error) + raise UnorderableElements(error) from error if "not supported between instances of" in str(error): - raise UnorderableElements(error) + raise UnorderableElements(error) from error if "unhashable" in str(error): - msg = "Can't make histogram of unhashable type ({})".format( - type(key) - ) - raise UnhashableType(msg) + msg = f"Can't make histogram of unhashable type ({type(key)})" + raise UnhashableType(msg) from error - raise error + raise return result def total(self): @@ -141,7 +135,7 @@ def min(self, include_zero=False): if value > 0 or include_zero: return key - def _quantile_function(self, alpha=0.5, smallest_count=None): + def _quantile_function(self, alpha=0.5, smallest_count=None): # noqa: C901 """Return a function that returns the quantile values for this histogram. @@ -181,9 +175,8 @@ def _quantile_function(self, alpha=0.5, smallest_count=None): # print '' def function(q): - if q < 0.0 or q > 1.0: - msg = "invalid quantile {}, need `0 <= q <= 1`".format(q) + msg = f"invalid quantile {q}, need `0 <= q <= 1`" raise ValueError(msg) elif q < q_min: q = q_min @@ -228,7 +221,9 @@ def quantiles(self, q_list, alpha=0.5, smallest_count=None): def quantile(self, q, alpha=0.5, smallest_count=None): return self.quantiles( - [q], alpha=alpha, smallest_count=smallest_count, + [q], + alpha=alpha, + smallest_count=smallest_count, )[0] def add(self, other): diff --git a/traces/plot.py b/traces/plot.py index 62ffb76..7a1a939 100644 --- a/traces/plot.py +++ b/traces/plot.py @@ -58,16 +58,15 @@ def plot( aspect_ratio=None, font=None, ): - try: import matplotlib.pyplot as plt from matplotlib import font_manager - except ImportError: + except ImportError as error: msg = "need to install matplotlib for `plot` function" - raise ImportError(msg) + raise ImportError(msg) from error if font is None: - available_fonts = set(f.name for f in font_manager.fontManager.ttflist) + available_fonts = {f.name for f in font_manager.fontManager.ttflist} for font in FONTS: if font in available_fonts: break @@ -84,14 +83,14 @@ def plot( try: drawstyle = INTERPOLATE_DRAWSTYLE[interpolate] - except KeyError: - raise ValueError(( - "invalid value for interpolate='{}', " - "must be in {}" - ).format(interpolate, set(INTERPOLATE_DRAWSTYLE.keys()))) + except KeyError as error: + msg = ( + f"invalid value for interpolate='{interpolate}', " + f"must be in {set(INTERPOLATE_DRAWSTYLE.keys())}" + ) + raise ValueError(msg) from error with plt.style.context(PLOT_STYLE): - figure, axes = plt.subplots( figsize=(figure_width, aspect_ratio * figure_width), ) @@ -102,7 +101,7 @@ def plot( else: x, y = [], [] - plot = axes.plot( + axes.plot( x, y, linewidth=linewidth, diff --git a/traces/timeseries.py b/traces/timeseries.py index 356b8d2..f84dd11 100644 --- a/traces/timeseries.py +++ b/traces/timeseries.py @@ -4,20 +4,21 @@ http://en.wikipedia.org/wiki/Unevenly_spaced_time_series """ + +import contextlib import csv import datetime import itertools -import pprint from queue import PriorityQueue import sortedcontainers from dateutil.parser import parse as date_parse from infinity import inf -from . import histogram, operations, utils, plot +from . import histogram, operations, plot, utils -class TimeSeries(object): +class TimeSeries: """A class to help manipulate and analyze time series that are the result of taking measurements at irregular points in time. For example, here would be a simple time series that starts at 8am and @@ -112,24 +113,23 @@ def _get_previous(self, time): return self.default else: msg = ( - "self._d.bisect_right({}) returned a negative value. " + f"self._d.bisect_right({time}) returned a negative value. " """This "can't" happen: please file an issue at """ "https://github.com/datascopeanalytics/traces/issues" - ).format(time) + ) raise ValueError(msg) def get(self, time, interpolate="previous"): - """Get the value of the time series, even in-between measured values. - - """ + """Get the value of the time series, even in-between measured values.""" try: getter = self.getter_functions[interpolate] - except KeyError: + except KeyError as error: + getter_string = ", ".join(self.getter_functions) msg = ( - "unknown value '{}' for interpolate, " - "valid values are in [{}]" - ).format(interpolate, ", ".join(self.getter_functions)) - raise ValueError(msg) + f"unknown value '{interpolate}' for interpolate, " + f"valid values are in [{getter_string}]" + ) + raise ValueError(msg) from error else: return getter(time) @@ -180,7 +180,7 @@ def set_interval(self, start, end, value, compact=False): """ # for each interval to render - for i, (s, e, v) in enumerate(self.iterperiods(start, end)): + for i, (s, _e, v) in enumerate(self.iterperiods(start, end)): # noqa: B007 # look at all intervals included in the current interval # (always at least 1) if i == 0: @@ -216,9 +216,9 @@ def exists(self): otherwise """ - result = TimeSeries(default=False if self.default is None else True) + result = TimeSeries(default=self.default is not None) for t, v in self: - result[t] = False if v is None else True + result[t] = v is not None return result def remove(self, time): @@ -228,19 +228,18 @@ def remove(self, time): """ try: del self._d[time] - except KeyError: - raise KeyError("no measurement at {}".format(time)) + except KeyError as error: + msg = f"no measurement at {time}" + raise KeyError(msg) from error def remove_points_from_interval(self, start, end): """Allow removal of all points from the time series within a interval [start:end]. """ - for s, e, v in self.iterperiods(start, end): - try: + for s, _e, _v in self.iterperiods(start, end): + with contextlib.suppress(KeyError): del self._d[s] - except KeyError: - pass def n_measurements(self): """Return the number of measurements in the time series.""" @@ -251,7 +250,39 @@ def __len__(self): return self.n_measurements() def __repr__(self): - return "\n%s\n" % pprint.pformat(self._d) + """A detailed string representation for debugging.""" + + def format_item(item): + return "{!r}: {!r}".format(*item) + + return "{name}({{{items}}})".format( + name=type(self).__name__, + items=", ".join(format_item(_) for _ in self._d.items()), + ) + + def __str__(self): + """A human-readable string representation (truncated if it gets too + long). + + """ + + def format_item(item): + return "{!s}: {!s}".format(*item) + + MAX_LENGTH = 20 + half = MAX_LENGTH // 2 + if len(self) > MAX_LENGTH: + one = ", ".join(format_item(_) for _ in self._d.items()[:half]) + two = ", ".join(format_item(_) for _ in self._d.items()[half:-half]) + three = ", ".join(format_item(_) for _ in self._d.items()[-half:]) + truncate_string = f"<...{len(self) - MAX_LENGTH} items...>" + if len(truncate_string) < len(two): + two = truncate_string + items = ", ".join([one, two, three]) + else: + items = ", ".join(format_item(_) for _ in self._d.items()) + + return f"{type(self).__name__}({{{items}}})" def iterintervals(self, n=2): """Iterate over groups of `n` consecutive measurement points in the @@ -275,12 +306,10 @@ def iterintervals(self, n=2): # now, zip the offset streams back together to yield tuples, # in the n=3 example it would yield: # (a, b, c), (b, c, d), ..., (w, x, y), (x, y, z) - for intervals in zip(*streams): - yield intervals + yield from zip(*streams) @staticmethod def _value_function(value): - # if value is None, don't filter if value is None: @@ -327,7 +356,6 @@ def iterperiods(self, start=None, end=None, value=None): interval_t0, interval_value = start, start_value for interval_t1 in self._d.islice(start_index, end_index): - if value_function(interval_t0, interval_t1, interval_value): yield interval_t0, interval_t1, interval_value @@ -337,9 +365,10 @@ def iterperiods(self, start=None, end=None, value=None): interval_value = self[interval_t0] # yield the time, duration, and value of the final period - if interval_t0 < end: - if value_function(interval_t0, end, interval_value): - yield interval_t0, end, interval_value + if interval_t0 < end and value_function( + interval_t0, end, interval_value + ): + yield interval_t0, end, interval_value def slice(self, start, end): """Return an equivalent TimeSeries that only has points between @@ -351,7 +380,7 @@ def slice(self, start, end): ) result = TimeSeries(default=self.default) - for t0, t1, value in self.iterperiods(start, end): + for t0, t1, value in self.iterperiods(start, end): # noqa: B007 result[t0] = value result[t1] = self[t1] @@ -359,10 +388,8 @@ def slice(self, start, end): return result def _check_regularization(self, start, end, sampling_period=None): - # only do these checks if sampling period is given if sampling_period is not None: - # cast to both seconds and timedelta for error checking if isinstance(sampling_period, datetime.timedelta): sampling_period_seconds = sampling_period.total_seconds() @@ -385,19 +412,18 @@ def _check_regularization(self, start, end, sampling_period=None): ) raise ValueError(msg) - if isinstance(start, datetime.date): - sampling_period = sampling_period_timedelta - else: - sampling_period = sampling_period_seconds + sampling_period = ( + sampling_period_timedelta + if isinstance(start, datetime.date) + else sampling_period_seconds + ) return sampling_period def sample( self, sampling_period, start=None, end=None, interpolate="previous" ): - """Sampling at regular time periods. - - """ + """Sampling at regular time periods.""" start, end, mask = self._check_boundaries(start, end) sampling_period = self._check_regularization( @@ -412,7 +438,7 @@ def sample( current_time += sampling_period return result - def moving_average( + def moving_average( # noqa: C901 self, sampling_period, window_size=None, @@ -421,8 +447,7 @@ def moving_average( placement="center", pandas=False, ): - """Averaging over regular intervals - """ + """Averaging over regular intervals""" start, end, mask = self._check_boundaries(start, end) # default to sampling_period if not given @@ -434,7 +459,7 @@ def moving_average( ) # convert to datetime if the times are datetimes - full_window = window_size * 1. + full_window = window_size * 1.0 half_window = full_window / 2 if isinstance(start, datetime.date) and not isinstance( full_window, datetime.timedelta @@ -445,7 +470,6 @@ def moving_average( result = [] current_time = start while current_time <= end: - if placement == "center": window_start = current_time - half_window window_end = current_time + half_window @@ -456,7 +480,7 @@ def moving_average( window_start = current_time - full_window window_end = current_time else: - msg = 'unknown placement "{}"'.format(placement) + msg = f'unknown placement "{placement}"' raise ValueError(msg) # calculate mean over window and add (t, v) tuple to list @@ -466,29 +490,28 @@ def moving_average( if "NoneType" in str(e): mean = None else: - raise e + raise result.append((current_time, mean)) current_time += sampling_period # convert to pandas Series if pandas=True if pandas: - try: import pandas as pd - except ImportError: + except ImportError as error: msg = "can't have pandas=True if pandas is not installed" - raise ImportError(msg) + raise ImportError(msg) from error result = pd.Series( - [v for t, v in result], index=[t for t, v in result], + [v for t, v in result], + index=[t for t, v in result], ) return result @staticmethod def rebin(binned, key_function): - result = sortedcontainers.SortedDict() for bin_start, value in binned.items(): new_bin_start = key_function(bin_start) @@ -509,17 +532,17 @@ def bin( smaller=None, transform="distribution", ): - - # return an empty sorted dictionary if there is no time span if mask is not None and mask.is_empty(): return sortedcontainers.SortedDict() - elif start is not None and start == end: + + if start is not None and start == end: return sortedcontainers.SortedDict() # use smaller if available if smaller: return self.rebin( - smaller, lambda x: utils.datetime_floor(x, unit, n_units), + smaller, + lambda x: utils.datetime_floor(x, unit, n_units), ) start, end, mask = self._check_boundaries(start, end, mask=mask) @@ -593,13 +616,15 @@ def distribution( counter = histogram.Histogram() for i_start, i_end, _ in mask.iterperiods(value=True): for t0, t1, _ in self.iterperiods(i_start, i_end): - duration = utils.duration_to_number(t1 - t0, units="seconds",) + duration = utils.duration_to_number( + t1 - t0, + units="seconds", + ) midpoint = utils.time_midpoint(t0, t1) value = self.get(midpoint, interpolate=interpolate) try: counter[value] += duration except histogram.UnorderableElements: - counter = histogram.Histogram.from_dict( dict(counter), key=hash ) @@ -650,16 +675,17 @@ def n_points( count = 0 for i_start, i_end, _ in mask.iterperiods(value=True): + end_count = ( + self._d.bisect_right(i_end) + if include_end + else self._d.bisect_left(i_end) + ) - if include_end: - end_count = self._d.bisect_right(i_end) - else: - end_count = self._d.bisect_left(i_end) - - if include_start: - start_count = self._d.bisect_left(i_start) - else: - start_count = self._d.bisect_right(i_start) + start_count = ( + self._d.bisect_left(i_start) + if include_start + else self._d.bisect_right(i_start) + ) count += end_count - start_count @@ -674,10 +700,7 @@ def _check_time_series(self, other): """ if not isinstance(other, TimeSeries): - msg = "unsupported operand types(s) for +: %s and %s" % ( - type(self), - type(other), - ) + msg = f"unsupported operand types(s) for +: {type(self)} and {type(other)}" raise TypeError(msg) @staticmethod @@ -709,7 +732,6 @@ def _iter_merge(timeseries_list): # of the default value for each individual TimeSeries. state = [ts.default for ts in timeseries_list] while not queue.empty(): - # get the next time with a measurement from queue t, index, next_value, iterator = queue.get() @@ -779,10 +801,7 @@ def merge(cls, ts_list, compact=True, operation=None): result = cls(default=default) for t, merged in cls.iter_merge(ts_list): - if operation is None: - value = merged - else: - value = operation(merged) + value = merged if operation is None else operation(merged) result.set(t, value, compact=compact) return result @@ -805,7 +824,6 @@ def from_csv( skip_header=True, default=None, ): - # use default on class if not given if time_transform is None: time_transform = cls.csv_time_transform @@ -917,7 +935,8 @@ def __setitem__(self, time, value): def __getitem__(self, time): """Allow a[time] syntax.""" if isinstance(time, slice): - raise ValueError("Syntax a[start:end] not allowed") + msg = "Syntax a[start:end] not allowed" + raise ValueError(msg) # noqa: TRY004 else: return self.get(time) @@ -938,7 +957,7 @@ def __radd__(self, other): """ # skip type check if other is the integer 0 - if not other == 0: + if other != 0: self._check_time_series(other) # 0 + self = self @@ -971,7 +990,6 @@ def __ne__(self, other): return not (self == other) def _check_boundary(self, value, allow_infinite, lower_or_upper): - if lower_or_upper == "lower": infinity_value = -inf method_name = "first_key" @@ -979,8 +997,9 @@ def _check_boundary(self, value, allow_infinite, lower_or_upper): infinity_value = inf method_name = "last_key" else: - msg = '`lower_or_upper` must be "lower" or "upper", got {}'.format( - lower_or_upper, + msg = ( + f'`lower_or_upper` must be "lower" or "upper", ' + f"got {lower_or_upper}" ) raise ValueError(msg) @@ -990,19 +1009,19 @@ def _check_boundary(self, value, allow_infinite, lower_or_upper): else: try: return getattr(self, method_name)() - except IndexError: + except IndexError as error: msg = ( - "can't use '{}' for default {} boundary " - "of empty TimeSeries" - ).format(method_name, lower_or_upper) - raise KeyError(msg) + f"can't use '{method_name}' for default " + f"{lower_or_upper} boundary of empty TimeSeries" + ) + raise KeyError(msg) from error else: return value def _check_boundaries(self, start, end, mask=None, allow_infinite=False): - if mask is not None and mask.is_empty(): - raise ValueError("mask can not be empty") + msg = "mask can not be empty" + raise ValueError(msg) # if only a mask is passed in, return mask boundaries and mask if start is None and end is None and mask is not None: @@ -1013,24 +1032,20 @@ def _check_boundaries(self, start, end, mask=None, allow_infinite=False): end = self._check_boundary(end, allow_infinite, "upper") if start >= end: - msg = "start can't be >= end ({} >= {})".format(start, end) + msg = f"start can't be >= end ({start} >= {end})" raise ValueError(msg) start_end_mask = TimeSeries(default=False) start_end_mask[start] = True start_end_mask[end] = False - if mask is None: - mask = start_end_mask - else: - mask = mask & start_end_mask + mask = start_end_mask if mask is None else mask & start_end_mask return start, end, mask def distribution_by_hour_of_day( self, first=0, last=23, start=None, end=None ): - start, end, mask = self._check_boundaries(start, end) result = [] @@ -1043,7 +1058,6 @@ def distribution_by_hour_of_day( def distribution_by_day_of_week( self, first=0, last=6, start=None, end=None ): - start, end, mask = self._check_boundaries(start, end) result = [] @@ -1074,7 +1088,6 @@ def plot( def hour_of_day(start, end, hour): - # start should be date, or if datetime, will use date of datetime floored = utils.datetime_floor(start) @@ -1093,7 +1106,6 @@ def hour_of_day(start, end, hour): def day_of_week(start, end, weekday): - # allow weekday name or number number = utils.weekday_number(weekday) diff --git a/traces/utils.py b/traces/utils.py index 00bd166..225d59e 100644 --- a/traces/utils.py +++ b/traces/utils.py @@ -1,3 +1,4 @@ +import contextlib import datetime from infinity import inf @@ -65,7 +66,7 @@ def convert_args_to_list(args): if len(args) == 2: list_of_pairs.append(list(args)) else: - msg = "The argument type is invalid. {}".format(args) + msg = f"The argument type is invalid. {args}" raise TypeError(msg) return list_of_pairs @@ -122,12 +123,11 @@ def floor_datetime(dt, unit, n_units=1): dt.year, dt.month, dt.day, dt.hour, dt.minute, new_second ) else: - msg = "Unknown unit type {}".format(unit) + msg = f"Unknown unit type {unit}" raise ValueError(msg) def datetime_floor(value, unit="days", n_units=1): - # if it's a date, convert to datetime at start of day if type(value) is datetime.date: value = datetime.datetime.combine(value, datetime.time()) @@ -139,7 +139,7 @@ def datetime_floor(value, unit="days", n_units=1): elif value == inf: return inf else: - msg = "must be date, datetime, or inf; got {}".format(value) + msg = f"must be date, datetime, or inf; got {value}" raise ValueError(msg) @@ -155,7 +155,6 @@ def datetime_floor(value, unit="days", n_units=1): def weekday_number(value): - if isinstance(value, int): if 0 <= value < 7: return value @@ -168,18 +167,16 @@ def weekday_number(value): if result: return result else: - try: + with contextlib.suppress(TypeError): result = WEEKDAY_LOOKUP.get(value.lower()) - except TypeError: - pass if result: return result - msg = "must be a valid weekday, got {}".format(value) + msg = f"must be a valid weekday, got {value}" raise ValueError(msg) def pairwise(iterable): - """ given an interable `p1, p2, p3, ...` + """given an interable `p1, p2, p3, ...` it iterates through pairwise tuples `(p0, p1), (p1, p2), ...`""" it = iter(iterable) a = next(it, None)