Skip to content

Commit 830b4fc

Browse files
MNT: update vendored docs files (nipreps#834)
* MNT: update vendored docs files Copied from numpydoc 1.7.0. * MNT: Ignore vendored files in CI spellchecking
1 parent 857a7ba commit 830b4fc

File tree

4 files changed

+77
-51
lines changed

4 files changed

+77
-51
lines changed

Diff for: .codespellrc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[codespell]
2-
skip = .git,*.pdf,*.svg,viz-report.html
2+
skip = .git,*.pdf,*.svg,numpydoc.py,viz-report.html
33
# objekt - used in the code purposefully different from object
44
# nd - import scipy.ndimage as nd
55
ignore-words-list = objekt,nd

Diff for: docs/sphinxext/docscrape.py

+29-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Extract reference documentation from the NumPy source tree.
22
33
"""
4+
45
import inspect
56
import textwrap
67
import re
@@ -11,12 +12,7 @@
1112
import copy
1213
import sys
1314

14-
15-
# TODO: Remove try-except when support for Python 3.7 is dropped
16-
try:
17-
from functools import cached_property
18-
except ImportError: # cached_property added in Python 3.8
19-
cached_property = property
15+
from functools import cached_property
2016

2117

2218
def strip_blank_lines(l):
@@ -408,7 +404,7 @@ def _parse(self):
408404
msg = "Docstring contains a Receives section but not Yields."
409405
raise ValueError(msg)
410406

411-
for (section, content) in sections:
407+
for section, content in sections:
412408
if not section.startswith(".."):
413409
section = (s.capitalize() for s in section.split(" "))
414410
section = " ".join(section)
@@ -631,7 +627,6 @@ def __init__(self, obj, doc=None, config=None):
631627

632628

633629
class ClassDoc(NumpyDocString):
634-
635630
extra_public_methods = ["__call__"]
636631

637632
def __init__(self, cls, doc=None, modulename="", func_doc=FunctionDoc, config=None):
@@ -711,6 +706,7 @@ def properties(self):
711706
for name, func in inspect.getmembers(self._cls)
712707
if (
713708
not name.startswith("_")
709+
and not self._should_skip_member(name, self._cls)
714710
and (
715711
func is None
716712
or isinstance(func, (property, cached_property))
@@ -720,6 +716,19 @@ def properties(self):
720716
)
721717
]
722718

719+
@staticmethod
720+
def _should_skip_member(name, klass):
721+
if (
722+
# Namedtuples should skip everything in their ._fields as the
723+
# docstrings for each of the members is: "Alias for field number X"
724+
issubclass(klass, tuple)
725+
and hasattr(klass, "_asdict")
726+
and hasattr(klass, "_fields")
727+
and name in klass._fields
728+
):
729+
return True
730+
return False
731+
723732
def _is_show_member(self, name):
724733
if self.show_inherited_members:
725734
return True # show all class members
@@ -728,7 +737,15 @@ def _is_show_member(self, name):
728737
return True
729738

730739

731-
def get_doc_object(obj, what=None, doc=None, config=None):
740+
def get_doc_object(
741+
obj,
742+
what=None,
743+
doc=None,
744+
config=None,
745+
class_doc=ClassDoc,
746+
func_doc=FunctionDoc,
747+
obj_doc=ObjDoc,
748+
):
732749
if what is None:
733750
if inspect.isclass(obj):
734751
what = "class"
@@ -742,10 +759,10 @@ def get_doc_object(obj, what=None, doc=None, config=None):
742759
config = {}
743760

744761
if what == "class":
745-
return ClassDoc(obj, func_doc=FunctionDoc, doc=doc, config=config)
762+
return class_doc(obj, func_doc=func_doc, doc=doc, config=config)
746763
elif what in ("function", "method"):
747-
return FunctionDoc(obj, doc=doc, config=config)
764+
return func_doc(obj, doc=doc, config=config)
748765
else:
749766
if doc is None:
750767
doc = pydoc.getdoc(obj)
751-
return ObjDoc(obj, doc, config=config)
768+
return obj_doc(obj, doc, config=config)

Diff for: docs/sphinxext/docscrape_sphinx.py

+16-22
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from sphinx.jinja2glue import BuiltinTemplateLoader
1212

1313
from .docscrape import NumpyDocString, FunctionDoc, ClassDoc, ObjDoc
14+
from .docscrape import get_doc_object as get_doc_object_orig
1415
from .xref import make_xref
1516

1617

@@ -372,9 +373,11 @@ def __str__(self, indent=0, func_role="obj"):
372373
"notes": self._str_section("Notes"),
373374
"references": self._str_references(),
374375
"examples": self._str_examples(),
375-
"attributes": self._str_param_list("Attributes", fake_autosummary=True)
376-
if self.attributes_as_param_list
377-
else self._str_member_list("Attributes"),
376+
"attributes": (
377+
self._str_param_list("Attributes", fake_autosummary=True)
378+
if self.attributes_as_param_list
379+
else self._str_member_list("Attributes")
380+
),
378381
"methods": self._str_member_list("Methods"),
379382
}
380383
ns = {k: "\n".join(v) for k, v in ns.items()}
@@ -407,20 +410,10 @@ def __init__(self, obj, doc=None, config=None):
407410
ObjDoc.__init__(self, obj, doc=doc, config=config)
408411

409412

410-
# TODO: refactor to use docscrape.get_doc_object
411413
def get_doc_object(obj, what=None, doc=None, config=None, builder=None):
412-
if what is None:
413-
if inspect.isclass(obj):
414-
what = "class"
415-
elif inspect.ismodule(obj):
416-
what = "module"
417-
elif isinstance(obj, Callable):
418-
what = "function"
419-
else:
420-
what = "object"
421-
422414
if config is None:
423415
config = {}
416+
424417
template_dirs = [os.path.join(os.path.dirname(__file__), "templates")]
425418
if builder is not None:
426419
template_loader = BuiltinTemplateLoader()
@@ -430,11 +423,12 @@ def get_doc_object(obj, what=None, doc=None, config=None, builder=None):
430423
template_env = SandboxedEnvironment(loader=template_loader)
431424
config["template"] = template_env.get_template("numpydoc_docstring.rst")
432425

433-
if what == "class":
434-
return SphinxClassDoc(obj, func_doc=SphinxFunctionDoc, doc=doc, config=config)
435-
elif what in ("function", "method"):
436-
return SphinxFunctionDoc(obj, doc=doc, config=config)
437-
else:
438-
if doc is None:
439-
doc = pydoc.getdoc(obj)
440-
return SphinxObjDoc(obj, doc, config=config)
426+
return get_doc_object_orig(
427+
obj,
428+
what=what,
429+
doc=doc,
430+
config=config,
431+
class_doc=SphinxClassDoc,
432+
func_doc=SphinxFunctionDoc,
433+
obj_doc=SphinxObjDoc,
434+
)

Diff for: docs/sphinxext/numpydoc.py

+31-16
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
.. [1] https://github.com/numpy/numpydoc
1717
1818
"""
19+
1920
from copy import deepcopy
2021
import re
2122
import pydoc
@@ -24,17 +25,17 @@
2425
import hashlib
2526
import itertools
2627

27-
from docutils.nodes import citation, Text, section, comment, reference
28+
from docutils.nodes import citation, Text, section, comment, reference, inline
2829
import sphinx
2930
from sphinx.addnodes import pending_xref, desc_content
3031
from sphinx.util import logging
3132
from sphinx.errors import ExtensionError
3233

33-
if sphinx.__version__ < "4.2":
34-
raise RuntimeError("Sphinx 4.2 or newer is required")
34+
if sphinx.__version__ < "5":
35+
raise RuntimeError("Sphinx 5 or newer is required")
3536

3637
from .docscrape_sphinx import get_doc_object
37-
from .validate import validate, ERROR_MSGS
38+
from .validate import validate, ERROR_MSGS, get_validation_checks
3839
from .xref import DEFAULT_LINKS
3940
from . import __version__
4041

@@ -149,6 +150,10 @@ def clean_backrefs(app, doc, docname):
149150
for ref in _traverse_or_findall(doc, reference, descend=True):
150151
for id_ in ref["ids"]:
151152
known_ref_ids.add(id_)
153+
# some extensions produce backrefs to inline elements
154+
for ref in _traverse_or_findall(doc, inline, descend=True):
155+
for id_ in ref["ids"]:
156+
known_ref_ids.add(id_)
152157
for citation_node in _traverse_or_findall(doc, citation, descend=True):
153158
# remove backrefs to non-existent refs
154159
citation_node["backrefs"] = [
@@ -207,7 +212,19 @@ def mangle_docstrings(app, what, name, obj, options, lines):
207212
# TODO: Currently, all validation checks are run and only those
208213
# selected via config are reported. It would be more efficient to
209214
# only run the selected checks.
210-
errors = validate(doc)["errors"]
215+
report = validate(doc)
216+
errors = [
217+
err
218+
for err in report["errors"]
219+
if not (
220+
(
221+
overrides := app.config.numpydoc_validation_overrides.get(
222+
err[0]
223+
)
224+
)
225+
and re.search(overrides, report["docstring"])
226+
)
227+
]
211228
if {err[0] for err in errors} & app.config.numpydoc_validation_checks:
212229
msg = (
213230
f"[numpydoc] Validation warnings while processing "
@@ -285,6 +302,7 @@ def setup(app, get_doc_object_=get_doc_object):
285302
app.add_config_value("numpydoc_xref_ignore", set(), True)
286303
app.add_config_value("numpydoc_validation_checks", set(), True)
287304
app.add_config_value("numpydoc_validation_exclude", set(), False)
305+
app.add_config_value("numpydoc_validation_overrides", dict(), False)
288306

289307
# Extra mangling domains
290308
app.add_domain(NumpyPythonDomain)
@@ -310,17 +328,9 @@ def update_config(app, config=None):
310328

311329
# Processing to determine whether numpydoc_validation_checks is treated
312330
# as a blocklist or allowlist
313-
valid_error_codes = set(ERROR_MSGS.keys())
314-
if "all" in config.numpydoc_validation_checks:
315-
block = deepcopy(config.numpydoc_validation_checks)
316-
config.numpydoc_validation_checks = valid_error_codes - block
317-
# Ensure that the validation check set contains only valid error codes
318-
invalid_error_codes = config.numpydoc_validation_checks - valid_error_codes
319-
if invalid_error_codes:
320-
raise ValueError(
321-
f"Unrecognized validation code(s) in numpydoc_validation_checks "
322-
f"config value: {invalid_error_codes}"
323-
)
331+
config.numpydoc_validation_checks = get_validation_checks(
332+
config.numpydoc_validation_checks
333+
)
324334

325335
# Generate the regexp for docstrings to ignore during validation
326336
if isinstance(config.numpydoc_validation_exclude, str):
@@ -335,6 +345,11 @@ def update_config(app, config=None):
335345
)
336346
config.numpydoc_validation_excluder = exclude_expr
337347

348+
for check, patterns in config.numpydoc_validation_overrides.items():
349+
config.numpydoc_validation_overrides[check] = re.compile(
350+
r"|".join(exp for exp in patterns)
351+
)
352+
338353

339354
# ------------------------------------------------------------------------------
340355
# Docstring-mangling domains

0 commit comments

Comments
 (0)