Update linecache from CPython 3.10.6
@@ -13,17 +13,8 @@ except ImportError:
import _dummy_os as os
import tokenize
-__all__ = ["getline", "clearcache", "checkcache"]
+__all__ = ["getline", "clearcache", "checkcache", "lazycache"]
-def getline(filename, lineno, module_globals=None):
- lines = getlines(filename, module_globals)
- if 1 <= lineno <= len(lines):
- return lines[lineno-1]
- else:
- return ''
-
-
-# The cache
# The cache. Maps filenames to either a thunk which will provide source code,
# or a tuple (size, mtime, lines, fullname) once loaded.
@@ -32,9 +23,17 @@ cache = {}
def clearcache():
"""Clear the cache entirely."""
+ cache.clear()
- global cache
- cache = {}
+
+def getline(filename, lineno, module_globals=None):
+ """Get a line for a Python source file from the cache.
+ Update the cache if it doesn't contain an entry for this file already."""
+
+ lines = getlines(filename, module_globals)
+ if 1 <= lineno <= len(lines):
+ return lines[lineno - 1]
+ return ''
def getlines(filename, module_globals=None):
@@ -59,8 +58,7 @@ def checkcache(filename=None):
if filename is None:
filenames = list(cache.keys())
- else:
- if filename in cache:
+ elif filename in cache:
filenames = [filename]
else:
return
@@ -112,8 +110,10 @@ def updatecache(filename, module_globals=None):
# for this module.
return []
cache[filename] = (
- len(data), None,
- [line+'\n' for line in data.splitlines()], fullname
+ len(data),
+ None,
+ [line + '\n' for line in data.splitlines()],
+ fullname
)
return cache[filename][2]
@@ -138,7 +138,7 @@ def updatecache(filename, module_globals=None):
try:
with tokenize.open(fullname) as fp:
lines = fp.readlines()
- except OSError:
+ except (OSError, UnicodeDecodeError, SyntaxError):
return []
if lines and not lines[-1].endswith('\n'):
lines[-1] += '\n'
@@ -157,7 +157,7 @@ def lazycache(filename, module_globals):
:return: True if a lazy load is registered in the cache,
otherwise False. To register such a load a module loader with a
- get_source method must be found, the filename must be a cachable
+ get_source method must be found, the filename must be a cacheable
filename, and the filename must not be already cached.
"""
if filename in cache:
@@ -168,9 +168,14 @@ def lazycache(filename, module_globals):
if not filename or (filename.startswith('<') and filename.endswith('>')):
return False
# Try for a __loader__, if available
- if module_globals and '__loader__' in module_globals:
- name = module_globals.get('__name__')
- loader = module_globals['__loader__']
+ if module_globals and '__name__' in module_globals:
+ name = module_globals['__name__']
+ if (loader := module_globals.get('__loader__')) is None:
+ if spec := module_globals.get('__spec__'):
+ try:
+ loader = spec.loader
+ except AttributeError:
+ pass
get_source = getattr(loader, 'get_source', None)
if name and get_source:
