https://github.com/python/cpython/commit/78a50ee10ef73296eba98899d496bff3915ddc41
commit: 78a50ee10ef73296eba98899d496bff3915ddc41
branch: main
author: Stan Ulbrych <[email protected]>
committer: hugovk <[email protected]>
date: 2025-12-14T14:59:05+02:00
summary:

gh-76007: `pydoc`: Catch `DeprecationWarning` for stdlib module `__version__` 
attributes (#139997)

files:
A Misc/NEWS.d/next/Library/2025-10-12-12-43-56.gh-issue-76007.PyGM14.rst
M Lib/pydoc.py
M Lib/test/test_pydoc/test_pydoc.py

diff --git a/Lib/pydoc.py b/Lib/pydoc.py
index ee4457d9d3a932..c8d4aa7a88325b 100644
--- a/Lib/pydoc.py
+++ b/Lib/pydoc.py
@@ -450,6 +450,7 @@ class Doc:
     PYTHONDOCS = os.environ.get("PYTHONDOCS",
                                 "https://docs.python.org/%d.%d/library";
                                 % sys.version_info[:2])
+    STDLIB_DIR = sysconfig.get_path('stdlib')
 
     def document(self, object, name=None, *args):
         """Generate documentation for an object."""
@@ -475,23 +476,12 @@ def fail(self, object, name=None, *args):
 
     docmodule = docclass = docroutine = docother = docproperty = docdata = fail
 
-    def getdocloc(self, object, basedir=sysconfig.get_path('stdlib')):
+    def getdocloc(self, object, basedir=None):
         """Return the location of module docs or None"""
-
-        try:
-            file = inspect.getabsfile(object)
-        except TypeError:
-            file = '(built-in)'
-
+        basedir = self.STDLIB_DIR if basedir is None else basedir
         docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
 
-        basedir = os.path.normcase(basedir)
-        if (isinstance(object, type(os)) and
-            (object.__name__ in ('errno', 'exceptions', 'gc',
-                                 'marshal', 'posix', 'signal', 'sys',
-                                 '_thread', 'zipimport') or
-             (file.startswith(basedir) and
-              not file.startswith(os.path.join(basedir, 'site-packages')))) and
+        if (self._is_stdlib_module(object, basedir) and
             object.__name__ not in ('xml.etree', 'test.test_pydoc.pydoc_mod')):
             if docloc.startswith(("http://";, "https://";)):
                 docloc = "{}/{}.html".format(docloc.rstrip("/"), 
object.__name__.lower())
@@ -501,6 +491,36 @@ def getdocloc(self, object, 
basedir=sysconfig.get_path('stdlib')):
             docloc = None
         return docloc
 
+    def _get_version(self, object):
+        if self._is_stdlib_module(object):
+            with warnings.catch_warnings():
+                warnings.simplefilter("ignore", DeprecationWarning)
+                version = getattr(object, '__version__', None)
+        else:
+            version = getattr(object, '__version__', None)
+        return '' if version is None else str(version)
+
+    def _is_stdlib_module(self, object, basedir=None):
+        basedir = self.STDLIB_DIR if basedir is None else basedir
+
+        try:
+            file = inspect.getabsfile(object)
+        except TypeError:
+            file = '(built-in)'
+
+        if sysconfig.is_python_build():
+            srcdir = sysconfig.get_config_var('srcdir')
+            if srcdir:
+                basedir = os.path.join(srcdir, 'Lib')
+
+        basedir = os.path.normcase(basedir)
+        return (isinstance(object, type(os)) and
+                (object.__name__ in ('errno', 'exceptions', 'gc',
+                                     'marshal', 'posix', 'signal', 'sys',
+                                     '_thread', 'zipimport')
+                or (file.startswith(basedir) and
+                 not file.startswith(os.path.join(basedir, 'site-packages')))))
+
 # -------------------------------------------- HTML documentation generator
 
 class HTMLRepr(Repr):
@@ -760,8 +780,8 @@ def docmodule(self, object, name=None, mod=None, *ignored):
         except TypeError:
             filelink = '(built-in)'
         info = []
-        if hasattr(object, '__version__'):
-            version = str(object.__version__)
+
+        if version := self._get_version(object):
             if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
                 version = version[11:-1].strip()
             info.append('version %s' % self.escape(version))
@@ -1296,8 +1316,7 @@ def docmodule(self, object, name=None, mod=None, 
*ignored):
                 contents.append(self.docother(value, key, name, maxlen=70))
             result = result + self.section('DATA', '\n'.join(contents))
 
-        if hasattr(object, '__version__'):
-            version = str(object.__version__)
+        if version := self._get_version(object):
             if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
                 version = version[11:-1].strip()
             result = result + self.section('VERSION', version)
diff --git a/Lib/test/test_pydoc/test_pydoc.py 
b/Lib/test/test_pydoc/test_pydoc.py
index c640416327efbf..89480423d32bc7 100644
--- a/Lib/test/test_pydoc/test_pydoc.py
+++ b/Lib/test/test_pydoc/test_pydoc.py
@@ -2305,6 +2305,32 @@ def 
test_sys_path_adjustment_when_curdir_already_included(self):
                 trailing_argv0dir = trailing_curdir + [self.argv0dir]
                 self.assertIsNone(self._get_revised_path(trailing_argv0dir))
 
+    def test__get_version(self):
+        import json
+        import warnings
+
+        class MyModule:
+            __name__ = 'my_module'
+
+            @property
+            def __version__(self):
+                warnings._deprecated("__version__", remove=(3, 20))
+                return "1.2.3"
+
+        module = MyModule()
+        doc = pydoc.Doc()
+        with warnings.catch_warnings(record=True) as w: # TODO: remove in 3.20
+            warnings.simplefilter("always")
+            version = doc._get_version(json)
+            self.assertEqual(version, "2.0.9")
+            self.assertEqual(len(w), 0)
+
+        with warnings.catch_warnings(record=True) as w:
+            warnings.simplefilter("always")
+            version = doc._get_version(module)
+            self.assertEqual(version, "1.2.3")
+            self.assertEqual(len(w), 1)
+
 
 def setUpModule():
     thread_info = threading_helper.threading_setup()
diff --git 
a/Misc/NEWS.d/next/Library/2025-10-12-12-43-56.gh-issue-76007.PyGM14.rst 
b/Misc/NEWS.d/next/Library/2025-10-12-12-43-56.gh-issue-76007.PyGM14.rst
new file mode 100644
index 00000000000000..3a0914f38228bf
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-10-12-12-43-56.gh-issue-76007.PyGM14.rst
@@ -0,0 +1,2 @@
+:mod:`pydoc`: Fix :exc:`DeprecationWarning` being raised when generating doc 
for
+:term:`stdlib` modules.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to