]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-60115: Support frozen modules for linecache.getline() (#131638)
authorTian Gao <gaogaotiantian@hotmail.com>
Wed, 2 Apr 2025 23:50:01 +0000 (19:50 -0400)
committerGitHub <noreply@github.com>
Wed, 2 Apr 2025 23:50:01 +0000 (19:50 -0400)
Doc/library/linecache.rst
Doc/whatsnew/3.14.rst
Lib/linecache.py
Lib/test/test_linecache.py
Misc/NEWS.d/next/Library/2025-03-23-18-39-07.gh-issue-60115.AWdcmq.rst [new file with mode: 0644]

index 88c6079a05b7fa360b5a3eebfbf40e507dec91b8..e766a9280946d30a8442952a0d9678943fb46259 100644 (file)
@@ -30,6 +30,10 @@ The :mod:`linecache` module defines the following functions:
 
    .. index:: triple: module; search; path
 
+   If *filename* indicates a frozen module (starting with ``'<frozen '``), the function
+   will attepmt to get the real file name from ``module_globals['__file__']`` if
+   *module_globals* is not ``None``.
+
    If a file named *filename* is not found, the function first checks
    for a :pep:`302` ``__loader__`` in *module_globals*.
    If there is such a loader and it defines a ``get_source`` method,
@@ -38,6 +42,10 @@ The :mod:`linecache` module defines the following functions:
    Finally, if *filename* is a relative filename,
    it is looked up relative to the entries in the module search path, ``sys.path``.
 
+   .. versionchanged:: 3.14
+
+      Support *filename* of frozen modules.
+
 
 .. function:: clearcache()
 
index 5c0f2829809e3e4d5933dfc56828cc90d5f90033..108768de086bb201d761c1c743669745023b75a9 100644 (file)
@@ -706,6 +706,13 @@ json
   (Contributed by Trey Hunner in :gh:`122873`.)
 
 
+linecache
+---------
+
+* :func:`linecache.getline` can retrieve source code for frozen modules.
+  (Contributed by Tian Gao in :gh:`131638`.)
+
+
 mimetypes
 ---------
 
index dc02de19eb62cb6aeb5f2db0e0518a07bbb65615..87d7d6fda657e474f6e258a391df9199fe974c91 100644 (file)
@@ -63,6 +63,16 @@ def _getlines_from_code(code):
     return []
 
 
+def _source_unavailable(filename):
+    """Return True if the source code is unavailable for such file name."""
+    return (
+        not filename
+        or (filename.startswith('<')
+            and filename.endswith('>')
+            and not filename.startswith('<frozen '))
+    )
+
+
 def checkcache(filename=None):
     """Discard cache entries that are out of date.
     (This is not checked upon each call!)"""
@@ -118,10 +128,17 @@ def updatecache(filename, module_globals=None):
     if filename in cache:
         if len(cache[filename]) != 1:
             cache.pop(filename, None)
-    if not filename or (filename.startswith('<') and filename.endswith('>')):
+    if _source_unavailable(filename):
         return []
 
-    fullname = filename
+    if filename.startswith('<frozen ') and module_globals is not None:
+        # This is a frozen module, so we need to use the filename
+        # from the module globals.
+        fullname = module_globals.get('__file__')
+        if fullname is None:
+            return []
+    else:
+        fullname = filename
     try:
         stat = os.stat(fullname)
     except OSError:
index e23e1cc942856be1ac424a6c8b30974b9e4e298c..e4aa41ebb43762650d37b5d795e764b44c23bb69 100644 (file)
@@ -281,6 +281,19 @@ class LineCacheTests(unittest.TestCase):
         self.assertEqual(linecache.getlines(filename, module_globals),
                          ['source for x.y.z\n'])
 
+    def test_frozen(self):
+        filename = '<frozen fakemodule>'
+        module_globals = {'__file__': FILENAME}
+        empty = linecache.getlines(filename)
+        self.assertEqual(empty, [])
+        lines = linecache.getlines(filename, module_globals)
+        self.assertGreater(len(lines), 0)
+        lines_cached = linecache.getlines(filename)
+        self.assertEqual(lines, lines_cached)
+        linecache.clearcache()
+        empty = linecache.getlines(filename)
+        self.assertEqual(empty, [])
+
     def test_invalid_names(self):
         for name, desc in [
             ('\x00', 'NUL bytes filename'),
diff --git a/Misc/NEWS.d/next/Library/2025-03-23-18-39-07.gh-issue-60115.AWdcmq.rst b/Misc/NEWS.d/next/Library/2025-03-23-18-39-07.gh-issue-60115.AWdcmq.rst
new file mode 100644 (file)
index 0000000..6287e99
--- /dev/null
@@ -0,0 +1 @@
+Support frozen modules for :func:`linecache.getline`.