Skip to content

gh-148314: Fix pydoc not recognising stdlib modules behind a symlink#151897

Closed
iamsharduld wants to merge 1 commit into
python:mainfrom
iamsharduld:local-gh-148314-pydoc-symlink
Closed

gh-148314: Fix pydoc not recognising stdlib modules behind a symlink#151897
iamsharduld wants to merge 1 commit into
python:mainfrom
iamsharduld:local-gh-148314-pydoc-symlink

Conversation

@iamsharduld

@iamsharduld iamsharduld commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

pydoc.Doc._is_stdlib_module() compares the module file against the standard
library base directory with file.startswith(basedir). file comes from
inspect.getabsfile() (which uses os.path.abspath, so symlinks are not
resolved), while basedir is derived from sysconfig.get_config_var('srcdir'),
which on a source build can already have symlinks resolved. When the source tree
is referenced through a symlink the two paths have symlinks resolved
inconsistently, the prefix check fails, and standard-library modules are
classified as third-party (for example pydoc then omits the link to the online
documentation, and test_pydoc fails).

Resolve symlinks on both basedir and file before comparing. In the common,
non-symlinked case realpath() is a no-op.

A regression test is added that points a module's __file__ through a symlink
and checks that _is_stdlib_module() still recognises it.

…mlink

_is_stdlib_module() compared the module file against the standard
library base directory without resolving symlinks. When the source
tree was referenced through a symlink, basedir (from sysconfig's
srcdir) and the module file path had symlinks resolved inconsistently,
so the startswith() prefix check failed and stdlib modules were
treated as third-party. Resolve symlinks on both paths before
comparing.
@iamsharduld

Copy link
Copy Markdown
Contributor Author

The only failing check here, Sanitizers / TSan (free-threading), failed on a ThreadSanitizer: data race (... in memcmp) reported during test_ssl, which is unrelated to this change.

This PR only touches pure-Python code in Lib/pydoc.py (it adds os.path.realpath() calls in _is_stdlib_module()), so it can't introduce a C-level data race. In the same run the non-free-threading Sanitizers / TSan job passed, and test_free_threading and test_embed both passed; only the free-threaded sanitizer build tripped, on test_ssl. This looks like a pre-existing free-threading data race rather than anything from this PR.

@StanFromIreland

Copy link
Copy Markdown
Member

Closing, I'm sorry but as noted in the issue this has already been assigned to someone (#148314 (comment)). We also need a more general solution for this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants