PageRenderTime 278ms CodeModel.GetById 135ms app.highlight 10ms RepoModel.GetById 131ms app.codeStats 0ms

/Lib/linecache.py

http://unladen-swallow.googlecode.com/
Python | 138 lines | 129 code | 3 blank | 6 comment | 2 complexity | b20256f9679d51eee0e4c169b6b13e96 MD5 | raw file
  1"""Cache lines from files.
  2
  3This is intended to read lines from modules imported -- hence if a filename
  4is not found, it will look down the module search path for a file by
  5that name.
  6"""
  7
  8import sys
  9import os
 10
 11__all__ = ["getline", "clearcache", "checkcache"]
 12
 13def getline(filename, lineno, module_globals=None):
 14    lines = getlines(filename, module_globals)
 15    if 1 <= lineno <= len(lines):
 16        return lines[lineno-1]
 17    else:
 18        return ''
 19
 20
 21# The cache
 22
 23cache = {} # The cache
 24
 25
 26def clearcache():
 27    """Clear the cache entirely."""
 28
 29    global cache
 30    cache = {}
 31
 32
 33def getlines(filename, module_globals=None):
 34    """Get the lines for a file from the cache.
 35    Update the cache if it doesn't contain an entry for this file already."""
 36
 37    if filename in cache:
 38        return cache[filename][2]
 39    else:
 40        return updatecache(filename, module_globals)
 41
 42
 43def checkcache(filename=None):
 44    """Discard cache entries that are out of date.
 45    (This is not checked upon each call!)"""
 46
 47    if filename is None:
 48        filenames = cache.keys()
 49    else:
 50        if filename in cache:
 51            filenames = [filename]
 52        else:
 53            return
 54
 55    for filename in filenames:
 56        size, mtime, lines, fullname = cache[filename]
 57        if mtime is None:
 58            continue   # no-op for files loaded via a __loader__
 59        try:
 60            stat = os.stat(fullname)
 61        except os.error:
 62            del cache[filename]
 63            continue
 64        if size != stat.st_size or mtime != stat.st_mtime:
 65            del cache[filename]
 66
 67
 68def updatecache(filename, module_globals=None):
 69    """Update a cache entry and return its list of lines.
 70    If something's wrong, print a message, discard the cache entry,
 71    and return an empty list."""
 72
 73    if filename in cache:
 74        del cache[filename]
 75    if not filename or filename[0] + filename[-1] == '<>':
 76        return []
 77
 78    fullname = filename
 79    try:
 80        stat = os.stat(fullname)
 81    except os.error, msg:
 82        basename = filename
 83
 84        # Try for a __loader__, if available
 85        if module_globals and '__loader__' in module_globals:
 86            name = module_globals.get('__name__')
 87            loader = module_globals['__loader__']
 88            get_source = getattr(loader, 'get_source', None)
 89
 90            if name and get_source:
 91                try:
 92                    data = get_source(name)
 93                except (ImportError, IOError):
 94                    pass
 95                else:
 96                    if data is None:
 97                        # No luck, the PEP302 loader cannot find the source
 98                        # for this module.
 99                        return []
100                    cache[filename] = (
101                        len(data), None,
102                        [line+'\n' for line in data.splitlines()], fullname
103                    )
104                    return cache[filename][2]
105
106        # Try looking through the module search path, which is only useful
107        # when handling a relative filename.
108        if os.path.isabs(filename):
109            return []
110
111        for dirname in sys.path:
112            # When using imputil, sys.path may contain things other than
113            # strings; ignore them when it happens.
114            try:
115                fullname = os.path.join(dirname, basename)
116            except (TypeError, AttributeError):
117                # Not sufficiently string-like to do anything useful with.
118                pass
119            else:
120                try:
121                    stat = os.stat(fullname)
122                    break
123                except os.error:
124                    pass
125        else:
126            # No luck
127##          print '*** Cannot stat', filename, ':', msg
128            return []
129    try:
130        fp = open(fullname, 'rU')
131        lines = fp.readlines()
132        fp.close()
133    except IOError, msg:
134##      print '*** Cannot open', fullname, ':', msg
135        return []
136    size, mtime = stat.st_size, stat.st_mtime
137    cache[filename] = size, mtime, lines, fullname
138    return lines