mirror of
https://github.com/python/cpython.git
synced 2025-08-04 17:08:35 +00:00
gh-60115: Support frozen modules for linecache.getline() (#131638)
This commit is contained in:
parent
06822bfbf6
commit
6bd9689426
5 changed files with 48 additions and 2 deletions
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
---------
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Support frozen modules for :func:`linecache.getline`.
|
Loading…
Add table
Add a link
Reference in a new issue