diff --git a/.copier-answers.yml b/.copier-answers.yml index 2ba95be..98be4c0 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,12 +1,12 @@ # Changes here will be overwritten by Copier -_commit: 0.16.5 +_commit: 1.2.3 _src_path: gh:pawamoy/copier-pdm -author_email: pawamoy@pm.me +author_email: dev@pawamoy.fr author_fullname: Timothée Mazzucotelli author_username: pawamoy copyright_date: '2019' copyright_holder: Timothée Mazzucotelli -copyright_holder_email: pawamoy@pm.me +copyright_holder_email: dev@pawamoy.fr copyright_license: ISC License insiders: false project_description: Automatically link across pages in MkDocs. diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..d086173 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,61 @@ +--- +name: Bug report +about: Create a bug report to help us improve. +title: "bug: " +labels: unconfirmed +assignees: [pawamoy] +--- + +### Description of the bug + + +### To Reproduce + + +``` +WRITE MRE / INSTRUCTIONS HERE +``` + +### Full traceback + + +
Full traceback + +```python +PASTE TRACEBACK HERE +``` + +
+ +### Expected behavior + + +### Environment information + + +```bash +python -m mkdocs_autorefs.debug # | xclip -selection clipboard +``` + +PASTE OUTPUT HERE + +### Additional context + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..65beb72 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: +- name: I have a question / I need help + url: https://github.com/mkdocstrings/autorefs/discussions/new?category=q-a + about: Ask and answer questions in the Discussions tab. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..2df98fb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,19 @@ +--- +name: Feature request +about: Suggest an idea for this project. +title: "feature: " +labels: feature +assignees: pawamoy +--- + +### Is your feature request related to a problem? Please describe. + + +### Describe the solution you'd like + + +### Describe alternatives you've considered + + +### Additional context + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4f862f..80e7915 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,13 +23,13 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Fetch all tags run: git fetch --depth=1 --tags - name: Set up PDM - uses: pdm-project/setup-pdm@v3 + uses: pdm-project/setup-pdm@v4 with: python-version: "3.8" @@ -74,10 +74,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up PDM - uses: pdm-project/setup-pdm@v3 + uses: pdm-project/setup-pdm@v4 with: python-version: ${{ matrix.python-version }} allow-python-prereleases: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c1f92ec..07d2809 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ jobs: if: startsWith(github.ref, 'refs/tags/') steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Fetch all tags run: git fetch --depth=1 --tags - name: Setup Python diff --git a/.gitignore b/.gitignore index 675f6c8..f59144c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .idea/ +.vscode/ __pycache__/ *.py[cod] dist/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 872ba0d..7c81b08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,26 @@ 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). +## [0.5.0](https://github.com/mkdocstrings/autorefs/releases/tag/0.5.0) - 2023-08-02 + +[Compare with 0.4.1](https://github.com/mkdocstrings/autorefs/compare/0.4.1...0.5.0) + +### Breaking Changes + +- Drop support for Python 3.7 + +### Build + +- Migrate to pdm-backend ([48b92fb](https://github.com/mkdocstrings/autorefs/commit/48b92fb2c12e97242007e5fbbc1b18a36b7f29b6) by Michał Górny). + +### Bug Fixes + +- Stop using deprecated `warning_filter` ([7721103](https://github.com/mkdocstrings/autorefs/commit/77211035bb10b8e55f595eb7d0392344669ffdec) by Kyle King). [PR #30](https://github.com/mkdocstrings/autorefs/pull/30) + +### Code Refactoring + +- Use new MkDocs plugin logger if available ([ca8d758](https://github.com/mkdocstrings/autorefs/commit/ca8d75805ac289e9a5a8123565aa7833b34bd214) by Timothée Mazzucotelli). + ## [0.4.1](https://github.com/mkdocstrings/autorefs/releases/tag/0.4.1) - 2022-03-07 [Compare with 0.4.0](https://github.com/mkdocstrings/autorefs/compare/0.4.0...0.4.1) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index fe3eefb..255e0ee 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -60,7 +60,7 @@ representative at an online or offline event. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at -pawamoy@pm.me. +dev@pawamoy.fr. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ba3ecf0..c243dd4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -44,8 +44,9 @@ on multiple Python versions, you run the task directly with `pdm run duty TASK`. The Makefile detects if a virtual environment is activated, so `make` will work the same with the virtualenv activated or not. -If you work in VSCode, -[see examples of tasks and run configurations](https://pawamoy.github.io/copier-pdm/work/#vscode-setup). +If you work in VSCode, we provide +[an action to configure VSCode](https://pawamoy.github.io/copier-pdm/work/#vscode-setup) +for the project. ## Development diff --git a/Makefile b/Makefile index fed1c5e..bd432a4 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ SHELL := bash DUTY := $(if $(VIRTUAL_ENV),,pdm run) duty export PDM_MULTIRUN_VERSIONS ?= 3.8 3.9 3.10 3.11 3.12 +export PDM_MULTIRUN_USE_VENVS ?= $(if $(shell pdm config python.use_venv | grep True),1,0) args = $(foreach a,$($(subst -,_,$1)_args),$(if $(value $a),$a="$($a)")) check_quality_args = files @@ -18,7 +19,8 @@ BASIC_DUTIES = \ docs \ docs-deploy \ format \ - release + release \ + vscode QUALITY_DUTIES = \ check-quality \ diff --git a/README.md b/README.md index b8115d7..bb60430 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,14 @@ [![pypi version](https://img.shields.io/pypi/v/mkdocs-autorefs.svg)](https://pypi.org/project/mkdocs-autorefs/) [![conda version](https://img.shields.io/conda/vn/conda-forge/mkdocs-autorefs.svg)](https://anaconda.org/conda-forge/mkdocs-autorefs) [![gitpod](https://img.shields.io/badge/gitpod-workspace-blue.svg?style=flat)](https://gitpod.io/#https://github.com/mkdocstrings/autorefs) -[![gitter](https://badges.gitter.im/join%20chat.svg)](https://gitter.im/mkdocstrings/autorefs) +[![gitter](https://badges.gitter.im/join%20chat.svg)](https://app.gitter.im/#/room/#autorefs:gitter.im) Automatically link across pages in MkDocs. ## Installation With `pip`: + ```bash python3 -m pip install mkdocs-autorefs ``` diff --git a/config/git-changelog.toml b/config/git-changelog.toml new file mode 100644 index 0000000..44e2b1f --- /dev/null +++ b/config/git-changelog.toml @@ -0,0 +1,8 @@ +bump = "auto" +convention = "angular" +in-place = true +output = "CHANGELOG.md" +parse-refs = false +parse-trailers = true +sections = ["build", "deps", "feat", "fix", "refactor"] +template = "keepachangelog" diff --git a/config/ruff.toml b/config/ruff.toml index ff1421f..02cf84e 100644 --- a/config/ruff.toml +++ b/config/ruff.toml @@ -1,5 +1,5 @@ target-version = "py38" -line-length = 132 +line-length = 120 exclude = [ "fixtures", "site", @@ -77,6 +77,9 @@ ignore = [ "src/*/cli.py" = [ "T201", # Print statement ] +"src/*/debug.py" = [ + "T201", # Print statement +] "scripts/*.py" = [ "INP001", # File is part of an implicit namespace package "T201", # Print statement @@ -99,3 +102,7 @@ known-first-party = ["mkdocs_autorefs"] [pydocstyle] convention = "google" + +[format] +docstring-code-format = true +docstring-code-line-length = 80 diff --git a/config/vscode/launch.json b/config/vscode/launch.json new file mode 100644 index 0000000..d056cce --- /dev/null +++ b/config/vscode/launch.json @@ -0,0 +1,36 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "python (current file)", + "type": "debugpy", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "justMyCode": false + }, + { + "name": "test", + "type": "debugpy", + "request": "launch", + "module": "pytest", + "justMyCode": false, + "args": [ + "-c=config/pytest.ini", + "-vvv", + "--no-cov", + "--dist=no", + "tests", + "-k=${input:tests_selection}" + ] + } + ], + "inputs": [ + { + "id": "tests_selection", + "type": "promptString", + "description": "Tests selection", + "default": "" + } + ] +} \ No newline at end of file diff --git a/config/vscode/settings.json b/config/vscode/settings.json new file mode 100644 index 0000000..17beee4 --- /dev/null +++ b/config/vscode/settings.json @@ -0,0 +1,52 @@ +{ + "files.watcherExclude": { + "**/__pypackages__/**": true, + "**/.venv*/**": true, + "**/venv*/**": true + }, + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter" + }, + "python.autoComplete.extraPaths": [ + "__pypackages__/3.8/lib", + "__pypackages__/3.9/lib", + "__pypackages__/3.10/lib", + "__pypackages__/3.11/lib", + "__pypackages__/3.12/lib" + ], + "python.analysis.extraPaths": [ + "__pypackages__/3.8/lib", + "__pypackages__/3.9/lib", + "__pypackages__/3.10/lib", + "__pypackages__/3.11/lib", + "__pypackages__/3.12/lib" + ], + "black-formatter.args": [ + "--config=config/black.toml" + ], + "mypy-type-checker.args": [ + "--config-file=config/mypy.ini" + ], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true, + "python.testing.pytestArgs": [ + "--config-file=config/pytest.ini" + ], + "ruff.format.args": [ + "--config=config/ruff.toml" + ], + "ruff.lint.args": [ + "--config=config/ruff.toml" + ], + "yaml.schemas": { + "https://squidfunk.github.io/mkdocs-material/schema.json": "mkdocs.yml" + }, + "yaml.customTags": [ + "!ENV scalar", + "!ENV sequence", + "!relative scalar", + "tag:yaml.org,2002:python/name:materialx.emoji.to_svg", + "tag:yaml.org,2002:python/name:materialx.emoji.twemoji", + "tag:yaml.org,2002:python/name:pymdownx.superfences.fence_code_format" + ] +} \ No newline at end of file diff --git a/config/vscode/tasks.json b/config/vscode/tasks.json new file mode 100644 index 0000000..80cd13d --- /dev/null +++ b/config/vscode/tasks.json @@ -0,0 +1,93 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "changelog", + "type": "shell", + "command": "pdm run duty changelog" + }, + { + "label": "check", + "type": "shell", + "command": "pdm run duty check" + }, + { + "label": "check-quality", + "type": "shell", + "command": "pdm run duty check-quality" + }, + { + "label": "check-types", + "type": "shell", + "command": "pdm run duty check-types" + }, + { + "label": "check-docs", + "type": "shell", + "command": "pdm run duty check-docs" + }, + { + "label": "check-dependencies", + "type": "shell", + "command": "pdm run duty check-dependencies" + }, + { + "label": "check-api", + "type": "shell", + "command": "pdm run duty check-api" + }, + { + "label": "clean", + "type": "shell", + "command": "pdm run duty clean" + }, + { + "label": "docs", + "type": "shell", + "command": "pdm run duty docs" + }, + { + "label": "docs-deploy", + "type": "shell", + "command": "pdm run duty docs-deploy" + }, + { + "label": "format", + "type": "shell", + "command": "pdm run duty format" + }, + { + "label": "lock", + "type": "shell", + "command": "pdm lock -G:all" + }, + { + "label": "release", + "type": "shell", + "command": "pdm run duty release ${input:version}" + }, + { + "label": "setup", + "type": "shell", + "command": "bash scripts/setup.sh" + }, + { + "label": "test", + "type": "shell", + "command": "pdm run duty test coverage", + "group": "test" + }, + { + "label": "vscode", + "type": "shell", + "command": "pdm run duty vscode" + } + ], + "inputs": [ + { + "id": "version", + "type": "promptString", + "description": "Version" + } + ] +} \ No newline at end of file diff --git a/docs/credits.md b/docs/credits.md index 9db4587..f758db8 100644 --- a/docs/credits.md +++ b/docs/credits.md @@ -3,6 +3,8 @@ hide: - toc --- + ```python exec="yes" --8<-- "scripts/gen_credits.py" ``` + diff --git a/docs/css/mkdocstrings.css b/docs/css/mkdocstrings.css index fe191c8..727a614 100644 --- a/docs/css/mkdocstrings.css +++ b/docs/css/mkdocstrings.css @@ -9,6 +9,7 @@ a.external::after, a.autorefs-external::after { /* https://primer.style/octicons/arrow-up-right-24 */ mask-image: url('data:image/svg+xml,'); + -webkit-mask-image: url('data:image/svg+xml,'); content: ' '; display: inline-block; diff --git a/duties.py b/duties.py index ed8bbd4..0da5c11 100644 --- a/duties.py +++ b/duties.py @@ -4,21 +4,18 @@ import os import sys +from contextlib import contextmanager +from importlib.metadata import version as pkgversion from pathlib import Path -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Iterator from duty import duty -from duty.callables import black, blacken_docs, coverage, lazy, mkdocs, mypy, pytest, ruff, safety - -if sys.version_info < (3, 8): - from importlib_metadata import version as pkgversion -else: - from importlib.metadata import version as pkgversion - +from duty.callables import coverage, lazy, mkdocs, mypy, pytest, ruff, safety if TYPE_CHECKING: from duty.context import Context + PY_SRC_PATHS = (Path(_) for _ in ("src", "tests", "duties.py", "scripts")) PY_SRC_LIST = tuple(str(_) for _ in PY_SRC_PATHS) PY_SRC = " ".join(PY_SRC_LIST) @@ -35,32 +32,16 @@ def pyprefix(title: str) -> str: # noqa: D103 return title -def merge(d1: Any, d2: Any) -> Any: # noqa: D103 - basic_types = (int, float, str, bool, complex) - if isinstance(d1, dict) and isinstance(d2, dict): - for key, value in d2.items(): - if key in d1: - if isinstance(d1[key], basic_types): - d1[key] = value - else: - d1[key] = merge(d1[key], value) - else: - d1[key] = value - return d1 - if isinstance(d1, list) and isinstance(d2, list): - return d1 + d2 - return d2 - - -def mkdocs_config() -> str: # noqa: D103 - import mergedeep - - # force YAML loader to merge arrays - mergedeep.merge = merge - +@contextmanager +def material_insiders() -> Iterator[bool]: # noqa: D103 if "+insiders" in pkgversion("mkdocs-material"): - return "mkdocs.insiders.yml" - return "mkdocs.yml" + os.environ["MATERIAL_INSIDERS"] = "true" + try: + yield True + finally: + os.environ.pop("MATERIAL_INSIDERS") + else: + yield False @duty @@ -70,23 +51,9 @@ def changelog(ctx: Context) -> None: Parameters: ctx: The context instance (passed automatically). """ - from git_changelog.cli import build_and_render + from git_changelog.cli import main as git_changelog - git_changelog = lazy(build_and_render, name="git_changelog") - ctx.run( - git_changelog( - repository=".", - output="CHANGELOG.md", - convention="angular", - template="keepachangelog", - parse_trailers=True, - parse_refs=False, - sections=["build", "deps", "feat", "fix", "refactor"], - bump_latest=True, - in_place=True, - ), - title="Updating changelog", - ) + ctx.run(git_changelog, args=[[]], title="Updating changelog") @duty(pre=["check_quality", "check_types", "check_docs", "check_dependencies", "check-api"]) @@ -142,12 +109,12 @@ def check_docs(ctx: Context) -> None: """ Path("htmlcov").mkdir(parents=True, exist_ok=True) Path("htmlcov/index.html").touch(exist_ok=True) - config = mkdocs_config() - ctx.run( - mkdocs.build(strict=True, config_file=config, verbose=True), - title=pyprefix("Building documentation"), - command=f"mkdocs build -vsf {config}", - ) + with material_insiders(): + ctx.run( + mkdocs.build(strict=True, verbose=True), + title=pyprefix("Building documentation"), + command="mkdocs build -vs", + ) @duty @@ -210,11 +177,12 @@ def docs(ctx: Context, host: str = "127.0.0.1", port: int = 8000) -> None: host: The host to serve the docs from. port: The port to serve the docs on. """ - ctx.run( - mkdocs.serve(dev_addr=f"{host}:{port}", config_file=mkdocs_config()), - title="Serving documentation", - capture=False, - ) + with material_insiders(): + ctx.run( + mkdocs.serve(dev_addr=f"{host}:{port}"), + title="Serving documentation", + capture=False, + ) @duty @@ -225,10 +193,10 @@ def docs_deploy(ctx: Context) -> None: ctx: The context instance (passed automatically). """ os.environ["DEPLOY"] = "true" - config_file = mkdocs_config() - if config_file == "mkdocs.yml": - ctx.run(lambda: False, title="Not deploying docs without Material for MkDocs Insiders!") - ctx.run(mkdocs.gh_deploy(config_file=config_file), title="Deploying documentation") + with material_insiders() as insiders: + if not insiders: + ctx.run(lambda: False, title="Not deploying docs without Material for MkDocs Insiders!") + ctx.run(mkdocs.gh_deploy(), title="Deploying documentation") @duty @@ -242,12 +210,7 @@ def format(ctx: Context) -> None: ruff.check(*PY_SRC_LIST, config="config/ruff.toml", fix_only=True, exit_zero=True), title="Auto-fixing code", ) - ctx.run(black.run(*PY_SRC_LIST, config="config/black.toml"), title="Formatting code") - ctx.run( - blacken_docs.run(*PY_SRC_LIST, "docs", exts=["py", "md"], line_length=120), - title="Formatting docs", - nofail=True, - ) + ctx.run(ruff.format(*PY_SRC_LIST, config="config/ruff.toml"), title="Formatting code") @duty(post=["docs-deploy"]) @@ -295,3 +258,28 @@ def test(ctx: Context, match: str = "") -> None: 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/mkdocs.insiders.yml b/mkdocs.insiders.yml deleted file mode 100644 index 9afba9a..0000000 --- a/mkdocs.insiders.yml +++ /dev/null @@ -1,4 +0,0 @@ -INHERIT: mkdocs.yml - -plugins: -- typeset diff --git a/mkdocs.yml b/mkdocs.yml index ea70acf..db81916 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -77,10 +77,11 @@ markdown_extensions: - callouts - footnotes - pymdownx.emoji: - emoji_index: !!python/name:materialx.emoji.twemoji - emoji_generator: !!python/name:materialx.emoji.to_svg + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg - pymdownx.magiclink - pymdownx.snippets: + base_path: [!relative $config_dir] check_paths: true - pymdownx.superfences - pymdownx.tabbed: @@ -102,7 +103,7 @@ plugins: scripts: - scripts/gen_ref_nav.py - literate-nav: - nav_file: SUMMARY.txt + nav_file: SUMMARY.md - coverage - mkdocstrings: handlers: @@ -110,11 +111,14 @@ plugins: import: - https://docs.python.org/3/objects.inv - https://www.mkdocs.org/objects.inv + paths: [src] options: docstring_options: ignore_init_summary: true docstring_section_style: list + filters: ["!^_"] heading_level: 1 + inherited_members: true merge_init_into_class: true separate_signature: true show_root_heading: true @@ -123,11 +127,16 @@ plugins: show_symbol_type_heading: true show_symbol_type_toc: true signature_crossrefs: true + summary: true - git-committers: enabled: !ENV [DEPLOY, false] repository: mkdocstrings/autorefs - minify: minify_html: !ENV [DEPLOY, false] +- group: + enabled: !ENV [MATERIAL_INSIDERS, false] + plugins: + - typeset extra: social: diff --git a/pyproject.toml b/pyproject.toml index 3c0e795..eec6329 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ name = "mkdocs-autorefs" description = "Automatically link across pages in MkDocs." authors = [ {name = "Oleh Prypin", email = "oleh@pryp.in"}, - {name = "Timothée Mazzucotelli", email = "pawamoy@pm.me"}, + {name = "Timothée Mazzucotelli", email = "dev@pawamoy.fr"}, ] license = {text = "ISC"} readme = "README.md" @@ -64,39 +64,38 @@ duty = ["duty>=0.10"] ci-quality = ["mkdocs-autorefs[duty,docs,quality,typing,security]"] ci-tests = ["mkdocs-autorefs[duty,tests]"] docs = [ - "black>=23.1", - "markdown-callouts>=0.2", - "markdown-exec>=0.5", + "black>=23.9", + "markdown-callouts>=0.3", + "markdown-exec>=1.7", "mkdocs>=1.5", - "mkdocs-coverage>=0.2", - "mkdocs-gen-files>=0.3", - "mkdocs-git-committers-plugin-2>=1.1", - "mkdocs-literate-nav>=0.4", - "mkdocs-material>=7.3", - "mkdocs-minify-plugin>=0.6.4", - "mkdocstrings[python]>=0.18", - "toml>=0.10", + "mkdocs-coverage>=1.0", + "mkdocs-gen-files>=0.5", + "mkdocs-git-committers-plugin-2>=1.2", + "mkdocs-literate-nav>=0.6", + "mkdocs-material>=9.4", + "mkdocs-minify-plugin>=0.7", + "mkdocstrings[python]>=0.23", + "tomli>=2.0; python_version < '3.11'", ] maintain = [ - "black>=23.1", - "blacken-docs>=1.13", - "git-changelog>=1.0", + "black>=23.9", + "blacken-docs>=1.16", + "git-changelog>=2.3", ] quality = [ - "ruff>=0.0.246", + "ruff>=0.0", ] tests = [ - "pytest>=6.2", - "pytest-cov>=3.0", - "pytest-randomly>=3.10", - "pytest-xdist>=2.4", + "pytest>=7.4", + "pytest-cov>=4.1", + "pytest-randomly>=3.15", + "pytest-xdist>=3.3", ] typing = [ - "mypy>=0.910", - "types-markdown>=3.3", + "mypy>=1.5", + "types-markdown>=3.5", "types-pyyaml>=6.0", - "types-toml>=0.10", ] security = [ - "safety>=2", + "safety>=2.3", ] diff --git a/scripts/gen_credits.py b/scripts/gen_credits.py index bc01c0b..bf35f0d 100644 --- a/scripts/gen_credits.py +++ b/scripts/gen_credits.py @@ -2,27 +2,31 @@ from __future__ import annotations +import os import re import sys +from importlib.metadata import PackageNotFoundError, metadata from itertools import chain from pathlib import Path from textwrap import dedent from typing import Mapping, cast -import toml from jinja2 import StrictUndefined from jinja2.sandbox import SandboxedEnvironment -if sys.version_info < (3, 8): - from importlib_metadata import PackageNotFoundError, metadata +# TODO: Remove once support for Python 3.10 is dropped. +if sys.version_info >= (3, 11): + import tomllib else: - from importlib.metadata import PackageNotFoundError, metadata + import tomli as tomllib -project_dir = Path(".") -pyproject = toml.load(project_dir / "pyproject.toml") +project_dir = Path(os.getenv("MKDOCS_CONFIG_DIR", ".")) +with project_dir.joinpath("pyproject.toml").open("rb") as pyproject_file: + pyproject = tomllib.load(pyproject_file) project = pyproject["project"] pdm = pyproject["tool"]["pdm"] -lock_data = toml.load(project_dir / "pdm.lock") +with project_dir.joinpath("pdm.lock").open("rb") as lock_file: + lock_data = tomllib.load(lock_file) lock_pkgs = {pkg["name"].lower(): pkg for pkg in lock_data["package"]} project_name = project["name"] regex = re.compile(r"(?P[\w.-]+)(?P.*)$") @@ -35,7 +39,7 @@ def _get_license(pkg_name: str) -> str: return "?" license_name = cast(dict, data).get("License", "").strip() multiple_lines = bool(license_name.count("\n")) - # TODO: remove author logic once all my packages licenses are fixed + # TODO: Remove author logic once all my packages licenses are fixed. author = "" if multiple_lines or not license_name or license_name == "UNKNOWN": for header, value in cast(dict, data).items(): diff --git a/scripts/gen_ref_nav.py b/scripts/gen_ref_nav.py index 713522b..7285ac1 100644 --- a/scripts/gen_ref_nav.py +++ b/scripts/gen_ref_nav.py @@ -7,9 +7,11 @@ nav = mkdocs_gen_files.Nav() mod_symbol = '' -for path in sorted(Path("src").rglob("*.py")): - module_path = path.relative_to("src").with_suffix("") - doc_path = path.relative_to("src").with_suffix(".md") +src = Path(__file__).parent.parent / "src" + +for path in sorted(src.rglob("*.py")): + module_path = path.relative_to(src).with_suffix("") + doc_path = path.relative_to(src).with_suffix(".md") full_doc_path = Path("reference", doc_path) parts = tuple(module_path.parts) @@ -30,5 +32,5 @@ mkdocs_gen_files.set_edit_path(full_doc_path, ".." / path) -with mkdocs_gen_files.open("reference/SUMMARY.txt", "w") as nav_file: +with mkdocs_gen_files.open("reference/SUMMARY.md", "w") as nav_file: nav_file.writelines(nav.build_literate_nav()) diff --git a/scripts/setup.sh b/scripts/setup.sh index bbf0d11..eef3843 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -12,6 +12,13 @@ if ! pdm self list 2>/dev/null | grep -q pdm-multirun; then fi if [ -n "${PDM_MULTIRUN_VERSIONS}" ]; then + if [ "${PDM_MULTIRUN_USE_VENVS}" -eq "1" ]; then + for version in ${PDM_MULTIRUN_VERSIONS}; do + if ! pdm venv --path "${version}" &>/dev/null; then + pdm venv create --name "${version}" "${version}" + fi + done + fi pdm multirun -v pdm install -G:all else pdm install -G:all diff --git a/src/mkdocs_autorefs/debug.py b/src/mkdocs_autorefs/debug.py new file mode 100644 index 0000000..05af0e6 --- /dev/null +++ b/src/mkdocs_autorefs/debug.py @@ -0,0 +1,106 @@ +"""Debugging utilities.""" + +from __future__ import annotations + +import os +import platform +import sys +from dataclasses import dataclass +from importlib import metadata + + +@dataclass +class Variable: + """Dataclass describing an environment variable.""" + + name: str + """Variable name.""" + value: str + """Variable value.""" + + +@dataclass +class Package: + """Dataclass describing a Python package.""" + + name: str + """Package name.""" + version: str + """Package version.""" + + +@dataclass +class Environment: + """Dataclass to store environment information.""" + + interpreter_name: str + """Python interpreter name.""" + interpreter_version: str + """Python interpreter version.""" + platform: str + """Operating System.""" + packages: list[Package] + """Installed packages.""" + variables: list[Variable] + """Environment variables.""" + + +def _interpreter_name_version() -> tuple[str, str]: + if hasattr(sys, "implementation"): + impl = sys.implementation.version + version = f"{impl.major}.{impl.minor}.{impl.micro}" + kind = impl.releaselevel + if kind != "final": + version += kind[0] + str(impl.serial) + return sys.implementation.name, version + return "", "0.0.0" + + +def get_version(dist: str = "mkdocs-autorefs") -> str: + """Get version of the given distribution. + + Parameters: + dist: A distribution name. + + Returns: + A version number. + """ + try: + return metadata.version(dist) + except metadata.PackageNotFoundError: + return "0.0.0" + + +def get_debug_info() -> Environment: + """Get debug/environment information. + + Returns: + Environment information. + """ + py_name, py_version = _interpreter_name_version() + packages = ["mkdocs-autorefs"] + variables = ["PYTHONPATH", *[var for var in os.environ if var.startswith("MKDOCS_AUTOREFS")]] + return Environment( + interpreter_name=py_name, + interpreter_version=py_version, + 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], + ) + + +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("- __Environment variables__:") + for var in info.variables: + print(f" - `{var.name}`: `{var.value}`") + print("- __Installed packages__:") + for pkg in info.packages: + print(f" - `{pkg.name}` v{pkg.version}") + + +if __name__ == "__main__": + print_debug_info() diff --git a/src/mkdocs_autorefs/references.py b/src/mkdocs_autorefs/references.py index dd527de..66b4931 100644 --- a/src/mkdocs_autorefs/references.py +++ b/src/mkdocs_autorefs/references.py @@ -18,6 +18,7 @@ AUTO_REF_RE = re.compile( r"autorefs-identifier|autorefs-optional|autorefs-optional-hover)=" r'("?)(?P[^"<>]*)\2>(?P.*?)</span>', + flags=re.DOTALL, ) """A regular expression to match mkdocs-autorefs' special reference markers in the [`on_post_page` hook][mkdocs_autorefs.plugin.AutorefsPlugin.on_post_page]. diff --git a/tests/test_references.py b/tests/test_references.py index 14e9a78..5a25844 100644 --- a/tests/test_references.py +++ b/tests/test_references.py @@ -111,6 +111,15 @@ def test_reference_to_relative_path() -> None: ) +def test_multiline_links() -> None: + """Check that links with multiline text are recognized.""" + run_references_test( + url_map={"foo-bar": "foo.html#bar"}, + source="This [Foo\nbar][foo-bar].", + output='<p>This <a class="autorefs autorefs-internal" href="foo.html#bar">Foo\nbar</a>.</p>', + ) + + def test_no_reference_with_space() -> None: """Check that references with spaces are not fixed.""" run_references_test(