mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Update linecache from CPython 3.10.6
This commit is contained in:
1 parent
3073947a8b
commit
5dbab96678
2 files changed
+82
-35
No files matched your search
Vendored
+28
-23
@@ -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,11 +58,10 @@ def checkcache(filename=None):
|
||||
|
||||
if filename is None:
|
||||
filenames = list(cache.keys())
|
||||
elif filename in cache:
|
||||
filenames = [filename]
|
||||
else:
|
||||
if filename in cache:
|
||||
filenames = [filename]
|
||||
else:
|
||||
return
|
||||
return
|
||||
|
||||
for filename in filenames:
|
||||
entry = cache[filename]
|
||||
@@ -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:
|
||||
|
||||
Vendored
+54
-12
@@ -73,12 +73,10 @@ class GetLineTestsBadData(TempFile):
|
||||
# file_byte_string = b'Bad data goes here'
|
||||
|
||||
def test_getline(self):
|
||||
self.assertRaises((SyntaxError, UnicodeDecodeError),
|
||||
linecache.getline, self.file_name, 1)
|
||||
self.assertEqual(linecache.getline(self.file_name, 1), '')
|
||||
|
||||
def test_getlines(self):
|
||||
self.assertRaises((SyntaxError, UnicodeDecodeError),
|
||||
linecache.getlines, self.file_name)
|
||||
self.assertEqual(linecache.getlines(self.file_name), [])
|
||||
|
||||
|
||||
class EmptyFile(GetLineTestsGoodData, unittest.TestCase):
|
||||
@@ -92,9 +90,11 @@ class SingleEmptyLine(GetLineTestsGoodData, unittest.TestCase):
|
||||
class GoodUnicode(GetLineTestsGoodData, unittest.TestCase):
|
||||
file_list = ['á\n', 'b\n', 'abcdef\n', 'ááááá\n']
|
||||
|
||||
class BadUnicode_NoDeclaration(GetLineTestsBadData, unittest.TestCase):
|
||||
file_byte_string = b'\n\x80abc'
|
||||
|
||||
class BadUnicode(GetLineTestsBadData, unittest.TestCase):
|
||||
file_byte_string = b'\x80abc'
|
||||
class BadUnicode_WithDeclaration(GetLineTestsBadData, unittest.TestCase):
|
||||
file_byte_string = b'# coding=utf-8\n\x80abc'
|
||||
|
||||
|
||||
class LineCacheTests(unittest.TestCase):
|
||||
@@ -116,7 +116,7 @@ class LineCacheTests(unittest.TestCase):
|
||||
# Check module loading
|
||||
for entry in MODULES:
|
||||
filename = os.path.join(MODULE_PATH, entry) + '.py'
|
||||
with open(filename) as file:
|
||||
with open(filename, encoding='utf-8') as file:
|
||||
for index, line in enumerate(file):
|
||||
self.assertEqual(line, getline(filename, index + 1))
|
||||
|
||||
@@ -126,7 +126,7 @@ class LineCacheTests(unittest.TestCase):
|
||||
|
||||
def test_no_ending_newline(self):
|
||||
self.addCleanup(os_helper.unlink, os_helper.TESTFN)
|
||||
with open(os_helper.TESTFN, "w") as fp:
|
||||
with open(os_helper.TESTFN, "w", encoding='utf-8') as fp:
|
||||
fp.write(SOURCE_3)
|
||||
lines = linecache.getlines(os_helper.TESTFN)
|
||||
self.assertEqual(lines, ["\n", "def f():\n", " return 3\n"])
|
||||
@@ -153,18 +153,18 @@ class LineCacheTests(unittest.TestCase):
|
||||
# Create a source file and cache its contents
|
||||
source_name = os_helper.TESTFN + '.py'
|
||||
self.addCleanup(os_helper.unlink, source_name)
|
||||
with open(source_name, 'w') as source:
|
||||
with open(source_name, 'w', encoding='utf-8') as source:
|
||||
source.write(SOURCE_1)
|
||||
getline(source_name, 1)
|
||||
|
||||
# Keep a copy of the old contents
|
||||
source_list = []
|
||||
with open(source_name) as source:
|
||||
with open(source_name, encoding='utf-8') as source:
|
||||
for index, line in enumerate(source):
|
||||
self.assertEqual(line, getline(source_name, index + 1))
|
||||
source_list.append(line)
|
||||
|
||||
with open(source_name, 'w') as source:
|
||||
with open(source_name, 'w', encoding='utf-8') as source:
|
||||
source.write(SOURCE_2)
|
||||
|
||||
# Try to update a bogus cache entry
|
||||
@@ -176,7 +176,7 @@ class LineCacheTests(unittest.TestCase):
|
||||
|
||||
# Update the cache and check whether it matches the new source file
|
||||
linecache.checkcache(source_name)
|
||||
with open(source_name) as source:
|
||||
with open(source_name, encoding='utf-8') as source:
|
||||
for index, line in enumerate(source):
|
||||
self.assertEqual(line, getline(source_name, index + 1))
|
||||
source_list.append(line)
|
||||
@@ -245,5 +245,47 @@ class LineCacheTests(unittest.TestCase):
|
||||
self.assertEqual(linecache.getlines(FILENAME), lines)
|
||||
|
||||
|
||||
class LineCacheInvalidationTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
linecache.clearcache()
|
||||
self.deleted_file = os_helper.TESTFN + '.1'
|
||||
self.modified_file = os_helper.TESTFN + '.2'
|
||||
self.unchanged_file = os_helper.TESTFN + '.3'
|
||||
|
||||
for fname in (self.deleted_file,
|
||||
self.modified_file,
|
||||
self.unchanged_file):
|
||||
self.addCleanup(os_helper.unlink, fname)
|
||||
with open(fname, 'w', encoding='utf-8') as source:
|
||||
source.write(f'print("I am {fname}")')
|
||||
|
||||
self.assertNotIn(fname, linecache.cache)
|
||||
linecache.getlines(fname)
|
||||
self.assertIn(fname, linecache.cache)
|
||||
|
||||
os.remove(self.deleted_file)
|
||||
with open(self.modified_file, 'w', encoding='utf-8') as source:
|
||||
source.write('print("was modified")')
|
||||
|
||||
def test_checkcache_for_deleted_file(self):
|
||||
linecache.checkcache(self.deleted_file)
|
||||
self.assertNotIn(self.deleted_file, linecache.cache)
|
||||
self.assertIn(self.modified_file, linecache.cache)
|
||||
self.assertIn(self.unchanged_file, linecache.cache)
|
||||
|
||||
def test_checkcache_for_modified_file(self):
|
||||
linecache.checkcache(self.modified_file)
|
||||
self.assertIn(self.deleted_file, linecache.cache)
|
||||
self.assertNotIn(self.modified_file, linecache.cache)
|
||||
self.assertIn(self.unchanged_file, linecache.cache)
|
||||
|
||||
def test_checkcache_with_no_parameter(self):
|
||||
linecache.checkcache()
|
||||
self.assertNotIn(self.deleted_file, linecache.cache)
|
||||
self.assertNotIn(self.modified_file, linecache.cache)
|
||||
self.assertIn(self.unchanged_file, linecache.cache)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user