https://github.com/python/cpython/commit/c85549cc61175740bc1fbad88aea2f2c7e9d1d5a
commit: c85549cc61175740bc1fbad88aea2f2c7e9d1d5a
branch: 3.13
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-08-29T20:20:41Z
summary:

[3.13] gh-69370: Fix "python -m inspect --details" for unencodable paths 
(GH-155246) (GH-156607)

It failed with UnicodeEncodeError if the path of the module contains
characters unencodable in the encoding of sys.stdout, e.g. undecodable
bytes of a file name.  Such characters are now escaped with backslashes,
unless stdout uses an error handler which can handle them.

(cherry picked from commit abf7a184bd94da4d1a6b54503a27ede1957b48b7)

Co-authored-by: Claude Opus 5 (1M context) <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-08-05-17-30-00.gh-issue-69370.inspCLI.rst
M Lib/inspect.py
M Lib/test/test_inspect/test_inspect.py

diff --git a/Lib/inspect.py b/Lib/inspect.py
index f8db5bdb7958ecf..9711cb874022ca0 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -3422,6 +3422,10 @@ def _main():
     import argparse
     import importlib
 
+    # The printed text can contain characters unencodable in the encoding
+    # of stdout, e.g. undecodable bytes of a file name.
+    sys.stdout.reconfigure(errors='backslashreplace')
+
     parser = argparse.ArgumentParser()
     parser.add_argument(
         'object',
diff --git a/Lib/test/test_inspect/test_inspect.py 
b/Lib/test/test_inspect/test_inspect.py
index 6ae9436293774d6..ae5b1a1c5a72e92 100644
--- a/Lib/test/test_inspect/test_inspect.py
+++ b/Lib/test/test_inspect/test_inspect.py
@@ -39,7 +39,7 @@
 from test.support import cpython_only, import_helper, suppress_immortalization
 from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ
 from test.support.import_helper import DirsOnSysPath, ready_to_import
-from test.support.os_helper import TESTFN, temp_cwd
+from test.support.os_helper import TESTFN, TESTFN_UNDECODABLE, temp_cwd
 from test.support.script_helper import assert_python_ok, 
assert_python_failure, kill_python
 from test.support import has_subprocess_support, SuppressCrashReport
 from test import support
@@ -6556,6 +6556,25 @@ def test_builtins(self):
         lines = err.decode().splitlines()
         self.assertEqual(lines, ["Can't get info for builtin modules."])
 
+    @unittest.skipUnless(TESTFN_UNDECODABLE,
+                         'requires undecodable file names')
+    def test_details_undecodable_path(self):
+        # gh-69370: the path of the module is not encodable in the encoding
+        # of stdout.
+        with temp_cwd() as test_dir:
+            subdir = os.path.join(os.fsencode(test_dir), TESTFN_UNDECODABLE)
+            try:
+                os.mkdir(subdir)
+            except OSError:
+                self.skipTest('undecodable paths are not supported')
+            with open(os.path.join(subdir, b'undecodable_mod.py'), 'w') as f:
+                f.write('"""Module docstring."""\n')
+            rc, out, err = assert_python_ok('-X', 'utf8=0', '-m', 'inspect',
+                                            '--details', 'undecodable_mod',
+                                            PYTHONPATH=os.fsdecode(subdir))
+        self.assertIn(b'Target: undecodable_mod', out)
+        self.assertEqual(err, b'')
+
     def test_details(self):
         module = importlib.import_module('unittest')
         args = support.optim_args_from_interpreter_flags()
diff --git 
a/Misc/NEWS.d/next/Library/2026-08-05-17-30-00.gh-issue-69370.inspCLI.rst 
b/Misc/NEWS.d/next/Library/2026-08-05-17-30-00.gh-issue-69370.inspCLI.rst
new file mode 100644
index 000000000000000..27c97f9bdf07b48
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-08-05-17-30-00.gh-issue-69370.inspCLI.rst
@@ -0,0 +1,4 @@
+:program:`python -m inspect --details` no longer fails with
+:exc:`UnicodeEncodeError` if the path of the module contains characters
+unencodable in the encoding of :data:`sys.stdout`.  Such characters are now
+escaped with backslashes.

_______________________________________________
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