Initial commit
This commit is contained in:
commit
f9100af28c
|
@ -0,0 +1,162 @@
|
|||
# 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
|
||||
.pdm-python
|
||||
.pdm-build/
|
||||
|
||||
# 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/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
.idea/
|
|
@ -0,0 +1,4 @@
|
|||
# operator_repo
|
||||
|
||||
Library and utilities to handle repositories of kubernetes operators.
|
||||
|
|
@ -0,0 +1,761 @@
|
|||
# This file is @generated by PDM.
|
||||
# It is not intended for manual editing.
|
||||
|
||||
[metadata]
|
||||
groups = ["default", "lint", "test"]
|
||||
cross_platform = true
|
||||
static_urls = false
|
||||
lock_version = "4.3"
|
||||
content_hash = "sha256:07f4b815eeaa6dbe224b4ee7979fbb8c21b87844efc59fea54e86e786d8733b9"
|
||||
|
||||
[[package]]
|
||||
name = "astroid"
|
||||
version = "2.11.7"
|
||||
requires_python = ">=3.6.2"
|
||||
summary = "An abstract syntax tree for Python with inference support."
|
||||
dependencies = [
|
||||
"lazy-object-proxy>=1.4.0",
|
||||
"setuptools>=20.0",
|
||||
"typed-ast<2.0,>=1.4.0; implementation_name == \"cpython\" and python_version < \"3.8\"",
|
||||
"typing-extensions>=3.10; python_version < \"3.10\"",
|
||||
"wrapt<2,>=1.11",
|
||||
]
|
||||
files = [
|
||||
{file = "astroid-2.11.7-py3-none-any.whl", hash = "sha256:86b0a340a512c65abf4368b80252754cda17c02cdbbd3f587dddf98112233e7b"},
|
||||
{file = "astroid-2.11.7.tar.gz", hash = "sha256:bb24615c77f4837c707669d16907331374ae8a964650a66999da3f5ca68dc946"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "black"
|
||||
version = "23.3.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "The uncompromising code formatter."
|
||||
dependencies = [
|
||||
"click>=8.0.0",
|
||||
"mypy-extensions>=0.4.3",
|
||||
"packaging>=22.0",
|
||||
"pathspec>=0.9.0",
|
||||
"platformdirs>=2",
|
||||
"tomli>=1.1.0; python_version < \"3.11\"",
|
||||
"typed-ast>=1.4.2; python_version < \"3.8\" and implementation_name == \"cpython\"",
|
||||
"typing-extensions>=3.10.0.0; python_version < \"3.10\"",
|
||||
]
|
||||
files = [
|
||||
{file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"},
|
||||
{file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"},
|
||||
{file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"},
|
||||
{file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"},
|
||||
{file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"},
|
||||
{file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"},
|
||||
{file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"},
|
||||
{file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"},
|
||||
{file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"},
|
||||
{file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"},
|
||||
{file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"},
|
||||
{file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"},
|
||||
{file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"},
|
||||
{file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"},
|
||||
{file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"},
|
||||
{file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"},
|
||||
{file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"},
|
||||
{file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"},
|
||||
{file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"},
|
||||
{file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"},
|
||||
{file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"},
|
||||
{file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"},
|
||||
{file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"},
|
||||
{file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"},
|
||||
{file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cachetools"
|
||||
version = "5.3.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Extensible memoizing collections and decorators"
|
||||
files = [
|
||||
{file = "cachetools-5.3.1-py3-none-any.whl", hash = "sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590"},
|
||||
{file = "cachetools-5.3.1.tar.gz", hash = "sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chardet"
|
||||
version = "5.1.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Universal encoding detector for Python 3"
|
||||
files = [
|
||||
{file = "chardet-5.1.0-py3-none-any.whl", hash = "sha256:362777fb014af596ad31334fde1e8c327dfdb076e1960d1694662d46a6917ab9"},
|
||||
{file = "chardet-5.1.0.tar.gz", hash = "sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.1.6"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Composable command line interface toolkit"
|
||||
dependencies = [
|
||||
"colorama; platform_system == \"Windows\"",
|
||||
"importlib-metadata; python_version < \"3.8\"",
|
||||
]
|
||||
files = [
|
||||
{file = "click-8.1.6-py3-none-any.whl", hash = "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5"},
|
||||
{file = "click-8.1.6.tar.gz", hash = "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||
summary = "Cross-platform colored terminal text."
|
||||
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 = "coverage"
|
||||
version = "7.2.7"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Code coverage measurement for Python"
|
||||
files = [
|
||||
{file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"},
|
||||
{file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"},
|
||||
{file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "coverage"
|
||||
version = "7.2.7"
|
||||
extras = ["toml"]
|
||||
requires_python = ">=3.7"
|
||||
summary = "Code coverage measurement for Python"
|
||||
dependencies = [
|
||||
"coverage==7.2.7",
|
||||
"tomli; python_full_version <= \"3.11.0a6\"",
|
||||
]
|
||||
files = [
|
||||
{file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"},
|
||||
{file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"},
|
||||
{file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dill"
|
||||
version = "0.3.7"
|
||||
requires_python = ">=3.7"
|
||||
summary = "serialize all of Python"
|
||||
files = [
|
||||
{file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"},
|
||||
{file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "distlib"
|
||||
version = "0.3.7"
|
||||
summary = "Distribution utilities"
|
||||
files = [
|
||||
{file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"},
|
||||
{file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "exceptiongroup"
|
||||
version = "1.1.2"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Backport of PEP 654 (exception groups)"
|
||||
files = [
|
||||
{file = "exceptiongroup-1.1.2-py3-none-any.whl", hash = "sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f"},
|
||||
{file = "exceptiongroup-1.1.2.tar.gz", hash = "sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filelock"
|
||||
version = "3.12.2"
|
||||
requires_python = ">=3.7"
|
||||
summary = "A platform independent file lock."
|
||||
files = [
|
||||
{file = "filelock-3.12.2-py3-none-any.whl", hash = "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec"},
|
||||
{file = "filelock-3.12.2.tar.gz", hash = "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "importlib-metadata"
|
||||
version = "6.7.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Read metadata from Python packages"
|
||||
dependencies = [
|
||||
"typing-extensions>=3.6.4; python_version < \"3.8\"",
|
||||
"zipp>=0.5",
|
||||
]
|
||||
files = [
|
||||
{file = "importlib_metadata-6.7.0-py3-none-any.whl", hash = "sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5"},
|
||||
{file = "importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iniconfig"
|
||||
version = "2.0.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "brain-dead simple config-ini parsing"
|
||||
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 = "isort"
|
||||
version = "5.11.5"
|
||||
requires_python = ">=3.7.0"
|
||||
summary = "A Python utility / library to sort Python imports."
|
||||
files = [
|
||||
{file = "isort-5.11.5-py3-none-any.whl", hash = "sha256:ba1d72fb2595a01c7895a5128f9585a5cc4b6d395f1c8d514989b9a7eb2a8746"},
|
||||
{file = "isort-5.11.5.tar.gz", hash = "sha256:6be1f76a507cb2ecf16c7cf14a37e41609ca082330be4e3436a18ef74add55db"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy-object-proxy"
|
||||
version = "1.9.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "A fast and thorough lazy object proxy."
|
||||
files = [
|
||||
{file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"},
|
||||
{file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mccabe"
|
||||
version = "0.7.0"
|
||||
requires_python = ">=3.6"
|
||||
summary = "McCabe checker, plugin for flake8"
|
||||
files = [
|
||||
{file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
|
||||
{file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mypy-extensions"
|
||||
version = "1.0.0"
|
||||
requires_python = ">=3.5"
|
||||
summary = "Type system extensions for programs checked with the mypy type checker."
|
||||
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 = "packaging"
|
||||
version = "23.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Core utilities for Python packages"
|
||||
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.2"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Utility library for gitignore style pattern matching of file paths."
|
||||
files = [
|
||||
{file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"},
|
||||
{file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "platformdirs"
|
||||
version = "3.9.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||
dependencies = [
|
||||
"typing-extensions>=4.6.3; python_version < \"3.8\"",
|
||||
]
|
||||
files = [
|
||||
{file = "platformdirs-3.9.1-py3-none-any.whl", hash = "sha256:ad8291ae0ae5072f66c16945166cb11c63394c7a3ad1b1bc9828ca3162da8c2f"},
|
||||
{file = "platformdirs-3.9.1.tar.gz", hash = "sha256:1b42b450ad933e981d56e59f1b97495428c9bd60698baab9f3eb3d00d5822421"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
version = "1.2.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "plugin and hook calling mechanisms for python"
|
||||
dependencies = [
|
||||
"importlib-metadata>=0.12; python_version < \"3.8\"",
|
||||
]
|
||||
files = [
|
||||
{file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"},
|
||||
{file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pylint"
|
||||
version = "2.13.9"
|
||||
requires_python = ">=3.6.2"
|
||||
summary = "python code static checker"
|
||||
dependencies = [
|
||||
"astroid<=2.12.0-dev0,>=2.11.5",
|
||||
"colorama; sys_platform == \"win32\"",
|
||||
"dill>=0.2",
|
||||
"isort<6,>=4.2.5",
|
||||
"mccabe<0.8,>=0.6",
|
||||
"platformdirs>=2.2.0",
|
||||
"tomli>=1.1.0; python_version < \"3.11\"",
|
||||
"typing-extensions>=3.10.0; python_version < \"3.10\"",
|
||||
]
|
||||
files = [
|
||||
{file = "pylint-2.13.9-py3-none-any.whl", hash = "sha256:705c620d388035bdd9ff8b44c5bcdd235bfb49d276d488dd2c8ff1736aa42526"},
|
||||
{file = "pylint-2.13.9.tar.gz", hash = "sha256:095567c96e19e6f57b5b907e67d265ff535e588fe26b12b5ebe1fc5645b2c731"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyproject-api"
|
||||
version = "1.5.3"
|
||||
requires_python = ">=3.7"
|
||||
summary = "API to interact with the python pyproject.toml based projects"
|
||||
dependencies = [
|
||||
"packaging>=23.1",
|
||||
"tomli>=2.0.1; python_version < \"3.11\"",
|
||||
]
|
||||
files = [
|
||||
{file = "pyproject_api-1.5.3-py3-none-any.whl", hash = "sha256:14cf09828670c7b08842249c1f28c8ee6581b872e893f81b62d5465bec41502f"},
|
||||
{file = "pyproject_api-1.5.3.tar.gz", hash = "sha256:ffb5b2d7cad43f5b2688ab490de7c4d3f6f15e0b819cb588c4b771567c9729eb"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "7.4.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "pytest: simple powerful testing with Python"
|
||||
dependencies = [
|
||||
"colorama; sys_platform == \"win32\"",
|
||||
"exceptiongroup>=1.0.0rc8; python_version < \"3.11\"",
|
||||
"importlib-metadata>=0.12; python_version < \"3.8\"",
|
||||
"iniconfig",
|
||||
"packaging",
|
||||
"pluggy<2.0,>=0.12",
|
||||
"tomli>=1.0.0; python_version < \"3.11\"",
|
||||
]
|
||||
files = [
|
||||
{file = "pytest-7.4.0-py3-none-any.whl", hash = "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32"},
|
||||
{file = "pytest-7.4.0.tar.gz", hash = "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-cov"
|
||||
version = "4.1.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Pytest plugin for measuring coverage."
|
||||
dependencies = [
|
||||
"coverage[toml]>=5.2.1",
|
||||
"pytest>=4.6",
|
||||
]
|
||||
files = [
|
||||
{file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"},
|
||||
{file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0.1"
|
||||
requires_python = ">=3.6"
|
||||
summary = "YAML parser and emitter for Python"
|
||||
files = [
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
|
||||
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "3.0.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Python helper for Semantic Versioning (https://semver.org)"
|
||||
files = [
|
||||
{file = "semver-3.0.1-py3-none-any.whl", hash = "sha256:2a23844ba1647362c7490fe3995a86e097bb590d16f0f32dfc383008f19e4cdf"},
|
||||
{file = "semver-3.0.1.tar.gz", hash = "sha256:9ec78c5447883c67b97f98c3b6212796708191d22e4ad30f4570f840171cbce1"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "68.0.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||
files = [
|
||||
{file = "setuptools-68.0.0-py3-none-any.whl", hash = "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f"},
|
||||
{file = "setuptools-68.0.0.tar.gz", hash = "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
version = "2.0.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "A lil' TOML parser"
|
||||
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 = "tox"
|
||||
version = "4.6.4"
|
||||
requires_python = ">=3.7"
|
||||
summary = "tox is a generic virtualenv management and test command line tool"
|
||||
dependencies = [
|
||||
"cachetools>=5.3.1",
|
||||
"chardet>=5.1",
|
||||
"colorama>=0.4.6",
|
||||
"filelock>=3.12.2",
|
||||
"importlib-metadata>=6.7; python_version < \"3.8\"",
|
||||
"packaging>=23.1",
|
||||
"platformdirs>=3.8",
|
||||
"pluggy>=1.2",
|
||||
"pyproject-api>=1.5.2",
|
||||
"tomli>=2.0.1; python_version < \"3.11\"",
|
||||
"typing-extensions>=4.6.3; python_version < \"3.8\"",
|
||||
"virtualenv>=20.23.1",
|
||||
]
|
||||
files = [
|
||||
{file = "tox-4.6.4-py3-none-any.whl", hash = "sha256:1b8f8ae08d6a5475cad9d508236c51ea060620126fd7c3c513d0f5c7f29cc776"},
|
||||
{file = "tox-4.6.4.tar.gz", hash = "sha256:5e2ad8845764706170d3dcaac171704513cc8a725655219acb62fe4380bdadda"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tox-pdm"
|
||||
version = "0.6.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "A plugin for tox that utilizes PDM as the package manager and installer"
|
||||
dependencies = [
|
||||
"tomli; python_version < \"3.11\"",
|
||||
"tox>=3.18.0",
|
||||
]
|
||||
files = [
|
||||
{file = "tox-pdm-0.6.1.tar.gz", hash = "sha256:952ea67f2ec891f11eb00749f63fc0f980384435ca782c448d154390f9f42f5e"},
|
||||
{file = "tox_pdm-0.6.1-py3-none-any.whl", hash = "sha256:9e3cf83b7b55c3e33aaee0e65cf341739581ff4604a4178f0ef7dbab73a0bb35"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typed-ast"
|
||||
version = "1.5.5"
|
||||
requires_python = ">=3.6"
|
||||
summary = "a fork of Python 2 and 3 ast modules with type comment support"
|
||||
files = [
|
||||
{file = "typed_ast-1.5.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4bc1efe0ce3ffb74784e06460f01a223ac1f6ab31c6bc0376a21184bf5aabe3b"},
|
||||
{file = "typed_ast-1.5.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5f7a8c46a8b333f71abd61d7ab9255440d4a588f34a21f126bbfc95f6049e686"},
|
||||
{file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:597fc66b4162f959ee6a96b978c0435bd63791e31e4f410622d19f1686d5e769"},
|
||||
{file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d41b7a686ce653e06c2609075d397ebd5b969d821b9797d029fccd71fdec8e04"},
|
||||
{file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5fe83a9a44c4ce67c796a1b466c270c1272e176603d5e06f6afbc101a572859d"},
|
||||
{file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d5c0c112a74c0e5db2c75882a0adf3133adedcdbfd8cf7c9d6ed77365ab90a1d"},
|
||||
{file = "typed_ast-1.5.5-cp310-cp310-win_amd64.whl", hash = "sha256:e1a976ed4cc2d71bb073e1b2a250892a6e968ff02aa14c1f40eba4f365ffec02"},
|
||||
{file = "typed_ast-1.5.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c631da9710271cb67b08bd3f3813b7af7f4c69c319b75475436fcab8c3d21bee"},
|
||||
{file = "typed_ast-1.5.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b445c2abfecab89a932b20bd8261488d574591173d07827c1eda32c457358b18"},
|
||||
{file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc95ffaaab2be3b25eb938779e43f513e0e538a84dd14a5d844b8f2932593d88"},
|
||||
{file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61443214d9b4c660dcf4b5307f15c12cb30bdfe9588ce6158f4a005baeb167b2"},
|
||||
{file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6eb936d107e4d474940469e8ec5b380c9b329b5f08b78282d46baeebd3692dc9"},
|
||||
{file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e48bf27022897577d8479eaed64701ecaf0467182448bd95759883300ca818c8"},
|
||||
{file = "typed_ast-1.5.5-cp311-cp311-win_amd64.whl", hash = "sha256:83509f9324011c9a39faaef0922c6f720f9623afe3fe220b6d0b15638247206b"},
|
||||
{file = "typed_ast-1.5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2188bc33d85951ea4ddad55d2b35598b2709d122c11c75cffd529fbc9965508e"},
|
||||
{file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0635900d16ae133cab3b26c607586131269f88266954eb04ec31535c9a12ef1e"},
|
||||
{file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57bfc3cf35a0f2fdf0a88a3044aafaec1d2f24d8ae8cd87c4f58d615fb5b6311"},
|
||||
{file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:fe58ef6a764de7b4b36edfc8592641f56e69b7163bba9f9c8089838ee596bfb2"},
|
||||
{file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d09d930c2d1d621f717bb217bf1fe2584616febb5138d9b3e8cdd26506c3f6d4"},
|
||||
{file = "typed_ast-1.5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:d40c10326893ecab8a80a53039164a224984339b2c32a6baf55ecbd5b1df6431"},
|
||||
{file = "typed_ast-1.5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fd946abf3c31fb50eee07451a6aedbfff912fcd13cf357363f5b4e834cc5e71a"},
|
||||
{file = "typed_ast-1.5.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ed4a1a42df8a3dfb6b40c3d2de109e935949f2f66b19703eafade03173f8f437"},
|
||||
{file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:045f9930a1550d9352464e5149710d56a2aed23a2ffe78946478f7b5416f1ede"},
|
||||
{file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:381eed9c95484ceef5ced626355fdc0765ab51d8553fec08661dce654a935db4"},
|
||||
{file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bfd39a41c0ef6f31684daff53befddae608f9daf6957140228a08e51f312d7e6"},
|
||||
{file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8c524eb3024edcc04e288db9541fe1f438f82d281e591c548903d5b77ad1ddd4"},
|
||||
{file = "typed_ast-1.5.5-cp38-cp38-win_amd64.whl", hash = "sha256:7f58fabdde8dcbe764cef5e1a7fcb440f2463c1bbbec1cf2a86ca7bc1f95184b"},
|
||||
{file = "typed_ast-1.5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:042eb665ff6bf020dd2243307d11ed626306b82812aba21836096d229fdc6a10"},
|
||||
{file = "typed_ast-1.5.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:622e4a006472b05cf6ef7f9f2636edc51bda670b7bbffa18d26b255269d3d814"},
|
||||
{file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1efebbbf4604ad1283e963e8915daa240cb4bf5067053cf2f0baadc4d4fb51b8"},
|
||||
{file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0aefdd66f1784c58f65b502b6cf8b121544680456d1cebbd300c2c813899274"},
|
||||
{file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:48074261a842acf825af1968cd912f6f21357316080ebaca5f19abbb11690c8a"},
|
||||
{file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:429ae404f69dc94b9361bb62291885894b7c6fb4640d561179548c849f8492ba"},
|
||||
{file = "typed_ast-1.5.5-cp39-cp39-win_amd64.whl", hash = "sha256:335f22ccb244da2b5c296e6f96b06ee9bed46526db0de38d2f0e5a6597b81155"},
|
||||
{file = "typed_ast-1.5.5.tar.gz", hash = "sha256:94282f7a354f36ef5dbce0ef3467ebf6a258e370ab33d5b40c249fa996e590dd"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "types-pyyaml"
|
||||
version = "6.0.12.11"
|
||||
summary = "Typing stubs for PyYAML"
|
||||
files = [
|
||||
{file = "types-PyYAML-6.0.12.11.tar.gz", hash = "sha256:7d340b19ca28cddfdba438ee638cd4084bde213e501a3978738543e27094775b"},
|
||||
{file = "types_PyYAML-6.0.12.11-py3-none-any.whl", hash = "sha256:a461508f3096d1d5810ec5ab95d7eeecb651f3a15b71959999988942063bf01d"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.7.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Backported and Experimental Type Hints for Python 3.7+"
|
||||
files = [
|
||||
{file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"},
|
||||
{file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "virtualenv"
|
||||
version = "20.24.2"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Virtual Python Environment builder"
|
||||
dependencies = [
|
||||
"distlib<1,>=0.3.7",
|
||||
"filelock<4,>=3.12.2",
|
||||
"importlib-metadata>=6.6; python_version < \"3.8\"",
|
||||
"platformdirs<4,>=3.9.1",
|
||||
]
|
||||
files = [
|
||||
{file = "virtualenv-20.24.2-py3-none-any.whl", hash = "sha256:43a3052be36080548bdee0b42919c88072037d50d56c28bd3f853cbe92b953ff"},
|
||||
{file = "virtualenv-20.24.2.tar.gz", hash = "sha256:fd8a78f46f6b99a67b7ec5cf73f92357891a7b3a40fd97637c27f854aae3b9e0"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wrapt"
|
||||
version = "1.15.0"
|
||||
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
|
||||
summary = "Module for decorators, wrappers and monkey patching."
|
||||
files = [
|
||||
{file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"},
|
||||
{file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"},
|
||||
{file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zipp"
|
||||
version = "3.15.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Backport of pathlib-compatible object wrapper for zip files"
|
||||
files = [
|
||||
{file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
|
||||
{file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
|
||||
]
|
|
@ -0,0 +1,34 @@
|
|||
[project]
|
||||
name = "operator_repo"
|
||||
version = "0.1.0"
|
||||
description = "Library and utilities to handle repositories of kubernetes operators"
|
||||
authors = [
|
||||
{name = "Maurizio Porrato", email = "mporrato@redhat.com"},
|
||||
]
|
||||
dependencies = [
|
||||
"pyyaml>=6.0.1",
|
||||
"semver>=3.0.1",
|
||||
]
|
||||
requires-python = ">=3.7"
|
||||
readme = "README.md"
|
||||
license = {text = "Apache-2.0"}
|
||||
|
||||
[project.scripts]
|
||||
optool = "operator_repo.cli:main"
|
||||
|
||||
[build-system]
|
||||
requires = ["pdm-backend"]
|
||||
build-backend = "pdm.backend"
|
||||
|
||||
[tool.pdm.dev-dependencies]
|
||||
test = [
|
||||
"pytest>=7.4.0",
|
||||
"pytest-cov>=4.1.0",
|
||||
"tox-pdm>=0.6.1",
|
||||
]
|
||||
lint = [
|
||||
"black>=23.3.0",
|
||||
"isort>=5.11.5",
|
||||
"pylint>=2.13.9",
|
||||
"types-PyYAML>=6.0.12.11",
|
||||
]
|
|
@ -0,0 +1 @@
|
|||
from .classes import Bundle, Operator, Repo
|
|
@ -0,0 +1,488 @@
|
|||
"""
|
||||
Definition of Repo, Operator and Bundle classes
|
||||
"""
|
||||
|
||||
import logging
|
||||
from functools import cached_property, total_ordering
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Iterator, List, Optional, Set, Union, Tuple
|
||||
|
||||
from semver import Version
|
||||
|
||||
from .exceptions import (
|
||||
InvalidBundleException,
|
||||
InvalidOperatorException,
|
||||
InvalidRepoException,
|
||||
)
|
||||
from .utils import load_yaml
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@total_ordering
|
||||
class Bundle:
|
||||
"""
|
||||
An operator bundle as specified in
|
||||
https://github.com/operator-framework/operator-registry/blob/master/docs/design/operator-bundle.md
|
||||
"""
|
||||
|
||||
METADATA_DIR = "metadata"
|
||||
MANIFESTS_DIR = "manifests"
|
||||
|
||||
def __init__(self, bundle_path: Union[str, Path]):
|
||||
log.debug("Loading bundle at %s", bundle_path)
|
||||
self._bundle_path = Path(bundle_path).resolve()
|
||||
if not self.probe(self._bundle_path):
|
||||
raise InvalidBundleException(f"Not a valid bundle: {self._bundle_path}")
|
||||
self.operator_version = self._bundle_path.name
|
||||
self.operator_name = self._bundle_path.parent.name
|
||||
self._manifests_path = self._bundle_path / self.MANIFESTS_DIR
|
||||
self._metadata_path = self._bundle_path / self.METADATA_DIR
|
||||
|
||||
@cached_property
|
||||
def annotations(self) -> Dict[str, Any]:
|
||||
"""
|
||||
:return: The content of the "annotations" field in metadata/annotations.yaml
|
||||
"""
|
||||
return self.load_metadata("annotations.yaml").get("annotations", {})
|
||||
|
||||
@cached_property
|
||||
def dependencies(self) -> List[Any]:
|
||||
"""
|
||||
:return: The content of the "dependencies" field in metadata/dependencies.yaml
|
||||
"""
|
||||
return self.load_metadata("dependencies.yaml").get("dependencies", [])
|
||||
|
||||
@cached_property
|
||||
def csv(self) -> Dict[str, Any]:
|
||||
"""
|
||||
:return: The content of the CSV file for the bundle
|
||||
"""
|
||||
csv = load_yaml(self.csv_file_name)
|
||||
if not isinstance(csv, dict):
|
||||
raise InvalidBundleException(f"Invalid CSV contents ({self.csv_file_name})")
|
||||
return csv
|
||||
|
||||
@cached_property
|
||||
def csv_full_name(self) -> Tuple[str, str]:
|
||||
try:
|
||||
csv_full_name = self.csv["metadata"]["name"]
|
||||
name, version = csv_full_name.split(".", 1)
|
||||
return name, version.lstrip('v')
|
||||
except (KeyError, ValueError) as exc:
|
||||
raise InvalidBundleException(
|
||||
f"CSV for {self} has invalid .metadata.name"
|
||||
) from exc
|
||||
|
||||
@property
|
||||
def csv_operator_name(self) -> str:
|
||||
name, _ = self.csv_full_name
|
||||
return name
|
||||
|
||||
@property
|
||||
def csv_operator_version(self) -> str:
|
||||
_, version = self.csv_full_name
|
||||
return version
|
||||
|
||||
@classmethod
|
||||
def probe(cls, path: Path) -> bool:
|
||||
"""
|
||||
:return: True if path looks like a bundle
|
||||
"""
|
||||
return (
|
||||
path.is_dir()
|
||||
and (path / cls.MANIFESTS_DIR).is_dir()
|
||||
and (path / cls.METADATA_DIR).is_dir()
|
||||
)
|
||||
|
||||
@property
|
||||
def root(self) -> str:
|
||||
"""
|
||||
:return: The path to the root of the bundle
|
||||
"""
|
||||
return str(self._bundle_path)
|
||||
|
||||
def operator(self) -> "Operator":
|
||||
"""
|
||||
:return: The operator the bundle belongs to
|
||||
"""
|
||||
return Operator(self._bundle_path.parent)
|
||||
|
||||
def load_metadata(self, filename: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Load and parse a yaml file from the metadata directory of the bundle
|
||||
:param filename: Name of the file
|
||||
:return: The parsed content of the file
|
||||
"""
|
||||
try:
|
||||
content = load_yaml(self._metadata_path / filename)
|
||||
if not isinstance(content, dict):
|
||||
if content is None:
|
||||
return {}
|
||||
raise InvalidBundleException(f"Invalid {filename} contents")
|
||||
return content
|
||||
except FileNotFoundError:
|
||||
return {}
|
||||
|
||||
@cached_property
|
||||
def csv_file_name(self) -> Path:
|
||||
"""
|
||||
:return: The path of the CSV file for the bundle
|
||||
"""
|
||||
for suffix in ["yaml", "yml"]:
|
||||
try:
|
||||
return next(self._manifests_path.glob(f"*.clusterserviceversion.{suffix}"))
|
||||
except StopIteration:
|
||||
continue
|
||||
raise InvalidBundleException(
|
||||
f"CSV file for {self.operator_name}/{self.operator_version} not found"
|
||||
)
|
||||
|
||||
@property
|
||||
def channels(self) -> Set[str]:
|
||||
"""
|
||||
:return: Set of channels the bundle belongs to
|
||||
"""
|
||||
try:
|
||||
return {
|
||||
x.strip()
|
||||
for x in self.annotations[
|
||||
"operators.operatorframework.io.bundle.channels.v1"
|
||||
].split(",")
|
||||
}
|
||||
except KeyError:
|
||||
return set()
|
||||
|
||||
@property
|
||||
def default_channel(self) -> Optional[str]:
|
||||
"""
|
||||
:return: Default channel for the bundle
|
||||
"""
|
||||
try:
|
||||
return self.annotations[
|
||||
"operators.operatorframework.io.bundle.channel.default.v1"
|
||||
].strip()
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if not isinstance(other, self.__class__):
|
||||
raise TypeError(
|
||||
f"== not supported between instances of '{self.__class__.__name__}'"
|
||||
f" and '{other.__class__.__name__}"
|
||||
)
|
||||
if self.csv_operator_name != other.csv_operator_name:
|
||||
return False
|
||||
try:
|
||||
return Version.parse(
|
||||
self.csv_operator_version.lstrip("v")
|
||||
) == Version.parse(other.csv_operator_version.lstrip("v"))
|
||||
except ValueError:
|
||||
log.warning(
|
||||
"Can't compare bundle versions %s and %s as semver: using lexical order instead",
|
||||
self,
|
||||
other,
|
||||
)
|
||||
return self.csv_operator_version == other.csv_operator_version
|
||||
|
||||
def __ne__(self, other: object) -> bool:
|
||||
return not self == other
|
||||
|
||||
def __lt__(self, other: object) -> bool:
|
||||
if not isinstance(other, self.__class__):
|
||||
raise TypeError(
|
||||
f"< not supported between instances of '{self.__class__.__name__}'"
|
||||
f" and '{other.__class__.__name__}"
|
||||
)
|
||||
if self.csv_operator_name != other.csv_operator_name:
|
||||
raise ValueError("Can't compare bundles from different operators")
|
||||
try:
|
||||
return Version.parse(self.csv_operator_version.lstrip("v")) < Version.parse(
|
||||
other.csv_operator_version.lstrip("v")
|
||||
)
|
||||
except ValueError:
|
||||
log.warning(
|
||||
"Can't compare bundle versions %s and %s as semver: using lexical order instead",
|
||||
self,
|
||||
other,
|
||||
)
|
||||
return self.csv_operator_version < other.csv_operator_version
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.operator_name, self.operator_version))
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return (
|
||||
f"{self.__class__.__name__}({self.operator_name}/{self.operator_version})"
|
||||
)
|
||||
|
||||
|
||||
@total_ordering
|
||||
class Operator:
|
||||
"""An operator containing a collection of bundles"""
|
||||
|
||||
def __init__(self, operator_path: Union[str, Path]):
|
||||
log.debug("Loading operator at %s", operator_path)
|
||||
self._operator_path = Path(operator_path).resolve()
|
||||
if not self.probe(self._operator_path):
|
||||
raise InvalidOperatorException(
|
||||
f"Not a valid operator: {self._operator_path}"
|
||||
)
|
||||
self.operator_name = self._operator_path.name
|
||||
|
||||
@cached_property
|
||||
def config(self) -> Any:
|
||||
"""
|
||||
:return: The contents of the ci.yaml for the operator
|
||||
"""
|
||||
try:
|
||||
return load_yaml(self._operator_path / "ci.yaml")
|
||||
except FileNotFoundError:
|
||||
log.info("No ci.yaml found for %s", self)
|
||||
return {}
|
||||
|
||||
@classmethod
|
||||
def probe(cls, path: Path) -> bool:
|
||||
"""
|
||||
:return: True if path looks like an operator
|
||||
"""
|
||||
return path.is_dir() and any(Bundle.probe(x) for x in path.iterdir())
|
||||
|
||||
@property
|
||||
def root(self) -> str:
|
||||
"""
|
||||
:return: The path to the root of the operator
|
||||
"""
|
||||
return str(self._operator_path)
|
||||
|
||||
def all_bundles(self) -> Iterator[Bundle]:
|
||||
"""
|
||||
:return: All the bundles for the operator
|
||||
"""
|
||||
for version_path in self._operator_path.iterdir():
|
||||
if Bundle.probe(version_path):
|
||||
yield self.bundle(version_path.name)
|
||||
|
||||
def bundle_path(self, operator_version: str) -> Path:
|
||||
"""
|
||||
Return the path where a bundle for the given version
|
||||
would be located
|
||||
:param operator_version: Version of the bundle
|
||||
:return: Path to the bundle
|
||||
"""
|
||||
return self._operator_path / operator_version
|
||||
|
||||
def bundle(self, operator_version: str) -> Bundle:
|
||||
"""
|
||||
Load the bundle for the given version
|
||||
:param operator_version: Version of the bundle
|
||||
:return: The loaded bundle
|
||||
"""
|
||||
return Bundle(self.bundle_path(operator_version))
|
||||
|
||||
def has(self, operator_version: str) -> bool:
|
||||
"""
|
||||
Check if the operator has a bundle for the given version
|
||||
:param operator_version: Version to check for
|
||||
:return: True if the operator contains a bundle for such version
|
||||
"""
|
||||
return Bundle.probe(self.bundle_path(operator_version))
|
||||
|
||||
@cached_property
|
||||
def channels(self) -> Set[str]:
|
||||
"""
|
||||
:return: All channels defined by the operator bundles
|
||||
"""
|
||||
return {x for y in self.all_bundles() for x in y.channels}
|
||||
|
||||
@cached_property
|
||||
def default_channel(self) -> Optional[str]:
|
||||
"""
|
||||
:return: Default channel as defined in
|
||||
https://github.com/operator-framework/operator-registry/blob/master/docs/design/opm-tooling.md
|
||||
"""
|
||||
try:
|
||||
return sorted(
|
||||
[
|
||||
(
|
||||
Version.parse(x.csv_operator_version.lstrip("v")),
|
||||
x.default_channel,
|
||||
)
|
||||
for x in self.all_bundles()
|
||||
if x.default_channel is not None
|
||||
]
|
||||
)[-1][1]
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
def channel_bundles(self, channel: str) -> List[Bundle]:
|
||||
"""
|
||||
:param channel: Name of the channel
|
||||
:return: List of bundles in the given channel
|
||||
"""
|
||||
return sorted({x for x in self.all_bundles() if channel in x.channels})
|
||||
|
||||
def head(self, channel: str) -> Bundle:
|
||||
"""
|
||||
:param channel: Name of the channel
|
||||
:return: Head of the channel
|
||||
"""
|
||||
return self.channel_bundles(channel)[-1]
|
||||
|
||||
def update_graph(self, channel: str) -> Dict[Bundle, Set[Bundle]]:
|
||||
"""
|
||||
Return the update graph for the given channel
|
||||
:param channel: Name of the channel
|
||||
:return: Update graph edges in the form of a dictionary mapping each bundle
|
||||
to a set of bundles that can replace it
|
||||
"""
|
||||
all_bundles = self.channel_bundles(channel)
|
||||
update_strategy = self.config.get("updateGraph", "replaces-mode")
|
||||
if update_strategy == "semver-mode":
|
||||
return {x: {y} for x, y in zip(all_bundles, all_bundles[1:])}
|
||||
if update_strategy == "semver-skippatch":
|
||||
# TODO: implement semver-skippatch
|
||||
raise NotImplementedError("%s: semver-skippatch is not implemented yet")
|
||||
if update_strategy == "replaces-mode":
|
||||
edges: Dict[Bundle, set[Bundle]] = {}
|
||||
all_bundles_set = set(all_bundles)
|
||||
for bundle in all_bundles_set:
|
||||
try:
|
||||
spec = bundle.csv["spec"]
|
||||
except KeyError:
|
||||
continue
|
||||
replaces = spec.get("replaces")
|
||||
skips = spec.get("skips", [])
|
||||
for replaced_bundle_name in skips + [replaces]:
|
||||
if replaced_bundle_name is None:
|
||||
continue
|
||||
if ".v" not in replaced_bundle_name:
|
||||
raise ValueError(
|
||||
f"{bundle} has invalid 'replaces' field: '{replaced_bundle_name}'"
|
||||
)
|
||||
(
|
||||
replaced_bundle_operator,
|
||||
replaced_bundle_version,
|
||||
) = replaced_bundle_name.split(".", 1)
|
||||
if replaced_bundle_operator != bundle.csv_operator_name:
|
||||
raise ValueError(
|
||||
f"{self}: {bundle} replaces a bundle from a different operator"
|
||||
)
|
||||
try:
|
||||
replaced_bundle = self.bundle(
|
||||
replaced_bundle_version.lstrip("v")
|
||||
)
|
||||
edges.setdefault(replaced_bundle, set()).add(bundle)
|
||||
except InvalidBundleException:
|
||||
pass
|
||||
return edges
|
||||
raise ValueError(f"{self}: unknown updateGraph value: {update_strategy}")
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if not isinstance(other, self.__class__):
|
||||
raise NotImplementedError(
|
||||
f"Can't compare {self.__class__.__name__} to {other.__class__.__name__}"
|
||||
)
|
||||
return self.operator_name == other.operator_name
|
||||
|
||||
def __ne__(self, other: object) -> bool:
|
||||
if not isinstance(other, self.__class__):
|
||||
raise NotImplementedError(
|
||||
f"Can't compare {self.__class__.__name__} to {other.__class__.__name__}"
|
||||
)
|
||||
return self.operator_name != other.operator_name
|
||||
|
||||
def __lt__(self, other: object) -> bool:
|
||||
if not isinstance(other, self.__class__):
|
||||
raise NotImplementedError(
|
||||
f"Can't compare {self.__class__.__name__} to {other.__class__.__name__}"
|
||||
)
|
||||
return self.operator_name < other.operator_name
|
||||
|
||||
def __iter__(self) -> Iterator[Bundle]:
|
||||
yield from self.all_bundles()
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.operator_name,))
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"{self.__class__.__name__}({self.operator_name})"
|
||||
|
||||
|
||||
class Repo:
|
||||
"""A repository containing a collection of operators"""
|
||||
|
||||
OPERATORS_DIR = "operators"
|
||||
|
||||
def __init__(self, repo_path: Union[str, Path]):
|
||||
log.debug("Loading repo at %s", repo_path)
|
||||
self._repo_path = Path(repo_path).resolve()
|
||||
if not self.probe(self._repo_path):
|
||||
raise InvalidRepoException(
|
||||
f"Not a valid operator repository: {self._repo_path}"
|
||||
)
|
||||
self._operators_path = self._repo_path / self.OPERATORS_DIR
|
||||
|
||||
@cached_property
|
||||
def config(self) -> Any:
|
||||
"""
|
||||
:return: The contents of the ci/pipeline-config.yaml for the repo
|
||||
"""
|
||||
try:
|
||||
return load_yaml(self._repo_path / "ci" / "pipeline-config.yaml")
|
||||
except FileNotFoundError:
|
||||
log.warning("No ci/pipeline-config.yaml found for %s", self)
|
||||
return {}
|
||||
|
||||
@classmethod
|
||||
def probe(cls, path: Path) -> bool:
|
||||
"""
|
||||
:return: True if path looks like an operator repo
|
||||
"""
|
||||
return path.is_dir() and (path / cls.OPERATORS_DIR).is_dir()
|
||||
|
||||
@property
|
||||
def root(self) -> str:
|
||||
"""
|
||||
:return: The path to the root of the repository
|
||||
"""
|
||||
return str(self._repo_path)
|
||||
|
||||
def all_operators(self) -> Iterator[Operator]:
|
||||
"""
|
||||
:return: All the operators in the repo
|
||||
"""
|
||||
for operator_path in self._operators_path.iterdir():
|
||||
if Operator.probe(operator_path):
|
||||
yield self.operator(operator_path.name)
|
||||
|
||||
def operator_path(self, operator_name: str) -> Path:
|
||||
"""
|
||||
Return the path where an operator with the given
|
||||
name would be located
|
||||
:param operator_name: Name of the operator
|
||||
:return: Path to the operator
|
||||
"""
|
||||
return self._operators_path / operator_name
|
||||
|
||||
def operator(self, operator_name: str) -> Operator:
|
||||
"""
|
||||
Load the operator with the given name
|
||||
:param operator_name: Name of the operator
|
||||
:return: The loaded operator
|
||||
"""
|
||||
return Operator(self.operator_path(operator_name))
|
||||
|
||||
def has(self, operator_name: str) -> bool:
|
||||
"""
|
||||
Check if the repo contains an operator with the given name
|
||||
:param operator_name: Name of the operator to look for
|
||||
:return: True if the repo contains an operator with the given name
|
||||
"""
|
||||
return Operator.probe(self.operator_path(operator_name))
|
||||
|
||||
def __iter__(self) -> Iterator[Operator]:
|
||||
yield from self.all_operators()
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"{self.__class__.__name__}({self._repo_path})"
|
|
@ -0,0 +1,169 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
CLI tool to handle operator repositories
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
from itertools import chain
|
||||
from pathlib import Path
|
||||
from typing import Union, Dict, Any, Iterator, Tuple
|
||||
|
||||
from operator_repo.classes import Bundle, Operator, Repo
|
||||
|
||||
|
||||
def parse_target(repo: Repo, target: str) -> Union[Operator, Bundle]:
|
||||
if "/" in target:
|
||||
operator_name, operator_version = target.split("/", 1)
|
||||
return repo.operator(operator_name).bundle(operator_version)
|
||||
return repo.operator(target)
|
||||
|
||||
|
||||
def indent(depth: int) -> str:
|
||||
return " " * depth
|
||||
|
||||
|
||||
def _list(
|
||||
target: Union[Repo, Operator, Bundle], recursive: bool = False, depth: int = 0
|
||||
) -> None:
|
||||
if isinstance(target, Repo):
|
||||
print(indent(depth) + str(target))
|
||||
for operator in target:
|
||||
if recursive:
|
||||
_list(operator, True, depth + 1)
|
||||
else:
|
||||
print(indent(depth + 1) + str(operator))
|
||||
elif isinstance(target, Operator):
|
||||
print(indent(depth) + str(target))
|
||||
for bundle in target:
|
||||
if recursive:
|
||||
_list(bundle, True, depth + 1)
|
||||
else:
|
||||
print(indent(depth + 1) + str(bundle))
|
||||
elif isinstance(target, Bundle):
|
||||
print(indent(depth) + str(target))
|
||||
csv_annotations = target.csv.get("metadata", {}).get("annotations", {})
|
||||
info = [
|
||||
("Description", csv_annotations.get("description", "")),
|
||||
("Name", f"{target.csv_operator_name}.{target.csv_operator_version}"),
|
||||
("Channels", ", ".join(target.channels)),
|
||||
("Default channel", target.default_channel),
|
||||
("Container image", csv_annotations.get("containerImage", "")),
|
||||
]
|
||||
max_width = max([len(key) for key, _ in info])
|
||||
for key, value in info:
|
||||
message = f"{key.ljust(max_width+1)}: {value}"
|
||||
print(indent(depth + 1) + message)
|
||||
|
||||
|
||||
def action_list(repo_path, *what: str, recursive: bool = False) -> None:
|
||||
repo = Repo(repo_path)
|
||||
if not what:
|
||||
_list(repo, recursive)
|
||||
else:
|
||||
for target in what:
|
||||
_list(parse_target(repo, target), recursive)
|
||||
|
||||
|
||||
def lookup_dict(data: Dict[str, Any], path: str, default: Any = None, separator: str = '.') -> Any:
|
||||
keys = path.split(separator)
|
||||
subtree = data
|
||||
for key in keys:
|
||||
if key not in subtree:
|
||||
return default
|
||||
subtree = subtree[key]
|
||||
return subtree
|
||||
|
||||
|
||||
def do_check_bundle_operator_name(bundle: Bundle) -> Iterator[Tuple[str, str]]:
|
||||
name = bundle.annotations.get("operators.operatorframework.io.bundle.package.v1")
|
||||
if name is None:
|
||||
yield "fail", "Bundle does not define the operator name in annotations.yaml"
|
||||
return
|
||||
if name != bundle.csv_operator_name:
|
||||
yield "fail", "Operator name from annotations.yaml does not match the name defined in the CSV"
|
||||
if name != bundle.operator_name:
|
||||
yield "fail", "Operator name from annotations.yaml does not match the operator's directory name"
|
||||
|
||||
|
||||
def do_check_bundle_image(bundle: Bundle) -> Iterator[Tuple[str, str]]:
|
||||
container_image = lookup_dict(bundle.csv, "metadata.annotations.containerImage")
|
||||
if container_image is None:
|
||||
yield "fail", "CSV doesn't define .metadata.annotations.containerImage"
|
||||
return
|
||||
deployments = lookup_dict(bundle.csv, "spec.install.spec.deployments")
|
||||
if deployments is None:
|
||||
yield "fail", "CSV doesn't define .spec.install.spec.deployments"
|
||||
return
|
||||
for deployment in deployments:
|
||||
containers = lookup_dict(deployment, "spec.template.spec.containers", [])
|
||||
if any(container_image == x.get("image") for x in containers):
|
||||
return
|
||||
yield "fail", f"container image {container_image} not used by any deployment"
|
||||
|
||||
|
||||
def action_check_bundles(repo_path: Path, *what: str) -> None:
|
||||
for bundle_name in what:
|
||||
print(f"Checking {bundle_name}")
|
||||
bundle = parse_target(Repo(repo_path), bundle_name)
|
||||
for result, message in chain(do_check_bundle_image(bundle), do_check_bundle_operator_name(bundle)):
|
||||
print(f"{result.upper()}: {message}")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
main_parser = argparse.ArgumentParser(
|
||||
description="Operator repository manipulation tool",
|
||||
)
|
||||
main_parser.add_argument(
|
||||
"-r", "--repo", help="path to the root of the operator repository", type=Path
|
||||
)
|
||||
main_parser.add_argument(
|
||||
"-v", "--verbose", action="count", default=0, help="increase log verbosity"
|
||||
)
|
||||
main_subparsers = main_parser.add_subparsers(dest="action")
|
||||
|
||||
# list
|
||||
list_parser = main_subparsers.add_parser(
|
||||
"list", help="list contents of repo, operators or bundles"
|
||||
)
|
||||
list_parser.add_argument(
|
||||
"-R", "--recursive", action="store_true", help="descend the tree"
|
||||
)
|
||||
list_parser.add_argument(
|
||||
"target",
|
||||
nargs="*",
|
||||
help="name of the repos or bundles to list; if omitted, list the contents of the repo",
|
||||
)
|
||||
|
||||
# check_bundle
|
||||
check_bundle_parser = main_subparsers.add_parser(
|
||||
"check-bundle", help="check validity of a bundle"
|
||||
)
|
||||
check_bundle_parser.add_argument(
|
||||
"target",
|
||||
nargs="*",
|
||||
help="name of the bundles to check",
|
||||
)
|
||||
|
||||
args = main_parser.parse_args()
|
||||
# print(args)
|
||||
|
||||
verbosity = {0: logging.ERROR, 1: logging.WARNING, 2: logging.INFO}
|
||||
log = logging.getLogger(__package__)
|
||||
log.setLevel(verbosity.get(args.verbose, logging.DEBUG))
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(
|
||||
logging.Formatter("%(asctime)s %(name)-12s %(levelname)-8s %(message)s")
|
||||
)
|
||||
log.addHandler(handler)
|
||||
|
||||
if args.action == "list":
|
||||
action_list(args.repo or Path.cwd(), *args.target, recursive=args.recursive)
|
||||
elif args.action == "check-bundle":
|
||||
action_check_bundles(args.repo or Path.cwd(), *args.target)
|
||||
else:
|
||||
main_parser.print_help()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -0,0 +1,19 @@
|
|||
"""
|
||||
Exceptions
|
||||
"""
|
||||
|
||||
|
||||
class OperatorRepoException(Exception):
|
||||
"""Base exception class"""
|
||||
|
||||
|
||||
class InvalidRepoException(OperatorRepoException):
|
||||
"""Error caused by an invalid repository structure"""
|
||||
|
||||
|
||||
class InvalidOperatorException(OperatorRepoException):
|
||||
"""Error caused by an invalid operator"""
|
||||
|
||||
|
||||
class InvalidBundleException(OperatorRepoException):
|
||||
"""Error caused by an invalid bundle"""
|
|
@ -0,0 +1,41 @@
|
|||
"""
|
||||
Utility functions to load yaml files
|
||||
"""
|
||||
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import yaml
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _find_yaml(path: Path) -> Path:
|
||||
"""Look for yaml files with alternate extensions"""
|
||||
|
||||
if path.is_file():
|
||||
return path
|
||||
tries = [path]
|
||||
for alt_extension in [".yaml", ".yml"]:
|
||||
if alt_extension == path.suffix:
|
||||
continue
|
||||
new_path = path.with_suffix(alt_extension)
|
||||
if new_path.is_file():
|
||||
return new_path
|
||||
tries.append(new_path)
|
||||
tries_str = ", ".join([str(x) for x in tries])
|
||||
raise FileNotFoundError(f"Can't find yaml file. Tried: {tries_str}")
|
||||
|
||||
|
||||
def _load_yaml_strict(path: Path) -> Any:
|
||||
"""Returns the parsed contents of the YAML file at the given path"""
|
||||
|
||||
log.debug("Loading %s", path)
|
||||
with path.open("r") as yaml_file:
|
||||
return yaml.safe_load(yaml_file)
|
||||
|
||||
|
||||
def load_yaml(path: Path) -> Any:
|
||||
"""Same as _load_yaml_strict but tries both .yaml and .yml extensions"""
|
||||
return _load_yaml_strict(_find_yaml(path))
|
|
@ -0,0 +1,63 @@
|
|||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
def merge(a, b, path=None):
|
||||
if path is None:
|
||||
path = []
|
||||
for key in b:
|
||||
if key in a:
|
||||
if isinstance(a[key], dict) and isinstance(b[key], dict):
|
||||
merge(a[key], b[key], path + [str(key)])
|
||||
else:
|
||||
a[key] = b[key]
|
||||
else:
|
||||
a[key] = b[key]
|
||||
return a
|
||||
|
||||
|
||||
def create_files(path, *contents):
|
||||
root = Path(path)
|
||||
for element in contents:
|
||||
for file_name, content in element.items():
|
||||
full_path = root / file_name
|
||||
if content is None:
|
||||
full_path.mkdir(parents=True, exist_ok=True)
|
||||
else:
|
||||
full_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
if isinstance(content, (str, bytes)):
|
||||
full_path.write_text(content)
|
||||
else:
|
||||
full_path.write_text(yaml.safe_dump(content))
|
||||
|
||||
|
||||
def bundle_files(
|
||||
operator_name, bundle_version, annotations=None, csv=None, other_files=None
|
||||
):
|
||||
bundle_path = f"operators/{operator_name}/{bundle_version}"
|
||||
base_annotations = {
|
||||
"operators.operatorframework.io.bundle.mediatype.v1": "registry+v1",
|
||||
"operators.operatorframework.io.bundle.manifests.v1": "manifests/",
|
||||
"operators.operatorframework.io.bundle.metadata.v1": "metadata/",
|
||||
"operators.operatorframework.io.bundle.package.v1": operator_name,
|
||||
"operators.operatorframework.io.bundle.channel.default.v1": "beta",
|
||||
"operators.operatorframework.io.bundle.channels.v1": "beta",
|
||||
}
|
||||
base_csv = {
|
||||
"metadata": {
|
||||
"name": f"{operator_name}.v{bundle_version}",
|
||||
"spec": {"version": bundle_version},
|
||||
}
|
||||
}
|
||||
return merge(
|
||||
{
|
||||
f"{bundle_path}/metadata/annotations.yaml": {
|
||||
"annotations": merge(base_annotations, annotations or {})
|
||||
},
|
||||
f"{bundle_path}/manifests/{operator_name}.clusterserviceversion.yaml": merge(
|
||||
base_csv, csv or {}
|
||||
),
|
||||
},
|
||||
other_files or {},
|
||||
)
|
|
@ -0,0 +1,109 @@
|
|||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from operator_repo import Bundle, Repo
|
||||
from operator_repo.exceptions import InvalidBundleException, InvalidOperatorException
|
||||
from tests import bundle_files, create_files
|
||||
|
||||
|
||||
def test_bundle(tmp_path: Path) -> None:
|
||||
create_files(
|
||||
tmp_path,
|
||||
bundle_files("hello", "0.0.1"),
|
||||
)
|
||||
repo = Repo(tmp_path)
|
||||
operator = repo.operator("hello")
|
||||
bundle = operator.bundle("0.0.1")
|
||||
assert bundle.root == operator.root + "/0.0.1"
|
||||
assert bundle.csv_operator_name == "hello"
|
||||
assert bundle.csv_operator_version == "0.0.1"
|
||||
assert (
|
||||
bundle.annotations["operators.operatorframework.io.bundle.package.v1"]
|
||||
== "hello"
|
||||
)
|
||||
assert bundle.dependencies == []
|
||||
|
||||
|
||||
def test_bundle_compare(tmp_path: Path) -> None:
|
||||
create_files(
|
||||
tmp_path,
|
||||
bundle_files("hello", "0.0.1"),
|
||||
bundle_files("hello", "0.0.2"),
|
||||
bundle_files("world", "0.1.0"),
|
||||
)
|
||||
repo = Repo(tmp_path)
|
||||
operator_hello = repo.operator("hello")
|
||||
operator_world = repo.operator("world")
|
||||
assert operator_hello == repo.operator("hello")
|
||||
assert operator_hello != operator_world
|
||||
assert operator_hello < operator_world
|
||||
hello_bundle_1 = operator_hello.bundle("0.0.1")
|
||||
hello_bundle_2 = operator_hello.bundle("0.0.2")
|
||||
world_bundle_1 = operator_world.bundle("0.1.0")
|
||||
assert hello_bundle_1 != hello_bundle_2
|
||||
assert hello_bundle_1 < hello_bundle_2
|
||||
assert hello_bundle_1 != world_bundle_1
|
||||
with pytest.raises(ValueError):
|
||||
_ = hello_bundle_1 < world_bundle_1
|
||||
|
||||
|
||||
def test_bundle_non_semver(tmp_path: Path) -> None:
|
||||
create_files(
|
||||
tmp_path,
|
||||
bundle_files("hello", "0.0.99.0"),
|
||||
bundle_files("hello", "0.0.100.0"),
|
||||
)
|
||||
repo = Repo(tmp_path)
|
||||
operator = repo.operator("hello")
|
||||
bundle_99 = operator.bundle("0.0.99.0")
|
||||
bundle_100 = operator.bundle("0.0.100.0")
|
||||
assert bundle_99 > bundle_100
|
||||
|
||||
|
||||
def test_bundle_invalid(tmp_path: Path) -> None:
|
||||
create_files(
|
||||
tmp_path,
|
||||
bundle_files(
|
||||
"invalid_csv_name", "0.0.1", csv={"metadata": {"name": "rubbish"}}
|
||||
),
|
||||
{
|
||||
"operators/missing_manifests/0.0.1/metadata/annotations.yaml": {
|
||||
"annotations": {}
|
||||
}
|
||||
},
|
||||
bundle_files("invalid_csv_contents", "0.0.1"),
|
||||
{
|
||||
"operators/invalid_csv_contents/0.0.1/manifests/invalid_csv_contents.clusterserviceversion.yaml": [],
|
||||
},
|
||||
bundle_files("invalid_metadata_contents", "0.0.1"),
|
||||
{
|
||||
"operators/invalid_metadata_contents/0.0.1/metadata/annotations.yaml": [],
|
||||
},
|
||||
bundle_files("empty_metadata", "0.0.1"),
|
||||
{
|
||||
"operators/empty_metadata/0.0.1/metadata/annotations.yaml": "",
|
||||
},
|
||||
{
|
||||
"operators/missing_csv/0.0.1/metadata/annotations.yaml": {
|
||||
"annotations": {}
|
||||
},
|
||||
"operators/missing_csv/0.0.1/manifests": None,
|
||||
},
|
||||
)
|
||||
repo = Repo(tmp_path)
|
||||
with pytest.raises(InvalidBundleException, match="has invalid .metadata.name"):
|
||||
_ = repo.operator("invalid_csv_name").bundle("0.0.1").csv_operator_name
|
||||
assert not repo.has("missing_manifests")
|
||||
with pytest.raises(InvalidBundleException, match="Not a valid bundle"):
|
||||
_ = Bundle(repo.root + "/operators/missing_manifests/0.0.1")
|
||||
with pytest.raises(InvalidOperatorException, match="Not a valid operator"):
|
||||
_ = repo.operator("missing_manifests")
|
||||
assert repo.has("invalid_csv_contents")
|
||||
with pytest.raises(InvalidBundleException, match="Invalid CSV contents"):
|
||||
_ = repo.operator("invalid_csv_contents").bundle("0.0.1").csv_operator_version
|
||||
with pytest.raises(InvalidBundleException, match="Invalid .* contents"):
|
||||
_ = repo.operator("invalid_metadata_contents").bundle("0.0.1").annotations
|
||||
assert repo.operator("empty_metadata").bundle("0.0.1").annotations == {}
|
||||
assert repo.has("missing_csv")
|
||||
with pytest.raises(InvalidBundleException, match="CSV file for .* not found"):
|
||||
_ = repo.operator("missing_csv").bundle("0.0.1").csv_operator_name
|
|
@ -0,0 +1,98 @@
|
|||
from pathlib import Path
|
||||
|
||||
from operator_repo import Repo
|
||||
from tests import bundle_files, create_files
|
||||
|
||||
|
||||
def test_operator_empty(tmp_path: Path) -> None:
|
||||
create_files(tmp_path, {"operators/hello/readme.txt": "hello"})
|
||||
repo = Repo(tmp_path)
|
||||
assert not repo.has("hello")
|
||||
|
||||
|
||||
def test_operator_one_bundle(tmp_path: Path) -> None:
|
||||
create_files(tmp_path, bundle_files("hello", "0.0.1"))
|
||||
repo = Repo(tmp_path)
|
||||
operator = repo.operator("hello")
|
||||
bundle = operator.bundle("0.0.1")
|
||||
assert len(list(operator)) == 1
|
||||
assert set(operator) == {bundle}
|
||||
assert operator.has("0.0.1")
|
||||
assert bundle.operator() == operator
|
||||
assert operator.config == {}
|
||||
assert bundle.dependencies == []
|
||||
assert operator.root == repo.root + "/operators/hello"
|
||||
assert "hello" in repr(operator)
|
||||
|
||||
|
||||
def test_channels(tmp_path: Path) -> None:
|
||||
create_files(
|
||||
tmp_path,
|
||||
bundle_files("hello", "0.0.1"),
|
||||
bundle_files("hello", "0.0.2", csv={"spec": {"replaces": "hello.v0.0.1"}}),
|
||||
bundle_files(
|
||||
"hello",
|
||||
"0.1.0",
|
||||
csv={"spec": {"replaces": "hello.v0.0.2"}},
|
||||
annotations={
|
||||
"operators.operatorframework.io.bundle.channel.default.v1": "candidate",
|
||||
"operators.operatorframework.io.bundle.channels.v1": "beta,candidate",
|
||||
},
|
||||
),
|
||||
bundle_files(
|
||||
"hello",
|
||||
"1.0.0",
|
||||
csv={"spec": {"replaces": "hello.v0.1.0"}},
|
||||
annotations={
|
||||
"operators.operatorframework.io.bundle.channel.default.v1": "stable",
|
||||
"operators.operatorframework.io.bundle.channels.v1": "beta,candidate,stable",
|
||||
},
|
||||
),
|
||||
bundle_files("hello", "1.0.1", csv={"spec": {"replaces": "hello.v1.0.0"}}),
|
||||
)
|
||||
repo = Repo(tmp_path)
|
||||
operator = repo.operator("hello")
|
||||
bundle001 = operator.bundle("0.0.1")
|
||||
bundle002 = operator.bundle("0.0.2")
|
||||
bundle010 = operator.bundle("0.1.0")
|
||||
bundle100 = operator.bundle("1.0.0")
|
||||
bundle101 = operator.bundle("1.0.1")
|
||||
assert operator.channels == {"beta", "candidate", "stable"}
|
||||
assert operator.default_channel == "beta"
|
||||
assert operator.channel_bundles("beta") == [
|
||||
bundle001,
|
||||
bundle002,
|
||||
bundle010,
|
||||
bundle100,
|
||||
bundle101,
|
||||
]
|
||||
assert operator.channel_bundles("candidate") == [bundle010, bundle100]
|
||||
assert operator.channel_bundles("stable") == [bundle100]
|
||||
assert operator.head("beta") == bundle101
|
||||
assert operator.head("candidate") == bundle100
|
||||
assert operator.head("stable") == bundle100
|
||||
|
||||
|
||||
def test_update_graph(tmp_path: Path) -> None:
|
||||
create_files(
|
||||
tmp_path,
|
||||
bundle_files("hello", "0.0.1"),
|
||||
bundle_files("hello", "0.0.2", csv={"spec": {"replaces": "hello.v0.0.1"}}),
|
||||
bundle_files("hello", "0.0.3", csv={"spec": {"replaces": "hello.v0.0.2"}}),
|
||||
bundle_files(
|
||||
"hello",
|
||||
"0.0.4",
|
||||
csv={"spec": {"replaces": "hello.v0.0.2", "skips": ["hello.v0.0.3"]}},
|
||||
),
|
||||
)
|
||||
repo = Repo(tmp_path)
|
||||
operator = repo.operator("hello")
|
||||
bundle1 = operator.bundle("0.0.1")
|
||||
bundle2 = operator.bundle("0.0.2")
|
||||
bundle3 = operator.bundle("0.0.3")
|
||||
bundle4 = operator.bundle("0.0.4")
|
||||
assert operator.head("beta") == bundle4
|
||||
update = operator.update_graph("beta")
|
||||
assert update[bundle1] == {bundle2}
|
||||
assert update[bundle2] == {bundle3, bundle4}
|
||||
assert update[bundle3] == {bundle4}
|
|
@ -0,0 +1,40 @@
|
|||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from operator_repo import Repo
|
||||
from operator_repo.exceptions import InvalidRepoException
|
||||
from tests import bundle_files, create_files
|
||||
|
||||
|
||||
def test_repo_non_existent() -> None:
|
||||
with pytest.raises(InvalidRepoException, match="Not a valid operator repository"):
|
||||
_ = Repo("/non_existent")
|
||||
|
||||
|
||||
def test_repo_empty(tmp_path: Path) -> None:
|
||||
with pytest.raises(InvalidRepoException, match="Not a valid operator repository"):
|
||||
_ = Repo(str(tmp_path))
|
||||
|
||||
|
||||
def test_repo_no_operators(tmp_path: Path) -> None:
|
||||
create_files(
|
||||
tmp_path,
|
||||
{
|
||||
"operators": None,
|
||||
"ci/pipeline-config.yaml": {"hello": "world"},
|
||||
},
|
||||
)
|
||||
repo = Repo(tmp_path)
|
||||
assert len(list(repo)) == 0
|
||||
assert repo.config == {"hello": "world"}
|
||||
assert repo.root == str(tmp_path.resolve())
|
||||
assert str(tmp_path) in repr(repo)
|
||||
|
||||
|
||||
def test_repo_one_bundle(tmp_path: Path) -> None:
|
||||
create_files(tmp_path, bundle_files("hello", "0.0.1"))
|
||||
repo = Repo(tmp_path)
|
||||
assert repo.config == {}
|
||||
assert len(list(repo)) == 1
|
||||
assert set(repo) == {repo.operator("hello")}
|
||||
assert repo.has("hello")
|
|
@ -0,0 +1,23 @@
|
|||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from operator_repo.utils import load_yaml
|
||||
from tests import create_files
|
||||
|
||||
|
||||
def test_load_yaml(tmp_path: Path) -> None:
|
||||
create_files(
|
||||
tmp_path,
|
||||
{"data/en.yml": {"hello": "world"}},
|
||||
{"data/it.yaml": {"ciao": "mondo"}},
|
||||
{"data/something.txt": {"foo": "bar"}},
|
||||
)
|
||||
assert load_yaml(tmp_path / "data/en.yaml") == {"hello": "world"}
|
||||
assert load_yaml(tmp_path / "data/en.yml") == {"hello": "world"}
|
||||
assert load_yaml(tmp_path / "data/it.yaml") == {"ciao": "mondo"}
|
||||
assert load_yaml(tmp_path / "data/it.yml") == {"ciao": "mondo"}
|
||||
assert load_yaml(tmp_path / "data/something.txt") == {"foo": "bar"}
|
||||
with pytest.raises(FileNotFoundError):
|
||||
_ = load_yaml(tmp_path / "data/something.yaml")
|
||||
with pytest.raises(FileNotFoundError):
|
||||
_ = load_yaml(tmp_path / "data/something.yml")
|
|
@ -0,0 +1,9 @@
|
|||
[tox]
|
||||
envlist = py{38,39,310,311}, pypy39
|
||||
isolated_build = True ; This is required for a pyproject.toml based project.
|
||||
|
||||
[testenv]
|
||||
groups = ; Dependency groups in pyproject.toml
|
||||
dev
|
||||
commands =
|
||||
pytest --cov-report term-missing --cov=operator_repo -v tests/
|
Loading…
Reference in New Issue