diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 7b7b298c..5ea3973f 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -27,7 +27,6 @@ jobs: - "3.13" - "3.12" - "3.11" - - "3.10" os: - ubuntu-24.04 - windows-2025 @@ -42,9 +41,10 @@ jobs: - name: Install the latest version of uv uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0 with: + python-version: "3.15" enable-cache: false - name: Install tox - run: uv tool install --python-preference only-managed --python 3.14 tox --with tox-uv + run: uv tool install --python-preference only-managed --python 3.15 tox --with tox-uv - name: Install Python run: uv python install --python-preference only-managed ${{ matrix.py }} - name: Setup test suite @@ -71,7 +71,7 @@ jobs: shell: python - name: Upload coverage data if: ${{ !startsWith(matrix.py, 'pypy')}} - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: include-hidden-files: true name: .coverage.${{ matrix.os }}.${{ matrix.py }} @@ -89,7 +89,7 @@ jobs: - name: Download coverage data id: coverage-data background: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: path: .tox pattern: .coverage.* @@ -97,11 +97,12 @@ jobs: - name: Install the latest version of uv uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0 with: + python-version: "3.15" enable-cache: false - name: Install tox - run: uv tool install --python-preference only-managed --python 3.14 tox --with tox-uv + run: uv tool install --python-preference only-managed --python 3.15 tox --with tox-uv - name: Build package to generate version - run: uv build --python 3.14 --python-preference only-managed --wheel . --out-dir dist + run: uv build --python 3.15 --python-preference only-managed --wheel . --out-dir dist - name: Setup coverage tool run: tox -e coverage --notest env: @@ -112,7 +113,7 @@ jobs: env: UV_PYTHON_PREFERENCE: only-managed - name: Upload HTML report - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: html-report path: .tox/htmlcov @@ -140,9 +141,10 @@ jobs: - name: Install the latest version of uv uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0 with: + python-version: "3.15" enable-cache: false - name: Install tox - run: uv tool install --python-preference only-managed --python 3.14 tox --with tox-uv + run: uv tool install --python-preference only-managed --python 3.15 tox --with tox-uv - name: Setup test suite run: tox run -vv --notest --skip-missing-interpreters false -e ${{ matrix.tox_env }} env: @@ -166,6 +168,7 @@ jobs: - name: Install the latest version of uv uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0 with: + python-version: "3.15" enable-cache: false - name: Require a news fragment run: uvx towncrier check --compare-with "origin/${GITHUB_BASE_REF}" diff --git a/.github/workflows/prepare-release.yaml b/.github/workflows/prepare-release.yaml index 4c31ba96..ecca6799 100644 --- a/.github/workflows/prepare-release.yaml +++ b/.github/workflows/prepare-release.yaml @@ -28,6 +28,7 @@ jobs: - name: 📦 Setup uv uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0 with: + python-version: "3.15" enable-cache: false - name: 🔢 Compute next version id: version diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index fb4a62a3..96cc6a44 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -26,11 +26,12 @@ jobs: - name: 📦 Setup uv uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0 with: + python-version: "3.15" enable-cache: false # this workflow builds the artifact that gets published; no cache to poison - name: 📦 Build package - run: uv build --python 3.14 --python-preference only-managed --sdist --wheel . --out-dir dist + run: uv build --python 3.15 --python-preference only-managed --sdist --wheel . --out-dir dist - name: 📤 Store the distribution packages - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ env.dists-artifact-name }} path: dist/* @@ -61,7 +62,7 @@ jobs: exit 1 fi - name: ⬇️ Download all the dists - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: ${{ env.dists-artifact-name }} path: dist/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1bacc348..6a0dee2d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,5 @@ +default_language_version: + python: python3.15 repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v6.0.0 @@ -13,7 +15,6 @@ repos: rev: v2.4.3 hooks: - id: codespell - additional_dependencies: ["tomli>=2.4"] - repo: https://github.com/tox-dev/tox-toml-fmt rev: "v1.11.0" hooks: diff --git a/.readthedocs.yml b/.readthedocs.yml index af60a61c..84f75c67 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,10 +1,8 @@ version: 2 build: os: ubuntu-lts-latest - tools: - python: "3" + tools: {} commands: - - pip install uv - - uv venv - - uv pip install tox-uv - - .venv/bin/tox run -e docs -- + - curl -LsSf https://astral.sh/uv/install.sh | sh + - ~/.local/bin/uv tool install tox --with tox-uv -p 3.15 --managed-python + - ~/.local/bin/tox run -e docs -- diff --git a/docs/changelog/613.packaging.rst b/docs/changelog/613.packaging.rst new file mode 100644 index 00000000..a6350e6f --- /dev/null +++ b/docs/changelog/613.packaging.rst @@ -0,0 +1 @@ +Use Python 3.15 for development and automation. diff --git a/docs/conf.py b/docs/conf.py index 9bbbbfba..4e98c32b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -4,7 +4,7 @@ from __future__ import annotations import os -from datetime import datetime, timezone +from datetime import UTC, datetime from pathlib import Path from platformdirs.version import __version__ @@ -32,7 +32,7 @@ ] html_theme = "furo" html_logo = html_favicon = "platformdirs.svg" -html_title, html_last_updated_fmt = "platformdirs", datetime.now(tz=timezone.utc).isoformat() +html_title, html_last_updated_fmt = "platformdirs", datetime.now(tz=UTC).isoformat() pygments_style, pygments_dark_style = "sphinx", "monokai" autoclass_content, autodoc_member_order, autodoc_typehints = "class", "bysource", "none" autodoc_default_options = { diff --git a/pyproject.toml b/pyproject.toml index 32581a7a..0a145e6e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ maintainers = [ { name = "Ofek Lev", email = "oss@ofek.dev" }, { name = "Ronny Pfannschmidt", email = "opensource@ronnypfannschmidt.de" }, ] -requires-python = ">=3.10" +requires-python = ">=3.11" classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", @@ -32,7 +32,6 @@ classifiers = [ "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", @@ -76,7 +75,6 @@ type = [ ] docs = [ "furo>=2025.12.19", - "proselint>=0.16", "sphinx>=9.1", "sphinx-autodoc-typehints>=3.9.2", "sphinx-copybutton>=0.5.2", @@ -87,6 +85,7 @@ docs = [ "sphinxcontrib-towncrier>=0.5.0a0", "sphinxext-opengraph>=0.13", "towncrier>=24.8", + "uv>=0.12.22", ] coverage = [ "covdefaults>=2.3", @@ -121,28 +120,28 @@ lint.select = [ "ALL", ] lint.ignore = [ - "COM812", # conflict - "CPY", # no copyright notices - "D203", # `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible - "D205", # 1 blank line required between summary line and description - "D213", # `multi-line-summary-second-line` (D213) conflicts with docstrfmt which uses D212 style - "D301", # Use `r"""` if any backslashes in a docstring - "D401", # The first line of docstring should be in imperative mood - "DOC", # no support for restructuredtext - "E501", # line length handled by ruff format (code) and docstrfmt (docstrings) - "RUF067", # `__init__` module should only contain docstrings and re-exports - "S104", # Possible binding to all interfaces + "CPY", # no copyright notices + "DOC", # no support for restructuredtext + "escape-sequence-in-docstring", # Use `r"""` if any backslashes in a docstring + "hardcoded-bind-all-interfaces", # Possible binding to all interfaces + "incorrect-blank-line-before-class", # `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible + "line-too-long", # line length handled by ruff format (code) and docstrfmt (docstrings) + "missing-blank-line-after-summary", # 1 blank line required between summary line and description + "missing-trailing-comma", # conflict + "multi-line-summary-second-line", # `multi-line-summary-second-line` (D213) conflicts with docstrfmt which uses D212 style + "non-empty-init-module", # `__init__` module should only contain docstrings and re-exports + "non-imperative-mood", # The first line of docstring should be in imperative mood ] lint.per-file-ignores."tests/**/*.py" = [ - "D", # don't care about documentation in tests - "FBT", # don't care about booleans as positional arguments in tests - "INP001", # no implicit namespace - "PLC2701", # Private name import - "PLR0917", # Too many positional arguments - "PLR2004", # Magic value used in comparison, consider replacing with a constant variable - "pytest-fixture-autouse", # shared setup fixtures are meant to apply to every test - "S101", # asserts allowed in tests - "S603", # `subprocess` call: check for execution of untrusted input + "assert", # asserts allowed in tests + "D", # don't care about documentation in tests + "FBT", # don't care about booleans as positional arguments in tests + "implicit-namespace-package", # no implicit namespace + "import-private-name", # Private name import + "magic-value-comparison", # Magic value used in comparison, consider replacing with a constant variable + "pytest-fixture-autouse", # shared setup fixtures are meant to apply to every test + "subprocess-without-shell-equals-true", # `subprocess` call: check for execution of untrusted input + "too-many-positional-arguments", # Too many positional arguments ] lint.isort = { known-first-party = [ "platformdirs", @@ -161,7 +160,7 @@ quiet-level = 3 max_supported_python = "3.15" [tool.ty] -environment.python-version = "3.14" +environment.python-version = "3.15" [tool.coverage] run.parallel = true diff --git a/tox.toml b/tox.toml index 6dd9ac62..605d5983 100644 --- a/tox.toml +++ b/tox.toml @@ -1,11 +1,10 @@ -requires = [ "tox>=4.47" ] +requires = [ "tox>=4.64.7" ] env_list = [ "3.15", "3.14", "3.13", "3.12", "3.11", - "3.10", "pypy3.11", "3.15t", "coverage", @@ -18,6 +17,7 @@ skip_missing_interpreters = true [env_run_base] description = "run the tests with pytest under {env_name}" +default_base_python = [ "3.15" ] package = "wheel" wheel_build_env = ".pkg" dependency_groups = [ "test" ] @@ -59,6 +59,9 @@ commands = [ ], extend = true }, ] +[env_pkg_base] +default_base_python = [ "3.15" ] + [env.coverage] description = "combine coverage files and generate diff (against DIFF_AGAINST defaulting to origin/main)" skip_install = true @@ -84,7 +87,7 @@ commands = [ "{env_tmp_dir}{/}coverage.xml", ], ] -depends = [ "3.10", "3.11", "3.12", "3.13", "3.14", "3.15", "pypy3.11" ] +depends = [ "3.11", "3.12", "3.13", "3.14", "3.15", "pypy3.11" ] [env.docs] description = "build documentation" @@ -93,7 +96,11 @@ commands = [ [ "python", "-c", - "import glob; import subprocess; subprocess.check_call(['proselint', 'check'] + glob.glob('docs/*.rst'))", + # RE2 lacks Python 3.15 wheels: https://github.com/google/re2/issues/647 + """\ + import glob; import subprocess; subprocess.check_call(['uv', 'tool', 'run', '--python', '3.14', '--from', \ + 'proselint>=0.16', 'proselint', 'check', *glob.glob('docs/*.rst')])\ + """, ], [ "sphinx-build",