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

This commit is contained in:
Stan Ulbrych 2025-12-14 12:59:05 +00:00 committed by GitHub
parent 04da416e6b
commit 78a50ee10e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 65 additions and 18 deletions

View File

@ -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 @@ class Doc:
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 @@ class Doc:
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 @@ class HTMLDoc(Doc):
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 @@ location listed above.
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)

View File

@ -2305,6 +2305,32 @@ class TestInternalUtilities(unittest.TestCase):
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()

View File

@ -0,0 +1,2 @@
:mod:`pydoc`: Fix :exc:`DeprecationWarning` being raised when generating doc for
:term:`stdlib` modules.