diff --git a/.copier-answers.yml b/.copier-answers.yml
index 25f7ed9..3183924 100644
--- a/.copier-answers.yml
+++ b/.copier-answers.yml
@@ -1,5 +1,5 @@
# Changes here will be overwritten by Copier
-_commit: 0.16.8
+_commit: 1.2.0
_src_path: gh:pawamoy/copier-pdm
author_email: pawamoy@pm.me
author_fullname: Timothée Mazzucotelli
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 7ee8cad..05b0b29 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -1,32 +1,61 @@
---
name: Bug report
-about: Create a report to help us improve
-title: ''
+about: Create a bug report to help us improve.
+title: "bug: "
labels: unconfirmed
-assignees: ''
-
+assignees: [pawamoy]
---
-**Describe the bug**
-A clear and concise description of what the bug is.
+### Description of the bug
+
+
+### To Reproduce
+
+
+```
+WRITE MRE / INSTRUCTIONS HERE
+```
+
+### Full traceback
+
+
+Full traceback
+
+```python
+PASTE TRACEBACK HERE
+```
+
+
-**To Reproduce**
-Steps to reproduce the behavior:
-1. Go to '...'
-2. Run command '...'
-3. Scroll down to '...'
-4. See error
+### Expected behavior
+
-**Expected behavior**
-A clear and concise description of what you expected to happen.
+### Environment information
+
-**Screenshots**
-If applicable, add screenshots to help explain your problem.
+```bash
+python -m mkdocs_spellcheck.debug # | xclip -selection clipboard
+```
-**System (please complete the following information):**
-- `MkDocs SpellCheck` version: [e.g. 0.2.1]
-- Python version: [e.g. 3.8]
-- OS: [Windows/Linux]
+PASTE OUTPUT HERE
-**Additional context**
-Add any other context about the problem here.
+### Additional context
+
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..40e6647
--- /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/pawamoy/mkdocs-spellcheck/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
index 4fe86d5..2df98fb 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -1,20 +1,19 @@
---
name: Feature request
-about: Suggest an idea for this project
-title: ''
+about: Suggest an idea for this project.
+title: "feature: "
labels: feature
-assignees: ''
-
+assignees: pawamoy
---
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+### Is your feature request related to a problem? Please describe.
+
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.
+### Describe the solution you'd like
+
-**Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
+### Describe alternatives you've considered
+
-**Additional context**
-Add any other context or screenshots about the feature request here.
+### Additional context
+
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 9746ed5..90336c1 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 7e8de7c..8ad5209 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 beb4229..4e0bd1d 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
[![documentation](https://img.shields.io/badge/docs-mkdocs%20material-blue.svg?style=flat)](https://pawamoy.github.io/mkdocs-spellcheck/)
[![pypi version](https://img.shields.io/pypi/v/mkdocs-spellcheck.svg)](https://pypi.org/project/mkdocs-spellcheck/)
[![gitpod](https://img.shields.io/badge/gitpod-workspace-blue.svg?style=flat)](https://gitpod.io/#https://github.com/pawamoy/mkdocs-spellcheck)
-[![gitter](https://badges.gitter.im/join%20chat.svg)](https://gitter.im/mkdocs-spellcheck/community)
+[![gitter](https://badges.gitter.im/join%20chat.svg)](https://app.gitter.im/#/room/#mkdocs-spellcheck:gitter.im)
A spell checker plugin for MkDocs.
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 46e4a5f..b22cbd7 100644
--- a/config/ruff.toml
+++ b/config/ruff.toml
@@ -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
diff --git a/config/vscode/launch.json b/config/vscode/launch.json
new file mode 100644
index 0000000..2e0d651
--- /dev/null
+++ b/config/vscode/launch.json
@@ -0,0 +1,36 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "python (current file)",
+ "type": "python",
+ "request": "launch",
+ "program": "${file}",
+ "console": "integratedTerminal",
+ "justMyCode": false
+ },
+ {
+ "name": "test",
+ "type": "python",
+ "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/known_words.txt b/docs/known_words.txt
index a15ee0f..969973d 100644
--- a/docs/known_words.txt
+++ b/docs/known_words.txt
@@ -24,4 +24,6 @@ www
https
html
faq
-code_of_conduct
\ No newline at end of file
+code_of_conduct
+dataclass
+ahrens
\ No newline at end of file
diff --git a/duties.py b/duties.py
index ea28f9c..fc87e90 100644
--- a/duties.py
+++ b/duties.py
@@ -4,12 +4,13 @@
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
+from duty.callables import black, coverage, lazy, mkdocs, mypy, pytest, ruff, safety
if TYPE_CHECKING:
from duty.context import Context
@@ -31,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
@@ -66,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"])
@@ -138,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
@@ -207,11 +178,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
@@ -222,10 +194,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
@@ -240,11 +212,6 @@ def format(ctx: Context) -> None:
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,
- )
@duty(post=["docs-deploy"])
@@ -291,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 b7583fa..851b8c4 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -79,10 +79,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:
@@ -143,6 +144,10 @@ plugins:
repository: pawamoy/mkdocs-spellcheck
- 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 c2a058a..79eed3d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -63,41 +63,40 @@ duty = ["duty>=0.10"]
ci-quality = ["mkdocs-spellcheck[duty,docs,quality,typing,security]"]
ci-tests = ["mkdocs-spellcheck[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",
"mkdocs-spellcheck[all]",
+ "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",
"mkdocs-spellcheck[all]",
+ "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 459f293..bf35f0d 100644
--- a/scripts/gen_credits.py
+++ b/scripts/gen_credits.py
@@ -2,22 +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
-project_dir = Path(".")
-pyproject = toml.load(project_dir / "pyproject.toml")
+# TODO: Remove once support for Python 3.10 is dropped.
+if sys.version_info >= (3, 11):
+ import tomllib
+else:
+ import tomli as tomllib
+
+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.*)$")
@@ -30,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_spellcheck/debug.py b/src/mkdocs_spellcheck/debug.py
new file mode 100644
index 0000000..2e9afdd
--- /dev/null
+++ b/src/mkdocs_spellcheck/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-spellcheck") -> 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-spellcheck"]
+ variables = ["PYTHONPATH", *[var for var in os.environ if var.startswith("MKDOCS_SPELLCHECK")]]
+ 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()