diff --git a/.github/change_version.py b/.github/change_version.py index 54f7574..9a322a1 100755 --- a/.github/change_version.py +++ b/.github/change_version.py @@ -6,6 +6,11 @@ VERSION_PY = Path(__file__).parent.parent / 'defectdojo_api_generated' / '__init__.py' VERSION_RE = re.compile(r"__version__ = '(.*?)'") +CLI_VERSION_PY = ( + Path(__file__).parent.parent / 'packages' / 'cli' / 'src' / 'defectdojo_api_generated_cli' / '__init__.py' +) +CLI_DEPENDENCY_PYPROJECT = Path(__file__).parent.parent / 'packages' / 'cli' / 'pyproject.toml' +CLI_DEPENDENCY_RE = re.compile(r'("defectdojo-api-generated==)([^"]+)(")') def main(): @@ -22,6 +27,10 @@ def main(): if args.set: VERSION_PY.write_text(VERSION_RE.sub(f"__version__ = '{args.set}'", data)) + cli_version_data = CLI_VERSION_PY.read_text() + CLI_VERSION_PY.write_text(VERSION_RE.sub(f"__version__ = '{args.set}'", cli_version_data)) + cli_pyproject_data = CLI_DEPENDENCY_PYPROJECT.read_text() + CLI_DEPENDENCY_PYPROJECT.write_text(CLI_DEPENDENCY_RE.sub(rf'\g<1>{args.set}\g<3>', cli_pyproject_data)) print(f'New version: {args.set}') diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 6790207..227ee5b 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -57,12 +57,15 @@ jobs: run: | .github/change_version.py --set '${{ inputs.version }}' - name: Build - run: uv run pyproject-build + run: | + rm -rf dist packages/cli/dist + uv run pyproject-build + uv run pyproject-build packages/cli - name: Publish env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.twine_token }} - run: uv run twine upload --verbose --repository ${{ inputs.repository }} dist/* + run: uv run twine upload --verbose --repository ${{ inputs.repository }} dist/* packages/cli/dist/* - name: highlight run: | INDEX="" @@ -70,8 +73,9 @@ jobs: INDEX=" -i ${{ inputs.repository }}" fi cat <> ${GITHUB_STEP_SUMMARY} - \`example\` uploaded to ${{ inputs.repository }} + Packages uploaded to ${{ inputs.repository }} \`\`\` pip install${INDEX} defectdojo-api-generated==${{ inputs.version }} + pip install${INDEX} defectdojo-api-generated-cli==${{ inputs.version }} \`\`\` EOF diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f658502..89368d1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,6 +33,10 @@ jobs: run: | make lint-check + - name: Build CLI package + run: | + uv run pyproject-build packages/cli + unit-tests: runs-on: ubuntu-latest strategy: @@ -50,7 +54,7 @@ jobs: - name: Install dependencies run: | pip install uv - uv sync --dev --extra cli + uv sync --dev - name: Run unit tests run: | @@ -76,7 +80,7 @@ jobs: - name: Install dependencies run: | pip install uv - uv sync --dev --extra cli + uv sync --dev - name: Run e2e tests run: | @@ -96,7 +100,7 @@ jobs: - name: Install dependencies run: | pip install uv - uv sync --dev --extra cli + uv sync --dev - name: build docs run: | diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 64f1212..ab20343 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -12,7 +12,7 @@ build: jobs: post_install: - pip install uv - - UV_PROJECT_ENVIRONMENT=$READTHEDOCS_VIRTUALENV_PATH uv sync --dev --extra cli + - UV_PROJECT_ENVIRONMENT=$READTHEDOCS_VIRTUALENV_PATH uv sync --dev --all-extras # Build documentation with Mkdocs mkdocs: diff --git a/AGENTS.md b/AGENTS.md index 15233a4..9e7bbac 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -121,6 +121,11 @@ Formatting and lint: - `make lint` - `make lint-check` +Repo-specific expectation: + +- After any code, template, packaging, or GitHub Actions change, run `make lint`. +- Do not treat `make lint` as optional or defer it unless the user explicitly asks not to run it or you are blocked. + Tests: - `make test` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4fc2849..b81975f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,13 +3,22 @@ This project uses `uv`, so set up the virtualenv by running ``` -uv sync --dev --extra cli +uv sync --dev ``` Use `make test` to make sure all tests pass before pushing. Use `make lint` to make sure lint check passes before pushing. +## Packaging layout + +The main package, `defectdojo-api-generated`, is intentionally library-only. +It does not publish console scripts and should remain installable without CLI-only dependencies. + +The `dojo` entrypoint lives in the thin wrapper package under `packages/cli/`. +That package depends on the main library plus the CLI stack and should stay small: +keep CLI packaging, entrypoints, and CLI-only dependency wiring there, while the actual CLI implementation can continue to live under `defectdojo_api_generated/cli/`. + ## Guidelines ### Update openapi-generator version diff --git a/Makefile b/Makefile index 8afdb55..29323c1 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ sync: .venv39: export VIRTUAL_ENV=.venv39 .venv39: - uv sync --dev --extra cli --python 3.9 --active + uv sync --dev --all-extras --python 3.9 --active test39: .venv39 test39: export VIRTUAL_ENV=.venv39 diff --git a/README.md b/README.md index df7d5f3..5c1e597 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Multiple changes done on top of default openapi-generator: * Remove most of pydantic/schema validations due to inconsistencies with actual database schema/requirements (tracked in https://github.com/fopina/defectdojo-api-generated/issues/39) * *Iterator* methods for every *list* API method to handle pagination automatically * A nice CLI exposing all the API methods <3 - * installed only as an extra, to keep everything clean when package is used as library only + * published as a separate package, to keep library-only installs free of console-script conflicts ## Example @@ -49,7 +49,7 @@ pip install defectojo-api-generated > [uv](https://docs.astral.sh/uv/) recommended or [pipx](https://github.com/pypa/pipx) ``` -uv tool install 'defectojo-api-generated[cli]' +uv tool install defectdojo-api-generated-cli ``` ``` @@ -69,7 +69,7 @@ Commands: You can also skip tool install and just run it with: ``` -$ uvx 'defectojo-api-generated[cli]' +$ uvx defectdojo-api-generated-cli Usage: dojo [OPTIONS] COMMAND [ARGS]... ... ``` diff --git a/packages/cli/.gitignore b/packages/cli/.gitignore new file mode 100644 index 0000000..86e5a2d --- /dev/null +++ b/packages/cli/.gitignore @@ -0,0 +1,4 @@ +.venv/ +dist/ +src/*.egg-info/ +uv.lock diff --git a/packages/cli/README.md b/packages/cli/README.md new file mode 100644 index 0000000..c507e5b --- /dev/null +++ b/packages/cli/README.md @@ -0,0 +1,5 @@ +# defectdojo-api-generated-cli + +Thin CLI wrapper distribution for [`defectdojo-api-generated`](https://pypi.org/project/defectdojo-api-generated/). + +This package owns the `dojo` console entrypoint and pulls in the optional CLI dependencies. diff --git a/packages/cli/pyproject.toml b/packages/cli/pyproject.toml new file mode 100644 index 0000000..b97e99f --- /dev/null +++ b/packages/cli/pyproject.toml @@ -0,0 +1,29 @@ +[build-system] +requires = ["setuptools>=69.5.0,<80.0.0"] +build-backend = "setuptools.build_meta" + +[project] +name = "defectdojo-api-generated-cli" +version = "1.0.0" +description = "CLI wrapper for defectdojo-api-generated" +readme = "README.md" +requires-python = ">=3.9,<4" +dependencies = [ + "classyclick==1.0.0", + "defectdojo-api-generated==1.0.0", + "jmespath>=1.0.1", +] + +[project.scripts] +dojo = "defectdojo_api_generated_cli.__main__:main" +defectdojo-api-generated = "defectdojo_api_generated_cli.__main__:main" + +[project.urls] +Homepage = "https://github.com/fopina/defectdojo-api-generated" + +[tool.uv.sources] +defectdojo-api-generated = { path = "../.." } + +[tool.setuptools.packages.find] +where = ["src"] +include = ["defectdojo_api_generated_cli"] diff --git a/packages/cli/src/defectdojo_api_generated_cli/__init__.py b/packages/cli/src/defectdojo_api_generated_cli/__init__.py new file mode 100644 index 0000000..d661f43 --- /dev/null +++ b/packages/cli/src/defectdojo_api_generated_cli/__init__.py @@ -0,0 +1,3 @@ +"""Thin wrapper distribution for the DefectDojo CLI.""" + +__version__ = '1.0.0' diff --git a/packages/cli/src/defectdojo_api_generated_cli/__main__.py b/packages/cli/src/defectdojo_api_generated_cli/__main__.py new file mode 100644 index 0000000..b1160ae --- /dev/null +++ b/packages/cli/src/defectdojo_api_generated_cli/__main__.py @@ -0,0 +1,6 @@ +"""Entrypoint owned by the separate CLI distribution.""" + +from defectdojo_api_generated.cli.__main__ import main + +if __name__ == '__main__': + main() diff --git a/pyproject.toml b/pyproject.toml index 0ba8842..d731677 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,20 +16,11 @@ dependencies = [ "typing-extensions>= 4.7.1", ] -[project.optional-dependencies] -cli = [ - "classyclick==1.0.0", - "jmespath>=1.0.1", -] - -[project.scripts] -dojo = "defectdojo_api_generated.cli.__main__:main" -# duplicated entrypoint to be able to use uvx without `--from` -defectdojo-api-generated = "defectdojo_api_generated.cli.__main__:main" - [dependency-groups] dev = [ "build", + "classyclick==1.0.0", + "jmespath>=1.0.1", "mkdocs>=1.6.1", "mkdocs-click>=0.9.0", "pytest", @@ -44,7 +35,7 @@ dev = [ Homepage = "https://github.com/fopina/defectdojo-api-generated" [tool.setuptools.packages.find] -include = ["defectdojo_api_generated*"] +include = ["defectdojo_api_generated", "defectdojo_api_generated.*"] [tool.setuptools.dynamic] version = {attr = "defectdojo_api_generated.__version__"} diff --git a/tests/unit/test_packaging.py b/tests/unit/test_packaging.py new file mode 100644 index 0000000..76ed893 --- /dev/null +++ b/tests/unit/test_packaging.py @@ -0,0 +1,45 @@ +import pathlib +import re +import unittest + +try: + import tomllib +except ModuleNotFoundError: # pragma: no cover - Python < 3.11 + import tomli as tomllib + +import defectdojo_api_generated + +ROOT = pathlib.Path(__file__).resolve().parents[2] + + +class TestPackagingLayout(unittest.TestCase): + def test_library_package_has_no_console_scripts(self): + pyproject = tomllib.loads((ROOT / 'pyproject.toml').read_text()) + + self.assertNotIn('scripts', pyproject['project']) + + def test_cli_wrapper_package_owns_console_scripts(self): + pyproject = tomllib.loads((ROOT / 'packages' / 'cli' / 'pyproject.toml').read_text()) + + self.assertEqual( + pyproject['project']['scripts'], + { + 'dojo': 'defectdojo_api_generated_cli.__main__:main', + 'defectdojo-api-generated': 'defectdojo_api_generated_cli.__main__:main', + }, + ) + + def test_cli_wrapper_version_matches_library_version(self): + wrapper_init = (ROOT / 'packages' / 'cli' / 'src' / 'defectdojo_api_generated_cli' / '__init__.py').read_text() + match = re.search(r"__version__ = '([^']+)'", wrapper_init) + + self.assertIsNotNone(match) + self.assertEqual(match.group(1), defectdojo_api_generated.__version__) + + def test_cli_wrapper_dependency_matches_library_version(self): + pyproject = tomllib.loads((ROOT / 'packages' / 'cli' / 'pyproject.toml').read_text()) + + self.assertIn( + f'defectdojo-api-generated=={defectdojo_api_generated.__version__}', + pyproject['project']['dependencies'], + ) diff --git a/uv.lock b/uv.lock index a73d8e2..47bae63 100644 --- a/uv.lock +++ b/uv.lock @@ -61,36 +61,50 @@ sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8 wheels = [ { url = "https://files.pythonhosted.org/packages/50/bd/b1a6362b80628111e6653c961f987faa55262b4002fcec42308cad1db680/cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c", size = 208811, upload-time = "2025-09-08T23:22:12.267Z" }, { url = "https://files.pythonhosted.org/packages/4f/27/6933a8b2562d7bd1fb595074cf99cc81fc3789f6a6c05cdabb46284a3188/cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb", size = 216402, upload-time = "2025-09-08T23:22:13.455Z" }, + { url = "https://files.pythonhosted.org/packages/05/eb/b86f2a2645b62adcfff53b0dd97e8dfafb5c8aa864bd0d9a2c2049a0d551/cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0", size = 203217, upload-time = "2025-09-08T23:22:14.596Z" }, + { url = "https://files.pythonhosted.org/packages/9f/e0/6cbe77a53acf5acc7c08cc186c9928864bd7c005f9efd0d126884858a5fe/cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4", size = 203079, upload-time = "2025-09-08T23:22:15.769Z" }, { url = "https://files.pythonhosted.org/packages/98/29/9b366e70e243eb3d14a5cb488dfd3a0b6b2f1fb001a203f653b93ccfac88/cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453", size = 216475, upload-time = "2025-09-08T23:22:17.427Z" }, { url = "https://files.pythonhosted.org/packages/21/7a/13b24e70d2f90a322f2900c5d8e1f14fa7e2a6b3332b7309ba7b2ba51a5a/cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495", size = 218829, upload-time = "2025-09-08T23:22:19.069Z" }, { url = "https://files.pythonhosted.org/packages/60/99/c9dc110974c59cc981b1f5b66e1d8af8af764e00f0293266824d9c4254bc/cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5", size = 211211, upload-time = "2025-09-08T23:22:20.588Z" }, { url = "https://files.pythonhosted.org/packages/49/72/ff2d12dbf21aca1b32a40ed792ee6b40f6dc3a9cf1644bd7ef6e95e0ac5e/cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb", size = 218036, upload-time = "2025-09-08T23:22:22.143Z" }, { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" }, { url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476, upload-time = "2025-09-08T23:22:31.063Z" }, + { url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", size = 203374, upload-time = "2025-09-08T23:22:32.507Z" }, + { url = "https://files.pythonhosted.org/packages/84/ef/a7b77c8bdc0f77adc3b46888f1ad54be8f3b7821697a7b89126e829e676a/cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", size = 202597, upload-time = "2025-09-08T23:22:34.132Z" }, { url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", size = 215574, upload-time = "2025-09-08T23:22:35.443Z" }, { url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971, upload-time = "2025-09-08T23:22:36.805Z" }, { url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972, upload-time = "2025-09-08T23:22:38.436Z" }, { url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078, upload-time = "2025-09-08T23:22:39.776Z" }, { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, + { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, + { url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" }, { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, + { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, + { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, { url = "https://files.pythonhosted.org/packages/9b/13/c92e36358fbcc39cf0962e83223c9522154ee8630e1df7c0b3a39a8124e2/cffi-2.0.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c", size = 208813, upload-time = "2025-09-08T23:23:51.263Z" }, { url = "https://files.pythonhosted.org/packages/15/12/a7a79bd0df4c3bff744b2d7e52cc1b68d5e7e427b384252c42366dc1ecbc/cffi-2.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165", size = 216498, upload-time = "2025-09-08T23:23:52.494Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ad/5c51c1c7600bdd7ed9a24a203ec255dccdd0ebf4527f7b922a0bde2fb6ed/cffi-2.0.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534", size = 203243, upload-time = "2025-09-08T23:23:53.836Z" }, + { url = "https://files.pythonhosted.org/packages/32/f2/81b63e288295928739d715d00952c8c6034cb6c6a516b17d37e0c8be5600/cffi-2.0.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f", size = 203158, upload-time = "2025-09-08T23:23:55.169Z" }, { url = "https://files.pythonhosted.org/packages/1f/74/cc4096ce66f5939042ae094e2e96f53426a979864aa1f96a621ad128be27/cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63", size = 216548, upload-time = "2025-09-08T23:23:56.506Z" }, { url = "https://files.pythonhosted.org/packages/e8/be/f6424d1dc46b1091ffcc8964fa7c0ab0cd36839dd2761b49c90481a6ba1b/cffi-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2", size = 218897, upload-time = "2025-09-08T23:23:57.825Z" }, { url = "https://files.pythonhosted.org/packages/f7/e0/dda537c2309817edf60109e39265f24f24aa7f050767e22c98c53fe7f48b/cffi-2.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65", size = 211249, upload-time = "2025-09-08T23:23:59.139Z" }, @@ -551,15 +565,11 @@ dependencies = [ { name = "urllib3" }, ] -[package.optional-dependencies] -cli = [ - { name = "classyclick" }, - { name = "jmespath" }, -] - [package.dev-dependencies] dev = [ { name = "build" }, + { name = "classyclick" }, + { name = "jmespath" }, { name = "mkdocs" }, { name = "mkdocs-click" }, { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, @@ -573,18 +583,17 @@ dev = [ [package.metadata] requires-dist = [ - { name = "classyclick", marker = "extra == 'cli'", specifier = "==1.0.0" }, - { name = "jmespath", marker = "extra == 'cli'", specifier = ">=1.0.1" }, { name = "pydantic", specifier = ">=2" }, { name = "python-dateutil", specifier = ">=2.8.2" }, { name = "typing-extensions", specifier = ">=4.7.1" }, { name = "urllib3", specifier = ">=2.1.0,<3.0.0" }, ] -provides-extras = ["cli"] [package.metadata.requires-dev] dev = [ { name = "build" }, + { name = "classyclick", specifier = "==1.0.0" }, + { name = "jmespath", specifier = ">=1.0.1" }, { name = "mkdocs", specifier = ">=1.6.1" }, { name = "mkdocs-click", specifier = ">=0.9.0" }, { name = "pytest" },