summaryrefslogtreecommitdiffstats
path: root/Lib/linecache.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/linecache.py')
-rw-r--r--Lib/linecache.py106
1 files changed, 34 insertions, 72 deletions
diff --git a/Lib/linecache.py b/Lib/linecache.py
index 3afcce1..4b97be3 100644
--- a/Lib/linecache.py
+++ b/Lib/linecache.py
@@ -1,14 +1,12 @@
-"""Cache lines from Python source files.
+"""Cache lines from files.
This is intended to read lines from modules imported -- hence if a filename
is not found, it will look down the module search path for a file by
that name.
"""
-import functools
import sys
import os
-import tokenize
__all__ = ["getline", "clearcache", "checkcache"]
@@ -22,9 +20,7 @@ def getline(filename, lineno, module_globals=None):
# The cache
-# The cache. Maps filenames to either a thunk which will provide source code,
-# or a tuple (size, mtime, lines, fullname) once loaded.
-cache = {}
+cache = {} # The cache
def clearcache():
@@ -35,13 +31,11 @@ def clearcache():
def getlines(filename, module_globals=None):
- """Get the lines for a Python source file from the cache.
+ """Get the lines for a file from the cache.
Update the cache if it doesn't contain an entry for this file already."""
if filename in cache:
- entry = cache[filename]
- if len(entry) != 1:
- return cache[filename][2]
+ return cache[filename][2]
try:
return updatecache(filename, module_globals)
@@ -55,7 +49,7 @@ def checkcache(filename=None):
(This is not checked upon each call!)"""
if filename is None:
- filenames = list(cache.keys())
+ filenames = cache.keys()
else:
if filename in cache:
filenames = [filename]
@@ -63,16 +57,12 @@ def checkcache(filename=None):
return
for filename in filenames:
- entry = cache[filename]
- if len(entry) == 1:
- # lazy cache entry, leave it lazy.
- continue
- size, mtime, lines, fullname = entry
+ size, mtime, lines, fullname = cache[filename]
if mtime is None:
continue # no-op for files loaded via a __loader__
try:
stat = os.stat(fullname)
- except OSError:
+ except os.error:
del cache[filename]
continue
if size != stat.st_size or mtime != stat.st_mtime:
@@ -85,8 +75,7 @@ def updatecache(filename, module_globals=None):
and return an empty list."""
if filename in cache:
- if len(cache[filename]) != 1:
- del cache[filename]
+ del cache[filename]
if not filename or (filename.startswith('<') and filename.endswith('>')):
return []
@@ -96,23 +85,27 @@ def updatecache(filename, module_globals=None):
except OSError:
basename = filename
- # Realise a lazy loader based lookup if there is one
- # otherwise try to lookup right now.
- if lazycache(filename, module_globals):
- try:
- data = cache[filename][0]()
- except (ImportError, OSError):
- pass
- else:
- if data is None:
- # No luck, the PEP302 loader cannot find the source
- # for this module.
- return []
- cache[filename] = (
- len(data), None,
- [line+'\n' for line in data.splitlines()], fullname
- )
- return cache[filename][2]
+ # Try for a __loader__, if available
+ if module_globals and '__loader__' in module_globals:
+ name = module_globals.get('__name__')
+ loader = module_globals['__loader__']
+ get_source = getattr(loader, 'get_source', None)
+
+ if name and get_source:
+ try:
+ data = get_source(name)
+ except (ImportError, IOError):
+ pass
+ else:
+ if data is None:
+ # No luck, the PEP302 loader cannot find the source
+ # for this module.
+ return []
+ cache[filename] = (
+ len(data), None,
+ [line+'\n' for line in data.splitlines()], fullname
+ )
+ return cache[filename][2]
# Try looking through the module search path, which is only useful
# when handling a relative filename.
@@ -120,6 +113,8 @@ def updatecache(filename, module_globals=None):
return []
for dirname in sys.path:
+ # When using imputil, sys.path may contain things other than
+ # strings; ignore them when it happens.
try:
fullname = os.path.join(dirname, basename)
except (TypeError, AttributeError):
@@ -128,50 +123,17 @@ def updatecache(filename, module_globals=None):
try:
stat = os.stat(fullname)
break
- except OSError:
+ except os.error:
pass
else:
return []
try:
- with tokenize.open(fullname) as fp:
+ with open(fullname, 'rU') as fp:
lines = fp.readlines()
- except OSError:
+ except IOError:
return []
if lines and not lines[-1].endswith('\n'):
lines[-1] += '\n'
size, mtime = stat.st_size, stat.st_mtime
cache[filename] = size, mtime, lines, fullname
return lines
-
-
-def lazycache(filename, module_globals):
- """Seed the cache for filename with module_globals.
-
- The module loader will be asked for the source only when getlines is
- called, not immediately.
-
- If there is an entry in the cache already, it is not altered.
-
- :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
- filename, and the filename must not be already cached.
- """
- if filename in cache:
- if len(cache[filename]) == 1:
- return True
- else:
- return False
- 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__']
- get_source = getattr(loader, 'get_source', None)
-
- if name and get_source:
- get_lines = functools.partial(get_source, name)
- cache[filename] = (get_lines,)
- return True
- return False