From c9adb39bfe40b555edb6ab1f3adc3a51f4c43744 Mon Sep 17 00:00:00 2001 From: Christopher Barber Date: Fri, 6 Feb 2026 11:05:37 -0500 Subject: [PATCH 1/4] Drop python 3.9 support (#46) - Also update pixi version in CI --- .github/workflows/main.yml | 6 +++--- .idea/garpy.mkdocstrings.iml | 2 +- CHANGELOG.md | 4 ++++ pixi.lock | 6 +++--- pyproject.toml | 4 ++-- src/mkdocstrings_handlers/python_xref/VERSION | 2 +- src/mkdocstrings_handlers/python_xref/crossref.py | 15 +++------------ src/mkdocstrings_handlers/python_xref/handler.py | 10 ++-------- 8 files changed, 19 insertions(+), 30 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 64d27db..1891bfc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,12 +9,12 @@ jobs: fail-fast: true matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.9", "3.11", "3.13"] + python-version: ["3.10", "3.12", "3.14"] steps: - uses: actions/checkout@v3 - - uses: prefix-dev/setup-pixi@v0.8.3 + - uses: prefix-dev/setup-pixi@28eb668aafebd9dede9d97c4ba1cd9989a4d0004 # v0.9.2 with: - pixi-version: v0.43.3 + pixi-version: v0.59.0 cache: true auth-host: prefix.dev auth-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.idea/garpy.mkdocstrings.iml b/.idea/garpy.mkdocstrings.iml index c97fdb6..d7e1d9e 100644 --- a/.idea/garpy.mkdocstrings.iml +++ b/.idea/garpy.mkdocstrings.iml @@ -8,7 +8,7 @@ - + diff --git a/CHANGELOG.md b/CHANGELOG.md index cd500d4..691c0da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ *Note that versions roughly correspond to the version of mkdocstrings-python that they are compatible with.* +## 1.16.5 + +* Drop python 3.9 support + ## 1.16.4 * Fix handling of aliases (see bug #47) diff --git a/pixi.lock b/pixi.lock index fc18bd0..03c7f6e 100644 --- a/pixi.lock +++ b/pixi.lock @@ -1738,8 +1738,8 @@ packages: timestamp: 1748965218001 - pypi: ./ name: mkdocstrings-python-xref - version: 1.16.4 - sha256: fcb8e760b689ad912bcffadf901d9984a3505913fd40b332b764877724e4d3a2 + version: 1.16.5 + sha256: 3f50d9a09fadaa223ffd98709a8027102555c96384e89637ad8c534d27e3f058 requires_dist: - griffe>=1.0 - mkdocstrings-python>=1.16.6,<2.0 @@ -1756,7 +1756,7 @@ packages: - pytest-cov>=5.0 ; extra == 'dev' - pytest>=8.2 ; extra == 'dev' - ruff>=0.4.10 ; extra == 'dev' - requires_python: '>=3.9' + requires_python: '>=3.10' editable: true - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.7.0-pyhd8ed1ab_0.conda sha256: d0c2253dcb1da6c235797b57d29de688dabc2e48cc49645b1cff2b52b7907428 diff --git a/pyproject.toml b/pyproject.toml index cfc9b73..43fddfd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,17 +13,17 @@ classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Topic :: Software Development :: Documentation", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", ] keywords = [ "documentation-tool", "mkdocstrings", "mkdocstrings-handler", "python" ] dynamic = ["version"] -requires-python = ">=3.9" +requires-python = ">=3.10" dependencies = [ "mkdocstrings-python >=1.16.6,<2.0", "griffe >=1.0", diff --git a/src/mkdocstrings_handlers/python_xref/VERSION b/src/mkdocstrings_handlers/python_xref/VERSION index a232073..0d92a10 100644 --- a/src/mkdocstrings_handlers/python_xref/VERSION +++ b/src/mkdocstrings_handlers/python_xref/VERSION @@ -1 +1 @@ -1.16.4 +1.16.5 diff --git a/src/mkdocstrings_handlers/python_xref/crossref.py b/src/mkdocstrings_handlers/python_xref/crossref.py index 57ed60e..af22d42 100644 --- a/src/mkdocstrings_handlers/python_xref/crossref.py +++ b/src/mkdocstrings_handlers/python_xref/crossref.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2025. Analog Devices Inc. +# Copyright (c) 2022-2026. Analog Devices Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,8 +17,7 @@ import ast import re -import sys -from typing import Any, Callable, List, Optional, cast +from typing import Callable, List, Optional, cast from griffe import Alias, Docstring, GriffeError, Object from mkdocstrings import get_logger @@ -365,7 +364,7 @@ def doc_value_offset_to_location(doc: Docstring, offset: int) -> tuple[int,int]: try: source = doc.source # compute docstring without cleaning up spaces and indentation - rawvalue = str(safe_eval(source)) + rawvalue = str(ast.literal_eval(source)) # adjust line offset by number of lines removed from front of docstring lineoffset += leading_space(rawvalue).count("\n") @@ -401,12 +400,4 @@ def leading_space(s: str) -> str: return m[0] return "" # pragma: no cover -if sys.version_info < (3, 10) or True: - # TODO: remove when 3.9 support is dropped - # In 3.9, literal_eval cannot handle comments in input - def safe_eval(s: str) -> Any: - """Safely evaluate a string expression.""" - return eval(s) #eval(s, dict(__builtins__={}), {}) -else: - save_eval = ast.literal_eval diff --git a/src/mkdocstrings_handlers/python_xref/handler.py b/src/mkdocstrings_handlers/python_xref/handler.py index a1a61dc..cae0109 100644 --- a/src/mkdocstrings_handlers/python_xref/handler.py +++ b/src/mkdocstrings_handlers/python_xref/handler.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2025. Analog Devices Inc. +# Copyright (c) 2022-2026. Analog Devices Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ from __future__ import annotations import re -import sys from dataclasses import dataclass, field, fields from functools import partial from pathlib import Path @@ -37,12 +36,7 @@ logger = get_logger(__name__) -# TODO python 3.9 - remove when 3.9 support is dropped -_dataclass_options = {"frozen": True} -if sys.version_info >= (3, 10): - _dataclass_options["kw_only"] = True - -@dataclass(**_dataclass_options) +@dataclass(frozen=True, kw_only=True) class PythonRelXRefOptions(PythonOptions): check_crossrefs: bool = True check_crossrefs_exclude: list[str | re.Pattern] = field(default_factory=list) From 3658f8df3302c64c167755afdfc5e68c85bf4a89 Mon Sep 17 00:00:00 2001 From: Christopher Barber Date: Fri, 6 Feb 2026 12:16:00 -0500 Subject: [PATCH 2/4] Use different security token in CI for pixi --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1891bfc..6f1f846 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,7 +17,7 @@ jobs: pixi-version: v0.59.0 cache: true auth-host: prefix.dev - auth-token: ${{ secrets.GITHUB_TOKEN }} + auth-token: ${{ secrets.PREFIX_DEV_TOKEN }} - name: ruff run: | pixi run ruff From efaf461246d3e079480c7f6e1e67bc0925030719 Mon Sep 17 00:00:00 2001 From: Christopher Barber Date: Sat, 7 Feb 2026 11:29:31 -0500 Subject: [PATCH 3/4] Ad pip and whl2conda dev dependencies for deploy testing --- pixi.lock | 93 ++++++++++++++++++++++++++++++++++++++++++++++++-- pyproject.toml | 2 ++ 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/pixi.lock b/pixi.lock index 03c7f6e..78f89a7 100644 --- a/pixi.lock +++ b/pixi.lock @@ -5,6 +5,8 @@ environments: - url: https://conda.anaconda.org/conda-forge/ indexes: - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 @@ -135,6 +137,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h7f98852_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.23.0-py312h66e93f0_2.conda + - pypi: https://files.pythonhosted.org/packages/66/24/845d560e657dbede375c8d924eaad6e63c01b1bebc04aff70a0c2cf89cef/conda_package_handling-2.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/39/0bd20aa98ae43756b0bb5d8b055c19de842b422fe588eaa16f11dce1f399/conda_package_streaming-0.12.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/11/87d6d29fb5d237229d67973a6c9e06e048f01cf4994dee194ab0ea841814/tomlkit-0.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/22/b76d483683216dde3d67cba61fb2444be8d5be289bf628c13fc0fd90e5f9/wheel-0.46.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b9/d0/154a4759c7cd237d1bf08550867cd9ddc7ca9afc431bb395b0851297503e/whl2conda-25.3.0-py3-none-any.whl - pypi: ./ osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda @@ -250,6 +258,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h3422bc3_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.23.0-py313h90d716c_2.conda + - pypi: https://files.pythonhosted.org/packages/66/24/845d560e657dbede375c8d924eaad6e63c01b1bebc04aff70a0c2cf89cef/conda_package_handling-2.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/39/0bd20aa98ae43756b0bb5d8b055c19de842b422fe588eaa16f11dce1f399/conda_package_streaming-0.12.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/11/87d6d29fb5d237229d67973a6c9e06e048f01cf4994dee194ab0ea841814/tomlkit-0.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/22/b76d483683216dde3d67cba61fb2444be8d5be289bf628c13fc0fd90e5f9/wheel-0.46.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b9/d0/154a4759c7cd237d1bf08550867cd9ddc7ca9afc431bb395b0851297503e/whl2conda-25.3.0-py3-none-any.whl - pypi: ./ win-64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda @@ -368,6 +382,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h8ffe710_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.23.0-py313ha7868ed_2.conda + - pypi: https://files.pythonhosted.org/packages/66/24/845d560e657dbede375c8d924eaad6e63c01b1bebc04aff70a0c2cf89cef/conda_package_handling-2.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/39/0bd20aa98ae43756b0bb5d8b055c19de842b422fe588eaa16f11dce1f399/conda_package_streaming-0.12.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/11/87d6d29fb5d237229d67973a6c9e06e048f01cf4994dee194ab0ea841814/tomlkit-0.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/22/b76d483683216dde3d67cba61fb2444be8d5be289bf628c13fc0fd90e5f9/wheel-0.46.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b9/d0/154a4759c7cd237d1bf08550867cd9ddc7ca9afc431bb395b0851297503e/whl2conda-25.3.0-py3-none-any.whl - pypi: ./ packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 @@ -746,6 +766,44 @@ packages: - pkg:pypi/colorama?source=hash-mapping size: 27011 timestamp: 1733218222191 +- pypi: https://files.pythonhosted.org/packages/66/24/845d560e657dbede375c8d924eaad6e63c01b1bebc04aff70a0c2cf89cef/conda_package_handling-2.4.0-py3-none-any.whl + name: conda-package-handling + version: 2.4.0 + sha256: f835b17a5d8283555e13e0e7b7af80770007a1ff4924b07994aedad96bfb5e0c + requires_dist: + - conda-package-streaming>=0.9.0 + - furo ; extra == 'docs' + - sphinx ; extra == 'docs' + - sphinx-argparse ; extra == 'docs' + - myst-parser ; extra == 'docs' + - mdit-py-plugins>=0.3.0 ; extra == 'docs' + - mock ; extra == 'test' + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-mock ; extra == 'test' + - bottle ; extra == 'test' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/87/39/0bd20aa98ae43756b0bb5d8b055c19de842b422fe588eaa16f11dce1f399/conda_package_streaming-0.12.0-py3-none-any.whl + name: conda-package-streaming + version: 0.12.0 + sha256: 45ae0ac0e198188703e845a42ac21292b73cd7077df358ea882d25923ab26f96 + requires_dist: + - requests + - zstandard>=0.15 + - furo ; extra == 'docs' + - sphinx ; extra == 'docs' + - myst-parser ; extra == 'docs' + - mdit-py-plugins>=0.3.0 ; extra == 'docs' + - pytest>=7 ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-mock ; extra == 'test' + - boto3 ; extra == 'test' + - boto3-stubs[essential] ; extra == 'test' + - bottle ; extra == 'test' + - conda ; extra == 'test' + - conda-package-handling>=2 ; extra == 'test' + - responses ; extra == 'test' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.9.1-py312h178313f_0.conda sha256: bef32c5830b7701705660ef18d5d6ad7c597ebab196954c012e8a1cb4af0d3bc md5: 4c18b79fa2a3371557ed3663876e5dcc @@ -1739,7 +1797,7 @@ packages: - pypi: ./ name: mkdocstrings-python-xref version: 1.16.5 - sha256: 3f50d9a09fadaa223ffd98709a8027102555c96384e89637ad8c534d27e3f058 + sha256: c7c2cec5ee6116d08034079ee503c91e5823ccf4dcab09f134c1e01ab5b1d602 requires_dist: - griffe>=1.0 - mkdocstrings-python>=1.16.6,<2.0 @@ -1753,11 +1811,12 @@ packages: - mkdocs-material>=9.5.4 ; extra == 'dev' - mkdocs>=1.5.3,<2.0 ; extra == 'dev' - mypy>=1.10 ; extra == 'dev' + - pip>=25.0 ; extra == 'dev' - pytest-cov>=5.0 ; extra == 'dev' - pytest>=8.2 ; extra == 'dev' - ruff>=0.4.10 ; extra == 'dev' + - whl2conda>=25.3 ; extra == 'dev' requires_python: '>=3.10' - editable: true - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.7.0-pyhd8ed1ab_0.conda sha256: d0c2253dcb1da6c235797b57d29de688dabc2e48cc49645b1cff2b52b7907428 md5: 7c65a443d58beb0518c35b26c70e201d @@ -1987,6 +2046,11 @@ packages: purls: [] size: 1197308 timestamp: 1745955064657 +- pypi: https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl + name: pip + version: 26.0.1 + sha256: bdb1b08f4274833d62c1aa29e20907365a2ceb950410df15fc9521bad440122b + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.3.8-pyhe01879c_0.conda sha256: 0f48999a28019c329cd3f6fd2f01f09fc32cc832f7d6bbe38087ddac858feaa3 md5: 424844562f5d337077b445ec6b1398a7 @@ -2656,6 +2720,11 @@ packages: - pkg:pypi/tomli?source=hash-mapping size: 19167 timestamp: 1733256819729 +- pypi: https://files.pythonhosted.org/packages/b5/11/87d6d29fb5d237229d67973a6c9e06e048f01cf4994dee194ab0ea841814/tomlkit-0.14.0-py3-none-any.whl + name: tomlkit + version: 0.14.0 + sha256: 592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680 + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2025.5.9.12-pyhd8ed1ab_0.conda sha256: 455b7b0dc0cf7e4a6fcc41455b4fd7f646b3b842e6dc0d894438366827d7d9b2 md5: 764db08a8d868de9e377d88277c75d83 @@ -2829,6 +2898,26 @@ packages: - pkg:pypi/watchdog?source=hash-mapping size: 167930 timestamp: 1730493160417 +- pypi: https://files.pythonhosted.org/packages/87/22/b76d483683216dde3d67cba61fb2444be8d5be289bf628c13fc0fd90e5f9/wheel-0.46.3-py3-none-any.whl + name: wheel + version: 0.46.3 + sha256: 4b399d56c9d9338230118d705d9737a2a468ccca63d5e813e2a4fc7815d8bc4d + requires_dist: + - packaging>=24.0 + - pytest>=6.0.0 ; extra == 'test' + - setuptools>=77 ; extra == 'test' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/b9/d0/154a4759c7cd237d1bf08550867cd9ddc7ca9afc431bb395b0851297503e/whl2conda-25.3.0-py3-none-any.whl + name: whl2conda + version: 25.3.0 + sha256: 8637af49fe4296689ce374fcb8159f9b805de589aaa02301277c29b831b0e735 + requires_dist: + - conda-package-handling>=2.2 + - platformdirs>=3.10 + - pyyaml>=6.0 + - tomlkit>=0.12 + - wheel>=0.41 + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda sha256: 93807369ab91f230cf9e6e2a237eaa812492fe00face5b38068735858fba954f md5: 46e441ba871f524e2b067929da3051c2 diff --git a/pyproject.toml b/pyproject.toml index 43fddfd..18d6030 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,7 +36,9 @@ Documentation = "https://analog-garage.github.io/mkdocstrings-python-xref/" [project.optional-dependencies] dev = [ "build >=1.0.0", # python-build on conda + "pip >=25.0", "hatchling >=1.21", + "whl2conda >=25.3", "coverage >=7.4.0", "pytest >=8.2", "pytest-cov >=5.0", From 074a14fa0d71243f26fcd75e5639ad931ea3533e Mon Sep 17 00:00:00 2001 From: Christopher Barber Date: Sat, 7 Feb 2026 11:32:30 -0500 Subject: [PATCH 4/4] Update CI to use pixi 0.63.2 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6f1f846..a1a6279 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v3 - uses: prefix-dev/setup-pixi@28eb668aafebd9dede9d97c4ba1cd9989a4d0004 # v0.9.2 with: - pixi-version: v0.59.0 + pixi-version: v0.63.2 cache: true auth-host: prefix.dev auth-token: ${{ secrets.PREFIX_DEV_TOKEN }}