Skip to content

Fine-grained Configuration of check_crossrefs #44

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 10, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Change check_crossrefs to be stored as a class attribute instead of v…
…ia global_config, and add a blacklist option
  • Loading branch information
thetianshuhuang committed Jun 8, 2025
commit bdfa2fc626851698b8e4ab53afa8d90e517a118c
30 changes: 20 additions & 10 deletions src/mkdocstrings_handlers/python_xref/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@

from __future__ import annotations

import re
import sys
from dataclasses import dataclass, fields
from dataclasses import dataclass, field, fields
from functools import partial
from pathlib import Path
from typing import Any, ClassVar, Mapping, MutableMapping, Optional
from warnings import warn
Expand All @@ -43,6 +45,7 @@
@dataclass(**_dataclass_options)
class PythonRelXRefOptions(PythonOptions):
check_crossrefs: bool = True
check_crossrefs_exclude: list[str] = field(default_factory=list)

class PythonRelXRefHandler(PythonHandler):
"""Extended version of mkdocstrings Python handler
Expand All @@ -62,26 +65,30 @@ def __init__(self, config: PythonConfig, base_dir: Path, **kwargs: Any) -> None:
base_dir: The base directory of the project.
**kwargs: Arguments passed to the parent constructor.
"""
check_crossrefs = config.options.pop('check_crossrefs', None) # Remove
self.check_crossrefs = config.options.pop('check_crossrefs', None)
self.check_crossrefs_exclude = config.options.pop(
'check_crossrefs_exclude', [])
super().__init__(config, base_dir, **kwargs)
if check_crossrefs is not None:
self.global_options["check_crossrefs"] = check_crossrefs

def get_options(self, local_options: Mapping[str, Any]) -> PythonRelXRefOptions:
local_options = dict(local_options)
check_crossrefs = local_options.pop('check_crossrefs', None)
check_crossrefs = local_options.pop(
'check_crossrefs', self.check_crossrefs)
check_crossrefs_exclude = local_options.pop(
'check_crossrefs_exclude', self.check_crossrefs_exclude)
_opts = super().get_options(local_options)
opts = PythonRelXRefOptions(
check_crossrefs=check_crossrefs,
check_crossrefs_exclude=check_crossrefs_exclude,
**{field.name: getattr(_opts, field.name) for field in fields(_opts)}
)
if check_crossrefs is not None:
opts.check_crossrefs = bool(check_crossrefs)
return opts

def render(self, data: CollectorItem, options: PythonOptions) -> str:
if options.relative_crossrefs:
if isinstance(options, PythonRelXRefOptions):
checkref = self._check_ref if options.check_crossrefs else None
if isinstance(options, PythonRelXRefOptions) and options.check_crossrefs:
checkref = partial(
self._check_ref, exclude=options.check_crossrefs_exclude)
else:
checkref = None
substitute_relative_crossrefs(data, checkref=checkref)
Expand All @@ -98,8 +105,11 @@ def get_templates_dir(self, handler: Optional[str] = None) -> Path:
handler = 'python'
return super().get_templates_dir(handler)

def _check_ref(self, ref:str) -> bool:
def _check_ref(self, ref : str, exclude: list[str] = []) -> bool:
"""Check for existence of reference"""
for ex in exclude:
if re.match(ex, ref):
return True
try:
self.collect(ref, PythonOptions())
return True
Expand Down