pax_global_header 0000666 0000000 0000000 00000000064 14423450507 0014516 g ustar 00root root 0000000 0000000 52 comment=655524758181d24b15c62126229aebcd056d17fb
AutoPyTabs-0.4.0/ 0000775 0000000 0000000 00000000000 14423450507 0013552 5 ustar 00root root 0000000 0000000 AutoPyTabs-0.4.0/.github/ 0000775 0000000 0000000 00000000000 14423450507 0015112 5 ustar 00root root 0000000 0000000 AutoPyTabs-0.4.0/.github/workflows/ 0000775 0000000 0000000 00000000000 14423450507 0017147 5 ustar 00root root 0000000 0000000 AutoPyTabs-0.4.0/.github/workflows/CI.yml 0000664 0000000 0000000 00000003447 14423450507 0020175 0 ustar 00root root 0000000 0000000 name: CI
on:
pull_request:
push:
branches:
- main
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.11"
- name: Install Pre-Commit
run: python -m pip install pre-commit && pre-commit install
- name: Load cached Pre-Commit Dependencies
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
path: ~/.cache/pre-commit/
key: pre-commit|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }}
- name: Execute Pre-Commit
run: pre-commit run --show-diff-on-failure --color=always --all-files
test:
strategy:
fail-fast: true
matrix:
os:
- "ubuntu-latest"
- "windows-latest"
python-version:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
steps:
- name: Check out repository
uses: actions/checkout@v3
- name: Set up python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install Poetry
uses: snok/install-poetry@v1
with:
virtualenvs-create: true
installer-parallel: true
virtualenvs-in-project: true
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
path: .venv
key: venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }}
- name: Install dependencies
run: poetry install
- name: Run tests
run: |
source $VENV
pytest
AutoPyTabs-0.4.0/.github/workflows/publish.yml 0000664 0000000 0000000 00000001137 14423450507 0021342 0 ustar 00root root 0000000 0000000 name: Publish
on:
workflow_dispatch:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v3
- name: Set up python 3.11
uses: actions/setup-python@v4
with:
python-version: "3.11"
- name: Install poetry
uses: snok/install-poetry@v1
- name: Install dependencies
run: poetry install --no-root --no-dev
- name: build & publish
run: |
poetry config pypi-token.pypi ${{ secrets.PYPI_TOKEN }}
poetry publish --build
AutoPyTabs-0.4.0/.gitignore 0000664 0000000 0000000 00000005324 14423450507 0015546 0 ustar 00root root 0000000 0000000 # 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/
.idea/
/.python-version
/.auto_pytabs_cache/
/.ruff_cache/
/docs_test/
AutoPyTabs-0.4.0/.pre-commit-config.yaml 0000664 0000000 0000000 00000002004 14423450507 0020027 0 ustar 00root root 0000000 0000000 repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
exclude: "_test_data"
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: 'v0.0.260'
hooks:
- id: ruff
args: ["--fix"]
exclude: test/sphinx_ext_test_data/example.py
- repo: https://github.com/executablebooks/mdformat
rev: 0.7.16
hooks:
- id: mdformat
exclude: "_test_data"
args: ["--number"]
additional_dependencies:
- mdformat-gfm
- repo: https://github.com/pre-commit/mirrors-mypy
rev: "v1.1.1"
hooks:
- id: mypy
exclude: "test"
args: ["--strict"]
additional_dependencies:
- types-docutils
- sphinx
- types-markdown
- mkdocs
- pymdown-extensions
AutoPyTabs-0.4.0/LICENSE 0000664 0000000 0000000 00000002055 14423450507 0014561 0 ustar 00root root 0000000 0000000 MIT License
Copyright (c) 2022 provinzkraut
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
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.
AutoPyTabs-0.4.0/README.md 0000664 0000000 0000000 00000033164 14423450507 0015040 0 ustar 00root root 0000000 0000000 # AutoPyTabs
Automatically generate code examples for different Python versions in
[mkdocs](https://www.mkdocs.org) or [Sphinx](https://www.sphinx-doc.org) based documentations, or a plain
[markdown](https://python-markdown.github.io/) workflow, making use of the
[pymdown "tabbed"](https://facelessuser.github.io/pymdown-extensions/extensions/tabbed/) markdown extension for markdown,
and [sphinx{design} tabs](https://sphinx-design.readthedocs.io/en/latest/tabs.html) for Sphinx.
## Rationale
### The problem
Python project documentation typically include code examples. Given that most of the time, a project will support
multiple versions of Python, it would be ideal to showcase the adjustments that can or need to be made for different
Python versions. This can be achieved by including several versions of the example code, conveniently displayed using
the [pymdown "tabbed"](https://facelessuser.github.io/pymdown-extensions/extensions/tabbed/) extension for markdown, or
[sphinx{design} tabs](https://sphinx-design.readthedocs.io/en/latest/tabs.html) for Sphinx.
This, however, raises several problems:
1. Maintaining multiple versions of a single example is tedious and error-prone as they can easily
become out of sync
2. Figuring out which examples need to be changed for which specific Python version is a labour intensive task
3. Dropping or adding support for Python versions requires revisiting every example in the documentation
4. Checking potentially ~4 versions of a single example into VCS creates unnecessary noise
Given those, it's no surprise that the current standard is to only show examples for the lowest supported version of Python.
### The solution
**AutoPyTabs** aims to solve all of these problems by automatically generating versions (using the awsome
[ruff](https://github.com/charliermarsh/ruff) project) of code examples, targeting different Python versions
**at build-time**, based on a base version (the lowest supported Python version).
This means that:
1. There exists only one version of each example: The lowest supported version becomes the source of truth,
therefore preventing out-of-sync examples and reducing maintenance burden
2. Dropping or adding support for Python versions can be done via a simple change in a configuration file
## Table of contents
1. [Usage with mkdocs / markdown](#usage-markdown)
1. [Configuration](#markdown-config)
2. [Differences between the mkdocs plugin vs markdown extension](#differences-between-the-mkdocs-plugin-and-markdown-extension)
3. [Examples](#markdown-examples)
4. [Selectively disable](#selectively-disable)
5. [Compatibility with `pymdownx.snippets`](#compatibility-with-pymdownxsnippets)
2. [Usage with Sphinx](#usage-with-sphinx)
1. [Configuration](#sphinx-config)
2. [Directives](#directives)
3. [Examples](#sphinx-examples)
4. [Compatibility with other extensions](#compatibility-with-other-extensions)
## Installation
For mkdocs: `pip install auto-pytabs[mkdocs]`
For markdown: `pip install auto-pytabs[markdown]`
For sphinx: `pip install auto-pytabs[sphinx]`
Usage with mkdocs / markdown
Configuration
#### Mkdocs plugin
```yaml
site_name: My Docs
markdown_extensions:
- pymdownx.tabbed:
plugins:
- auto_pytabs:
min_version: "3.7" # optional
max_version: "3.11" # optional
tab_title_template: "Python {min_version}+" # optional
no_cache: false # optional
default_tab: "highest" # optional
reverse_order: false # optional
```
*Available configuration options*
| Name | Default | Description |
| -------------------- | ------------------------- | -------------------------------------------------------------------------- |
| `min_version` | `(3, 7)` | Minimum python version |
| `max_version` | `(3, 7)` | Maximum python version |
| `tab_title_template` | `"Python {min_version}+"` | Template for tab titles |
| `no_cache` | `False` | Disable file system caching |
| `default_tab` | `highest` | (`highest` or `lowest`) Version tab to preselect |
| `reverse_order` | `False` | Reverse the order of tabs. Default is to go from lowest to highest version |
#### Markdown extension
```python
import markdown
md = markdown.Markdown(
extensions=["auto_pytabs"],
extension_configs={
"auto_pytabs": {
"min_version": "3.7", # optional
"max_version": "3.11", # optional
"tab_title_template": "Python {min_version}+", # optional
"default_tab": "highest", # optional
"reverse_order": False, # optional
}
},
)
```
*Available configuration options*
| Name | Default | Description |
| -------------------- | ------------------------- | -------------------------------------------------------------------------- |
| `min_version` | `(3, 7)` | Minimum python version to generate code for |
| `max_version` | `(3, 7)` | Maximum python version to generate code for |
| `tab_title_template` | `"Python {min_version}+"` | Template for tab titles |
| `default_tab` | `highest` | (`highest` or `lowest`) Version tab to preselect |
| `reverse_order` | `False` | Reverse the order of tabs. Default is to go from lowest to highest version |
### Differences between the mkdocs plugin and markdown extension
AutoPyTabs ships as a markdown extension and an mkdocs plugin, both of which can be used in mkdocs. The only difference
between them is that the mkdocs plugin supports caching, which can make subsequent builds faster (i.e. when using `mkdocs serve`).
The reason why the markdown extension does not support caching is that `markdown` does not have clearly defined build
steps with wich an extension could interact (like mkdocs [plugin events](https://www.mkdocs.org/dev-guide/plugins/#events)),
making it impossible to know when to persist cached items to disk / evict unused items.
**If you are using mkdocs, the mkdocs plugin is recommended**. If you have caching disabled, there will be no difference either way.
Should you wish to integrate the markdown extension into a build process where you can manually persist the cache after the build,
you can explicitly pass it a cache:
```python
import markdown
from auto_pytabs.core import Cache
cache = Cache()
md = markdown.Markdown(
extensions=["auto_pytabs"],
extension_configs={
"auto_pytabs": {
"cache": cache
}
},
)
def build_markdown() -> None:
md.convertFile("document.md", "document.html")
cache.persist()
```
Examples
**Input**
```python
from typing import Optional, Dict
def foo(bar: Optional[str]) -> Dict[str, str]:
...
```
**Equivalent markdown**
=== "Python 3.7+"
```python
from typing import Optional, Dict
def foo(bar: Optional[str]) -> Dict[str, str]:
...
```
=== "Python 3.9+"
```python
from typing import Optional
def foo(bar: Optional[str]) -> dict[str, str]:
...
```
==== "Python 3.10+"
```python
def foo(bar: str | None) -> dict[str, str]:
...
```
#### Nested blocks
Nested tabs are supported as well:
**Input**
=== "Level 1-1"
=== "Level 2-1"
```python
from typing import List
x: List[str]
```
=== "Level 2-2"
Hello, world!
=== "Level 1-2"
Goodbye, world!
**Equivalent markdown**
=== "Level 1-1"
=== "Level 2-1"
=== "Python 3.7+"
```python
from typing import List
x: List[str]
```
=== "Python 3.9+"
```python
x: list[str]
```
=== "Level 2-2"
Goodbye, world!
=== "Level 1-2"
Hello, world!
### Selectively disable
You can disable conversion for a single code block:
````
```python
from typing import Set, Optional
def bar(baz: Optional[str]) -> Set[str]:
...
```
````
Or for whole sections / files
```
everything after this will be ignored
re-enables conversion again
```
### Compatibility with `pymdownx.snippets`
If the `pymdownx.snippets` extension is used, make sure that it runs **before** AutoPyTab
## Usage with Sphinx
AutPyTabs provides a Sphinx extension `auto_pytabs.sphinx_ext`, enabling its functionality
for the `.. code-block` and `.. literalinclude` directives.
Configuration
#### Example configuration
```python
extensions = ["auto_pytabs.sphinx_ext", "sphinx_design"]
auto_pytabs_min_version = (3, 7) # optional
auto_pytabs_max_version = (3, 11) # optional
auto_pytabs_tab_title_template = "Python {min_version}+" # optional
# auto_pytabs_no_cache = True # disabled file system caching
# auto_pytabs_compat_mode = True # enable compatibility mode
# auto_pytabs_default_tab = "lowest" # Pre-select the tab with the lowest version
# auto_pytabs_reverse_order = True # reverse the order of tabs to highest > lowest
```
#### Available configuration options
| Name | Default | Description |
| -------------------------------- | ------------------------- | -------------------------------------------------------------------------- |
| `auto_pytabs_min_version` | `(3, 7)` | Minimum python version to generate code for |
| `auto_pytabs_max_version` | `(3, 7)` | Maximum python version to generate code for |
| `auto_pytabs_tab_title_template` | `"Python {min_version}+"` | Template for tab titles |
| `auto_pytabs_no_cache` | `False` | Disable file system caching |
| `auto_pytabs_compat_mode` | `False` | Enable [compatibility mode](#compatibility-mode) |
| `auto_pytabs_default_tab` | `highest` | Either `highest` or `lowest`. Version tab to preselect |
| `auto_pytabs_reverse_order` | `False` | Reverse the order of tabs. Default is to go from lowest to highest version |
Examples
**Input**
```rst
.. code-block:: python
from typing import Optional, Dict
def foo(bar: Optional[str]) -> Dict[str, str]:
...
```
**Equivalent ReST**
```rst
.. tab-set::
.. tab-item:: Python 3.7+
.. code-block:: python
from typing import Optional, Dict
def foo(bar: Optional[str]) -> Dict[str, str]:
...
.. tab-item:: Python 3.9+
.. code-block:: python
from typing import Optional
def foo(bar: Optional[str]) -> dict[str, str]:
...
.. tab-item:: Python 3.10+
.. code-block:: python
def foo(bar: str | None) -> dict[str, str]:
...
```
### Directives
AutoPyTabs overrides the built-in `code-block` and `literal-include` directives,
extending them with auto-upgrade and tabbing functionality, which means no special
directives, and therefore changes to existing documents are needed.
Additionally, a `:no-upgrade:` option is added to the directives, which can be used to
selectively fall back the default behaviour.
Two new directives are provided as well:
- `.. pytabs-code-block::`
- `.. pytabs-literalinclude::`
which by default act exactly like `.. code-block` and `.. literalinclude` respectively,
and are mainly to provide AutoPyTab's functionality in [compatibility mode](#compatibility-mode).
### Compatibility mode
If you don't want the default behaviour of directive overrides, and instead wish to use the
`.. pytabs-` directives manually (e.g. because of compatibility issues with other extensions
or because you only want to apply it to select code blocks) you can make use AutoPyTabs' compatibility
mode. To enable it, simply use the `auto_pytabs_compat_mode = True` in `conf.py`. Now, only content within `.. pytabs-`
directives will be upgraded.
### Compatibility with other extensions
Normally the directive overrides don't cause any problems and are very convenient,
since no changes to existing documents have to be made. However, if other extensions are included,
which themselves override one of those directives, one of them will inadvertently override the other,
depending on the order they're defined in `extensions`.
To combat this, you can use the [compatibility mode](#compatibility-mode) extension instead, which
only includes the new directives.
If you control the conflicting overrides, you can alternatively inherit from
`auto_py_tabs.sphinx_ext.CodeBlockOverride` and `auto_py_tabs.sphinx_ext.LiteralIncludeOverride`
instead of `sphinx.directives.code.CodeBlock` and `sphinx.directives.code.LiteralInclude` respectively.
AutoPyTabs-0.4.0/auto_pytabs/ 0000775 0000000 0000000 00000000000 14423450507 0016104 5 ustar 00root root 0000000 0000000 AutoPyTabs-0.4.0/auto_pytabs/__init__.py 0000664 0000000 0000000 00000000000 14423450507 0020203 0 ustar 00root root 0000000 0000000 AutoPyTabs-0.4.0/auto_pytabs/core.py 0000664 0000000 0000000 00000012417 14423450507 0017413 0 ustar 00root root 0000000 0000000 from __future__ import annotations
import shutil
import subprocess
from concurrent.futures import ThreadPoolExecutor, as_completed
from hashlib import sha1
from pathlib import Path
from typing import Any, Dict, NamedTuple
RUFF_BASE_ARGS = [
"ruff",
"--no-cache",
"--fix",
"--quiet",
"--select",
"UP",
"--select",
"F401",
"--isolated",
"-",
"--target-version",
]
class VersionTuple(NamedTuple):
major: int
minor: int
@classmethod
def from_string(cls, version: str) -> VersionTuple:
major, minor = version.split(".")
return VersionTuple(major=int(major), minor=int(minor))
VersionedCode = Dict[VersionTuple, str]
class Cache:
"""Simple hybrid file system / memory cache.
Follows the
`Cache Directory Tagging Specification http://www.brynosaurus.com/cachedir/>`_.
"""
def __init__(self) -> None:
self.cache_dir = Path(".auto_pytabs_cache")
self.cache_content_dir = self.cache_dir / "content"
self._cache: dict[str, str] = {}
self._touched: set[str] = set()
self._load()
def _init_cache_dir(self) -> None:
self.cache_content_dir.mkdir(exist_ok=True, parents=True)
cachedir_tag = self.cache_dir / "CACHEDIR.TAG"
gitignore_file = self.cache_dir / ".gitignore"
if not cachedir_tag.exists():
cachedir_tag.write_text(
"""Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by (application name).
# For information about cache directory tags, see:
# http://www.brynosaurus.com/cachedir/"""
)
if not gitignore_file.exists():
gitignore_file.write_text("*\n")
def _load(self) -> None:
self._init_cache_dir()
cache: dict[str, str] = {}
with ThreadPoolExecutor() as executor:
futures = {
executor.submit(file.read_text): file.name
for file in self.cache_content_dir.iterdir()
}
for future in as_completed(futures):
cache[futures[future]] = future.result()
self._cache.update(cache)
@staticmethod
def make_cache_key(*parts: Any) -> str:
"""Create a cache key using an md5 hash of ``parts``."""
return sha1("".join(map(str, parts)).encode()).hexdigest()
def get(self, key: str) -> str | None:
"""Get an item specified by ``key`` the cache."""
self._touched.add(key)
return self._cache.get(key)
def set(self, key: str, content: str) -> None:
"""Store an ``content``."""
self._cache[key] = content
self._touched.add(key)
def persist(self, evict: bool = True) -> None:
"""
Persist internal cache to disk. If ``evict`` is ``True``, evict unused items.
"""
with ThreadPoolExecutor() as executor:
for key, content in self._cache.items():
if key in self._touched:
executor.submit(
self.cache_content_dir.joinpath(key).write_text, content
)
elif evict:
executor.submit(
self.cache_content_dir.joinpath(key).unlink, missing_ok=True
)
def clear_all(self) -> None:
"""Clear all cached items from memory and disk."""
self._cache = {}
self._touched = set()
if not self.cache_dir.exists():
return
shutil.rmtree(self.cache_dir)
def get_version_requirements(
min_version: VersionTuple, max_version: VersionTuple
) -> list[VersionTuple]:
"""Given a min and max version, generate all versions in between."""
min_major, min_minor = min_version
max_major, max_minor = max_version
return [
VersionTuple(major=major, minor=minor)
for major in range(min_major, max_major + 1)
for minor in range(min_minor, max_minor + 1)
]
def _run_ruff(source: str, target_version: str) -> str:
with subprocess.Popen(
[*RUFF_BASE_ARGS, target_version],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
encoding="utf-8",
) as process:
return process.communicate(input=source)[0]
def _upgrade_code(
code: str, min_version: VersionTuple, cache: Cache | None = None
) -> str:
cache_key: str | None = None
if cache:
cache_key = cache.make_cache_key(code, min_version)
if cached_code := cache.get(cache_key):
return cached_code
code = _run_ruff(code, target_version=f"py3{min_version.minor}")
if cache_key and cache:
cache.set(cache_key, code)
return code
def version_code(
code: str, version_requirements: list[VersionTuple], cache: Cache | None = None
) -> VersionedCode:
"""Create versions of ``code`` for all python versions specified in
``version_requirements`` and return a dictionary of version-tuples/code.
"""
latest_code = code
versioned_code: VersionedCode = {version_requirements[0]: code}
for version in version_requirements:
upgraded_code = _upgrade_code(latest_code, version, cache=cache)
if upgraded_code != latest_code:
versioned_code[version] = upgraded_code
latest_code = upgraded_code
return versioned_code
AutoPyTabs-0.4.0/auto_pytabs/markdown_ext.py 0000664 0000000 0000000 00000017074 14423450507 0021171 0 ustar 00root root 0000000 0000000 from __future__ import annotations
import re
from typing import TYPE_CHECKING, Any, Literal, cast
from markdown import Extension
from markdown.preprocessors import Preprocessor
from auto_pytabs.core import (
Cache,
VersionedCode,
VersionTuple,
get_version_requirements,
version_code,
)
if TYPE_CHECKING:
from markdown import Markdown
RGX_BLOCK_TOKENS = re.compile(r"(.*```py[\w\W]*)|(.*```)")
RGX_PYTABS_DIRECTIVE = re.compile(r"")
PyTabDirective = Literal["disable", "enable", "disable-block"]
PYTAB_DIRECTIVES: set[PyTabDirective] = {"disable", "enable", "disable-block"}
def _strip_indentation(lines: list[str]) -> tuple[list[str], str]:
if not lines:
return [], ""
first_line = lines[0]
indent_char = ""
if first_line[0] in [" ", "\t"]:
indent_char = first_line[0]
indent = indent_char * (len(first_line) - len(first_line.lstrip(indent_char)))
if indent:
return [line.split(indent, 1)[1] if line else "" for line in lines], indent
return lines, indent
def _add_indentation(source: str | list[str], indentation: str) -> str:
lines = source.splitlines() if isinstance(source, str) else source
return "\n".join(indentation + line for line in lines)
def _get_pytabs_directive(line: str) -> PyTabDirective | None:
match = RGX_PYTABS_DIRECTIVE.match(line)
if match:
matched_directive = match.group(1).strip()
if matched_directive in PYTAB_DIRECTIVES:
return cast(PyTabDirective, matched_directive)
raise RuntimeError(f"Invalid AutoPytabs directive: {matched_directive!r}")
return None
def _extract_code_blocks(lines: list[str]) -> tuple[list[str], dict[int, list[str]]]:
in_block = False
enabled = True
new_lines: list[str] = []
to_transform = {}
start = 0
for i, line in enumerate(lines):
is_comment_line = False
directive = _get_pytabs_directive(line)
if directive:
is_comment_line = True
if directive == "disable":
enabled = False
elif directive == "enable":
enabled = True
match = RGX_BLOCK_TOKENS.match(line)
if match:
if match.group(1):
in_block = True
start = i
elif match.group(2) and in_block:
in_block = False
block = lines[start : i + 1]
block_directive = _get_pytabs_directive(lines[start - 1])
if enabled and block_directive != "disable-block":
to_transform[len(new_lines)] = block
new_lines.append("")
else:
new_lines.extend(block)
else:
new_lines.append(line)
elif not in_block and not is_comment_line:
new_lines.append(line)
return new_lines, to_transform
def _build_tab(title: str, body: list[str], selected: bool) -> str:
out = f'==={"+" if selected else ""} "{title}"\n'
out += _add_indentation(body, indentation=" ")
out += "\n"
return out
def _build_tabs(
*,
versioned_code: VersionedCode,
head: str,
tail: str,
tab_title_template: str,
default_tab_version: VersionTuple,
reverse_order: bool,
) -> str:
out = []
for version, code in versioned_code.items():
version_string = f"{version[0]}.{version[1]}"
lines = [head, *code.splitlines(), tail]
tab_title = tab_title_template.format(min_version=version_string)
out.append(
_build_tab(
title=tab_title, body=lines, selected=version == default_tab_version
)
)
if reverse_order:
out = reversed(out) # type: ignore[assignment]
return "\n".join(out)
def _convert_block(
*,
block: list[str],
versions: list[VersionTuple],
tab_title_template: str,
cache: Cache | None,
default_tab_strategy: Literal["highest", "lowest"],
reverse_order: bool,
) -> str:
block, indentation = _strip_indentation(block)
head, *code_lines, tail = block
code = "\n".join(code_lines)
versioned_code = version_code(code, versions, cache=cache)
if len(versioned_code) > 1:
versions = list(versioned_code.keys())
default_tab_version = versions[-1 if default_tab_strategy == "highest" else 0]
code = _build_tabs(
versioned_code=versioned_code,
head=head,
tail=tail,
tab_title_template=tab_title_template,
default_tab_version=default_tab_version,
reverse_order=reverse_order,
)
else:
code = "\n".join([head, versioned_code[versions[0]], tail])
code = _add_indentation(code, indentation)
return code
class UpgradePreprocessor(Preprocessor):
def __init__(
self,
*args: Any,
min_version: str,
max_version: str,
tab_title_template: str | None = None,
cache: Cache | None = None,
default_tab_strategy: Literal["highest", "lowest"] = "highest",
reverse_order: bool = False,
**kwargs: Any,
) -> None:
self.min_version = VersionTuple.from_string(min_version)
self.max_version = VersionTuple.from_string(max_version)
self.versions = get_version_requirements(self.min_version, self.max_version)
self.tab_title_template = tab_title_template or "Python {min_version}+"
self.cache = cache
self.default_tab_strategy = default_tab_strategy
self.reverse_order = reverse_order
super().__init__(*args, **kwargs)
def run(self, lines: list[str]) -> list[str]:
new_lines, to_transform = _extract_code_blocks(lines)
output_lines = []
for i, line in enumerate(new_lines):
block_to_transform = to_transform.get(i)
if block_to_transform:
transformed_block = _convert_block(
block=block_to_transform,
versions=self.versions,
tab_title_template=self.tab_title_template,
cache=self.cache,
default_tab_strategy=self.default_tab_strategy,
reverse_order=self.reverse_order,
).splitlines()
output_lines.extend(transformed_block)
else:
output_lines.append(line)
return output_lines
class AutoPyTabsExtension(Extension):
def __init__(self, *args: Any, cache: Cache | None, **kwargs: Any):
self.config = {
"min_version": ["3.7", "minimum version"],
"max_version": ["3.11", "maximum version"],
"tab_title_template": ["", "tab title format-string"],
"default_tab": ["highest", "version tab to preselect"],
"reverse_order": [False, "reverse the order of tabs"],
}
self.cache = cache
super().__init__(*args, **kwargs)
def extendMarkdown(self, md: Markdown) -> None:
"""Register the extension."""
self.md = md
md.registerExtension(self)
config = self.getConfigs()
md.preprocessors.register(
UpgradePreprocessor(
min_version=config["min_version"],
max_version=config["max_version"],
tab_title_template=config["tab_title_template"],
cache=self.cache,
default_tab_strategy=config["default_tab"],
reverse_order=config["reverse_order"],
),
"auto_pytabs",
32,
)
def makeExtension(**kwargs: Any) -> AutoPyTabsExtension:
return AutoPyTabsExtension(**kwargs)
AutoPyTabs-0.4.0/auto_pytabs/mkdocs_plugin.py 0000664 0000000 0000000 00000003437 14423450507 0021323 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.config import Config, config_options
from mkdocs.plugins import BasePlugin
from auto_pytabs.core import Cache
class PluginConfig(Config): # type: ignore[no-untyped-call]
min_version = config_options.Type(str, default="3.7")
max_version = config_options.Type(str, default="3.11")
tab_title_template = config_options.Type(str, default="Python {min_version}+")
no_cache = config_options.Type(bool, default=False)
default_tab = config_options.Choice(["highest", "lowest"], default="highest")
reverse_order = config_options.Type(bool, default=False)
class AutoPyTabsPlugin(BasePlugin[PluginConfig]): # type: ignore[no-untyped-call]
def __init__(self) -> None:
self.cache: Cache | None = None
def on_config(self, config: MkDocsConfig) -> Config | None:
if not self.config.no_cache:
self.cache = Cache()
config.markdown_extensions.append("auto_pytabs")
config["mdx_configs"].update(
{
"auto_pytabs": {
"min_version": self.config.min_version,
"max_version": self.config.max_version,
"tab_title_template": self.config.tab_title_template,
"cache": self.cache,
"default_tab": self.config.default_tab,
"reverse_order": self.config.reverse_order,
}
}
)
return None
def on_post_build(self, config: MkDocsConfig) -> None:
if self.cache:
self.cache.persist()
def on_build_error(self, error: Exception) -> None:
if self.cache:
self.cache.persist(evict=False)
AutoPyTabs-0.4.0/auto_pytabs/sphinx_ext.py 0000664 0000000 0000000 00000020123 14423450507 0020645 0 ustar 00root root 0000000 0000000 from __future__ import annotations
import importlib
import importlib.metadata
from collections.abc import Iterable
from typing import TYPE_CHECKING, Any, Literal, cast
from docutils.nodes import Node, container, section
from docutils.parsers.rst import directives
from docutils.statemachine import ViewList
from sphinx.directives.code import CodeBlock, LiteralInclude
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import nested_parse_with_titles
from auto_pytabs.core import (
Cache,
VersionedCode,
get_version_requirements,
version_code,
)
if TYPE_CHECKING:
from sphinx.application import Sphinx
from sphinx.config import Config
from sphinx.environment import BuildEnvironment
def indent(
text: str | Iterable[str], indent_char: str = " ", level: int = 4
) -> list[str]:
lines = text.splitlines() if isinstance(text, str) else text
return list((indent_char * level) + line for line in lines)
def _render_directive(
*,
name: str,
argument: str = "",
options: dict[str, Any] | None = None,
body: str | Iterable[str],
) -> list[str]:
directive = [f".. {name}:: {argument}"]
if options:
rendered_options = [
f":{option}: {value if (value is not True and value) else ''}"
for option, value in options.items()
if value is not False
]
directive.extend(indent(rendered_options))
directive.append("")
directive.extend(indent(body))
return directive
class UpgradeMixin(SphinxDirective):
compat: bool = False
def _get_directive_options(self) -> dict[str, Any]:
options: dict[str, Any] = {}
if not self.compat:
options["no-upgrade"] = True
for option, value in self.options.items():
if option not in CodeBlock.option_spec:
continue
if self.option_spec[option] is directives.flag:
value = True
if isinstance(value, Iterable) and not isinstance(value, str):
value = "\n".join(value)
options[option] = value
return options
def _create_tabs(
self,
versioned_code: VersionedCode,
tab_title_template: str,
) -> list[str]:
directive_options = self._get_directive_options()
if len(versioned_code) == 1:
return _render_directive(
name="code-block",
argument="python",
body=versioned_code.popitem()[1],
options=directive_options,
)
default_tab_strategy: Literal["highest", "lowest"] = self.config[
"auto_pytabs_default_tab"
]
versions = list(versioned_code.keys())
default_selected_version = versions[
-1 if default_tab_strategy == "highest" else 0
]
tab_set_body = []
if self.config["auto_pytabs_reverse_order"]:
versioned_code = dict(reversed(versioned_code.items()))
for version, code in versioned_code.items():
version_string = f"{version[0]}.{version[1]}"
code_block = _render_directive(
name="code-block",
argument="python",
options=directive_options,
body=code,
)
tab_item = _render_directive(
name="tab-item",
argument=tab_title_template.format(min_version=version_string),
options={
"sync": version_string,
"selected": version == default_selected_version,
},
body=code_block,
)
tab_set_body.extend(tab_item)
return _render_directive(name="tab-set", body=tab_set_body)
@property
def cache(self) -> Cache | None:
return getattr(self.env, "auto_pytabs_cache", None)
def _create_py_tab_nodes(self, code: str) -> list[Node]:
version_requirements = self.config["auto_pytabs_versions"]
versioned_code = version_code(code, version_requirements, cache=self.cache)
tabs = self._create_tabs(
versioned_code, self.env.config["auto_pytabs_tab_title_template"]
)
rst = ViewList()
source, lineno = self.get_source_info()
for line in tabs:
rst.append(line, source, lineno)
node = section()
node.document = self.state.document
nested_parse_with_titles(self.state, rst, node)
nodes = node.children
return cast("list[Node]", nodes)
class PyTabsCodeBlock(CodeBlock, UpgradeMixin):
compat = True
def run(self) -> list[Node]:
if not self.arguments or self.arguments[0] != "python":
return super().run()
self.assert_has_content()
return self._create_py_tab_nodes("\n".join(self.content))
class PyTabsLiteralInclude(LiteralInclude, UpgradeMixin):
compat = True
def run(self) -> list[Node]:
base_node = super().run()[0]
if self.options.get("language") != "python":
return [base_node]
if isinstance(base_node, container):
base_node = base_node.children[1]
return self._create_py_tab_nodes(base_node.rawsource) # type: ignore[attr-defined] # noqa: E501
class CodeBlockOverride(PyTabsCodeBlock):
compat = False
option_spec = {**CodeBlock.option_spec, "no-upgrade": directives.flag}
def run(self) -> list[Node]:
if "no-upgrade" in self.options:
return CodeBlock.run(self)
return super().run()
class LiteralIncludeOverride(PyTabsLiteralInclude):
compat = False
option_spec = {**LiteralInclude.option_spec, "no-upgrade": directives.flag}
def run(self) -> list[Node]:
if "no-upgrade" in self.options:
return LiteralInclude.run(self)
return super().run()
def on_config_inited(app: Sphinx, config: Config) -> None:
config["auto_pytabs_versions"] = get_version_requirements(
config["auto_pytabs_min_version"], config["auto_pytabs_max_version"]
)
if not config["auto_pytabs_compat_mode"]:
app.add_directive("code-block", CodeBlockOverride, override=True)
app.add_directive("literalinclude", LiteralIncludeOverride, override=True)
def on_build_finished(app: Sphinx, exception: Exception | None) -> None:
if cache := getattr(app.env, "auto_pytabs_cache", None):
cache.persist()
def on_env_before_read_docs(
app: Sphinx, env: BuildEnvironment, docnames: list[str]
) -> None:
if not app.config["auto_pytabs_no_cache"]:
env.auto_pytabs_cache = Cache() # type: ignore[attr-defined]
def on_env_merge_info(
app: Sphinx, env: BuildEnvironment, docnames: list[str], other: BuildEnvironment
) -> None:
cache: Cache | None = getattr(env, "auto_pytabs_cache", None)
other_cache: Cache | None = getattr(other, "auto_pytabs_cache", None)
if cache and other_cache:
cache._touched.update(other_cache._touched)
cache._cache.update(other_cache._cache)
def setup(app: Sphinx) -> dict[str, bool | str]:
app.add_directive("pytabs-code-block", PyTabsCodeBlock)
app.add_directive("pytabs-literalinclude", PyTabsLiteralInclude)
app.add_config_value(
"auto_pytabs_tab_title_template",
default="Python {min_version}+",
rebuild="html",
)
app.add_config_value("auto_pytabs_min_version", default=(3, 7), rebuild="html")
app.add_config_value("auto_pytabs_max_version", default=(3, 11), rebuild="html")
app.add_config_value("auto_pytabs_no_cache", default=False, rebuild="html")
app.add_config_value("auto_pytabs_compat_mode", default=False, rebuild="html")
app.add_config_value("auto_pytabs_default_tab", default="highest", rebuild="html")
app.add_config_value("auto_pytabs_reverse_order", default=False, rebuild="html")
app.connect("config-inited", on_config_inited)
app.connect("build-finished", on_build_finished)
app.connect("env-before-read-docs", on_env_before_read_docs)
app.connect("env-merge-info", on_env_merge_info)
return {
"version": importlib.metadata.version("auto_pytabs"),
"parallel_read_safe": True,
"parallel_write_safe": True,
}
AutoPyTabs-0.4.0/poetry.lock 0000664 0000000 0000000 00000221273 14423450507 0015755 0 ustar 00root root 0000000 0000000 # This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand.
[[package]]
name = "alabaster"
version = "0.7.13"
description = "A configurable sidebar-enabled Sphinx theme"
category = "main"
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 = "babel"
version = "2.12.1"
description = "Internationalization utilities"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"},
{file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"},
]
[package.dependencies]
pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""}
[[package]]
name = "black"
version = "22.12.0"
description = "The uncompromising code formatter."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"},
{file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"},
{file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"},
{file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"},
{file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"},
{file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"},
{file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"},
{file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"},
{file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"},
{file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"},
{file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"},
{file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"},
]
[package.dependencies]
click = ">=8.0.0"
mypy-extensions = ">=0.4.3"
pathspec = ">=0.9.0"
platformdirs = ">=2"
tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""}
typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
[package.extras]
colorama = ["colorama (>=0.4.3)"]
d = ["aiohttp (>=3.7.4)"]
jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "certifi"
version = "2022.12.7"
description = "Python package for providing Mozilla's CA Bundle."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
{file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
]
[[package]]
name = "cfgv"
version = "3.3.1"
description = "Validate configuration and produce human readable error messages."
category = "dev"
optional = false
python-versions = ">=3.6.1"
files = [
{file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"},
{file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"},
]
[[package]]
name = "charset-normalizer"
version = "3.1.0"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "main"
optional = false
python-versions = ">=3.7.0"
files = [
{file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"},
{file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"},
{file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"},
{file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"},
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"},
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"},
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"},
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"},
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"},
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"},
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"},
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"},
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"},
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"},
{file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"},
{file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"},
{file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"},
{file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"},
{file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"},
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"},
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"},
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"},
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"},
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"},
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"},
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"},
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"},
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"},
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"},
{file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"},
{file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"},
{file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"},
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"},
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"},
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"},
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"},
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"},
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"},
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"},
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"},
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"},
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"},
{file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"},
{file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"},
{file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"},
{file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"},
{file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"},
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"},
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"},
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"},
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"},
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"},
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"},
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"},
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"},
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"},
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"},
{file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"},
{file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"},
{file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"},
{file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"},
{file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"},
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"},
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"},
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"},
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"},
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"},
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"},
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"},
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"},
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"},
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"},
{file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"},
{file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"},
{file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"},
]
[[package]]
name = "click"
version = "8.1.3"
description = "Composable command line interface toolkit"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
]
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
category = "main"
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 = "distlib"
version = "0.3.6"
description = "Distribution utilities"
category = "dev"
optional = false
python-versions = "*"
files = [
{file = "distlib-0.3.6-py2.py3-none-any.whl", hash = "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e"},
{file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"},
]
[[package]]
name = "docutils"
version = "0.19"
description = "Docutils -- Python Documentation Utilities"
category = "main"
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 = "exceptiongroup"
version = "1.1.1"
description = "Backport of PEP 654 (exception groups)"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"},
{file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"},
]
[package.extras]
test = ["pytest (>=6)"]
[[package]]
name = "filelock"
version = "3.12.0"
description = "A platform independent file lock."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "filelock-3.12.0-py3-none-any.whl", hash = "sha256:ad98852315c2ab702aeb628412cbf7e95b7ce8c3bf9565670b4eaecf1db370a9"},
{file = "filelock-3.12.0.tar.gz", hash = "sha256:fc03ae43288c013d2ea83c8597001b1129db351aad9c57fe2409327916b8e718"},
]
[package.extras]
docs = ["furo (>=2023.3.27)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
testing = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"]
[[package]]
name = "ghp-import"
version = "2.1.0"
description = "Copy your docs directly to the gh-pages branch."
category = "main"
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.23"
description = "File identification library for Python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "identify-2.5.23-py2.py3-none-any.whl", hash = "sha256:17d9351c028a781456965e781ed2a435755cac655df1ebd930f7186b54399312"},
{file = "identify-2.5.23.tar.gz", hash = "sha256:50b01b9d5f73c6b53e5fa2caf9f543d3e657a9d0bbdeb203ebb8d45960ba7433"},
]
[package.extras]
license = ["ukkonen"]
[[package]]
name = "idna"
version = "3.4"
description = "Internationalized Domain Names in Applications (IDNA)"
category = "main"
optional = false
python-versions = ">=3.5"
files = [
{file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
]
[[package]]
name = "imagesize"
version = "1.4.1"
description = "Getting image size from png/jpeg/jpeg2000/gif file"
category = "main"
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 = "6.6.0"
description = "Read metadata from Python packages"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"},
{file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"},
]
[package.dependencies]
zipp = ">=0.5"
[package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
perf = ["ipython"]
testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
[[package]]
name = "iniconfig"
version = "2.0.0"
description = "brain-dead simple config-ini parsing"
category = "dev"
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.2"
description = "A very fast and expressive template engine."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
{file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
]
[package.dependencies]
MarkupSafe = ">=2.0"
[package.extras]
i18n = ["Babel (>=2.7)"]
[[package]]
name = "markdown"
version = "3.3.7"
description = "Python implementation of Markdown."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "Markdown-3.3.7-py3-none-any.whl", hash = "sha256:f5da449a6e1c989a4cea2631aa8ee67caa5a2ef855d551c88f9e309f4634c621"},
{file = "Markdown-3.3.7.tar.gz", hash = "sha256:cbb516f16218e643d8e0a95b309f77eb118cb138d39a4f27851e6a63581db874"},
]
[package.dependencies]
importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""}
[package.extras]
testing = ["coverage", "pyyaml"]
[[package]]
name = "markupsafe"
version = "2.1.2"
description = "Safely add untrusted strings to HTML/XML markup."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"},
{file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"},
{file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"},
{file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"},
{file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"},
{file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"},
{file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"},
{file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"},
{file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"},
{file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"},
{file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"},
{file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"},
{file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"},
{file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"},
{file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"},
{file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"},
{file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"},
{file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"},
{file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"},
{file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"},
{file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"},
{file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"},
{file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"},
{file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"},
{file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"},
{file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"},
{file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"},
{file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"},
{file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"},
{file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"},
{file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"},
{file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"},
{file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"},
{file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"},
{file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"},
{file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"},
{file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"},
{file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"},
{file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"},
{file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"},
{file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"},
]
[[package]]
name = "mergedeep"
version = "1.3.4"
description = "A deep merge function for 🐍."
category = "main"
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.4.2"
description = "Project documentation with Markdown."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "mkdocs-1.4.2-py3-none-any.whl", hash = "sha256:c8856a832c1e56702577023cd64cc5f84948280c1c0fcc6af4cd39006ea6aa8c"},
{file = "mkdocs-1.4.2.tar.gz", hash = "sha256:8947af423a6d0facf41ea1195b8e1e8c85ad94ac95ae307fe11232e0424b11c5"},
]
[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,<3.4"
mergedeep = ">=1.3.4"
packaging = ">=20.5"
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)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"]
[[package]]
name = "mypy"
version = "0.990"
description = "Optional static typing for Python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "mypy-0.990-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aaf1be63e0207d7d17be942dcf9a6b641745581fe6c64df9a38deb562a7dbafa"},
{file = "mypy-0.990-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d555aa7f44cecb7ea3c0ac69d58b1a5afb92caa017285a8e9c4efbf0518b61b4"},
{file = "mypy-0.990-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f694d6d09a460b117dccb6857dda269188e3437c880d7b60fa0014fa872d1e9"},
{file = "mypy-0.990-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:269f0dfb6463b8780333310ff4b5134425157ef0d2b1d614015adaf6d6a7eabd"},
{file = "mypy-0.990-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8798c8ed83aa809f053abff08664bdca056038f5a02af3660de00b7290b64c47"},
{file = "mypy-0.990-cp310-cp310-win_amd64.whl", hash = "sha256:47a9955214615108c3480a500cfda8513a0b1cd3c09a1ed42764ca0dd7b931dd"},
{file = "mypy-0.990-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4a8a6c10f4c63fbf6ad6c03eba22c9331b3946a4cec97f008e9ffb4d3b31e8e2"},
{file = "mypy-0.990-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cd2dd3730ba894ec2a2082cc703fbf3e95a08479f7be84912e3131fc68809d46"},
{file = "mypy-0.990-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7da0005e47975287a92b43276e460ac1831af3d23032c34e67d003388a0ce8d0"},
{file = "mypy-0.990-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:262c543ef24deb10470a3c1c254bb986714e2b6b1a67d66daf836a548a9f316c"},
{file = "mypy-0.990-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3ff201a0c6d3ea029d73b1648943387d75aa052491365b101f6edd5570d018ea"},
{file = "mypy-0.990-cp311-cp311-win_amd64.whl", hash = "sha256:1767830da2d1afa4e62b684647af0ff79b401f004d7fa08bc5b0ce2d45bcd5ec"},
{file = "mypy-0.990-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6826d9c4d85bbf6d68cb279b561de6a4d8d778ca8e9ab2d00ee768ab501a9852"},
{file = "mypy-0.990-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46897755f944176fbc504178422a5a2875bbf3f7436727374724842c0987b5af"},
{file = "mypy-0.990-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0680389c34284287fe00e82fc8bccdea9aff318f7e7d55b90d967a13a9606013"},
{file = "mypy-0.990-cp37-cp37m-win_amd64.whl", hash = "sha256:b08541a06eed35b543ae1a6b301590eb61826a1eb099417676ddc5a42aa151c5"},
{file = "mypy-0.990-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:be88d665e76b452c26fb2bdc3d54555c01226fba062b004ede780b190a50f9db"},
{file = "mypy-0.990-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b8f4a8213b1fd4b751e26b59ae0e0c12896568d7e805861035c7a15ed6dc9eb"},
{file = "mypy-0.990-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b6f85c2ad378e3224e017904a051b26660087b3b76490d533b7344f1546d3ff"},
{file = "mypy-0.990-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ee5f99817ee70254e7eb5cf97c1b11dda29c6893d846c8b07bce449184e9466"},
{file = "mypy-0.990-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49082382f571c3186ce9ea0bd627cb1345d4da8d44a8377870f4442401f0a706"},
{file = "mypy-0.990-cp38-cp38-win_amd64.whl", hash = "sha256:aba38e3dd66bdbafbbfe9c6e79637841928ea4c79b32e334099463c17b0d90ef"},
{file = "mypy-0.990-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9d851c09b981a65d9d283a8ccb5b1d0b698e580493416a10942ef1a04b19fd37"},
{file = "mypy-0.990-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d847dd23540e2912d9667602271e5ebf25e5788e7da46da5ffd98e7872616e8e"},
{file = "mypy-0.990-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cc6019808580565040cd2a561b593d7c3c646badd7e580e07d875eb1bf35c695"},
{file = "mypy-0.990-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a3150d409609a775c8cb65dbe305c4edd7fe576c22ea79d77d1454acd9aeda8"},
{file = "mypy-0.990-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3227f14fe943524f5794679156488f18bf8d34bfecd4623cf76bc55958d229c5"},
{file = "mypy-0.990-cp39-cp39-win_amd64.whl", hash = "sha256:c76c769c46a1e6062a84837badcb2a7b0cdb153d68601a61f60739c37d41cc74"},
{file = "mypy-0.990-py3-none-any.whl", hash = "sha256:8f1940325a8ed460ba03d19ab83742260fa9534804c317224e5d4e5aa588e2d6"},
{file = "mypy-0.990.tar.gz", hash = "sha256:72382cb609142dba3f04140d016c94b4092bc7b4d98ca718740dc989e5271b8d"},
]
[package.dependencies]
mypy-extensions = ">=0.4.3"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
typing-extensions = ">=3.10"
[package.extras]
dmypy = ["psutil (>=4.0)"]
install-types = ["pip"]
python2 = ["typed-ast (>=1.4.0,<2)"]
reports = ["lxml"]
[[package]]
name = "mypy-extensions"
version = "1.0.0"
description = "Type system extensions for programs checked with the mypy type checker."
category = "dev"
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.7.0"
description = "Node.js virtual environment builder"
category = "dev"
optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
files = [
{file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"},
{file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"},
]
[package.dependencies]
setuptools = "*"
[[package]]
name = "packaging"
version = "23.1"
description = "Core utilities for Python packages"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
{file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
]
[[package]]
name = "pathspec"
version = "0.11.1"
description = "Utility library for gitignore style pattern matching of file paths."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"},
{file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
]
[[package]]
name = "platformdirs"
version = "3.5.0"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "platformdirs-3.5.0-py3-none-any.whl", hash = "sha256:47692bc24c1958e8b0f13dd727307cff1db103fca36399f457da8e05f222fdc4"},
{file = "platformdirs-3.5.0.tar.gz", hash = "sha256:7954a68d0ba23558d753f73437c55f89027cf8f5108c19844d4b82e5af396335"},
]
[package.extras]
docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
[[package]]
name = "pluggy"
version = "1.0.0"
description = "plugin and hook calling mechanisms for python"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
]
[package.extras]
dev = ["pre-commit", "tox"]
testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "pre-commit"
version = "3.2.2"
description = "A framework for managing and maintaining multi-language pre-commit hooks."
category = "dev"
optional = false
python-versions = ">=3.8"
files = [
{file = "pre_commit-3.2.2-py2.py3-none-any.whl", hash = "sha256:0b4210aea813fe81144e87c5a291f09ea66f199f367fa1df41b55e1d26e1e2b4"},
{file = "pre_commit-3.2.2.tar.gz", hash = "sha256:5b808fcbda4afbccf6d6633a56663fed35b6c2bc08096fd3d47ce197ac351d9d"},
]
[package.dependencies]
cfgv = ">=2.0.0"
identify = ">=1.0.0"
nodeenv = ">=0.11.1"
pyyaml = ">=5.1"
virtualenv = ">=20.10.0"
[[package]]
name = "pygments"
version = "2.15.1"
description = "Pygments is a syntax highlighting package written in Python."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"},
{file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"},
]
[package.extras]
plugins = ["importlib-metadata"]
[[package]]
name = "pymdown-extensions"
version = "9.11"
description = "Extension pack for Python Markdown."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "pymdown_extensions-9.11-py3-none-any.whl", hash = "sha256:a499191d8d869f30339de86fcf072a787e86c42b6f16f280f5c2cf174182b7f3"},
{file = "pymdown_extensions-9.11.tar.gz", hash = "sha256:f7e86c1d3981f23d9dc43294488ecb54abadd05b0be4bf8f0e15efc90f7853ff"},
]
[package.dependencies]
markdown = ">=3.2"
pyyaml = "*"
[[package]]
name = "pytest"
version = "7.3.1"
description = "pytest: simple powerful testing with Python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"},
{file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"},
]
[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", "xmlschema"]
[[package]]
name = "pytest-datadir"
version = "1.4.1"
description = "pytest plugin for test data directories and files"
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "pytest-datadir-1.4.1.tar.gz", hash = "sha256:9f7a3c4def6ac4cac3cc8181139ab53bd2667231052bd40cb07081748d4420f0"},
{file = "pytest_datadir-1.4.1-py3-none-any.whl", hash = "sha256:095f441782b1b907587eca7227fdbae94be43f1c96b4b2cbcc6801a4645be1af"},
]
[package.dependencies]
pytest = ">=5.0"
[[package]]
name = "pytest-mock"
version = "3.10.0"
description = "Thin-wrapper around the mock package for easier use with pytest"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "pytest-mock-3.10.0.tar.gz", hash = "sha256:fbbdb085ef7c252a326fd8cdcac0aa3b1333d8811f131bdcc701002e1be7ed4f"},
{file = "pytest_mock-3.10.0-py3-none-any.whl", hash = "sha256:f4c973eeae0282963eb293eb173ce91b091a79c1334455acfac9ddee8a1c784b"},
]
[package.dependencies]
pytest = ">=5.0"
[package.extras]
dev = ["pre-commit", "pytest-asyncio", "tox"]
[[package]]
name = "pytest-regressions"
version = "2.4.2"
description = "Easy to use fixtures to write regression tests."
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "pytest-regressions-2.4.2.tar.gz", hash = "sha256:eab89e7ba4aa339bdfe07b31047e8e6a70b1e7846e74a8bbfc31a588d01e7303"},
{file = "pytest_regressions-2.4.2-py3-none-any.whl", hash = "sha256:b47f92c39d5dd2faa90716ee74c584d705c08e14f435a947f67706c4e5b8ef9a"},
]
[package.dependencies]
pytest = ">=6.2.0"
pytest-datadir = ">=1.2.0"
pyyaml = "*"
[package.extras]
dataframe = ["numpy", "pandas"]
dev = ["matplotlib", "mypy", "numpy", "pandas", "pillow", "pre-commit", "restructuredtext-lint", "tox"]
image = ["numpy", "pillow"]
num = ["numpy", "pandas"]
[[package]]
name = "python-dateutil"
version = "2.8.2"
description = "Extensions to the standard Python datetime module"
category = "main"
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 = "2023.3"
description = "World timezone definitions, modern and historical"
category = "main"
optional = false
python-versions = "*"
files = [
{file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"},
{file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"},
]
[[package]]
name = "pyyaml"
version = "6.0"
description = "YAML parser and emitter for Python"
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
{file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
{file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
{file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
{file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"},
{file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"},
{file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"},
{file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"},
{file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"},
{file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"},
{file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"},
{file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
{file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
{file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
{file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
{file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
{file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
{file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
{file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
{file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
{file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
{file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
{file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
{file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
{file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
]
[[package]]
name = "pyyaml-env-tag"
version = "0.1"
description = "A custom YAML tag for referencing environment variables in YAML files. "
category = "main"
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 = "requests"
version = "2.29.0"
description = "Python HTTP for Humans."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "requests-2.29.0-py3-none-any.whl", hash = "sha256:e8f3c9be120d3333921d213eef078af392fba3933ab7ed2d1cba3b56f2568c3b"},
{file = "requests-2.29.0.tar.gz", hash = "sha256:f2e34a75f4749019bb0e3effb66683630e4ffeaf75819fb51bebef1bf5aef059"},
]
[package.dependencies]
certifi = ">=2017.4.17"
charset-normalizer = ">=2,<4"
idna = ">=2.5,<4"
urllib3 = ">=1.21.1,<1.27"
[package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "ruff"
version = "0.0.263"
description = "An extremely fast Python linter, written in Rust."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "ruff-0.0.263-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:ee6c7a77f142c427fa73e1f5f603fc1a39413a36fe6966ed0fc55e97f6921d9c"},
{file = "ruff-0.0.263-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:c3b7d4b365207f3e4c40d235127091478e595b31e35b6cd57d940920cdfae68b"},
{file = "ruff-0.0.263-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebc778d95f29c9917e6e7608b2b67815707e6ab8eb5af9341617beda479c3edf"},
{file = "ruff-0.0.263-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4f75fa1632ea065b8f10678e7b6ae9873f84d5046bdf146990112751e98af42a"},
{file = "ruff-0.0.263-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddcee0d91629a4fa4bc9faebf5b94d4615d50d1cd76d1098fa71fbe1c54f4104"},
{file = "ruff-0.0.263-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4010b156f2e9fa6e74b5581098467f6ff68beac48945599b3a9239481e578ab4"},
{file = "ruff-0.0.263-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:15386933dd8e03aafa3186f9e996d6823105492817311338fbcb64d0ecbcd95f"},
{file = "ruff-0.0.263-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04e0b280dd246448564c892bce5607d820ad1f14944f3d535db98692e2a7ac07"},
{file = "ruff-0.0.263-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82c41f276106017b6f075dd2f2cc68e1a0b434cc75488f816fc98bd41982628d"},
{file = "ruff-0.0.263-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3e9fcee3f81129eabc75da005d839235e32d7d374f2d4c0db0c708dad4703d6e"},
{file = "ruff-0.0.263-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:981e3c4d773f7ff52479c4fd74a65e408f1e13fa5f889b72214d400cd1299ce4"},
{file = "ruff-0.0.263-py3-none-musllinux_1_2_i686.whl", hash = "sha256:bed1d3fba306e3f7e13ce226927b84200350e25abd1e754e06ee361c6d41de15"},
{file = "ruff-0.0.263-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7890499c2c3dcb1e60de2a8b4c5f5775b2bfcdff7d3e68e38db5cb2d65b12006"},
{file = "ruff-0.0.263-py3-none-win32.whl", hash = "sha256:c2b79919ebd93674b93dfc2c843e264bf8e52fbe737467e9b58521775c85f4ad"},
{file = "ruff-0.0.263-py3-none-win_amd64.whl", hash = "sha256:9af932f665e177de62e172901704257fd6e5bfabb95893867ff7382a851459d3"},
{file = "ruff-0.0.263-py3-none-win_arm64.whl", hash = "sha256:ddf4503595b560bfa5fae92fa2e4cb09ec465ee4cf88cc248f10ad2e956deec3"},
{file = "ruff-0.0.263.tar.gz", hash = "sha256:1008f211ad8aa1d998517ac5bf3d68fbc68ec516d1da89b6081f25ff2f30b687"},
]
[[package]]
name = "setuptools"
version = "67.7.2"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "setuptools-67.7.2-py3-none-any.whl", hash = "sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b"},
{file = "setuptools-67.7.2.tar.gz", hash = "sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990"},
]
[package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
[[package]]
name = "six"
version = "1.16.0"
description = "Python 2 and 3 compatibility utilities"
category = "main"
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."
category = "main"
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 = "sphinx"
version = "5.3.0"
description = "Python documentation generator"
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "Sphinx-5.3.0.tar.gz", hash = "sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5"},
{file = "sphinx-5.3.0-py3-none-any.whl", hash = "sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d"},
]
[package.dependencies]
alabaster = ">=0.7,<0.8"
babel = ">=2.9"
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
docutils = ">=0.14,<0.20"
imagesize = ">=1.3"
importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""}
Jinja2 = ">=3.0"
packaging = ">=21.0"
Pygments = ">=2.12"
requests = ">=2.5.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-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.981)", "sphinx-lint", "types-requests", "types-typed-ast"]
test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"]
[[package]]
name = "sphinx-design"
version = "0.3.0"
description = "A sphinx extension for designing beautiful, view size responsive web components."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "sphinx_design-0.3.0-py3-none-any.whl", hash = "sha256:823c1dd74f31efb3285ec2f1254caefed29d762a40cd676f58413a1e4ed5cc96"},
{file = "sphinx_design-0.3.0.tar.gz", hash = "sha256:7183fa1fae55b37ef01bda5125a21ee841f5bbcbf59a35382be598180c4cefba"},
]
[package.dependencies]
sphinx = ">=4,<6"
[package.extras]
code-style = ["pre-commit (>=2.12,<3.0)"]
rtd = ["myst-parser (>=0.18.0,<0.19.0)"]
testing = ["myst-parser (>=0.18.0,<0.19.0)", "pytest (>=7.1,<8.0)", "pytest-cov", "pytest-regressions"]
theme-furo = ["furo (>=2022.06.04,<2022.07)"]
theme-pydata = ["pydata-sphinx-theme (>=0.9.0,<0.10.0)"]
theme-rtd = ["sphinx-rtd-theme (>=1.0,<2.0)"]
theme-sbt = ["sphinx-book-theme (>=0.3.0,<0.4.0)"]
[[package]]
name = "sphinxcontrib-applehelp"
version = "1.0.4"
description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books"
category = "main"
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-devhelp"
version = "1.0.2"
description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document."
category = "main"
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-htmlhelp"
version = "2.0.1"
description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
category = "main"
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-jsmath"
version = "1.0.1"
description = "A sphinx extension which renders display math in HTML via JavaScript"
category = "main"
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."
category = "main"
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-serializinghtml"
version = "1.1.5"
description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)."
category = "main"
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 = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
category = "dev"
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 = "types-docutils"
version = "0.19.1.8"
description = "Typing stubs for docutils"
category = "dev"
optional = false
python-versions = "*"
files = [
{file = "types-docutils-0.19.1.8.tar.gz", hash = "sha256:975f8a78a2f422d8c6e776a09988e25565f54f7971a9384bbe8b004a1e3b0f90"},
{file = "types_docutils-0.19.1.8-py3-none-any.whl", hash = "sha256:008094d649bb728ff3736ff69b09cf62c04d651c577109ea4ae0f381621a7509"},
]
[[package]]
name = "types-markdown"
version = "3.4.2.7"
description = "Typing stubs for Markdown"
category = "dev"
optional = false
python-versions = "*"
files = [
{file = "types-Markdown-3.4.2.7.tar.gz", hash = "sha256:ecea668b1e5aaa8fb4f7067622af3c3341cb9145baa4d939b7c75d3e1eb26f7f"},
{file = "types_Markdown-3.4.2.7-py3-none-any.whl", hash = "sha256:7fd3ecb487f1d41c043fa24c00258ab7e1fe37585ee6ad016a1a3c03bca34f73"},
]
[[package]]
name = "typing-extensions"
version = "4.5.0"
description = "Backported and Experimental Type Hints for Python 3.7+"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"},
{file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"},
]
[[package]]
name = "urllib3"
version = "1.26.15"
description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [
{file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"},
{file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"},
]
[package.extras]
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "virtualenv"
version = "20.23.0"
description = "Virtual Python Environment builder"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "virtualenv-20.23.0-py3-none-any.whl", hash = "sha256:6abec7670e5802a528357fdc75b26b9f57d5d92f29c5462ba0fbe45feacc685e"},
{file = "virtualenv-20.23.0.tar.gz", hash = "sha256:a85caa554ced0c0afbd0d638e7e2d7b5f92d23478d05d17a76daeac8f279f924"},
]
[package.dependencies]
distlib = ">=0.3.6,<1"
filelock = ">=3.11,<4"
platformdirs = ">=3.2,<4"
[package.extras]
docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"]
test = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.7.1)", "time-machine (>=2.9)"]
[[package]]
name = "watchdog"
version = "3.0.0"
description = "Filesystem events monitoring"
category = "main"
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.15.0"
description = "Backport of pathlib-compatible object wrapper for zip files"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
{file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
]
[package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
[extras]
markdown = ["markdown"]
mkdocs = ["mkdocs"]
sphinx = ["sphinx"]
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
content-hash = "6694ce1b7fbdde85d46e19bcbeaa2dd8a2d81d7781218667e5fda331ce74702e"
AutoPyTabs-0.4.0/pyproject.toml 0000664 0000000 0000000 00000004056 14423450507 0016473 0 ustar 00root root 0000000 0000000 [tool.poetry]
name = "auto-pytabs"
version = "0.4.0"
description = "Automatically generate code examples for different Python versions in mkdocs or Sphinx based documentations"
authors = ["Janek Nouvertné "]
readme = "README.md"
packages = [{ include = "auto_pytabs" }]
[tool.poetry.dependencies]
python = "^3.8"
ruff = ">=0.0.260"
sphinx = { version = ">=4", optional = true }
markdown = {version = ">=3.2.1", optional = true }
mkdocs = {version = ">=1.4.2,<2", optional = true}
[tool.poetry.group.dev.dependencies]
black = "^22.10.0"
mypy = "^0.990"
types-markdown = "^3.4.2.1"
pytest = "^7.2.0"
pymdown-extensions = "^9.9"
sphinx-design = "^0.3.0"
pytest-regressions = "^2.4.2"
types-docutils = "^0.19.1.1"
mkdocs = "^1.4.2"
pyyaml = "^6.0"
pytest-mock = "^3.10.0"
pre-commit = "^3.2.1"
[tool.poetry.extras]
sphinx = ["sphinx"]
markdown = ["markdown"]
mkdocs = ["mkdocs"]
[tool.poetry.plugins."markdown.extensions"]
auto_pytabs = "auto_pytabs.markdown_ext:AutoPyTabsExtension"
[tool.poetry.plugins."mkdocs.plugins"]
auto_pytabs = "auto_pytabs.mkdocs_plugin:AutoPyTabsPlugin"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.mypy]
strict = true
[tool.pytest.ini_options]
filterwarnings = [
"ignore::DeprecationWarning:sphinx_design.*:",
"ignore::DeprecationWarning:sphinx.util.images:4",
"ignore::DeprecationWarning:importlib.resources._legacy:80",
]
[tool.ruff]
select = [
"DTZ", # flake8-datetimez
"E", # pycodestyle errors
"ERA", # eradicate
"F", # pyflakes
"I", # isort
"ICN", # flake8-import-conventions
"PLE",
"PTH", # flake8-use-pathlib
"Q", # flake8-quotes
"RET", # flake8-return
"RUF", # Ruff-specific rules
"SIM", # flake8-simplify
"T10", # flake8-debugger
"T20", # flake8-print
"TCH", # flake8-type-checking
"TID", # flake8-tidy-imports
"UP", # pyupgrade
"W", # pycodestyle - warning
"YTT", # flake8-2020
]
src = ["auto_pytabs", "test"]
target-version = "py38"
[tool.ruff.per-file-ignores]
"test*" = ["S101"]
AutoPyTabs-0.4.0/test/ 0000775 0000000 0000000 00000000000 14423450507 0014531 5 ustar 00root root 0000000 0000000 AutoPyTabs-0.4.0/test/__init__.py 0000664 0000000 0000000 00000000000 14423450507 0016630 0 ustar 00root root 0000000 0000000 AutoPyTabs-0.4.0/test/conftest.py 0000664 0000000 0000000 00000006511 14423450507 0016733 0 ustar 00root root 0000000 0000000 """Largely adopted from
https://github.com/executablebooks/sphinx-design/blob/6df47513e9e221c61877e9308da7a41d216ae3c3/tests/conftest.py.
"""
from __future__ import annotations
import shutil
from pathlib import Path
from typing import TYPE_CHECKING, Any
import pytest
from auto_pytabs.core import Cache
from sphinx.testing.path import path as sphinx_path
if TYPE_CHECKING:
from unittest.mock import MagicMock
from docutils import nodes
from sphinx.testing.util import SphinxTestApp
pytest_plugins = "sphinx.testing.fixtures"
@pytest.fixture(autouse=True, scope="session")
def purge_cache():
Cache().clear_all()
yield
Cache().clear_all()
@pytest.fixture()
def mock_cache_persist(mocker) -> MagicMock:
return mocker.patch("auto_pytabs.core.Cache.persist")
class SphinxBuilder:
def __init__(self, app: SphinxTestApp, src_path: Path):
self.app = app
self._src_path = src_path
@property
def src_path(self) -> Path:
return self._src_path
@property
def out_path(self) -> Path:
return Path(self.app.outdir)
def build(self, assert_pass=True):
self.app.build()
if assert_pass:
assert self.warnings == "", self.status
return self
@property
def status(self):
return self.app._status.getvalue()
@property
def warnings(self):
return self.app._warning.getvalue()
def get_doctree(
self, docname: str, post_transforms: bool = False
) -> nodes.document:
doctree: nodes.document = self.app.env.get_doctree(docname)
if post_transforms:
self.app.env.apply_post_transforms(doctree, docname)
# make source path consistent for test comparisons
for node in doctree.findall(include_self=True):
if not ("source" in node and node["source"]):
continue
node["source"] = Path(node["source"]).relative_to(self.src_path).as_posix()
if node["source"].endswith(".rst"):
node["source"] = node["source"][:-4]
elif node["source"].endswith(".md"):
node["source"] = node["source"][:-3]
return doctree
@pytest.fixture()
def sphinx_builder(tmp_path: Path, make_app, monkeypatch):
def _create_project(
source: str,
compat: bool = False,
**conf_kwargs: dict[str, Any],
):
if compat:
conf_kwargs["auto_pytabs_compat_mode"] = True
src_path = tmp_path / "srcdir"
src_path.mkdir()
conf_kwargs = {
"extensions": [
"sphinx_design",
"auto_pytabs.sphinx_ext",
],
"auto_pytabs_no_cache": True,
**(conf_kwargs or {}),
}
content = "\n".join(
[f"{key} = {value!r}" for key, value in conf_kwargs.items()]
)
src_path.joinpath("conf.py").write_text(content, encoding="utf8")
app = make_app(srcdir=sphinx_path(str(src_path.resolve())), buildername="html")
shutil.copy(
"test/sphinx_ext_test_data/example.py", src_path.joinpath("example.py")
)
shutil.copy(
"test/sphinx_ext_test_data/example.js", src_path.joinpath("example.js")
)
src_path.joinpath("index.rst").write_text(source)
return SphinxBuilder(app, src_path)
yield _create_project
AutoPyTabs-0.4.0/test/md_ext_test_data/ 0000775 0000000 0000000 00000000000 14423450507 0020041 5 ustar 00root root 0000000 0000000 AutoPyTabs-0.4.0/test/md_ext_test_data/custom_tab_title_in.md 0000664 0000000 0000000 00000000134 14423450507 0024410 0 ustar 00root root 0000000 0000000 ```python foo="bar"
from typing import Set
def bar(baz: Set[str]) -> Set[str]:
...
```
AutoPyTabs-0.4.0/test/md_ext_test_data/custom_tab_title_out.md 0000664 0000000 0000000 00000000404 14423450507 0024611 0 ustar 00root root 0000000 0000000 === "Python 3.7 and above"
```python foo="bar"
from typing import Set
def bar(baz: Set[str]) -> Set[str]:
...
```
===+ "Python 3.9 and above"
```python foo="bar"
def bar(baz: set[str]) -> set[str]:
...
``` AutoPyTabs-0.4.0/test/md_ext_test_data/disable_block_in.md 0000664 0000000 0000000 00000000207 14423450507 0023625 0 ustar 00root root 0000000 0000000
```python
from typing import List
x: List[str]
```
```python
from typing import Set
y: Set[str]
``` AutoPyTabs-0.4.0/test/md_ext_test_data/disable_block_out.md 0000664 0000000 0000000 00000000300 14423450507 0024020 0 ustar 00root root 0000000 0000000 ```python
from typing import List
x: List[str]
```
=== "Python 3.7+"
```python
from typing import Set
y: Set[str]
```
===+ "Python 3.9+"
```python
y: set[str]
``` AutoPyTabs-0.4.0/test/md_ext_test_data/disable_section_in.md 0000664 0000000 0000000 00000000326 14423450507 0024201 0 ustar 00root root 0000000 0000000
```python
from typing import List
x: List[str]
```
```python
from typing import Set
y: Set[str]
```
```python
from typing import Dict
z: Dict[str, str]
``` AutoPyTabs-0.4.0/test/md_ext_test_data/disable_section_out.md 0000664 0000000 0000000 00000000377 14423450507 0024410 0 ustar 00root root 0000000 0000000 ```python
from typing import List
x: List[str]
```
```python
from typing import Set
y: Set[str]
```
=== "Python 3.7+"
```python
from typing import Dict
z: Dict[str, str]
```
===+ "Python 3.9+"
```python
z: dict[str, str]
``` AutoPyTabs-0.4.0/test/md_ext_test_data/nested_tabs_in.md 0000664 0000000 0000000 00000000263 14423450507 0023345 0 ustar 00root root 0000000 0000000 === "Level 1"
=== "Level 2"
```python
from typing import List
def func(x: List[str]) -> None:
def inner():
pass
``` AutoPyTabs-0.4.0/test/md_ext_test_data/nested_tabs_out.md 0000664 0000000 0000000 00000000621 14423450507 0023544 0 ustar 00root root 0000000 0000000 === "Level 1"
=== "Level 2"
=== "Python 3.7+"
```python
from typing import List
def func(x: List[str]) -> None:
def inner():
pass
```
===+ "Python 3.9+"
```python
def func(x: list[str]) -> None:
def inner():
pass
``` AutoPyTabs-0.4.0/test/md_ext_test_data/upgrade_in.md 0000664 0000000 0000000 00000000152 14423450507 0022476 0 ustar 00root root 0000000 0000000 ```python foo="bar"
from typing import Set, Optional
def bar(baz: Optional[str]) -> Set[str]:
...
``` AutoPyTabs-0.4.0/test/md_ext_test_data/upgrade_out_default_highest.md 0000664 0000000 0000000 00000000625 14423450507 0026123 0 ustar 00root root 0000000 0000000 === "Python 3.7+"
```python foo="bar"
from typing import Set, Optional
def bar(baz: Optional[str]) -> Set[str]:
...
```
=== "Python 3.9+"
```python foo="bar"
from typing import Optional
def bar(baz: Optional[str]) -> set[str]:
...
```
===+ "Python 3.10+"
```python foo="bar"
def bar(baz: str | None) -> set[str]:
...
``` AutoPyTabs-0.4.0/test/md_ext_test_data/upgrade_out_default_highest_reversed.md 0000664 0000000 0000000 00000000625 14423450507 0030022 0 ustar 00root root 0000000 0000000 ===+ "Python 3.10+"
```python foo="bar"
def bar(baz: str | None) -> set[str]:
...
```
=== "Python 3.9+"
```python foo="bar"
from typing import Optional
def bar(baz: Optional[str]) -> set[str]:
...
```
=== "Python 3.7+"
```python foo="bar"
from typing import Set, Optional
def bar(baz: Optional[str]) -> Set[str]:
...
``` AutoPyTabs-0.4.0/test/md_ext_test_data/upgrade_out_default_lowest.md 0000664 0000000 0000000 00000000625 14423450507 0026005 0 ustar 00root root 0000000 0000000 ===+ "Python 3.7+"
```python foo="bar"
from typing import Set, Optional
def bar(baz: Optional[str]) -> Set[str]:
...
```
=== "Python 3.9+"
```python foo="bar"
from typing import Optional
def bar(baz: Optional[str]) -> set[str]:
...
```
=== "Python 3.10+"
```python foo="bar"
def bar(baz: str | None) -> set[str]:
...
``` AutoPyTabs-0.4.0/test/md_ext_test_data/upgrade_out_default_lowest_reversed.md 0000664 0000000 0000000 00000000625 14423450507 0027704 0 ustar 00root root 0000000 0000000 === "Python 3.10+"
```python foo="bar"
def bar(baz: str | None) -> set[str]:
...
```
=== "Python 3.9+"
```python foo="bar"
from typing import Optional
def bar(baz: Optional[str]) -> set[str]:
...
```
===+ "Python 3.7+"
```python foo="bar"
from typing import Set, Optional
def bar(baz: Optional[str]) -> Set[str]:
...
``` AutoPyTabs-0.4.0/test/md_ext_test_data/upgrade_single_in.md 0000664 0000000 0000000 00000000126 14423450507 0024040 0 ustar 00root root 0000000 0000000 ```python foo="bar"
from typing import Set
def bar(baz: str) -> Set[str]:
...
``` AutoPyTabs-0.4.0/test/md_ext_test_data/upgrade_single_out.md 0000664 0000000 0000000 00000000077 14423450507 0024246 0 ustar 00root root 0000000 0000000 ```python foo="bar"
def bar(baz: str) -> set[str]:
...
``` AutoPyTabs-0.4.0/test/sphinx_ext_test_data/ 0000775 0000000 0000000 00000000000 14423450507 0020752 5 ustar 00root root 0000000 0000000 AutoPyTabs-0.4.0/test/sphinx_ext_test_data/example.js 0000664 0000000 0000000 00000000021 14423450507 0022734 0 ustar 00root root 0000000 0000000 const foo = "bar" AutoPyTabs-0.4.0/test/sphinx_ext_test_data/example.py 0000664 0000000 0000000 00000000177 14423450507 0022764 0 ustar 00root root 0000000 0000000 from typing import Dict, Union, List, Optional
def foo(x: Union[Dict[str, str], List[str]]) -> Optional[List[int]]:
pass
AutoPyTabs-0.4.0/test/sphinx_ext_test_data/tabs_all_versions.xml 0000664 0000000 0000000 00000016124 14423450507 0025211 0 ustar 00root root 0000000 0000000
Index
code-block
Python 3.7+
test caption
from typing import Dict, Union, List, Optional
def foo(x: Union[Dict[str, str], List[str]]) -> Optional[List[int]]:
pass
Python 3.9+
test caption
from typing import Union, Optional
def foo(x: Union[dict[str, str], list[str]]) -> Optional[list[int]]:
pass
Python 3.10+
test caption
def foo(x: dict[str, str] | list[str]) -> list[int] | None:
pass
code-block no upgrade
test caption
from typing import Dict, Union, List, Optional
def foo(x: Union[Dict[str, str], List[str]]) -> Optional[List[int]]:
pass
code-block non-python
const x = "hello"
code-block no language
this is something
literalinclude
Python 3.7+
test caption
from typing import Dict, Union, List, Optional
def foo(x: Union[Dict[str, str], List[str]]) -> Optional[List[int]]:
pass
Python 3.9+
test caption
from typing import Union, Optional
def foo(x: Union[dict[str, str], list[str]]) -> Optional[list[int]]:
pass
Python 3.10+
test caption
def foo(x: dict[str, str] | list[str]) -> list[int] | None:
pass
literalinclude non-python
const foo = "bar"
literalinclude no language
const foo = "bar"
AutoPyTabs-0.4.0/test/sphinx_ext_test_data/tabs_all_versions_reversed.xml 0000664 0000000 0000000 00000016124 14423450507 0027110 0 ustar 00root root 0000000 0000000
Index
code-block
Python 3.10+
test caption
def foo(x: dict[str, str] | list[str]) -> list[int] | None:
pass
Python 3.9+
test caption
from typing import Union, Optional
def foo(x: Union[dict[str, str], list[str]]) -> Optional[list[int]]:
pass
Python 3.7+
test caption
from typing import Dict, Union, List, Optional
def foo(x: Union[Dict[str, str], List[str]]) -> Optional[List[int]]:
pass
code-block no upgrade
test caption
from typing import Dict, Union, List, Optional
def foo(x: Union[Dict[str, str], List[str]]) -> Optional[List[int]]:
pass
code-block non-python
const x = "hello"
code-block no language
this is something
literalinclude
Python 3.10+
test caption
def foo(x: dict[str, str] | list[str]) -> list[int] | None:
pass
Python 3.9+
test caption
from typing import Union, Optional
def foo(x: Union[dict[str, str], list[str]]) -> Optional[list[int]]:
pass
Python 3.7+
test caption
from typing import Dict, Union, List, Optional
def foo(x: Union[Dict[str, str], List[str]]) -> Optional[List[int]]:
pass
literalinclude non-python
const foo = "bar"
literalinclude no language
const foo = "bar"
AutoPyTabs-0.4.0/test/sphinx_ext_test_data/tabs_default_tab_highest.xml 0000664 0000000 0000000 00000016124 14423450507 0026476 0 ustar 00root root 0000000 0000000
Index
code-block
Python 3.7+
test caption
from typing import Dict, Union, List, Optional
def foo(x: Union[Dict[str, str], List[str]]) -> Optional[List[int]]:
pass
Python 3.9+
test caption
from typing import Union, Optional
def foo(x: Union[dict[str, str], list[str]]) -> Optional[list[int]]:
pass
Python 3.10+
test caption
def foo(x: dict[str, str] | list[str]) -> list[int] | None:
pass
code-block no upgrade
test caption
from typing import Dict, Union, List, Optional
def foo(x: Union[Dict[str, str], List[str]]) -> Optional[List[int]]:
pass
code-block non-python
const x = "hello"
code-block no language
this is something
literalinclude
Python 3.7+
test caption
from typing import Dict, Union, List, Optional
def foo(x: Union[Dict[str, str], List[str]]) -> Optional[List[int]]:
pass
Python 3.9+
test caption
from typing import Union, Optional
def foo(x: Union[dict[str, str], list[str]]) -> Optional[list[int]]:
pass
Python 3.10+
test caption
def foo(x: dict[str, str] | list[str]) -> list[int] | None:
pass
literalinclude non-python
const foo = "bar"
literalinclude no language
const foo = "bar"
AutoPyTabs-0.4.0/test/sphinx_ext_test_data/tabs_default_tab_highest_reversed.xml 0000664 0000000 0000000 00000016124 14423450507 0030375 0 ustar 00root root 0000000 0000000
Index
code-block
Python 3.10+
test caption
def foo(x: dict[str, str] | list[str]) -> list[int] | None:
pass
Python 3.9+
test caption
from typing import Union, Optional
def foo(x: Union[dict[str, str], list[str]]) -> Optional[list[int]]:
pass
Python 3.7+
test caption
from typing import Dict, Union, List, Optional
def foo(x: Union[Dict[str, str], List[str]]) -> Optional[List[int]]:
pass
code-block no upgrade
test caption
from typing import Dict, Union, List, Optional
def foo(x: Union[Dict[str, str], List[str]]) -> Optional[List[int]]:
pass
code-block non-python
const x = "hello"
code-block no language
this is something
literalinclude
Python 3.10+
test caption
def foo(x: dict[str, str] | list[str]) -> list[int] | None:
pass
Python 3.9+
test caption
from typing import Union, Optional
def foo(x: Union[dict[str, str], list[str]]) -> Optional[list[int]]:
pass
Python 3.7+
test caption
from typing import Dict, Union, List, Optional
def foo(x: Union[Dict[str, str], List[str]]) -> Optional[List[int]]:
pass
literalinclude non-python
const foo = "bar"
literalinclude no language
const foo = "bar"
AutoPyTabs-0.4.0/test/sphinx_ext_test_data/tabs_default_tab_lowest.xml 0000664 0000000 0000000 00000016124 14423450507 0026360 0 ustar 00root root 0000000 0000000