Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-numpydoc for openSUSE:Factory 
checked in at 2026-03-24 18:48:50
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-numpydoc (Old)
 and      /work/SRC/openSUSE:Factory/.python-numpydoc.new.8177 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-numpydoc"

Tue Mar 24 18:48:50 2026 rev:20 rq:1342100 version:1.10.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-numpydoc/python-numpydoc.changes  
2025-08-02 00:41:21.605588128 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-numpydoc.new.8177/python-numpydoc.changes    
    2026-03-24 18:49:40.132436514 +0100
@@ -1,0 +2,10 @@
+Mon Mar 23 20:44:53 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 1.10.0:
+  * Added "exclude_files" option for pyproject.toml config usage.
+  * Constructor checking for AST validator
+  * FIX: account for unreleased changes to sphinx
+  * TST: A few minor test improvements
+  * MAINT: rm unused kwarg from private method.
+
+-------------------------------------------------------------------

Old:
----
  numpydoc-1.9.0.tar.gz

New:
----
  numpydoc-1.10.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-numpydoc.spec ++++++
--- /var/tmp/diff_new_pack.qE6Gds/_old  2026-03-24 18:49:40.636457310 +0100
+++ /var/tmp/diff_new_pack.qE6Gds/_new  2026-03-24 18:49:40.636457310 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-numpydoc
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-numpydoc
-Version:        1.9.0
+Version:        1.10.0
 Release:        0
 Summary:        Sphinx extension to support docstrings in Numpy format
 License:        BSD-3-Clause
@@ -27,16 +27,16 @@
 Source:         
https://files.pythonhosted.org/packages/source/n/numpydoc/numpydoc-%{version}.tar.gz
 # https://docs.python.org/3/objects.inv (changes from time to time, accessed 
2024-02-29)
 Source1:        python-objects.inv
-BuildRequires:  %{python_module Sphinx >= 5}
-BuildRequires:  %{python_module base >= 3.8}
+BuildRequires:  %{python_module Sphinx >= 6}
+BuildRequires:  %{python_module base >= 3.10}
 BuildRequires:  %{python_module pip}
-BuildRequires:  %{python_module setuptools}
+BuildRequires:  %{python_module setuptools >= 61.2}
 BuildRequires:  %{python_module wheel}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
 Requires(post): update-alternatives
 Requires(postun): update-alternatives
-Requires:       python-Sphinx >= 5
+Requires:       python-Sphinx >= 6
 BuildArch:      noarch
 # SECTION test requirements
 BuildRequires:  %{python_module pytest}

++++++ numpydoc-1.9.0.tar.gz -> numpydoc-1.10.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/PKG-INFO new/numpydoc-1.10.0/PKG-INFO
--- old/numpydoc-1.9.0/PKG-INFO 2025-06-24 14:22:24.037762600 +0200
+++ new/numpydoc-1.10.0/PKG-INFO        2025-12-02 17:38:47.474620000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: numpydoc
-Version: 1.9.0
+Version: 1.10.0
 Summary: Sphinx extension to support docstrings in Numpy format
 Author-email: Pauli Virtanen and others <[email protected]>
 License: Copyright (C) 2008-2023 Stefan van der Walt <[email protected]>, 
Pauli Virtanen <[email protected]>
@@ -38,13 +38,12 @@
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
 Classifier: Programming Language :: Python :: 3.13
 Classifier: Topic :: Documentation
-Requires-Python: >=3.9
+Requires-Python: >=3.10
 Description-Content-Type: text/x-rst
 License-File: LICENSE.txt
 Requires-Dist: sphinx>=6
@@ -70,7 +69,7 @@
 The extension also adds the code description directives
 ``np:function``, ``np-c:function``, etc.
 
-numpydoc requires Python 3.9+ and sphinx 6+.
+numpydoc requires Python 3.10+ and sphinx 6+.
 
 For usage information, please refer to the `documentation
 <https://numpydoc.readthedocs.io/>`_.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/README.rst 
new/numpydoc-1.10.0/README.rst
--- old/numpydoc-1.9.0/README.rst       2025-06-24 14:22:17.000000000 +0200
+++ new/numpydoc-1.10.0/README.rst      2025-12-02 17:38:37.000000000 +0100
@@ -17,7 +17,7 @@
 The extension also adds the code description directives
 ``np:function``, ``np-c:function``, etc.
 
-numpydoc requires Python 3.9+ and sphinx 6+.
+numpydoc requires Python 3.10+ and sphinx 6+.
 
 For usage information, please refer to the `documentation
 <https://numpydoc.readthedocs.io/>`_.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/doc/install.rst 
new/numpydoc-1.10.0/doc/install.rst
--- old/numpydoc-1.9.0/doc/install.rst  2025-06-24 14:22:17.000000000 +0200
+++ new/numpydoc-1.10.0/doc/install.rst 2025-12-02 17:38:37.000000000 +0100
@@ -5,7 +5,7 @@
 Installation
 ============
 
-This extension requires Python 3.9+, sphinx 6+ and is available from:
+This extension requires Python 3.10+, sphinx 6+ and is available from:
 
 * `numpydoc on PyPI <http://pypi.python.org/pypi/numpydoc>`_
 * `numpydoc on GitHub <https://github.com/numpy/numpydoc/>`_
@@ -139,6 +139,18 @@
     validation.
     Only has an effect when docstring validation is activated, i.e.
     ``numpydoc_validation_checks`` is not an empty set.
+numpydoc_validation_exclude_files : set
+    A container of strings using :py:mod:`re` syntax specifying path patterns 
to
+    ignore for docstring validation, relative to the package root.
+    For example, to skip docstring validation for all objects in
+    ``tests\``::
+
+        numpydoc_validation_exclude_files = {"^tests/.*$"}
+
+    The default is an empty set meaning no paths are excluded from docstring
+    validation.
+    Only has an effect when docstring validation is activated, i.e.
+    ``numpydoc_validation_checks`` is not an empty set.
 numpydoc_validation_overrides : dict
     A dictionary mapping :ref:`validation checks <validation_checks>` to a
     container of strings using :py:mod:`re` syntax specifying patterns to
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/doc/release/notes.rst 
new/numpydoc-1.10.0/doc/release/notes.rst
--- old/numpydoc-1.9.0/doc/release/notes.rst    2025-06-24 14:22:17.000000000 
+0200
+++ new/numpydoc-1.10.0/doc/release/notes.rst   2025-12-02 17:38:37.000000000 
+0100
@@ -20,7 +20,7 @@
 Documentation
 -------------
 
-- DOC: Do not use types for *args, **kwargs (`#585 
<https://github.com/numpy/numpydoc/pull/585>`_).
+- DOC: Do not use types for ``*args``, ``**kwargs`` (`#585 
<https://github.com/numpy/numpydoc/pull/585>`_).
 - mention conda-forge in installation docs (`#595 
<https://github.com/numpy/numpydoc/pull/595>`_).
 - Fix typo in validation.rst (`#605 
<https://github.com/numpy/numpydoc/pull/605>`_).
 - Fix broken link in ``format.rst`` (`#628 
<https://github.com/numpy/numpydoc/pull/628>`_).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/doc/validation.rst 
new/numpydoc-1.10.0/doc/validation.rst
--- old/numpydoc-1.9.0/doc/validation.rst       2025-06-24 14:22:17.000000000 
+0200
+++ new/numpydoc-1.10.0/doc/validation.rst      2025-12-02 17:38:37.000000000 
+0100
@@ -36,6 +36,10 @@
   expressions ``\.undocumented_method$`` or ``\.__repr__$``. This
   maps to ``numpydoc_validation_exclude`` from the
   :ref:`Sphinx build configuration <validation_during_sphinx_build>`.
+* ``exclude_files``: Exclude file paths (relative to the package root) matching
+  the regular expressions ``^tests/.*$`` or ``^module/gui.*$``. This maps to
+  ``numpydoc_validation_exclude_files`` from the
+  :ref:`Sphinx build configuration <validation_during_sphinx_build>`.
 * ``override_SS05``: Allow docstrings to start with "Process ", "Assess ",
   or "Access ". To override different checks, add a field for each code in
   the form of ``override_<code>`` with a collection of regular expression(s)
@@ -57,6 +61,10 @@
         '\.undocumented_method$',
         '\.__repr__$',
     ]
+    exclude_files = [ # don't process filepaths that match these regex
+        '^tests/.*',
+        '^module/gui.*',
+    ]
     override_SS05 = [  # override SS05 to allow docstrings starting with these 
words
         '^Process ',
         '^Assess ',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/numpydoc/_version.py 
new/numpydoc-1.10.0/numpydoc/_version.py
--- old/numpydoc-1.9.0/numpydoc/_version.py     2025-06-24 14:22:17.000000000 
+0200
+++ new/numpydoc-1.10.0/numpydoc/_version.py    2025-12-02 17:38:37.000000000 
+0100
@@ -1 +1 @@
-__version__ = "1.9.0"
+__version__ = "1.10.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/numpydoc/cli.py 
new/numpydoc-1.10.0/numpydoc/cli.py
--- old/numpydoc-1.9.0/numpydoc/cli.py  2025-06-24 14:22:17.000000000 +0200
+++ new/numpydoc-1.10.0/numpydoc/cli.py 2025-12-02 17:38:37.000000000 +0100
@@ -4,14 +4,14 @@
 import ast
 from collections.abc import Sequence
 from pathlib import Path
-from typing import List, Union
+from typing import List
 
 from .docscrape_sphinx import get_doc_object
 from .hooks import utils, validate_docstrings
 from .validate import ERROR_MSGS, Validator, validate
 
 
-def render_object(import_path: str, config: Union[List[str], None] = None) -> 
int:
+def render_object(import_path: str, config: List[str] | None = None) -> int:
     """Test numpydoc docstring generation for a given object."""
     # TODO: Move Validator._load_obj to a better place than validate
     print(get_doc_object(Validator._load_obj(import_path), config=dict(config 
or [])))
@@ -117,7 +117,7 @@
     return ap
 
 
-def main(argv: Union[Sequence[str], None] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     """CLI for numpydoc."""
     ap = get_parser()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/numpydoc/docscrape.py 
new/numpydoc-1.10.0/numpydoc/docscrape.py
--- old/numpydoc-1.9.0/numpydoc/docscrape.py    2025-06-24 14:22:17.000000000 
+0200
+++ new/numpydoc-1.10.0/numpydoc/docscrape.py   2025-12-02 17:38:37.000000000 
+0100
@@ -597,7 +597,7 @@
     def __str__(self):
         out = ""
 
-        func, func_name = self.get_func()
+        _func, func_name = self.get_func()
 
         roles = {"func": "function", "meth": "method"}
 
@@ -701,7 +701,7 @@
                 and not self._should_skip_member(name, self._cls)
                 and (
                     func is None
-                    or isinstance(func, (property, cached_property))
+                    or isinstance(func, property | cached_property)
                     or inspect.isdatadescriptor(func)
                 )
                 and self._is_show_member(name)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/numpydoc/docscrape_sphinx.py 
new/numpydoc-1.10.0/numpydoc/docscrape_sphinx.py
--- old/numpydoc-1.9.0/numpydoc/docscrape_sphinx.py     2025-06-24 
14:22:17.000000000 +0200
+++ new/numpydoc-1.10.0/numpydoc/docscrape_sphinx.py    2025-12-02 
17:38:37.000000000 +0100
@@ -37,7 +37,7 @@
             self.template = template_env.get_template("numpydoc_docstring.rst")
 
     # string conversion routines
-    def _str_header(self, name, symbol="`"):
+    def _str_header(self, name):
         return [".. rubric:: " + name, ""]
 
     def _str_field_list(self, name):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/numpydoc/hooks/validate_docstrings.py 
new/numpydoc-1.10.0/numpydoc/hooks/validate_docstrings.py
--- old/numpydoc-1.9.0/numpydoc/hooks/validate_docstrings.py    2025-06-24 
14:22:17.000000000 +0200
+++ new/numpydoc-1.10.0/numpydoc/hooks/validate_docstrings.py   2025-12-02 
17:38:37.000000000 +0100
@@ -63,7 +63,7 @@
 
     @property
     def is_function_or_method(self) -> bool:
-        return isinstance(self.node, (ast.FunctionDef, ast.AsyncFunctionDef))
+        return isinstance(self.node, ast.FunctionDef | ast.AsyncFunctionDef)
 
     @property
     def is_mod(self) -> bool:
@@ -236,7 +236,7 @@
             The node to visit.
         """
         if isinstance(
-            node, (ast.Module, ast.ClassDef, ast.FunctionDef, 
ast.AsyncFunctionDef)
+            node, ast.Module | ast.ClassDef | ast.FunctionDef | 
ast.AsyncFunctionDef
         ):
             self.stack.append(node)
 
@@ -273,7 +273,12 @@
     dict
         Config options for the numpydoc validation hook.
     """
-    options = {"checks": {"all"}, "exclude": set(), "overrides": {}}
+    options = {
+        "checks": {"all"},
+        "exclude": set(),
+        "overrides": {},
+        "exclude_files": set(),
+    }
     dir_path = Path(dir_path).expanduser().resolve()
 
     toml_path = dir_path / "pyproject.toml"
@@ -306,6 +311,13 @@
                 else [global_exclusions]
             )
 
+            file_exclusions = config.get("exclude_files", 
options["exclude_files"])
+            options["exclude_files"] = set(
+                file_exclusions
+                if not isinstance(file_exclusions, str)
+                else [file_exclusions]
+            )
+
             extract_check_overrides(options, config.items())
 
     elif cfg_path.is_file():
@@ -332,6 +344,16 @@
             except configparser.NoOptionError:
                 pass
 
+            try:
+                options["exclude_files"] = set(
+                    config.get(numpydoc_validation_config_section, 
"exclude_files")
+                    .rstrip(",")
+                    .split(",")
+                    or options["exclude_files"]
+                )
+            except configparser.NoOptionError:
+                pass
+
             extract_check_overrides(
                 options, config.items(numpydoc_validation_config_section)
             )
@@ -341,6 +363,7 @@
 
     options["checks"] = validate.get_validation_checks(options["checks"])
     options["exclude"] = compile_regex(options["exclude"])
+    options["exclude_files"] = compile_regex(options["exclude_files"])
     return options
 
 
@@ -372,8 +395,8 @@
 def run_hook(
     files: List[str],
     *,
-    config: Union[Dict[str, Any], None] = None,
-    ignore: Union[List[str], None] = None,
+    config: Dict[str, Any] | None = None,
+    ignore: List[str] | None = None,
 ) -> int:
     """
     Run the numpydoc validation hook.
@@ -395,9 +418,12 @@
     project_root, _ = find_project_root(files)
     config_options = parse_config(config or project_root)
     config_options["checks"] -= set(ignore or [])
+    exclude_re = config_options["exclude_files"]
 
     findings = False
     for file in files:
+        if exclude_re and exclude_re.match(file):
+            continue
         if file_issues := process_file(file, config_options):
             findings = True
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/numpydoc/numpydoc.py 
new/numpydoc-1.10.0/numpydoc/numpydoc.py
--- old/numpydoc-1.9.0/numpydoc/numpydoc.py     2025-06-24 14:22:17.000000000 
+0200
+++ new/numpydoc-1.10.0/numpydoc/numpydoc.py    2025-12-02 17:38:37.000000000 
+0100
@@ -18,15 +18,19 @@
 """
 
 import hashlib
+import importlib
 import inspect
 import itertools
 import pydoc
 import re
+import sys
 from collections.abc import Callable
 from copy import deepcopy
+from pathlib import Path
 
 from docutils.nodes import Text, citation, comment, inline, reference, section
 from sphinx.addnodes import desc_content, pending_xref
+from sphinx.application import Sphinx as SphinxApp
 from sphinx.util import logging
 
 from . import __version__
@@ -52,7 +56,7 @@
     )
 
 
-def rename_references(app, what, name, obj, options, lines):
+def rename_references(app: SphinxApp, what, name, obj, options, lines):
     # decorate reference numbers so that there are no duplicates
     # these are later undecorated in the doctree, in relabel_references
     references = set()
@@ -84,7 +88,7 @@
     section_node = citation_node.parent
 
     def is_docstring_section(node):
-        return isinstance(node, (section, desc_content))
+        return isinstance(node, section | desc_content)
 
     while not is_docstring_section(section_node):
         section_node = section_node.parent
@@ -114,7 +118,7 @@
     return False
 
 
-def relabel_references(app, doc):
+def relabel_references(app: SphinxApp, doc):
     # Change 'hash-ref' to 'ref' in label text
     for citation_node in _traverse_or_findall(doc, citation):
         if not _is_cite_in_numpydoc_docstring(citation_node):
@@ -141,7 +145,7 @@
             ref.replace(ref_text, new_text.copy())
 
 
-def clean_backrefs(app, doc, docname):
+def clean_backrefs(app: SphinxApp, doc, docname):
     # only::latex directive has resulted in citation backrefs without reference
     known_ref_ids = set()
     for ref in _traverse_or_findall(doc, reference, descend=True):
@@ -161,7 +165,7 @@
 DEDUPLICATION_TAG = "    !! processed by numpydoc !!"
 
 
-def mangle_docstrings(app, what, name, obj, options, lines):
+def mangle_docstrings(app: SphinxApp, what, name, obj, options, lines):
     if DEDUPLICATION_TAG in lines:
         return
     show_inherited_class_members = 
app.config.numpydoc_show_inherited_class_members
@@ -181,8 +185,12 @@
         "xref_aliases": app.config.numpydoc_xref_aliases_complete,
         "xref_ignore": app.config.numpydoc_xref_ignore,
     }
-
-    cfg.update(options or {})
+    # TODO: Find a cleaner way to take care of this change away from dict
+    # https://github.com/sphinx-doc/sphinx/issues/13942
+    try:
+        cfg.update(options or {})
+    except TypeError:
+        cfg.update(options.__dict__ or {})
     u_NL = "\n"
     if what == "module":
         # Strip top title
@@ -190,6 +198,38 @@
         title_re = re.compile(pattern, re.IGNORECASE | re.DOTALL)
         lines[:] = title_re.sub("", u_NL.join(lines)).split(u_NL)
     else:
+        # Test the obj to find the module path, and skip the check if it's 
path is matched by
+        # numpydoc_validation_exclude_files
+        if (
+            app.config.numpydoc_validation_exclude_files
+            and app.config.numpydoc_validation_checks
+        ):
+            excluder = app.config.numpydoc_validation_files_excluder
+            module = inspect.getmodule(obj)
+            try:
+                # Get the module relative path from the name
+                if module:
+                    mod_path = Path(module.__file__)
+                    package_rel_path = mod_path.parent.relative_to(
+                        Path(
+                            importlib.import_module(
+                                module.__name__.split(".")[0]
+                            ).__file__
+                        ).parent
+                    ).as_posix()
+                    module_file = mod_path.as_posix().replace(
+                        mod_path.parent.as_posix(), ""
+                    )
+                    path = package_rel_path + module_file
+                else:
+                    path = None
+            except AttributeError as e:
+                path = None
+
+            if path and excluder and excluder.search(path):
+                # Skip validation for this object.
+                return
+
         try:
             doc = get_doc_object(
                 obj, what, u_NL.join(lines), config=cfg, builder=app.builder
@@ -239,7 +279,7 @@
     lines += ["..", DEDUPLICATION_TAG]
 
 
-def mangle_signature(app, what, name, obj, options, sig, retann):
+def mangle_signature(app: SphinxApp, what, name, obj, options, sig, retann):
     # Do not try to inspect classes that don't define `__init__`
     if inspect.isclass(obj) and (
         not hasattr(obj, "__init__")
@@ -273,7 +313,7 @@
     return start_sig + sig + ")"
 
 
-def setup(app, get_doc_object_=get_doc_object):
+def setup(app: SphinxApp, get_doc_object_=get_doc_object):
     if not hasattr(app, "add_config_value"):
         return None  # probably called by nose, better bail out
 
@@ -299,6 +339,7 @@
     app.add_config_value("numpydoc_xref_ignore", set(), True, types=[set, str])
     app.add_config_value("numpydoc_validation_checks", set(), True)
     app.add_config_value("numpydoc_validation_exclude", set(), False)
+    app.add_config_value("numpydoc_validation_exclude_files", set(), False)
     app.add_config_value("numpydoc_validation_overrides", dict(), False)
 
     # Extra mangling domains
@@ -309,7 +350,7 @@
     return metadata
 
 
-def update_config(app, config=None):
+def update_config(app: SphinxApp, config=None):
     """Update the configuration with default values."""
     if config is None:  # needed for testing and old Sphinx
         config = app.config
@@ -342,6 +383,21 @@
         )
         config.numpydoc_validation_excluder = exclude_expr
 
+    # Generate the regexp for files to ignore during validation
+    if isinstance(config.numpydoc_validation_exclude_files, str):
+        raise ValueError(
+            f"numpydoc_validation_exclude_files must be a container of 
strings, "
+            f"e.g. [{config.numpydoc_validation_exclude_files!r}]."
+        )
+
+    config.numpydoc_validation_files_excluder = None
+    if config.numpydoc_validation_exclude_files:
+        exclude_files_expr = re.compile(
+            r"|".join(exp for exp in config.numpydoc_validation_exclude_files)
+        )
+        config.numpydoc_validation_files_excluder = exclude_files_expr
+
+    # Generate the regexp for validation overrides
     for check, patterns in config.numpydoc_validation_overrides.items():
         config.numpydoc_validation_overrides[check] = re.compile(
             r"|".join(exp for exp in patterns)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/numpydoc/tests/hooks/__init__.py 
new/numpydoc-1.10.0/numpydoc/tests/hooks/__init__.py
--- old/numpydoc-1.9.0/numpydoc/tests/hooks/__init__.py 2025-06-24 
14:22:17.000000000 +0200
+++ new/numpydoc-1.10.0/numpydoc/tests/hooks/__init__.py        1970-01-01 
01:00:00.000000000 +0100
@@ -1 +0,0 @@
-"""Tests for hooks."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/numpydoc-1.9.0/numpydoc/tests/hooks/example_module.py 
new/numpydoc-1.10.0/numpydoc/tests/hooks/example_module.py
--- old/numpydoc-1.9.0/numpydoc/tests/hooks/example_module.py   2025-06-24 
14:22:17.000000000 +0200
+++ new/numpydoc-1.10.0/numpydoc/tests/hooks/example_module.py  2025-12-02 
17:38:37.000000000 +0100
@@ -28,4 +28,35 @@
 
 
 class NewClass:
-    pass
+    class GoodConstructor:
+        """
+        A nested class to test constructors via AST hook.
+
+        Implements constructor via class docstring.
+
+        Parameters
+        ----------
+        name : str
+            The name of the new class.
+        """
+
+        def __init__(self, name):
+            self.name = name
+
+    class BadConstructor:
+        """
+        A nested class to test constructors via AST hook.
+
+        Implements a bad constructor docstring despite having a good class 
docstring.
+
+        Parameters
+        ----------
+        name : str
+            The name of the new class.
+        """
+
+        def __init__(self, name):
+            """
+            A failing constructor implementation without parameters.
+            """
+            self.name = name
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/numpydoc/tests/hooks/test_utils.py 
new/numpydoc-1.10.0/numpydoc/tests/hooks/test_utils.py
--- old/numpydoc-1.9.0/numpydoc/tests/hooks/test_utils.py       2025-06-24 
14:22:17.000000000 +0200
+++ new/numpydoc-1.10.0/numpydoc/tests/hooks/test_utils.py      2025-12-02 
17:38:37.000000000 +0100
@@ -23,7 +23,10 @@
         (tmp_path / reason_file).touch()
 
     if files:
-        expected_dir = Path("/") if expected_reason == "file system root" else 
tmp_path
+        expected_dir = (
+            Path(tmp_path.anchor) if expected_reason == "file system root" 
else tmp_path
+        )
+
         for file in files:
             (tmp_path / file).touch()
     else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/numpydoc-1.9.0/numpydoc/tests/hooks/test_validate_hook.py 
new/numpydoc-1.10.0/numpydoc/tests/hooks/test_validate_hook.py
--- old/numpydoc-1.9.0/numpydoc/tests/hooks/test_validate_hook.py       
2025-06-24 14:22:17.000000000 +0200
+++ new/numpydoc-1.10.0/numpydoc/tests/hooks/test_validate_hook.py      
2025-12-02 17:38:37.000000000 +0100
@@ -1,6 +1,7 @@
 """Test the numpydoc validate pre-commit hook."""
 
 import inspect
+import re
 from pathlib import Path
 
 import pytest
@@ -25,42 +26,58 @@
     """Test that a file is correctly processed in the absence of config 
files."""
 
     expected = inspect.cleandoc(
-        """
-        numpydoc/tests/hooks/example_module.py:4: ES01 No extended summary 
found
+        f"""
+        {example_module!s}:4: ES01 No extended summary found
+
+        {example_module!s}:4: PR01 Parameters {{'name'}} not documented
+
+        {example_module!s}:4: SA01 See Also section not found
+
+        {example_module!s}:4: EX01 No examples section found
+
+        {example_module!s}:8: ES01 No extended summary found
+
+        {example_module!s}:8: SA01 See Also section not found
+
+        {example_module!s}:8: EX01 No examples section found
 
-        numpydoc/tests/hooks/example_module.py:4: PR01 Parameters {'name'} not 
documented
+        {example_module!s}:11: GL08 The object does not have a docstring
 
-        numpydoc/tests/hooks/example_module.py:4: SA01 See Also section not 
found
+        {example_module!s}:17: ES01 No extended summary found
 
-        numpydoc/tests/hooks/example_module.py:4: EX01 No examples section 
found
+        {example_module!s}:17: PR01 Parameters {{'**kwargs'}} not documented
 
-        numpydoc/tests/hooks/example_module.py:8: ES01 No extended summary 
found
+        {example_module!s}:17: PR07 Parameter "*args" has no description
 
-        numpydoc/tests/hooks/example_module.py:8: SA01 See Also section not 
found
+        {example_module!s}:17: SA01 See Also section not found
 
-        numpydoc/tests/hooks/example_module.py:8: EX01 No examples section 
found
+        {example_module!s}:17: EX01 No examples section found
 
-        numpydoc/tests/hooks/example_module.py:11: GL08 The object does not 
have a docstring
+        {example_module!s}:26: SS05 Summary must start with infinitive verb, 
not third person (e.g. use "Generate" instead of "Generates")
 
-        numpydoc/tests/hooks/example_module.py:17: ES01 No extended summary 
found
+        {example_module!s}:26: ES01 No extended summary found
 
-        numpydoc/tests/hooks/example_module.py:17: PR01 Parameters 
{'**kwargs'} not documented
+        {example_module!s}:26: SA01 See Also section not found
 
-        numpydoc/tests/hooks/example_module.py:17: PR07 Parameter "*args" has 
no description
+        {example_module!s}:26: EX01 No examples section found
 
-        numpydoc/tests/hooks/example_module.py:17: SA01 See Also section not 
found
+        {example_module!s}:30: GL08 The object does not have a docstring
 
-        numpydoc/tests/hooks/example_module.py:17: EX01 No examples section 
found
+        {example_module!s}:31: SA01 See Also section not found
 
-        numpydoc/tests/hooks/example_module.py:26: SS05 Summary must start 
with infinitive verb, not third person (e.g. use "Generate" instead of 
"Generates")
+        {example_module!s}:31: EX01 No examples section found
 
-        numpydoc/tests/hooks/example_module.py:26: ES01 No extended summary 
found
+        {example_module!s}:46: SA01 See Also section not found
 
-        numpydoc/tests/hooks/example_module.py:26: SA01 See Also section not 
found
+        {example_module!s}:46: EX01 No examples section found
 
-        numpydoc/tests/hooks/example_module.py:26: EX01 No examples section 
found
+        {example_module!s}:58: ES01 No extended summary found
 
-        numpydoc/tests/hooks/example_module.py:30: GL08 The object does not 
have a docstring
+        {example_module!s}:58: PR01 Parameters {{'name'}} not documented
+
+        {example_module!s}:58: SA01 See Also section not found
+
+        {example_module!s}:58: EX01 No examples section found
         """
     )
 
@@ -76,18 +93,20 @@
     """
 
     expected = inspect.cleandoc(
-        """
-        numpydoc/tests/hooks/example_module.py:4: PR01 Parameters {'name'} not 
documented
+        f"""
+        {example_module!s}:4: PR01 Parameters {{'name'}} not documented
+
+        {example_module!s}:11: GL08 The object does not have a docstring
 
-        numpydoc/tests/hooks/example_module.py:11: GL08 The object does not 
have a docstring
+        {example_module!s}:17: PR01 Parameters {{'**kwargs'}} not documented
 
-        numpydoc/tests/hooks/example_module.py:17: PR01 Parameters 
{'**kwargs'} not documented
+        {example_module!s}:17: PR07 Parameter "*args" has no description
 
-        numpydoc/tests/hooks/example_module.py:17: PR07 Parameter "*args" has 
no description
+        {example_module!s}:26: SS05 Summary must start with infinitive verb, 
not third person (e.g. use "Generate" instead of "Generates")
 
-        numpydoc/tests/hooks/example_module.py:26: SS05 Summary must start 
with infinitive verb, not third person (e.g. use "Generate" instead of 
"Generates")
+        {example_module!s}:30: GL08 The object does not have a docstring
 
-        numpydoc/tests/hooks/example_module.py:30: GL08 The object does not 
have a docstring
+        {example_module!s}:58: PR01 Parameters {{'name'}} not documented
         """
     )
 
@@ -123,14 +142,14 @@
         )
 
     expected = inspect.cleandoc(
-        """
-        numpydoc/tests/hooks/example_module.py:4: PR01 Parameters {'name'} not 
documented
+        f"""
+        {example_module!s}:4: PR01 Parameters {{'name'}} not documented
 
-        numpydoc/tests/hooks/example_module.py:17: PR01 Parameters 
{'**kwargs'} not documented
+        {example_module!s}:17: PR01 Parameters {{'**kwargs'}} not documented
 
-        numpydoc/tests/hooks/example_module.py:17: PR07 Parameter "*args" has 
no description
+        {example_module!s}:17: PR07 Parameter "*args" has no description
 
-        numpydoc/tests/hooks/example_module.py:30: GL08 The object does not 
have a docstring
+        {example_module!s}:30: GL08 The object does not have a docstring
         """
     )
 
@@ -158,14 +177,14 @@
         )
 
     expected = inspect.cleandoc(
-        """
-        numpydoc/tests/hooks/example_module.py:4: PR01 Parameters {'name'} not 
documented
+        f"""
+        {example_module!s}:4: PR01 Parameters {{'name'}} not documented
 
-        numpydoc/tests/hooks/example_module.py:17: PR01 Parameters 
{'**kwargs'} not documented
+        {example_module!s}:17: PR01 Parameters {{'**kwargs'}} not documented
 
-        numpydoc/tests/hooks/example_module.py:17: PR07 Parameter "*args" has 
no description
+        {example_module!s}:17: PR07 Parameter "*args" has no description
 
-        numpydoc/tests/hooks/example_module.py:30: GL08 The object does not 
have a docstring
+        {example_module!s}:30: GL08 The object does not have a docstring
         """
     )
 
@@ -203,10 +222,10 @@
         )
 
     expected = inspect.cleandoc(
-        """
-        numpydoc/tests/hooks/example_module.py:4: PR01 Parameters {'name'} not 
documented
+        f"""
+        {example_module!s}:4: PR01 Parameters {{'name'}} not documented
 
-        numpydoc/tests/hooks/example_module.py:30: GL08 The object does not 
have a docstring
+        {example_module!s}:30: GL08 The object does not have a docstring
         """
     )
 
@@ -234,15 +253,83 @@
         )
 
     expected = inspect.cleandoc(
-        """
-        numpydoc/tests/hooks/example_module.py:4: PR01 Parameters {'name'} not 
documented
+        f"""
+        {example_module!s}:4: PR01 Parameters {{'name'}} not documented
 
-        numpydoc/tests/hooks/example_module.py:17: PR01 Parameters 
{'**kwargs'} not documented
+        {example_module!s}:17: PR01 Parameters {{'**kwargs'}} not documented
 
-        numpydoc/tests/hooks/example_module.py:17: PR07 Parameter "*args" has 
no description
+        {example_module!s}:17: PR07 Parameter "*args" has no description
         """
     )
 
     return_code = run_hook([example_module], config=tmp_path)
     assert return_code == 1
     assert capsys.readouterr().err.strip() == expected
+
+
[email protected](
+    "file_exists, expected_code",
+    [(True, 0), (False, 1)],
+)
+def test_validate_hook_exclude_files_option_pyproject(
+    example_module, file_exists, expected_code, tmp_path
+):
+    """
+    Test that the hook correctly processes the toml config and either includes
+    or excludes files based on the `exclude_files` option.
+    """
+    exclude = str(example_module) if file_exists else "does_not_exist.py"
+
+    with open(tmp_path / "pyproject.toml", "w") as config_file:
+        config_file.write(
+            inspect.cleandoc(
+                f"""
+                [tool.numpydoc_validation]
+                checks = [
+                    "all",
+                    "EX01",
+                    "SA01",
+                    "ES01",
+                ]
+                exclude = '\\.__init__$'
+                override_SS05 = [
+                    '^Creates',
+                ]
+                exclude_files = [
+                    '{re.escape(exclude)}',
+                ]"""
+            )
+        )
+
+    return_code = run_hook([example_module], config=tmp_path)
+    assert return_code == expected_code  # Should not-report/report findings.
+
+
[email protected](
+    "file_exists, expected_code",
+    [(True, 0), (False, 1)],
+)
+def test_validate_hook_exclude_files_option_setup_cfg(
+    example_module, file_exists, expected_code, tmp_path
+):
+    """
+    Test that the hook correctly processes the setup config and either includes
+    or excludes files based on the `exclude_files` option.
+    """
+    exclude = str(example_module) if file_exists else "does_not_exist.py"
+
+    with open(tmp_path / "setup.cfg", "w") as config_file:
+        config_file.write(
+            inspect.cleandoc(
+                f"""
+                [tool:numpydoc_validation]
+                checks = all,EX01,SA01,ES01
+                exclude = \\.NewClass$,\\.__init__$
+                override_SS05 = ^Creates
+                exclude_files = {re.escape(exclude)}
+                """
+            )
+        )
+
+    return_code = run_hook([example_module], config=tmp_path)
+    assert return_code == expected_code  # Should not-report/report findings.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/numpydoc/tests/test_docscrape.py 
new/numpydoc-1.10.0/numpydoc/tests/test_docscrape.py
--- old/numpydoc-1.9.0/numpydoc/tests/test_docscrape.py 2025-06-24 
14:22:17.000000000 +0200
+++ new/numpydoc-1.10.0/numpydoc/tests/test_docscrape.py        2025-12-02 
17:38:37.000000000 +0100
@@ -6,7 +6,6 @@
 
 import jinja2
 import pytest
-from pytest import warns as assert_warns
 
 from numpydoc.docscrape import ClassDoc, FunctionDoc, NumpyDocString
 from numpydoc.docscrape_sphinx import (
@@ -187,7 +186,9 @@
 def test_parameters(doc):
     assert len(doc["Parameters"]) == 4
     names = [n for n, _, _ in doc["Parameters"]]
-    assert all(a == b for a, b in zip(names, ["mean", "cov", "shape"]))
+    assert all(
+        a == b for a, b in zip(names, ["mean", "cov", "shape", "dtype"], 
strict=True)
+    )
 
     arg, arg_type, desc = doc["Parameters"][1]
     assert arg_type == "(N, N) ndarray"
@@ -209,7 +210,7 @@
 def test_other_parameters(doc):
     assert len(doc["Other Parameters"]) == 1
     assert [n for n, _, _ in doc["Other Parameters"]] == ["spam"]
-    arg, arg_type, desc = doc["Other Parameters"][0]
+    _arg, arg_type, desc = doc["Other Parameters"][0]
     assert arg_type == "parrot"
     assert desc[0].startswith("A parrot off its mortal coil")
 
@@ -242,7 +243,9 @@
         ("b", "int", "bananas."),
         ("", "int", "unknowns."),
     ]
-    for (arg, arg_type, desc), (arg_, arg_type_, end) in zip(section, truth):
+    for (arg, arg_type, desc), (arg_, arg_type_, end) in zip(
+        section, truth, strict=True
+    ):
         assert arg == arg_
         assert arg_type == arg_type_
         assert desc[0].startswith("The number of")
@@ -253,7 +256,9 @@
     section = doc_sent["Receives"]
     assert len(section) == 2
     truth = [("b", "int", "bananas."), ("c", "int", "oranges.")]
-    for (arg, arg_type, desc), (arg_, arg_type_, end) in zip(section, truth):
+    for (arg, arg_type, desc), (arg_, arg_type_, end) in zip(
+        section, truth, strict=True
+    ):
         assert arg == arg_
         assert arg_type == arg_type_
         assert desc[0].startswith("The number of")
@@ -374,7 +379,7 @@
     a = [l.rstrip() for l in _strip_blank_lines(a).split("\n")][:n_lines]
     b = [l.rstrip() for l in _strip_blank_lines(b).split("\n")][:n_lines]
     assert len(a) == len(b)
-    for ii, (aa, bb) in enumerate(zip(a, b)):
+    for ii, (aa, bb) in enumerate(zip(a, b, strict=True)):
         assert aa == bb
 
 
@@ -901,7 +906,7 @@
 
 def test_see_also_trailing_comma_warning():
     warnings.filterwarnings("error")
-    with assert_warns(
+    with pytest.warns(
         Warning,
         match="Unexpected comma or period after function list at index 43 of 
line .*",
     ):
@@ -994,13 +999,12 @@
 
 
 def test_no_summary():
-    str(
-        SphinxDocString(
-            """
-    Parameters
-    ----------"""
-        )
+    ds = SphinxDocString(
+        """
+        Parameters
+        ----------"""
     )
+    assert ds["Summary"] == [""]
 
 
 def test_unicode():
@@ -1593,6 +1597,7 @@
             # numpydoc.update_config fails if this config option not present
             self.numpydoc_validation_checks = set()
             self.numpydoc_validation_exclude = set()
+            self.numpydoc_validation_exclude_files = set()
             self.numpydoc_validation_overrides = dict()
 
     xref_aliases_complete = deepcopy(DEFAULT_LINKS)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/numpydoc/tests/test_numpydoc.py 
new/numpydoc-1.10.0/numpydoc/tests/test_numpydoc.py
--- old/numpydoc-1.9.0/numpydoc/tests/test_numpydoc.py  2025-06-24 
14:22:17.000000000 +0200
+++ new/numpydoc-1.10.0/numpydoc/tests/test_numpydoc.py 2025-12-02 
17:38:37.000000000 +0100
@@ -31,6 +31,7 @@
     numpydoc_attributes_as_param_list = True
     numpydoc_validation_checks = set()
     numpydoc_validation_exclude = set()
+    numpydoc_validation_exclude_files = set()
     numpydoc_validation_overrides = dict()
 
 
@@ -287,6 +288,61 @@
     assert "id1" in citation["backrefs"]
 
 
[email protected](
+    "exclude_files, has_warnings",
+    [
+        (
+            [
+                r"^doesnt_match_any_file$",
+            ],
+            True,
+        ),
+        (
+            [
+                r"^.*test_numpydoc\.py$",
+            ],
+            False,
+        ),
+    ],
+)
+def test_mangle_skip_exclude_files(exclude_files, has_warnings):
+    """
+    Check that the regex expressions in numpydoc_validation_files_exclude
+    are correctly used to skip checks on files that match the patterns.
+    """
+
+    def process_something_noop_function():
+        """Process something."""
+
+    app = MockApp()
+    app.config.numpydoc_validation_checks = {"all"}
+
+    # Class attributes for config persist - need to reset them to unprocessed 
states.
+    app.config.numpydoc_validation_exclude = set()  # Reset to default...
+    app.config.numpydoc_validation_overrides = dict()  # Reset to default...
+
+    app.config.numpydoc_validation_exclude_files = exclude_files
+    update_config(app)
+
+    # Setup for catching warnings
+    status, warning = StringIO(), StringIO()
+    logging.setup(app, status, warning)
+
+    # Simulate a file that matches the exclude pattern
+    mangle_docstrings(
+        app,
+        "function",
+        process_something_noop_function.__name__,
+        process_something_noop_function,
+        None,
+        process_something_noop_function.__doc__.split("\n"),
+    )
+
+    # Are warnings generated?
+    print(warning.getvalue())
+    assert bool(warning.getvalue()) is has_warnings
+
+
 if __name__ == "__main__":
     import pytest
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/numpydoc/tests/test_validate.py 
new/numpydoc-1.10.0/numpydoc/tests/test_validate.py
--- old/numpydoc-1.9.0/numpydoc/tests/test_validate.py  2025-06-24 
14:22:17.000000000 +0200
+++ new/numpydoc-1.10.0/numpydoc/tests/test_validate.py 2025-12-02 
17:38:37.000000000 +0100
@@ -1,5 +1,6 @@
 import warnings
 from contextlib import nullcontext
+from dataclasses import dataclass
 from functools import cached_property, partial, wraps
 from inspect import getsourcefile, getsourcelines
 
@@ -1305,6 +1306,109 @@
         pass
 
 
+class ConstructorDocumentedinEmbeddedClass:  # ignore Gl08, ES01
+    """
+    Class to test the initialisation behaviour of a embedded class.
+    """
+
+    class EmbeddedClass1:  # ignore GL08, ES01
+        """
+        An additional level for embedded class documentation checking.
+        """
+
+        class EmbeddedClass2:
+            """
+            This is an embedded class.
+
+            Extended summary.
+
+            Parameters
+            ----------
+            param1 : int
+                Description of param1.
+
+            See Also
+            --------
+            otherclass : A class that does something else.
+
+            Examples
+            --------
+            This is an example of how to use EmbeddedClass.
+            """
+
+            def __init__(self, param1: int) -> None:
+                pass
+
+
+class IncompleteConstructorDocumentedinEmbeddedClass:
+    """
+    Class to test the initialisation behaviour of a embedded class.
+    """
+
+    class EmbeddedClass1:
+        """
+        An additional level for embedded class documentation checking.
+        """
+
+        class EmbeddedClass2:
+            """
+            This is an embedded class.
+
+            Extended summary.
+
+            See Also
+            --------
+            otherclass : A class that does something else.
+
+            Examples
+            --------
+            This is an example of how to use EmbeddedClass.
+            """
+
+            def __init__(self, param1: int) -> None:
+                pass
+
+
+@dataclass
+class DataclassWithDocstring:
+    """
+    A class decorated by `dataclass`.
+
+    To check the functionality of `dataclass` objects do not break the 
Validator.
+    As param1 is not documented this class should also raise PR01.
+    """
+
+    param1: int
+
+
+class ClassWithPropertyObject:
+    """
+    A class with a `property`.
+
+    To check the functionality of `property` objects do not break the 
Validator.
+
+    Parameters
+    ----------
+    param1 : int
+        Description of param1.
+    """
+
+    def __init__(self, param1: int) -> None:
+        self._param1 = param1
+
+    @property
+    def param1(self) -> int:
+        """
+        Get the value of param1.
+
+        Returns
+        -------
+        int
+            The value of param1.
+        """
+        return self._param1
+
+
 class TestValidator:
     def _import_path(self, klass=None, func=None):
         """
@@ -1391,11 +1495,8 @@
         ],
     )
     def test_bad_generic_functions(self, capsys, func):
-        with pytest.warns(UserWarning):
-            errors = validate_one(
-                self._import_path(klass="WarnGenericFormat", func=func)
-            )
-        assert "is too short" in w.msg
+        with pytest.warns(UserWarning, match="is too short"):
+            validate_one(self._import_path(klass="WarnGenericFormat", 
func=func))
 
     @pytest.mark.parametrize(
         "func",
@@ -1660,6 +1761,18 @@
                 tuple(),
                 ("PR01"),  # Parameter not documented in class constructor
             ),
+            (
+                
"ConstructorDocumentedinEmbeddedClass.EmbeddedClass1.EmbeddedClass2",
+                tuple(),
+                ("GL08",),
+                tuple(),
+            ),
+            (
+                
"IncompleteConstructorDocumentedinEmbeddedClass.EmbeddedClass1.EmbeddedClass2",
+                ("GL08",),
+                tuple(),
+                ("PR01",),
+            ),
         ],
     )
     def test_constructor_docstrings(
@@ -1677,6 +1790,39 @@
         for code in exc_init_codes:
             assert code not in " ".join(err[0] for err in result["errors"])
 
+        if klass == "ConstructorDocumentedinEmbeddedClass":
+            raise NotImplementedError(
+                "Test for embedded class constructor docstring not implemented 
yet."
+            )
+
+    def test_dataclass_object(self):
+        # Test validator methods complete execution on dataclass objects and 
methods
+        # Test case ought to be removed if dataclass objects properly 
supported.
+        result = 
validate_one(self._import_path(klass="DataclassWithDocstring"))
+        # Check codes match as expected for dataclass objects.
+        errs = ["ES01", "SA01", "EX01", "PR01"]
+        for error in result["errors"]:
+            assert error[0] in errs
+            errs.remove(error[0])
+
+        # Test initialisation method (usually undocumented in dataclass) 
raises any errors.
+        init_fn = self._import_path(klass="DataclassWithDocstring", 
func="__init__")
+        result = validate_one(init_fn)
+        # Check that __init__ raises GL08 when the class docstring doesn't 
document params.
+        assert result["errors"][0][0] == "GL08"
+
+    def test_property_object(self):
+        # Test validator methods complete execution on class property objects
+        # Test case ought to be removed if property objects properly supported.
+        result = validate_one(
+            self._import_path(klass="ClassWithPropertyObject", func="param1")
+        )
+        # Check codes match as expected for property objects.
+        errs = ["ES01", "SA01", "EX01"]
+        for error in result["errors"]:
+            assert error[0] in errs
+            errs.remove(error[0])
+
 
 def decorator(x):
     """Test decorator."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/numpydoc/validate.py 
new/numpydoc-1.10.0/numpydoc/validate.py
--- old/numpydoc-1.9.0/numpydoc/validate.py     2025-06-24 14:22:17.000000000 
+0200
+++ new/numpydoc-1.10.0/numpydoc/validate.py    2025-12-02 17:38:37.000000000 
+0100
@@ -17,7 +17,7 @@
 import textwrap
 import tokenize
 from copy import deepcopy
-from typing import Any, Dict, List, Optional, Set
+from typing import Any, Dict, List, Set
 
 from .docscrape import get_doc_object
 
@@ -124,7 +124,7 @@
 # and pandas, and they had between ~500 and ~1300 .py files as of 2023-08-16.
 @functools.lru_cache(maxsize=2000)
 def extract_ignore_validation_comments(
-    filepath: Optional[os.PathLike],
+    filepath: os.PathLike | None,
     encoding: str = "utf-8",
 ) -> Dict[int, List[str]]:
     """
@@ -572,6 +572,14 @@
     return errs
 
 
+def _find_class_node(module_node: ast.AST, cls_name) -> ast.ClassDef:
+    #  Find the class node within a module, when checking constructor 
docstrings.
+    for node in ast.walk(module_node):
+        if isinstance(node, ast.ClassDef) and node.name == cls_name:
+            return node
+    raise ValueError(f"Could not find class node {cls_name}")
+
+
 def validate(obj_name, validator_cls=None, **validator_kwargs):
     """
     Validate the docstring.
@@ -639,20 +647,49 @@
         report_GL08: bool = True
         # Check if the object is a class and has a docstring in the constructor
         # Also check if code_obj is defined, as undefined for the AstValidator 
in validate_docstrings.py.
-        if (
-            doc.name.endswith(".__init__")
-            and doc.is_function_or_method
-            and hasattr(doc, "code_obj")
-        ):
-            cls_name = doc.code_obj.__qualname__.split(".")[0]
-            cls = Validator._load_obj(f"{doc.code_obj.__module__}.{cls_name}")
-            # cls = Validator._load_obj(f"{doc.name[:-9]}.{cls_name}") ## 
Alternative
-            cls_doc = Validator(get_doc_object(cls))
+        if doc.is_function_or_method and doc.name.endswith(".__init__"):
+            # Import here at runtime to avoid circular import as
+            # AstValidator is a subclass of Validator class without `doc_obj` 
attribute.
+            from numpydoc.hooks.validate_docstrings import (
+                AstValidator,  # Support abstract syntax tree hook.
+            )
+
+            if hasattr(doc, "code_obj"):  # All Validator objects have this 
attr.
+                cls_name = ".".join(
+                    doc.code_obj.__qualname__.split(".")[:-1]
+                )  # Collect all class depths before the constructor.
+                cls = 
Validator._load_obj(f"{doc.code_obj.__module__}.{cls_name}")
+                # cls = Validator._load_obj(f"{doc.name[:-9]}.{cls_name}") ## 
Alternative
+                cls_doc = Validator(get_doc_object(cls))
+            elif isinstance(doc, AstValidator):  # Supports class traversal 
for ASTs.
+                ancestry = doc.ancestry
+                if len(ancestry) > 2:  # e.g. module.class.__init__
+                    parent = doc.ancestry[-1]  # Get the parent
+                    cls_name = ".".join(
+                        [
+                            getattr(node, "name", node.__module__)
+                            for node in doc.ancestry
+                        ]
+                    )
+                    cls_doc = AstValidator(
+                        ast_node=parent,
+                        filename=doc.source_file_name,
+                        obj_name=cls_name,
+                        ancestry=doc.ancestry[:-1],
+                    )
+                else:
+                    # Ignore edge case: __init__ functions that don't belong 
to a class.
+                    cls_doc = None
+            else:
+                raise TypeError(
+                    f"Cannot load {doc.name} as a usable Validator object 
(Validator does not have `doc_obj` attr or type `AstValidator`)."
+                )
 
             # Parameter_mismatches, PR01, PR02, PR03 are checked for the class 
docstring.
             # If cls_doc has PR01, PR02, PR03 errors, i.e. invalid class 
docstring,
             # then we also report missing constructor docstring, GL08.
-            report_GL08 = len(cls_doc.parameter_mismatches) > 0
+            if cls_doc:
+                report_GL08 = len(cls_doc.parameter_mismatches) > 0
 
         # Check if GL08 is to be ignored:
         if "GL08" in ignore_validation_comments:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/numpydoc.egg-info/PKG-INFO 
new/numpydoc-1.10.0/numpydoc.egg-info/PKG-INFO
--- old/numpydoc-1.9.0/numpydoc.egg-info/PKG-INFO       2025-06-24 
14:22:24.000000000 +0200
+++ new/numpydoc-1.10.0/numpydoc.egg-info/PKG-INFO      2025-12-02 
17:38:47.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: numpydoc
-Version: 1.9.0
+Version: 1.10.0
 Summary: Sphinx extension to support docstrings in Numpy format
 Author-email: Pauli Virtanen and others <[email protected]>
 License: Copyright (C) 2008-2023 Stefan van der Walt <[email protected]>, 
Pauli Virtanen <[email protected]>
@@ -38,13 +38,12 @@
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
 Classifier: Programming Language :: Python :: 3.13
 Classifier: Topic :: Documentation
-Requires-Python: >=3.9
+Requires-Python: >=3.10
 Description-Content-Type: text/x-rst
 License-File: LICENSE.txt
 Requires-Dist: sphinx>=6
@@ -70,7 +69,7 @@
 The extension also adds the code description directives
 ``np:function``, ``np-c:function``, etc.
 
-numpydoc requires Python 3.9+ and sphinx 6+.
+numpydoc requires Python 3.10+ and sphinx 6+.
 
 For usage information, please refer to the `documentation
 <https://numpydoc.readthedocs.io/>`_.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/numpydoc.egg-info/SOURCES.txt 
new/numpydoc-1.10.0/numpydoc.egg-info/SOURCES.txt
--- old/numpydoc-1.9.0/numpydoc.egg-info/SOURCES.txt    2025-06-24 
14:22:24.000000000 +0200
+++ new/numpydoc-1.10.0/numpydoc.egg-info/SOURCES.txt   2025-12-02 
17:38:47.000000000 +0100
@@ -40,7 +40,6 @@
 numpydoc/tests/test_numpydoc.py
 numpydoc/tests/test_validate.py
 numpydoc/tests/test_xref.py
-numpydoc/tests/hooks/__init__.py
 numpydoc/tests/hooks/example_module.py
 numpydoc/tests/hooks/test_utils.py
 numpydoc/tests/hooks/test_validate_hook.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/numpydoc-1.9.0/pyproject.toml 
new/numpydoc-1.10.0/pyproject.toml
--- old/numpydoc-1.9.0/pyproject.toml   2025-06-24 14:22:17.000000000 +0200
+++ new/numpydoc-1.10.0/pyproject.toml  2025-12-02 17:38:37.000000000 +0100
@@ -6,7 +6,7 @@
 name = 'numpydoc'
 description = 'Sphinx extension to support docstrings in Numpy format'
 readme = 'README.rst'
-requires-python = '>=3.9'
+requires-python = '>=3.10'
 dynamic = ['version']
 keywords = [
     'sphinx',
@@ -20,7 +20,6 @@
     'Operating System :: OS Independent',
     'Programming Language :: Python',
     'Programming Language :: Python :: 3',
-    'Programming Language :: Python :: 3.9',
     'Programming Language :: Python :: 3.10',
     'Programming Language :: Python :: 3.11',
     'Programming Language :: Python :: 3.12',
@@ -46,7 +45,6 @@
 [dependency-groups]
 dev = [
     'pre-commit>=3.3',
-    "tomli; python_version < '3.11'",
     { include-group = "doc" },
     { include-group = "test" }
 ]
@@ -100,6 +98,7 @@
 ignore = [
   "PLR09",    # Too many <...>
   "PLR2004",  # Magic value used in comparison
+  "PLC0415",  # Imports not at top of file (we often nest intentionally)
   "ISC001",   # Conflicts with formatter
   "ARG001",   # FIXME: consider removing this and the following rules from 
this list
   "ARG002",
@@ -169,6 +168,7 @@
 [tool.setuptools.package-data]
 numpydoc = [
     'tests/test_*.py',
+    'tests/hooks/test_*.py',
     'tests/tinybuild/Makefile',
     'tests/tinybuild/index.rst',
     'tests/tinybuild/*.py',

Reply via email to