Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Support getting source file for frozen modules
  • Loading branch information
gaogaotiantian committed Mar 23, 2025
commit 7bbf5d6b69fb8ee577287242067d8c8b41000c29
21 changes: 19 additions & 2 deletions Lib/linecache.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"""
Comment thread
gaogaotiantian marked this conversation as resolved.
Outdated
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!)"""
Expand Down Expand Up @@ -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__', None)
Comment thread
gaogaotiantian marked this conversation as resolved.
Outdated
if fullname is None:
return []
else:
fullname = filename
try:
stat = os.stat(fullname)
except OSError:
Expand Down
13 changes: 13 additions & 0 deletions Lib/test/test_linecache.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,19 @@ def test_loader(self):
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)
Comment thread
picnixz marked this conversation as resolved.
linecache.clearcache()
empty = linecache.getlines(filename)
self.assertEqual(empty, [])

def test_invalid_names(self):
for name, desc in [
('\x00', 'NUL bytes filename'),
Expand Down
Loading