From ae9a5c23cbcb12659708f27857db850d14843818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Sat, 25 May 2024 19:24:52 +0200 Subject: [PATCH 1/7] chore: Template upgrade --- .copier-answers.yml | 2 +- .github/FUNDING.yml | 1 + .github/workflows/ci.yml | 24 +- .gitignore | 27 +- Makefile | 3 +- README.md | 4 +- config/git-changelog.toml | 1 + config/pytest.ini | 2 - config/ruff.toml | 6 +- config/vscode/tasks.json | 6 - devdeps.txt | 51 +-- docs/insiders/installation.md | 124 +------ duties.py | 206 ++++------- pyproject.toml | 7 + scripts/gen_credits.py | 26 +- scripts/gen_ref_nav.py | 2 +- scripts/make | 356 +++++++++++--------- src/mkdocstrings_handlers/python/debug.py | 5 +- src/mkdocstrings_handlers/python/handler.py | 2 +- 19 files changed, 362 insertions(+), 493 deletions(-) diff --git a/.copier-answers.yml b/.copier-answers.yml index 0e3a987e..769af3ed 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: 0.3.1 +_commit: 1.1.1 _src_path: gh:mkdocstrings/handler-template author_email: dev@pawamoy.fr author_fullname: Timothée Mazzucotelli diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 01e293ac..a502284a 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,4 +1,5 @@ github: pawamoy ko_fi: pawamoy +polar: pawamoy custom: - https://www.paypal.me/pawamoy diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 384bf7cc..e422aeb8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,9 +49,6 @@ jobs: - name: Check if the code is correctly typed run: make check-types - - name: Check for vulnerabilities in dependencies - run: make check-dependencies - - name: Check for breaking changes in the API run: make check-api @@ -69,10 +66,14 @@ jobs: {"python-version": "3.9"}, {"python-version": "3.10"}, {"python-version": "3.11"}, - {"python-version": "3.12"} + {"python-version": "3.12"}, + {"python-version": "3.13"} ]' | tr -d '[:space:]' >> $GITHUB_OUTPUT else - echo 'jobs=[]' >> $GITHUB_OUTPUT + echo 'jobs=[ + {"os": "macos-latest", "resolution": "lowest-direct"}, + {"os": "windows-latest", "resolution": "lowest-direct"} + ]' | tr -d '[:space:]' >> $GITHUB_OUTPUT fi tests: @@ -91,9 +92,13 @@ jobs: - "3.10" - "3.11" - "3.12" + - "3.13" + resolution: + - highest + - lowest-direct exclude: ${{ fromJSON(needs.exclude-test-jobs.outputs.jobs) }} runs-on: ${{ matrix.os }} - continue-on-error: ${{ matrix.python-version == '3.12' }} + continue-on-error: ${{ matrix.python-version == '3.13' }} steps: - name: Checkout @@ -109,10 +114,9 @@ jobs: run: pip install uv - name: Install dependencies - run: | - uv venv - uv pip install -r devdeps.txt - uv pip install "mkdocstrings-python @ ." + env: + UV_RESOLUTION: ${{ matrix.resolution }} + run: make setup - name: Run the test suite run: make test diff --git a/.gitignore b/.gitignore index 246951cc..41fee62d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,24 @@ +# editors .idea/ .vscode/ -__pycache__/ -*.py[cod] -dist/ + +# python *.egg-info/ -build/ -htmlcov/ +*.py[cod] +.venv/ +.venvs/ +/build/ +/dist/ + +# tools .coverage* -pip-wheel-metadata/ +/.pdm-build/ +/htmlcov/ +/site/ + +# cache +.cache/ .pytest_cache/ .mypy_cache/ .ruff_cache/ -site/ -.venv/ -.venvs/ -.cache/ +__pycache__/ diff --git a/Makefile b/Makefile index 771b333c..3fa72541 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,10 @@ # This Makefile is just here to allow auto-completion in the terminal. actions = \ + allrun \ changelog \ check \ check-api \ - check-dependencies \ check-docs \ check-quality \ check-types \ @@ -16,6 +16,7 @@ actions = \ docs-deploy \ format \ help \ + multirun \ release \ run \ setup \ diff --git a/README.md b/README.md index 23b6e809..a65bf00c 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@

A Python handler for mkdocstrings.

[![ci](https://github.com/mkdocstrings/python/workflows/ci/badge.svg)](https://github.com/mkdocstrings/python/actions?query=workflow%3Aci) -[![documentation](https://img.shields.io/badge/docs-mkdocs%20material-blue.svg?style=flat)](https://mkdocstrings.github.io/python/) +[![documentation](https://img.shields.io/badge/docs-mkdocs-708FCC.svg?style=flat)](https://mkdocstrings.github.io/python/) [![pypi version](https://img.shields.io/pypi/v/mkdocstrings-python.svg)](https://pypi.org/project/mkdocstrings-python/) -[![gitpod](https://img.shields.io/badge/gitpod-workspace-blue.svg?style=flat)](https://gitpod.io/#https://github.com/mkdocstrings/python) +[![gitpod](https://img.shields.io/badge/gitpod-workspace-708FCC.svg?style=flat)](https://gitpod.io/#https://github.com/mkdocstrings/python) [![gitter](https://badges.gitter.im/join%20chat.svg)](https://app.gitter.im/#/room/#python:gitter.im) --- diff --git a/config/git-changelog.toml b/config/git-changelog.toml index 44e2b1fb..57114e0c 100644 --- a/config/git-changelog.toml +++ b/config/git-changelog.toml @@ -6,3 +6,4 @@ parse-refs = false parse-trailers = true sections = ["build", "deps", "feat", "fix", "refactor"] template = "keepachangelog" +versioning = "pep440" diff --git a/config/pytest.ini b/config/pytest.ini index ebdeb484..052a2f18 100644 --- a/config/pytest.ini +++ b/config/pytest.ini @@ -1,8 +1,6 @@ [pytest] python_files = test_*.py - *_test.py - tests.py addopts = --cov --cov-config config/coverage.ini diff --git a/config/ruff.toml b/config/ruff.toml index 751bf595..e3c9ec30 100644 --- a/config/ruff.toml +++ b/config/ruff.toml @@ -3,8 +3,7 @@ line-length = 120 [lint] exclude = [ - "fixtures", - "site", + "tests/fixtures/*.py", ] select = [ "A", "ANN", "ARG", @@ -78,5 +77,8 @@ known-first-party = ["mkdocstrings_handlers.python"] convention = "google" [format] +exclude = [ + "tests/fixtures/*.py", +] docstring-code-format = true docstring-code-line-length = 80 diff --git a/config/vscode/tasks.json b/config/vscode/tasks.json index 30008cf2..73145eec 100644 --- a/config/vscode/tasks.json +++ b/config/vscode/tasks.json @@ -31,12 +31,6 @@ "command": "scripts/make", "args": ["check-docs"] }, - { - "label": "check-dependencies", - "type": "process", - "command": "scripts/make", - "args": ["check-dependencies"] - }, { "label": "check-api", "type": "process", diff --git a/devdeps.txt b/devdeps.txt index 4fe97996..c7bb98f5 100644 --- a/devdeps.txt +++ b/devdeps.txt @@ -1,27 +1,32 @@ -build>=1.0 -duty>=0.10 -black>=23.9 -markdown-callouts>=0.3 -markdown-exec>=1.7 -mkdocs>=1.5 +# dev +editables>=0.5 + +# maintenance +build>=1.2 +git-changelog>=2.5 +twine>=5.1; python_version < '3.13' + +# ci +duty>=1.4 +ruff>=0.4 +pytest>=8.2 +pytest-cov>=5.0 +pytest-randomly>=3.15 +pytest-xdist>=3.6 +mypy>=1.10 +types-markdown>=3.6 +types-pyyaml>=6.0 + +# docs +black>=24.4 +markdown-callouts>=0.4 +markdown-exec>=1.8 +mkdocs>=1.6 mkdocs-coverage>=1.0 mkdocs-gen-files>=0.5 -mkdocs-git-committers-plugin-2>=1.2 +mkdocs-git-committers-plugin-2>=2.3 mkdocs-literate-nav>=0.6 -mkdocs-material>=9.4 -mkdocs-minify-plugin>=0.7 -mkdocstrings[python]>=0.23 +mkdocs-material>=9.5 +mkdocs-minify-plugin>=0.8 +mkdocstrings[python]>=0.25 tomli>=2.0; python_version < '3.11' -black>=23.9 -blacken-docs>=1.16 -git-changelog>=2.3 -ruff>=0.0 -pytest>=7.4 -pytest-cov>=4.1 -pytest-randomly>=3.15 -pytest-xdist>=3.3 -mypy>=1.5 -types-markdown>=3.5 -types-pyyaml>=6.0 -safety>=2.3 -twine>=5.0 diff --git a/docs/insiders/installation.md b/docs/insiders/installation.md index 3ebe5dfd..0e4628ca 100644 --- a/docs/insiders/installation.md +++ b/docs/insiders/installation.md @@ -23,6 +23,9 @@ of Insiders projects in the PyPI index of your choice See [how to install it](https://pawamoy.github.io/pypi-insiders/#installation) and [how to use it](https://pawamoy.github.io/pypi-insiders/#usage). +**We kindly ask that you do not upload the distributions to public registries, +as it is against our [Terms of use](index.md#terms).** + ### with pip (ssh/https) *mkdocstrings-python Insiders* can be installed with `pip` [using SSH][using ssh]: @@ -58,130 +61,15 @@ pip install git+https://${GH_TOKEN}@github.com/pawamoy-insiders/mkdocstrings-pyt > token must be kept secret at all times, as it allows the owner to access your > private repositories. -### with pip (self-hosted) - -Self-hosting the Insiders package makes it possible to depend on *mkdocstrings-python* normally, -while transparently downloading and installing the Insiders version locally. -It means that you can specify your dependencies normally, and your contributors without access -to Insiders will get the public version, while you get the Insiders version on your machine. - -WARNING: **Limitation** -With this method, there is no way to force the installation of an Insiders version -rather than a public version. If there is a public version that is more recent -than your self-hosted Insiders version, the public version will take precedence. -Remember to regularly update your self-hosted versions by uploading latest distributions. - -You can build the distributions for Insiders yourself, by cloning the repository -and using [build] to build the distributions, -or you can download them from our [GitHub Releases]. -You can upload these distributions to a private PyPI-like registry -([Artifactory], [Google Cloud], [pypiserver], etc.) -with [Twine]: - - [build]: https://pypi.org/project/build/ - [Artifactory]: https://jfrog.com/help/r/jfrog-artifactory-documentation/pypi-repositories - [Google Cloud]: https://cloud.google.com/artifact-registry/docs/python - [pypiserver]: https://pypi.org/project/pypiserver/ - [Github Releases]: https://github.com/pawamoy-insiders/mkdocstrings-python/releases - [Twine]: https://pypi.org/project/twine/ - -```bash -# download distributions in ~/dists, then upload with: -twine upload --repository-url https://your-private-index.com ~/dists/* -``` - -You might also need to provide a username and password/token to authenticate against the registry. -Please check [Twine's documentation][twine docs]. - - [twine docs]: https://twine.readthedocs.io/en/stable/ - -You can then configure pip (or other tools) to look for packages into your package index. -For example, with pip: - -```bash -pip config set global.extra-index-url https://your-private-index.com/simple -``` - -Note that the URL might differ depending on whether your are uploading a package (with Twine) -or installing a package (with pip), and depending on the registry you are using (Artifactory, Google Cloud, etc.). -Please check the documentation of your registry to learn how to configure your environment. - -**We kindly ask that you do not upload the distributions to public registries, -as it is against our [Terms of use](index.md#terms).** +### with Git ->? TIP: **Full example with `pypiserver`** -> In this example we use [pypiserver] to serve a local PyPI index. -> -> ```bash -> pip install --user pypiserver -> # or pipx install pypiserver -> -> # create a packages directory -> mkdir -p ~/.local/pypiserver/packages -> -> # run the pypi server without authentication -> pypi-server run -p 8080 -a . -P . ~/.local/pypiserver/packages & -> ``` -> -> We can configure the credentials to access the server in [`~/.pypirc`][pypirc]: -> -> [pypirc]: https://packaging.python.org/en/latest/specifications/pypirc/ -> -> ```ini title=".pypirc" -> [distutils] -> index-servers = -> local -> -> [local] -> repository: http://localhost:8080 -> username: -> password: -> ``` -> -> We then clone the Insiders repository, build distributions and upload them to our local server: -> -> ```bash -> # clone the repository -> git clone git@github.com:pawamoy-insiders/mkdocstrings-python -> cd mkdocstrings-python -> -> # install build -> pip install --user build -> # or pipx install build -> -> # checkout latest tag -> git checkout $(git describe --tags --abbrev=0) -> -> # build the distributions -> pyproject-build -> -> # upload them to our local server -> twine upload -r local dist/* --skip-existing -> ``` -> -> Finally, we configure pip, and for example [PDM][pdm], to use our local index to find packages: -> -> ```bash -> pip config set global.extra-index-url http://localhost:8080/simple -> pdm config pypi.extra.url http://localhost:8080/simple -> ``` -> -> [pdm]: https://pdm.fming.dev/latest/ -> -> Now when running `pip install mkdocstrings-python`, -> or resolving dependencies with PDM, -> both tools will look into our local index and find the Insiders version. -> **Remember to update your local index regularly!** - -### with git - -Of course, you can use *mkdocstrings-python Insiders* directly from `git`: +Of course, you can use *mkdocstrings-python Insiders* directly using Git: ``` git clone git@github.com:pawamoy-insiders/mkdocstrings-python ``` -When cloning from `git`, the package must be installed: +When cloning with Git, the package must be installed: ``` pip install -e mkdocstrings-python diff --git a/duties.py b/duties.py index 1c3f6b79..56c54aa6 100644 --- a/duties.py +++ b/duties.py @@ -9,8 +9,7 @@ from pathlib import Path from typing import TYPE_CHECKING, Iterator -from duty import duty -from duty.callables import coverage, lazy, mkdocs, mypy, pytest, ruff, safety +from duty import duty, tools if TYPE_CHECKING: from duty.context import Context @@ -45,143 +44,72 @@ def material_insiders() -> Iterator[bool]: # noqa: D103 @duty -def changelog(ctx: Context) -> None: +def changelog(ctx: Context, bump: str = "") -> None: """Update the changelog in-place with latest commits. Parameters: - ctx: The context instance (passed automatically). + bump: Bump option passed to git-changelog. """ - from git_changelog.cli import main as git_changelog - - ctx.run(git_changelog, args=[[]], title="Updating changelog") + ctx.run(tools.git_changelog(bump=bump or None), title="Updating changelog") @duty(pre=["check_quality", "check_types", "check_docs", "check_dependencies", "check-api"]) def check(ctx: Context) -> None: # noqa: ARG001 - """Check it all! - - Parameters: - ctx: The context instance (passed automatically). - """ + """Check it all!""" @duty def check_quality(ctx: Context) -> None: - """Check the code quality. - - Parameters: - ctx: The context instance (passed automatically). - """ + """Check the code quality.""" ctx.run( - ruff.check(*PY_SRC_LIST, config="config/ruff.toml"), + tools.ruff.check(*PY_SRC_LIST, config="config/ruff.toml"), title=pyprefix("Checking code quality"), - command=f"ruff check --config config/ruff.toml {PY_SRC}", - ) - - -@duty -def check_dependencies(ctx: Context) -> None: - """Check for vulnerabilities in dependencies. - - Parameters: - ctx: The context instance (passed automatically). - """ - # retrieve the list of dependencies - requirements = ctx.run( - ["uv", "pip", "freeze"], - silent=True, - allow_overrides=False, - ) - - ctx.run( - safety.check(requirements), - title="Checking dependencies", - command="uv pip freeze | safety check --stdin", ) @duty def check_docs(ctx: Context) -> None: - """Check if the documentation builds correctly. - - Parameters: - ctx: The context instance (passed automatically). - """ + """Check if the documentation builds correctly.""" Path("htmlcov").mkdir(parents=True, exist_ok=True) Path("htmlcov/index.html").touch(exist_ok=True) with material_insiders(): ctx.run( - mkdocs.build(strict=True, verbose=True), + tools.mkdocs.build(strict=True, verbose=True), title=pyprefix("Building documentation"), - command="mkdocs build -vs", ) @duty def check_types(ctx: Context) -> None: - """Check that the code is correctly typed. - - Parameters: - ctx: The context instance (passed automatically). - """ + """Check that the code is correctly typed.""" os.environ["MYPYPATH"] = "src" ctx.run( - mypy.run(*PY_SRC_LIST, config_file="config/mypy.ini"), + tools.mypy(*PY_SRC_LIST, config_file="config/mypy.ini"), title=pyprefix("Type-checking"), - command=f"mypy --config-file config/mypy.ini {PY_SRC}", ) @duty -def check_api(ctx: Context) -> None: - """Check for API breaking changes. - - Parameters: - ctx: The context instance (passed automatically). - """ - from griffe.cli import check as g_check - - griffe_check = lazy(g_check, name="griffe.check") +def check_api(ctx: Context, *cli_args: str) -> None: + """Check for API breaking changes.""" ctx.run( - griffe_check("mkdocstrings_handlers.python", search_paths=["src"], color=True), + tools.griffe.check("mkdocstrings_handlers.python", search=["src"], color=True).add_args(*cli_args), title="Checking for API breaking changes", - command="griffe check -ssrc mkdocstrings_handlers.python", nofail=True, ) -@duty(silent=True) -def clean(ctx: Context) -> None: - """Delete temporary files. - - Parameters: - ctx: The context instance (passed automatically). - """ - ctx.run("rm -rf .coverage*") - ctx.run("rm -rf .mypy_cache") - ctx.run("rm -rf .pytest_cache") - ctx.run("rm -rf tests/.pytest_cache") - ctx.run("rm -rf build") - ctx.run("rm -rf dist") - ctx.run("rm -rf htmlcov") - ctx.run("rm -rf pip-wheel-metadata") - ctx.run("rm -rf site") - ctx.run("find . -type d -name __pycache__ | xargs rm -rf") - ctx.run("find . -name '*.rej' -delete") - - @duty -def docs(ctx: Context, host: str = "127.0.0.1", port: int = 8000) -> None: +def docs(ctx: Context, *cli_args: str, host: str = "127.0.0.1", port: int = 8000) -> None: """Serve the documentation (localhost:8000). Parameters: - ctx: The context instance (passed automatically). host: The host to serve the docs from. port: The port to serve the docs on. """ with material_insiders(): ctx.run( - mkdocs.serve(dev_addr=f"{host}:{port}"), + tools.mkdocs.serve(dev_addr=f"{host}:{port}").add_args(*cli_args), title="Serving documentation", capture=False, ) @@ -189,11 +117,7 @@ def docs(ctx: Context, host: str = "127.0.0.1", port: int = 8000) -> None: @duty def docs_deploy(ctx: Context) -> None: - """Deploy the documentation on GitHub pages. - - Parameters: - ctx: The context instance (passed automatically). - """ + """Deploy the documentation to GitHub pages.""" os.environ["DEPLOY"] = "true" with material_insiders() as insiders: if not insiders: @@ -206,7 +130,7 @@ def docs_deploy(ctx: Context) -> None: nofail=True, ) ctx.run( - mkdocs.gh_deploy(remote_name="upstream", force=True), + tools.mkdocs.gh_deploy(remote_name="upstream", force=True), title="Deploying documentation", ) else: @@ -219,24 +143,42 @@ def docs_deploy(ctx: Context) -> None: @duty def format(ctx: Context) -> None: - """Run formatting tools on the code. - - Parameters: - ctx: The context instance (passed automatically). - """ + """Run formatting tools on the code.""" ctx.run( - ruff.check(*PY_SRC_LIST, config="config/ruff.toml", fix_only=True, exit_zero=True), + tools.ruff.check(*PY_SRC_LIST, config="config/ruff.toml", fix_only=True, exit_zero=True), title="Auto-fixing code", ) - ctx.run(ruff.format(*PY_SRC_LIST, config="config/ruff.toml"), title="Formatting code") + ctx.run(tools.ruff.format(*PY_SRC_LIST, config="config/ruff.toml"), title="Formatting code") + + +@duty +def build(ctx: Context) -> None: + """Build source and wheel distributions.""" + ctx.run( + tools.build(), + title="Building source and wheel distributions", + pty=PTY, + ) + + +@duty +def publish(ctx: Context) -> None: + """Publish source and wheel distributions to PyPI.""" + if not Path("dist").exists(): + ctx.run("false", title="No distribution files found") + dists = [str(dist) for dist in Path("dist").iterdir()] + ctx.run( + tools.twine.upload(*dists, skip_existing=True), + title="Publishing source and wheel distributions to PyPI", + pty=PTY, + ) -@duty(post=["docs-deploy"]) -def release(ctx: Context, version: str) -> None: +@duty(post=["build", "publish", "docs-deploy"]) +def release(ctx: Context, version: str = "") -> None: """Release a new Python package. Parameters: - ctx: The context instance (passed automatically). version: The new version number to use. """ origin = ctx.run("git config --get remote.origin.url", silent=True) @@ -245,64 +187,38 @@ def release(ctx: Context, version: str) -> None: lambda: False, title="Not releasing from insiders repository (do that from public repo instead!)", ) + if not (version := (version or input("> Version to release: ")).strip()): + ctx.run("false", title="A version must be provided") ctx.run("git add pyproject.toml CHANGELOG.md", title="Staging files", pty=PTY) ctx.run(["git", "commit", "-m", f"chore: Prepare release {version}"], title="Committing changes", pty=PTY) ctx.run(f"git tag {version}", title="Tagging commit", pty=PTY) ctx.run("git push", title="Pushing commits", pty=False) ctx.run("git push --tags", title="Pushing tags", pty=False) - ctx.run("pyproject-build", title="Building dist/wheel", pty=PTY) - ctx.run("twine upload --skip-existing dist/*", title="Publishing version", pty=PTY) -@duty(silent=True, aliases=["coverage"]) -def cov(ctx: Context) -> None: - """Report coverage as text and HTML. - - Parameters: - ctx: The context instance (passed automatically). - """ - ctx.run(coverage.combine, nofail=True) - ctx.run(coverage.report(rcfile="config/coverage.ini"), capture=False) - ctx.run(coverage.html(rcfile="config/coverage.ini")) +@duty(silent=True, aliases=["cov"]) +def coverage(ctx: Context) -> None: + """Report coverage as text and HTML.""" + ctx.run(tools.coverage.combine(), nofail=True) + ctx.run(tools.coverage.report(rcfile="config/coverage.ini"), capture=False) + ctx.run(tools.coverage.html(rcfile="config/coverage.ini")) @duty -def test(ctx: Context, match: str = "") -> None: +def test(ctx: Context, *cli_args: str, match: str = "") -> None: """Run the test suite. Parameters: - ctx: The context instance (passed automatically). match: A pytest expression to filter selected tests. """ py_version = f"{sys.version_info.major}{sys.version_info.minor}" os.environ["COVERAGE_FILE"] = f".coverage.{py_version}" ctx.run( - pytest.run("-n", "auto", "tests", config_file="config/pytest.ini", select=match, color="yes"), + tools.pytest( + "tests", + config_file="config/pytest.ini", + select=match, + color="yes", + ).add_args("-n", "auto", *cli_args), title=pyprefix("Running tests"), - command=f"pytest -c config/pytest.ini -n auto -k{match!r} --color=yes tests", ) - - -@duty -def vscode(ctx: Context) -> None: - """Configure VSCode. - - This task will overwrite the following files, - so make sure to back them up: - - - `.vscode/launch.json` - - `.vscode/settings.json` - - `.vscode/tasks.json` - - Parameters: - ctx: The context instance (passed automatically). - """ - - def update_config(filename: str) -> None: - source_file = Path("config", "vscode", filename) - target_file = Path(".vscode", filename) - target_file.parent.mkdir(exist_ok=True) - target_file.write_text(source_file.read_text()) - - for filename in ("launch.json", "settings.json", "tasks.json"): - ctx.run(update_config, args=[filename], title=f"Update .vscode/{filename}") diff --git a/pyproject.toml b/pyproject.toml index 398d5d3a..6356bf14 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,7 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Topic :: Documentation", "Topic :: Software Development", "Topic :: Utilities", @@ -49,3 +50,9 @@ version = {source = "scm"} package-dir = "src" includes = ["src/mkdocstrings_handlers"] editable-backend = "editables" +source-includes = ["share"] + +[tool.pdm.build.wheel-data] +data = [ + {path = "share/**/*", relative-to = "."}, +] diff --git a/scripts/gen_credits.py b/scripts/gen_credits.py index a1115f55..b2f6d3e4 100644 --- a/scripts/gen_credits.py +++ b/scripts/gen_credits.py @@ -26,8 +26,8 @@ pyproject = tomllib.load(pyproject_file) project = pyproject["project"] project_name = project["name"] -with open("devdeps.txt") as devdeps_file: - devdeps = [line.strip() for line in devdeps_file if not line.startswith("-e")] +with project_dir.joinpath("devdeps.txt").open() as devdeps_file: + devdeps = [line.strip() for line in devdeps_file if line.strip() and not line.strip().startswith(("-e", "#"))] PackageMetadata = Dict[str, Union[str, Iterable[str]]] Metadata = Dict[str, PackageMetadata] @@ -47,13 +47,6 @@ def _norm_name(name: str) -> str: return name.replace("_", "-").replace(".", "-").lower() -def _norm_spec(spec: str) -> set[str]: - clean_spec = spec.split("]", 1)[-1].split(";", 1)[0].replace("(", "").replace(")", "").replace(" ", "").strip() - if clean_spec: - return set(clean_spec.split(",")) - return set() - - def _requirements(deps: list[str]) -> dict[str, Requirement]: return {_norm_name((req := Requirement(dep)).name): req for dep in deps} @@ -74,6 +67,7 @@ def _get_metadata() -> Metadata: metadata[name] = _merge_fields(pkg.metadata) # type: ignore[arg-type] metadata[name]["spec"] = set() metadata[name]["extras"] = set() + metadata[name].setdefault("summary", "") _set_license(metadata[name]) return metadata @@ -94,7 +88,7 @@ def _set_license(metadata: PackageMetadata) -> None: def _get_deps(base_deps: dict[str, Requirement], metadata: Metadata) -> Metadata: deps = {} for dep_name, dep_req in base_deps.items(): - if dep_name not in metadata: + if dep_name not in metadata or dep_name == "mkdocstrings-python": continue metadata[dep_name]["spec"] |= {str(spec) for spec in dep_req.specifier} # type: ignore[operator] metadata[dep_name]["extras"] |= dep_req.extras # type: ignore[operator] @@ -137,8 +131,8 @@ def _render_credits() -> str: template_data = { "project_name": project_name, - "prod_dependencies": sorted(prod_dependencies.values(), key=lambda dep: str(dep["name"])), - "dev_dependencies": sorted(dev_dependencies.values(), key=lambda dep: str(dep["name"])), + "prod_dependencies": sorted(prod_dependencies.values(), key=lambda dep: str(dep["name"]).lower()), + "dev_dependencies": sorted(dev_dependencies.values(), key=lambda dep: str(dep["name"]).lower()), "more_credits": "http://pawamoy.github.io/credits/", } template_text = dedent( @@ -147,12 +141,12 @@ def _render_credits() -> str: These projects were used to build *{{ project_name }}*. **Thank you!** - [`python`](https://www.python.org/) | - [`uv`](https://github.com/astral-sh/uv) | - [`copier-uv`](https://github.com/pawamoy/copier-uv) + [Python](https://www.python.org/) | + [uv](https://github.com/astral-sh/uv) | + [copier-uv](https://github.com/pawamoy/copier-uv) {% macro dep_line(dep) -%} - [`{{ dep.name }}`](https://pypi.org/project/{{ dep.name }}/) | {{ dep.summary }} | {{ ("`" ~ dep.spec|sort(reverse=True)|join(", ") ~ "`") if dep.spec else "" }} | `{{ dep.version }}` | {{ dep.license }} + [{{ dep.name }}](https://pypi.org/project/{{ dep.name }}/) | {{ dep.summary }} | {{ ("`" ~ dep.spec|sort(reverse=True)|join(", ") ~ "`") if dep.spec else "" }} | `{{ dep.version }}` | {{ dep.license }} {%- endmacro %} {% if prod_dependencies -%} diff --git a/scripts/gen_ref_nav.py b/scripts/gen_ref_nav.py index b369536c..6939e864 100644 --- a/scripts/gen_ref_nav.py +++ b/scripts/gen_ref_nav.py @@ -29,7 +29,7 @@ with mkdocs_gen_files.open(full_doc_path, "w") as fd: ident = ".".join(parts) - fd.write(f"::: {ident}") + fd.write(f"---\ntitle: {ident}\n---\n\n::: {ident}") mkdocs_gen_files.set_edit_path(full_doc_path, ".." / path.relative_to(root)) diff --git a/scripts/make b/scripts/make index 4190622e..c097985e 100755 --- a/scripts/make +++ b/scripts/make @@ -1,155 +1,203 @@ -#!/usr/bin/env bash - -set -e -export PYTHON_VERSIONS=${PYTHON_VERSIONS-3.8 3.9 3.10 3.11 3.12} - -exe="" -prefix="" - - -# Install runtime and development dependencies, -# as well as current project in editable mode. -uv_install() { - uv pip compile pyproject.toml devdeps.txt | uv pip install -r - - uv pip install -e . -} - - -# Setup the development environment by installing dependencies -# in multiple Python virtual environments with uv: -# one venv per Python version in `.venvs/$py`, -# and an additional default venv in `.venv`. -setup() { - if ! command -v uv &>/dev/null; then - echo "make: setup: uv must be installed, see https://github.com/astral-sh/uv" >&2 - return 1 - fi - - if [ -n "${PYTHON_VERSIONS}" ]; then - for version in ${PYTHON_VERSIONS}; do - if [ ! -d ".venvs/${version}" ]; then - uv venv --seed --python "${version}" ".venvs/${version}" - fi - VIRTUAL_ENV="${PWD}/.venvs/${version}" uv_install - done - fi - - if [ ! -d .venv ]; then uv venv --seed --python python; fi - uv_install -} - - -# Activate a Python virtual environments. -# The annoying operating system also requires -# that we set some global variables to help it find commands... -activate() { - local path - if [ -f "$1/bin/activate" ]; then - source "$1/bin/activate" +#!/usr/bin/env python3 +"""Management commands.""" + +import os +import shutil +import subprocess +import sys +from contextlib import contextmanager +from pathlib import Path +from typing import Any, Iterator + +PYTHON_VERSIONS = os.getenv("PYTHON_VERSIONS", "3.8 3.9 3.10 3.11 3.12 3.13").split() + +exe = "" +prefix = "" + + +def shell(cmd: str) -> None: + """Run a shell command.""" + subprocess.run(cmd, shell=True, check=True) # noqa: S602 + + +@contextmanager +def environ(**kwargs: str) -> Iterator[None]: + """Temporarily set environment variables.""" + original = dict(os.environ) + os.environ.update(kwargs) + try: + yield + finally: + os.environ.clear() + os.environ.update(original) + + +def uv_install() -> None: + """Install dependencies using uv.""" + uv_opts = "" + if "UV_RESOLUTION" in os.environ: + uv_opts = f"--resolution={os.getenv('UV_RESOLUTION')}" + cmd = f"uv pip compile {uv_opts} pyproject.toml devdeps.txt | uv pip install -r -" + shell(cmd) + if "CI" not in os.environ: + shell("uv pip install --no-deps -e .") + else: + shell("uv pip install --no-deps .") + + +def setup() -> None: + """Setup the project.""" + if not shutil.which("uv"): + raise ValueError("make: setup: uv must be installed, see https://github.com/astral-sh/uv") + + print("Installing dependencies (default environment)") # noqa: T201 + default_venv = Path(".venv") + if not default_venv.exists(): + shell("uv venv --python python") + uv_install() + + if PYTHON_VERSIONS: + for version in PYTHON_VERSIONS: + print(f"\nInstalling dependencies (python{version})") # noqa: T201 + venv_path = Path(f".venvs/{version}") + if not venv_path.exists(): + shell(f"uv venv --python {version} {venv_path}") + with environ(VIRTUAL_ENV=str(venv_path.resolve())): + uv_install() + + +def activate(path: str) -> None: + """Activate a virtual environment.""" + global exe, prefix # noqa: PLW0603 + + if (bin := Path(path, "bin")).exists(): + activate_script = bin / "activate_this.py" + elif (scripts := Path(path, "Scripts")).exists(): + activate_script = scripts / "activate_this.py" + exe = ".exe" + prefix = f"{path}/Scripts/" + else: + raise ValueError(f"make: activate: Cannot find activation script in {path}") + + if not activate_script.exists(): + raise ValueError(f"make: activate: Cannot find activation script in {path}") + + exec(activate_script.read_text(), {"__file__": str(activate_script)}) # noqa: S102 + + +def run(version: str, cmd: str, *args: str, **kwargs: Any) -> None: + """Run a command in a virtual environment.""" + kwargs = {"check": True, **kwargs} + if version == "default": + activate(".venv") + subprocess.run([f"{prefix}{cmd}{exe}", *args], **kwargs) # noqa: S603, PLW1510 + else: + activate(f".venvs/{version}") + os.environ["MULTIRUN"] = "1" + subprocess.run([f"{prefix}{cmd}{exe}", *args], **kwargs) # noqa: S603, PLW1510 + + +def multirun(cmd: str, *args: str, **kwargs: Any) -> None: + """Run a command for all configured Python versions.""" + if PYTHON_VERSIONS: + for version in PYTHON_VERSIONS: + run(version, cmd, *args, **kwargs) + else: + run("default", cmd, *args, **kwargs) + + +def allrun(cmd: str, *args: str, **kwargs: Any) -> None: + """Run a command in all virtual environments.""" + run("default", cmd, *args, **kwargs) + if PYTHON_VERSIONS: + multirun(cmd, *args, **kwargs) + + +def clean() -> None: + """Delete build artifacts and cache files.""" + paths_to_clean = ["build", "dist", "htmlcov", "site", ".coverage*", ".pdm-build"] + for path in paths_to_clean: + shell(f"rm -rf {path}") + + cache_dirs = [".cache", ".pytest_cache", ".mypy_cache", ".ruff_cache", "__pycache__"] + for dirpath in Path(".").rglob("*"): + if any(dirpath.match(pattern) for pattern in cache_dirs) and not (dirpath.match(".venv") or dirpath.match(".venvs")): + shutil.rmtree(path, ignore_errors=True) + + +def vscode() -> None: + """Configure VSCode to work on this project.""" + Path(".vscode").mkdir(parents=True, exist_ok=True) + shell("cp -v config/vscode/* .vscode") + + +def main() -> int: + """Main entry point.""" + args = list(sys.argv[1:]) + if not args or args[0] == "help": + if len(args) > 1: + run("default", "duty", "--help", args[1]) + else: + print("Available commands") # noqa: T201 + print(" help Print this help. Add task name to print help.") # noqa: T201 + print(" setup Setup all virtual environments (install dependencies).") # noqa: T201 + print(" run Run a command in the default virtual environment.") # noqa: T201 + print(" multirun Run a command for all configured Python versions.") # noqa: T201 + print(" allrun Run a command in all virtual environments.") # noqa: T201 + print(" 3.x Run a command in the virtual environment for Python 3.x.") # noqa: T201 + print(" clean Delete build artifacts and cache files.") # noqa: T201 + print(" vscode Configure VSCode to work on this project.") # noqa: T201 + try: + run("default", "python", "-V", capture_output=True) + except (subprocess.CalledProcessError, ValueError): + pass + else: + print("\nAvailable tasks") # noqa: T201 + run("default", "duty", "--list") return 0 - fi - if [ -f "$1/Scripts/activate.bat" ]; then - "$1/Scripts/activate.bat" - exe=".exe" - prefix="$1/Scripts/" - return 0 - fi - echo "run: Cannot activate venv $1" >&2 - return 1 -} - - -# Run a command in all configured Python virtual environments. -# We handle the case when the `PYTHON_VERSIONS` environment variable -# is unset or empty, for robustness. -multirun() { - local cmd="$1" - shift - - if [ -n "${PYTHON_VERSIONS}" ]; then - for version in ${PYTHON_VERSIONS}; do - (activate ".venvs/${version}" && MULTIRUN=1 "${prefix}${cmd}${exe}" "$@") - done - else - (activate .venv && "${prefix}${cmd}${exe}" "$@") - fi -} - - -# Run a command in the default Python virtual environment. -# We rely on `multirun`'s handling of empty `PYTHON_VERSIONS`. -singlerun() { - PYTHON_VERSIONS= multirun "$@" -} - - -# Record options following a command name, -# until a non-option argument is met or there are no more arguments. -# Output each option on a new line, so the parent caller can store them in an array. -# Return the number of times the parent caller must shift arguments. -options() { - local shift_count=0 - for arg in "$@"; do - if [[ "${arg}" =~ ^- || "${arg}" =~ ^.+= ]]; then - echo "${arg}" - ((shift_count++)) - else - break - fi - done - return ${shift_count} -} - - -# Main function. -main() { - local cmd - while [ $# -ne 0 ]; do - cmd="$1" - shift - - # Handle `run` early to simplify `case` below. - if [ "${cmd}" = "run" ]; then - singlerun "$@" - exit $? - fi - - # Handle `multirun` early to simplify `case` below. - if [ "${cmd}" = "multirun" ]; then - multirun "$@" - exit $? - fi - - # All commands except `run` and `multirun` can be chained on a single line. - # Some of them accept options in two formats: `-f`, `--flag` and `param=value`. - # Some of them don't, and will print warnings/errors if options were given. - opts=($(options "$@")) || shift $? - - case "${cmd}" in - # The following commands require special handling. - help|"") - singlerun duty --list ;; - setup) - setup ;; - check) - multirun duty check-quality check-types check-docs - singlerun duty check-dependencies check-api - ;; - - # The following commands run in all venvs. - check-quality|\ - check-docs|\ - check-types|\ - test) - multirun duty "${cmd}" "${opts[@]}" ;; - - # The following commands run in the default venv only. - *) - singlerun duty "${cmd}" "${opts[@]}" ;; - esac - done -} - - -# Execute the main function. -main "$@" + + while args: + cmd = args.pop(0) + + if cmd == "run": + run("default", *args) + return 0 + + if cmd == "multirun": + multirun(*args) + return 0 + + if cmd == "allrun": + allrun(*args) + return 0 + + if cmd.startswith("3."): + run(cmd, *args) + return 0 + + opts = [] + while args and (args[0].startswith("-") or "=" in args[0]): + opts.append(args.pop(0)) + + if cmd == "clean": + clean() + elif cmd == "setup": + setup() + elif cmd == "vscode": + vscode() + elif cmd == "check": + multirun("duty", "check-quality", "check-types", "check-docs") + run("default", "duty", "check-api") + elif cmd in {"check-quality", "check-docs", "check-types", "test"}: + multirun("duty", cmd, *opts) + else: + run("default", "duty", cmd, *opts) + + return 0 + + +if __name__ == "__main__": + try: + sys.exit(main()) + except Exception: # noqa: BLE001 + sys.exit(1) diff --git a/src/mkdocstrings_handlers/python/debug.py b/src/mkdocstrings_handlers/python/debug.py index 7a4e8791..e44f2be5 100644 --- a/src/mkdocstrings_handlers/python/debug.py +++ b/src/mkdocstrings_handlers/python/debug.py @@ -37,6 +37,8 @@ class Environment: """Python interpreter name.""" interpreter_version: str """Python interpreter version.""" + interpreter_path: str + """Path to Python executable.""" platform: str """Operating System.""" packages: list[Package] @@ -83,6 +85,7 @@ def get_debug_info() -> Environment: return Environment( interpreter_name=py_name, interpreter_version=py_version, + interpreter_path=sys.executable, platform=platform.platform(), variables=[Variable(var, val) for var in variables if (val := os.getenv(var))], packages=[Package(pkg, get_version(pkg)) for pkg in packages], @@ -93,7 +96,7 @@ def print_debug_info() -> None: """Print debug/environment information.""" info = get_debug_info() print(f"- __System__: {info.platform}") - print(f"- __Python__: {info.interpreter_name} {info.interpreter_version}") + print(f"- __Python__: {info.interpreter_name} {info.interpreter_version} ({info.interpreter_path})") print("- __Environment variables__:") for var in info.variables: print(f" - `{var.name}`: `{var.value}`") diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index a473f92a..9924715c 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -53,7 +53,7 @@ def chdir(path: str) -> Iterator[None]: # noqa: D103 class PythonHandler(BaseHandler): """The Python handler class.""" - name = "python" + name: str = "python" """The handler's name.""" domain: str = "py" # to match Sphinx's default domain """The cross-documentation domain/language for this handler.""" From 70f39f784768ad6822186637aabc88ad8feae495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Sat, 25 May 2024 19:30:19 +0200 Subject: [PATCH 2/7] ci: Quality --- tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index ab2a145a..f7b28105 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -93,4 +93,4 @@ def fixture_handler(plugin: MkdocstringsPlugin, ext_markdown: Markdown) -> Pytho """ handler = plugin.handlers.get_handler("python") handler._update_env(ext_markdown, plugin.handlers._config) - return handler + return handler # type: ignore[return-value] From 101dc2aa5cf364809684a7c59d37f70f92c8697c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Sat, 25 May 2024 19:56:10 +0200 Subject: [PATCH 3/7] chore: Template upgrade --- .copier-answers.yml | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.copier-answers.yml b/.copier-answers.yml index 769af3ed..a2111625 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: 1.1.1 +_commit: 1.1.2 _src_path: gh:mkdocstrings/handler-template author_email: dev@pawamoy.fr author_fullname: Timothée Mazzucotelli diff --git a/Makefile b/Makefile index 3fa72541..5e88121d 100644 --- a/Makefile +++ b/Makefile @@ -25,4 +25,4 @@ actions = \ .PHONY: $(actions) $(actions): - @bash scripts/make "$@" + @python scripts/make "$@" From ae5896c1604e9089162d0d63ec97a510a6bcef89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 17 Jun 2024 10:51:22 +0200 Subject: [PATCH 4/7] refactor: Change `load_external_modules` default value to `None` to support new default mode in Griffe --- docs/usage/index.md | 5 ++++- src/mkdocstrings_handlers/python/handler.py | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/usage/index.md b/docs/usage/index.md index 670f6e57..57b9fdc1 100644 --- a/docs/usage/index.md +++ b/docs/usage/index.md @@ -141,8 +141,11 @@ More details at [Finding modules](#finding-modules). This option allows resolving aliases (imports) to any external module. Modules are considered external when they are not part of the package your are injecting documentation for. -Enabling this option will tell the handler to resolve aliases recursively +Setting this option to `True` will tell the handler to resolve aliases recursively when they are made public through the [`__all__`][__all__] variable. +By default, the handler will only resolve aliases when they point at a private sibling +of the source package, for example aliases going from `ast` to `_ast`. +Set `load_external_modules` to `False` to prevent even that. WARNING: **Use with caution** This can load a *lot* of modules through [Griffe], diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index 9924715c..5f64cb84 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -197,7 +197,7 @@ def __init__( config_file_path: str | None = None, paths: list[str] | None = None, locale: str = "en", - load_external_modules: bool = False, + load_external_modules: bool | None = None, **kwargs: Any, ) -> None: """Initialize the handler. @@ -474,7 +474,7 @@ def get_handler( config_file_path: str | None = None, paths: list[str] | None = None, locale: str = "en", - load_external_modules: bool = False, + load_external_modules: bool | None = None, **config: Any, # noqa: ARG001 ) -> PythonHandler: """Simply return an instance of `PythonHandler`. From 321b407eb95195c44f3cf34d780784e0d6751998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 17 Jun 2024 10:55:56 +0200 Subject: [PATCH 5/7] refactor: Update code for Griffe 0.46 to avoid deprecation warnings --- pyproject.toml | 2 +- src/mkdocstrings_handlers/python/handler.py | 2 +- .../templates/material/_base/children.html.jinja | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6356bf14..9d99d612 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,7 @@ classifiers = [ ] dependencies = [ "mkdocstrings>=0.25", - "griffe>=0.44", + "griffe>=0.46", ] [project.urls] diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index 5f64cb84..9cc60f31 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -296,7 +296,7 @@ def collect(self, identifier: str, config: Mapping[str, Any]) -> CollectorItem: if unknown_module: extensions = self.normalize_extension_paths(final_config.get("extensions", [])) loader = GriffeLoader( - extensions=load_extensions(extensions), + extensions=load_extensions(*extensions), search_paths=self._paths, docstring_parser=parser, docstring_options=parser_options, diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/children.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/children.html.jinja index b0ec4007..492272a4 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/children.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/children.html.jinja @@ -49,7 +49,7 @@ Context: {% endif %} {% with heading_level = heading_level + extra_level %} {% for attribute in attributes|order_members(config.members_order, members_list) %} - {% if members_list is not none or attribute.is_public(check_name=False) %} + {% if members_list is not none or attribute.is_public %} {% include attribute|get_template with context %} {% endif %} {% endfor %} @@ -69,7 +69,7 @@ Context: {% endif %} {% with heading_level = heading_level + extra_level %} {% for class in classes|order_members(config.members_order, members_list) %} - {% if members_list is not none or class.is_public(check_name=False) %} + {% if members_list is not none or class.is_public %} {% include class|get_template with context %} {% endif %} {% endfor %} @@ -90,7 +90,7 @@ Context: {% with heading_level = heading_level + extra_level %} {% for function in functions|order_members(config.members_order, members_list) %} {% if not (obj.kind.value == "class" and function.name == "__init__" and config.merge_init_into_class) %} - {% if members_list is not none or function.is_public(check_name=False) %} + {% if members_list is not none or function.is_public %} {% include function|get_template with context %} {% endif %} {% endif %} @@ -112,7 +112,7 @@ Context: {% endif %} {% with heading_level = heading_level + extra_level %} {% for module in modules|order_members(config.members_order.alphabetical, members_list) %} - {% if members_list is not none or module.is_public(check_name=False) %} + {% if members_list is not none or module.is_public %} {% include module|get_template with context %} {% endif %} {% endfor %} @@ -137,7 +137,7 @@ Context: {% if not (obj.is_class and child.name == "__init__" and config.merge_init_into_class) %} - {% if members_list is not none or child.is_public(check_name=False) %} + {% if members_list is not none or child.is_public %} {% if child.is_attribute %} {% with attribute = child %} {% include attribute|get_template with context %} From e2f4b35d29eca6f68afbd2e728ef7542a2abc992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 18 Jun 2024 13:23:21 +0200 Subject: [PATCH 6/7] refactor: Only filter out imported objects instead of non-public ones after applying filters Issue-mkdocstrings/griffe-294: https://github.com/mkdocstrings/griffe/issues/294 --- pyproject.toml | 2 +- .../python/templates/material/_base/children.html.jinja | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9d99d612..4e3629f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,7 @@ classifiers = [ ] dependencies = [ "mkdocstrings>=0.25", - "griffe>=0.46", + "griffe>=0.47", ] [project.urls] diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/children.html.jinja b/src/mkdocstrings_handlers/python/templates/material/_base/children.html.jinja index 492272a4..97c276a4 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/children.html.jinja +++ b/src/mkdocstrings_handlers/python/templates/material/_base/children.html.jinja @@ -49,7 +49,7 @@ Context: {% endif %} {% with heading_level = heading_level + extra_level %} {% for attribute in attributes|order_members(config.members_order, members_list) %} - {% if members_list is not none or attribute.is_public %} + {% if members_list is not none or not attribute.is_imported %} {% include attribute|get_template with context %} {% endif %} {% endfor %} @@ -69,7 +69,7 @@ Context: {% endif %} {% with heading_level = heading_level + extra_level %} {% for class in classes|order_members(config.members_order, members_list) %} - {% if members_list is not none or class.is_public %} + {% if members_list is not none or not class.is_imported %} {% include class|get_template with context %} {% endif %} {% endfor %} @@ -90,7 +90,7 @@ Context: {% with heading_level = heading_level + extra_level %} {% for function in functions|order_members(config.members_order, members_list) %} {% if not (obj.kind.value == "class" and function.name == "__init__" and config.merge_init_into_class) %} - {% if members_list is not none or function.is_public %} + {% if members_list is not none or not function.is_imported %} {% include function|get_template with context %} {% endif %} {% endif %} @@ -112,7 +112,7 @@ Context: {% endif %} {% with heading_level = heading_level + extra_level %} {% for module in modules|order_members(config.members_order.alphabetical, members_list) %} - {% if members_list is not none or module.is_public %} + {% if members_list is not none or not module.is_alias %} {% include module|get_template with context %} {% endif %} {% endfor %} From 94b736b3b1b875c7cc918f6baaea79762e58f70b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 18 Jun 2024 13:25:23 +0200 Subject: [PATCH 7/7] chore: Prepare release 1.10.4 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2bc4c72..59e91671 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [1.10.4](https://github.com/mkdocstrings/python/releases/tag/1.10.4) - 2024-06-18 + +[Compare with 1.10.3](https://github.com/mkdocstrings/python/compare/1.10.3...1.10.4) + +### Code Refactoring + +- Only filter out imported objects instead of non-public ones after applying filters ([e2f4b35](https://github.com/mkdocstrings/python/commit/e2f4b35d29eca6f68afbd2e728ef7542a2abc992) by Timothée Mazzucotelli). [Issue-mkdocstrings/griffe-294](https://github.com/mkdocstrings/griffe/issues/294) +- Update code for Griffe 0.46 to avoid deprecation warnings ([321b407](https://github.com/mkdocstrings/python/commit/321b407eb95195c44f3cf34d780784e0d6751998) by Timothée Mazzucotelli). +- Change `load_external_modules` default value to `None` to support new default mode in Griffe ([ae5896c](https://github.com/mkdocstrings/python/commit/ae5896c1604e9089162d0d63ec97a510a6bcef89) by Timothée Mazzucotelli). + ## [1.10.3](https://github.com/mkdocstrings/python/releases/tag/1.10.3) - 2024-05-22 [Compare with 1.10.2](https://github.com/mkdocstrings/python/compare/1.10.2...1.10.3)