diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b3e5537..6871a17 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,3 +5,5 @@ updates: schedule: interval: daily open-pull-requests-limit: 1024 + cooldown: + default-days: 7 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 48fcbf6..e1968fd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,15 +17,25 @@ env: UV_NO_SYNC: "true" jobs: - pre-commit: - name: "pre-commit" + lint: + name: "lint" runs-on: ubuntu-latest steps: - - uses: "actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10" # v6.0.3 + - uses: "actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1" # v7.0.1 with: persist-credentials: false - - uses: "j178/prek-action@bdca6f102f98e2b4c7029491a53dfd366469e33d" # v2.0.4 + - uses: "actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97" # v7.0.0 + with: + python-version: "3.12" + - uses: "astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9" # v9.0.0 + with: + enable-cache: true + - uses: "j178/prek-action@5337cb91e0fa35a7ff31b9ca345126d8bbbcdf16" # v2.0.6 + - name: "Check source distribution contents" + run: | + uv sync --only-group check-sdist + uv run check-sdist tests: name: "Python ${{ matrix.python-version }}" @@ -37,14 +47,14 @@ jobs: python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - - uses: "actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10" # v6.0.3 + - uses: "actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1" # v7.0.1 with: persist-credentials: false - - uses: "actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405" # v6.2.0 + - uses: "actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97" # v7.0.0 with: python-version: "${{ matrix.python-version }}" allow-prereleases: true - - uses: "astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39" # v8.2.0 + - uses: "astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9" # v9.0.0 with: enable-cache: true - name: "Install dependencies" @@ -52,7 +62,7 @@ jobs: python -VV python -m site uv --version - uv sync --only-group nox --only-group coverage + uv sync --only-group nox --only-group coverage --no-install-project - name: "Run nox targets for ${{ matrix.python-version }}" run: "uv run nox --python ${{ matrix.python-version }}" - name: "Convert coverage" @@ -60,18 +70,18 @@ jobs: uv run coverage combine uv run coverage xml - name: "Upload coverage to Codecov" - uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} - required: + alls-green: name: "all required checks passed" runs-on: "ubuntu-latest" if: always() needs: - - pre-commit + - lint - tests steps: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..08d60b9 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,64 @@ +name: Upload Python Package + +on: + push: + tags: + - "*" + +permissions: + contents: read + +jobs: + deploy: + runs-on: ubuntu-latest + environment: + name: publish + url: https://pypi.org/p/spacetrack + permissions: + contents: read + id-token: write + attestations: write + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 + with: + enable-cache: false + - name: Set up Python + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.x" + - name: Build + run: "uv build" + - name: Publish + uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1 + + release: + needs: deploy + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - name: Extract release notes + run: | + awk -v version="$GITHUB_REF_NAME" ' + index($0, "/releases/tag/" version ">`_ - ") { found = 1; skip_underline = 1; next } + found && skip_underline { skip_underline = 0; next } + found && /^[0-9][^ ]*_ - [0-9]{4}-[0-9]{2}-[0-9]{2}$/ { exit } + found && /\/releases\/tag\/[^>]+>`_ - [0-9]{4}-[0-9]{2}-[0-9]{2}$/ { exit } + found { print } + END { if (!found) exit 1 } + ' docs/changelog.rst > release-notes.rst + grep -q '[^[:space:]]' release-notes.rst + - name: Create GitHub Release + run: | + gh release create "$GITHUB_REF_NAME" \ + --verify-tag \ + --title "$GITHUB_REF_NAME" \ + --notes-file release-notes.rst + env: + GH_TOKEN: ${{ github.token }} diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml deleted file mode 100644 index fedd204..0000000 --- a/.github/workflows/python-publish.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Upload Python Package - -on: - push: - tags: - - "*" - -permissions: - contents: read - -jobs: - deploy: - runs-on: ubuntu-latest - environment: publish - permissions: - id-token: write - attestations: write - steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - persist-credentials: false - - uses: "astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39" # v8.2.0 - with: - enable-cache: false - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: "3.x" - - name: Build - run: "uv build" - - name: Publish - uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index affd482..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,9 +0,0 @@ -include CHANGELOG.md -include LICENSE.txt -include tox.ini -recursive-include tests *.py -recursive-include docs * -prune docs/_build -include .pre-commit-config.yaml -include .readthedocs.yaml -include dev-requirements.txt diff --git a/README.rst b/README.rst index 977e14e..347358c 100644 --- a/README.rst +++ b/README.rst @@ -3,7 +3,7 @@ spacetrack |PyPI Version| |Documentation| |CI Status| |Coverage| |Python Version| |MIT License| -spacetrack is a python module for `Space-Track `__ +spacetrack is a Python client for `Space-Track `__. Installation ~~~~~~~~~~~~ @@ -63,22 +63,22 @@ Documentation ~~~~~~~~~~~~~ For in-depth information, `visit the -documentation `__! +documentation `__! Development ~~~~~~~~~~~ -spacetrack uses `semantic versioning `__ - -.. |CI Status| image:: https://github.com/python-astrodynamics/spacetrack/workflows/CI/badge.svg?branch=master - :target: https://github.com/python-astrodynamics/spacetrack/actions?workflow=CI -.. |PyPI Version| image:: http://img.shields.io/pypi/v/spacetrack.svg?style=flat-square - :target: https://pypi.python.org/pypi/spacetrack/ -.. |Python Version| image:: https://img.shields.io/badge/python-3.6%2B-brightgreen.svg?style=flat-square - :target: https://www.python.org/downloads/ -.. |MIT License| image:: http://img.shields.io/badge/license-MIT-blue.svg?style=flat-square - :target: https://raw.githubusercontent.com/python-astrodynamics/spacetrack/master/LICENSE.txt -.. |Coverage| image:: https://img.shields.io/codecov/c/github/python-astrodynamics/spacetrack/master.svg?style=flat-square - :target: https://codecov.io/github/python-astrodynamics/spacetrack?branch=master -.. |Documentation| image:: https://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat-square - :target: http://spacetrack.readthedocs.org/en/latest/ +spacetrack uses `semantic versioning `__. + +.. |CI Status| image:: https://github.com/python-astrodynamics/spacetrack/actions/workflows/ci.yml/badge.svg?branch=main + :target: https://github.com/python-astrodynamics/spacetrack/actions/workflows/ci.yml +.. |PyPI Version| image:: https://img.shields.io/pypi/v/spacetrack.svg?style=flat-square + :target: https://pypi.org/project/spacetrack/ +.. |Python Version| image:: https://img.shields.io/pypi/pyversions/spacetrack.svg?style=flat-square + :target: https://pypi.org/project/spacetrack/ +.. |MIT License| image:: https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square + :target: https://raw.githubusercontent.com/python-astrodynamics/spacetrack/main/LICENSE.txt +.. |Coverage| image:: https://codecov.io/gh/python-astrodynamics/spacetrack/branch/main/graph/badge.svg + :target: https://codecov.io/gh/python-astrodynamics/spacetrack +.. |Documentation| image:: https://readthedocs.org/projects/spacetrack/badge/?version=latest + :target: https://spacetrack.readthedocs.io/en/latest/ diff --git a/docs/changelog.rst b/docs/changelog.rst index c4c2c4e..b5592d7 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,8 @@ Change Log ========== +.. towncrier release notes start + 1.4.0_ - 2025-02-21 ------------------- diff --git a/newsfragments/+modernize.changed.rst b/newsfragments/+modernize.changed.rst new file mode 100644 index 0000000..f2e9d26 --- /dev/null +++ b/newsfragments/+modernize.changed.rst @@ -0,0 +1 @@ +Modernize the packaging, test, documentation, and release tooling. diff --git a/newsfragments/.gitignore b/newsfragments/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/newsfragments/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/noxfile.py b/noxfile.py index be925c3..999c80b 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1,3 +1,6 @@ +from collections.abc import Iterator +from contextlib import contextmanager + import nox nox.options.reuse_existing_virtualenvs = True @@ -36,3 +39,42 @@ def tests(session: nox.Session) -> None: ) session.run("coverage", "run", "-m", "pytest", *session.posargs) + + +@nox.session(name="test-min-deps", python=PYTHON_VERSIONS) +def test_min_deps(session: nox.Session) -> None: + with restore_file("uv.lock"): + session.run_install( + "uv", + "sync", + "--no-default-groups", + "--group=test", + "--resolution=lowest-direct", + ) + + session.run("pytest", *session.posargs) + + +@nox.session(name="test-latest", python=PYTHON_VERSIONS) +def test_latest(session: nox.Session) -> None: + session.run_install( + "uv", + "sync", + "--no-default-groups", + "--group=test", + "--no-install-project", + ) + session.run_install("uv", "pip", "install", "--upgrade", ".") + + session.run("pytest", *session.posargs) + + +@contextmanager +def restore_file(path: str) -> Iterator[None]: + with open(path, "rb") as f: + original = f.read() + try: + yield + finally: + with open(path, "wb") as f: + f.write(original) diff --git a/pyproject.toml b/pyproject.toml index a20eded..d9f6311 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [build-system] -requires = ["setuptools>=61"] -build-backend = "setuptools.build_meta" +requires = ["hatchling"] +build-backend = "hatchling.build" [project] name = "spacetrack" @@ -8,13 +8,12 @@ version = "1.4.0" description = "Python client for space-track.org" readme = "README.rst" requires-python = ">=3.10" -license = { text = "MIT" } +license = "MIT" authors = [ { name = "Frazer McLean", email = "frazer@frazermclean.co.uk" }, ] classifiers = [ "Development Status :: 5 - Production/Stable", - "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -35,16 +34,25 @@ dependencies = [ ] [project.urls] -Repository = "https://github.com/python-astrodynamics/spacetrack" Documentation = "https://spacetrack.readthedocs.io" +"Source Code" = "https://github.com/python-astrodynamics/spacetrack" +Issues = "https://github.com/python-astrodynamics/spacetrack/issues" +Changelog = "https://spacetrack.readthedocs.io/en/latest/changelog.html" [dependency-groups] dev = [ + { include-group = "check-sdist" }, { include-group = "coverage" }, + { include-group = "docs" }, + { include-group = "docstest" }, { include-group = "nox" }, { include-group = "test" }, + { include-group = "towncrier" }, "ruff==0.15.16", ] +check-sdist = [ + "check-sdist>=1.5.0", +] docs = [ "furo>=2024.8.6", "parver>=0.5", @@ -66,17 +74,15 @@ test = [ "pytest-trio>=0.8.0", "respx>=0.23.1", ] +towncrier = [ + "towncrier>=25.8.0", +] -[tool.setuptools] -package-dir = { "" = "src" } - -[tool.setuptools.packages.find] -where = ["src"] - [tool.coverage.run] branch = true -source = ["spacetrack", "tests/"] +relative_files = true +source = ["src/spacetrack", "tests/"] parallel = true [tool.coverage.paths] @@ -84,7 +90,13 @@ source = ["src/spacetrack", ".nox/**/site-packages/spacetrack"] [tool.coverage.report] precision = 1 -exclude_lines = ["pragma: no cover", "^\\s*pass\\s*$"] +exclude_also = [ + '^\s*pass$', + '^\s*raise NotImplementedError\b', + '^\s*return NotImplemented\b', + '^\s*raise$', + '^\s*(case _:\n\s*)?(typing\.)?assert_never\(', +] [tool.pytest] addopts = ["-r", "s"] @@ -98,10 +110,31 @@ select = [ "UP", # pyupgrade "RUF", # ruff ] -ignore = [ - "RUF012", -] - [tool.doc8] ignore-path = ["docs/_build"] ignore = ["D001"] + +[tool.towncrier] +directory = "newsfragments" +filename = "docs/changelog.rst" +issue_format = "`#{issue} `_" +title_format = "`{version} `_ - {project_date}" +underlines = ["-", "~"] + +[[tool.towncrier.type]] +name = "Added" + +[[tool.towncrier.type]] +name = "Changed" + +[[tool.towncrier.type]] +name = "Deprecated" + +[[tool.towncrier.type]] +name = "Removed" + +[[tool.towncrier.type]] +name = "Fixed" + +[[tool.towncrier.type]] +name = "Security" diff --git a/src/spacetrack/base.py b/src/spacetrack/base.py index 95198d9..cd4f44d 100644 --- a/src/spacetrack/base.py +++ b/src/spacetrack/base.py @@ -227,7 +227,7 @@ class SpaceTrackClient: ] ) - request_controllers["basicspacedata"] = { + request_controllers["basicspacedata"] = { # noqa: RUF012 "announcement", "boxscore", "cdm_public", @@ -241,7 +241,7 @@ class SpaceTrackClient: "tip", } - request_controllers["expandedspacedata"] = { + request_controllers["expandedspacedata"] = { # noqa: RUF012 "car", "cdm", "maneuver", @@ -250,7 +250,7 @@ class SpaceTrackClient: "satellite", } - request_controllers["fileshare"] = { + request_controllers["fileshare"] = { # noqa: RUF012 "delete", "download", "file", @@ -258,33 +258,33 @@ class SpaceTrackClient: "upload", } - request_controllers["spephemeris"] = { + request_controllers["spephemeris"] = { # noqa: RUF012 "download", "file", "file_history", } - request_controllers["publicfiles"] = { + request_controllers["publicfiles"] = { # noqa: RUF012 "dirs", "download", } # List of (class, controller) tuples for # requests which do not return a modeldef - offline_predicates = { + offline_predicates = { # noqa: RUF012 ("download", "fileshare"): {"file_id", "folder_id", "recursive"}, ("upload", "fileshare"): {"folder_id", "file"}, ("download", "spephemeris"): set(), ("dirs", "publicfiles"): set(), ("download", "publicfiles"): set(), } - deprecated_controllers = {} - param_fields = { + deprecated_controllers = {} # noqa: RUF012 + param_fields = { # noqa: RUF012 ("download", "publicfiles"): {"name"}, } # These predicates are available for every request class. - rest_predicates = { + rest_predicates = { # noqa: RUF012 Predicate("predicates", "str"), Predicate("metadata", "enum", values=("true", "false")), Predicate("limit", "str"), diff --git a/uv.lock b/uv.lock index 17e6d49..0f28202 100644 --- a/uv.lock +++ b/uv.lock @@ -91,6 +91,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, ] +[[package]] +name = "build" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "os_name == 'nt'" }, + { name = "importlib-metadata", marker = "python_full_version < '3.10.2'" }, + { name = "packaging" }, + { name = "pyproject-hooks" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/e0/df5e171f685f82f37b12e1f208064e24244911079d7b767447d1af7e0d70/build-1.5.0.tar.gz", hash = "sha256:302c22c3ba2a0fd5f3911918651341ebb3896176cbdec15bd421f80b1afc7647", size = 89796, upload-time = "2026-04-30T03:18:25.17Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl", hash = "sha256:13f3eecb844759ab66efec90ca17639bbf14dc06cb2fdf37a9010322d9c50a6f", size = 26018, upload-time = "2026-04-30T03:18:23.644Z" }, +] + [[package]] name = "certifi" version = "2026.5.20" @@ -233,6 +249,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/db/8f/61959034484a4a7c527811f4721e75d02d653a35afb0b6054474d8185d4c/charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d", size = 61958, upload-time = "2026-04-02T09:28:37.794Z" }, ] +[[package]] +name = "check-sdist" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "build" }, + { name = "pathspec" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/47/ea/1f1541f1b45d4bd1782e6ac153de4c9683b7c34dbc8e8abe413f0e17e437/check_sdist-1.5.0.tar.gz", hash = "sha256:c49671f7e4bf872141af7b4cfe96da58b912742fdc4d3c113f8280507eeaee7f", size = 24468, upload-time = "2026-06-18T14:49:04.65Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/bc/b7960e5ae84a3b0eb5302c685d9d9872974a09d044176d35338f18c0c2d9/check_sdist-1.5.0-py3-none-any.whl", hash = "sha256:df83f5ad78afc824a7143de70ed0a14c6bcfceb586cc72cbcc1153f995f49834", size = 21587, upload-time = "2026-06-18T14:49:03.332Z" }, +] + +[[package]] +name = "click" +version = "8.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/d4/81420972a676e8ffea40450d8c8c92943e7218a78fe9b64359836cc9876b/click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", size = 338000, upload-time = "2026-06-24T17:45:15.148Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/e2/79c688af8b210d232694e31e59da9f6ec747bae31c3f5946e4e9b98860d5/click-8.4.2-py3-none-any.whl", hash = "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76", size = 119243, upload-time = "2026-06-24T17:45:13.73Z" }, +] + [[package]] name = "colorama" version = "0.4.6" @@ -522,6 +564,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5f/53/fb7122b71361a0d121b669dcf3d31244ef75badbbb724af388948de543e2/imagesize-2.0.0-py2.py3-none-any.whl", hash = "sha256:5667c5bbb57ab3f1fa4bc366f4fbc971db3d5ed011fd2715fd8001f782718d96", size = 9441, upload-time = "2026-03-03T14:18:27.892Z" }, ] +[[package]] +name = "importlib-metadata" +version = "9.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a9/01/15bb152d77b21318514a96f43af312635eb2500c96b55398d020c93d86ea/importlib_metadata-9.0.0.tar.gz", hash = "sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc", size = 56405, upload-time = "2026-03-20T06:42:56.999Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl", hash = "sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7", size = 27789, upload-time = "2026-03-20T06:42:55.665Z" }, +] + [[package]] name = "iniconfig" version = "2.3.0" @@ -748,6 +802,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b9/e4/dcfdaf1fda1883e3fb34a410158cc61e68644c4024c4bdef81e1532cde06/parver-1.0-py3-none-any.whl", hash = "sha256:ba201193c651d5d4de3761ee2709a31fb451280271325607ce1632653617a43e", size = 20803, upload-time = "2026-05-19T22:30:33.343Z" }, ] +[[package]] +name = "pathspec" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/82/42f767fc1c1143d6fd36efb827202a2d997a375e160a71eb2888a925aac1/pathspec-1.1.1.tar.gz", hash = "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a", size = 135180, upload-time = "2026-04-27T01:46:08.907Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189", size = 57328, upload-time = "2026-04-27T01:46:07.06Z" }, +] + [[package]] name = "platformdirs" version = "4.10.0" @@ -784,6 +847,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, ] +[[package]] +name = "pyproject-hooks" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/82/28175b2414effca1cdac8dc99f76d660e7a4fb0ceefa4b4ab8f5f6742925/pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", size = 19228, upload-time = "2024-09-29T09:24:13.293Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216, upload-time = "2024-09-29T09:24:11.978Z" }, +] + [[package]] name = "pytest" version = "9.0.3" @@ -1011,17 +1083,28 @@ dependencies = [ ] [package.dev-dependencies] +check-sdist = [ + { name = "check-sdist" }, +] coverage = [ { name = "coverage", extra = ["toml"] }, ] dev = [ + { name = "check-sdist" }, { name = "coverage", extra = ["toml"] }, + { name = "doc8" }, + { name = "furo" }, { name = "nox" }, + { name = "parver" }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-trio" }, { name = "respx" }, { name = "ruff" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "towncrier" }, ] docs = [ { name = "furo" }, @@ -1047,6 +1130,9 @@ test = [ { name = "pytest-trio" }, { name = "respx" }, ] +towncrier = [ + { name = "towncrier" }, +] [package.metadata] requires-dist = [ @@ -1062,15 +1148,22 @@ requires-dist = [ ] [package.metadata.requires-dev] +check-sdist = [{ name = "check-sdist", specifier = ">=1.5.0" }] coverage = [{ name = "coverage", extras = ["toml"], specifier = ">=7.14.1" }] dev = [ + { name = "check-sdist", specifier = ">=1.5.0" }, { name = "coverage", extras = ["toml"], specifier = ">=7.14.1" }, + { name = "doc8", specifier = ">=1.1.2" }, + { name = "furo", specifier = ">=2024.8.6" }, { name = "nox", specifier = ">=2026.4.10" }, + { name = "parver", specifier = ">=0.5" }, { name = "pytest", specifier = ">=9.0.3" }, { name = "pytest-asyncio", specifier = ">=1.4.0" }, { name = "pytest-trio", specifier = ">=0.8.0" }, { name = "respx", specifier = ">=0.23.1" }, { name = "ruff", specifier = "==0.15.16" }, + { name = "sphinx", specifier = ">=7.4.7" }, + { name = "towncrier", specifier = ">=25.8.0" }, ] docs = [ { name = "furo", specifier = ">=2024.8.6" }, @@ -1090,6 +1183,7 @@ test = [ { name = "pytest-trio", specifier = ">=0.8.0" }, { name = "respx", specifier = ">=0.23.1" }, ] +towncrier = [{ name = "towncrier", specifier = ">=25.8.0" }] [[package]] name = "sphinx" @@ -1315,6 +1409,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" }, ] +[[package]] +name = "towncrier" +version = "25.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "jinja2" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c2/eb/5bf25a34123698d3bbab39c5bc5375f8f8bcbcc5a136964ade66935b8b9d/towncrier-25.8.0.tar.gz", hash = "sha256:eef16d29f831ad57abb3ae32a0565739866219f1ebfbdd297d32894eb9940eb1", size = 76322, upload-time = "2025-08-30T11:41:55.393Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/06/8ba22ec32c74ac1be3baa26116e3c28bc0e76a5387476921d20b6fdade11/towncrier-25.8.0-py3-none-any.whl", hash = "sha256:b953d133d98f9aeae9084b56a3563fd2519dfc6ec33f61c9cd2c61ff243fb513", size = 65101, upload-time = "2025-08-30T11:41:53.644Z" }, +] + [[package]] name = "trio" version = "0.33.0" @@ -1366,3 +1474,12 @@ sdist = { url = "https://files.pythonhosted.org/packages/e1/0d/4e93c8e6d1001a757 wheels = [ { url = "https://files.pythonhosted.org/packages/bf/c4/557dc082be035381b85fdb2b74e21d3d21b57750b74f2b47a32f3a639ff9/virtualenv-21.4.2-py3-none-any.whl", hash = "sha256:854210ca524a1a4d0d744734f4acbc721c3ffe163b85bbf5d56d14d5ae2f0fae", size = 7594079, upload-time = "2026-05-31T17:01:20.735Z" }, ] + +[[package]] +name = "zipp" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b9/d8/eab98a517c14134c0b2eb4e2387bc5f457334293ec5d2dd3857ec2966802/zipp-4.1.0.tar.gz", hash = "sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602", size = 26214, upload-time = "2026-05-18T20:08:57.967Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/13/547360d81e6d88d58492968ffda9f9542854f11310ee556fef14260cc886/zipp-4.1.0-py3-none-any.whl", hash = "sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f", size = 10238, upload-time = "2026-05-18T20:08:57.045Z" }, +]