]> git.lizzy.rs Git - plan9front.git/blob - sys/lib/python/linecache.py
aux/cpuid: decode family and model bitfields
[plan9front.git] / sys / lib / python / linecache.py
1 """Cache lines from files.
2
3 This is intended to read lines from modules imported -- hence if a filename
4 is not found, it will look down the module search path for a file by
5 that name.
6 """
7
8 import sys
9 import os
10
11 __all__ = ["getline", "clearcache", "checkcache"]
12
13 def 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
23 cache = {} # The cache
24
25
26 def clearcache():
27     """Clear the cache entirely."""
28
29     global cache
30     cache = {}
31
32
33 def 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
43 def 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
68 def 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 = os.path.split(filename)[1]
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                 if basename.startswith(name.split('.')[-1]+'.'):
92                     try:
93                         data = get_source(name)
94                     except (ImportError, IOError):
95                         pass
96                     else:
97                         if data is None:
98                             # No luck, the PEP302 loader cannot find the source
99                             # for this module.
100                             return []
101                         cache[filename] = (
102                             len(data), None,
103                             [line+'\n' for line in data.splitlines()], fullname
104                         )
105                         return cache[filename][2]
106
107         # Try looking through the module search path.
108
109         for dirname in sys.path:
110             # When using imputil, sys.path may contain things other than
111             # strings; ignore them when it happens.
112             try:
113                 fullname = os.path.join(dirname, basename)
114             except (TypeError, AttributeError):
115                 # Not sufficiently string-like to do anything useful with.
116                 pass
117             else:
118                 try:
119                     stat = os.stat(fullname)
120                     break
121                 except os.error:
122                     pass
123         else:
124             # No luck
125 ##          print '*** Cannot stat', filename, ':', msg
126             return []
127     try:
128         fp = open(fullname, 'rU')
129         lines = fp.readlines()
130         fp.close()
131     except IOError, msg:
132 ##      print '*** Cannot open', fullname, ':', msg
133         return []
134     size, mtime = stat.st_size, stat.st_mtime
135     cache[filename] = size, mtime, lines, fullname
136     return lines