1 """This module contains helper functions for working with the module cache.
2
3 Example operations:
4 - modulename = modulename_from_checksum(checksum)
5 - modulename = modulename_from_checksum(compute_checksum(signature))
6 - module = import_module_directly(path, modulename)
7 - module = import_module(modulename)
8 - module = import_module(checksum)
9 - module = import_module(compute_checksum(signature))
10 - modules = cached_modules()
11 - modules = cached_modules(cache_dir)
12 """
13
14 import os, sys, re
15 from .output import instant_warning, instant_assert, instant_debug
16 from .paths import get_default_cache_dir, validate_cache_dir
17 from .signatures import compute_checksum
18 from .locking import get_lock, release_lock
19
20
21 _modulename_prefix = "instant_module_"
23 "Construct a module name from a checksum for use in cache."
24 return _modulename_prefix + checksum
25
26
28 "Construct a module name from a checksum for use in cache."
29 return modulename.remove(_modulename_prefix)
30
31
33 "Import a module with the given module name that resides in the given path."
34 sys.path.insert(0, path)
35 e = None
36 try:
37 module = __import__(modulename)
38 except Exception as e:
39 instant_warning("In instant.import_module_directly: Failed to import module '%s' from '%s';\n%s:%s;" % (modulename, path, type(e).__name__, e))
40 module = None
41 finally:
42 sys.path.pop(0)
43 return module, e
44
45
46 _memory_cache = {}
48 "Returns the cached module if found."
49 import sys
50 module = _memory_cache.get(moduleid, None)
51 instant_debug("Found '%s' in memory cache with key '%r'." % (module, moduleid))
52 return module
53
54
56 "Place a compiled module in cache with given id."
57 _memory_cache[moduleid] = module
58 instant_debug("Added module '%s' to cache with key '%r'." % (module, moduleid))
59
60
62 NAMELENGTHLIMIT = 100
63 return len(name) < NAMELENGTHLIMIT and bool(re.search(r"^[a-zA-Z_][\w]*$", name))
64
65
72
73
75
76 moduleids = [moduleid]
77 module = memory_cached_module(moduleid)
78 if module: return module, moduleids
79
80
81
82 if hasattr(moduleid, "signature"):
83 moduleid = moduleid.signature()
84 instant_debug("In instant.check_memory_cache: Got signature "\
85 "'%s' from moduleid.signature()." % moduleid)
86 module = memory_cached_module(moduleid)
87 if module:
88
89
90
91
92
93
94 return module, moduleids
95 moduleids.append(moduleid)
96
97
98
99 if not is_valid_module_name(moduleid):
100 moduleid = modulename_from_checksum(compute_checksum(moduleid))
101 instant_debug("In instant.check_memory_cache: Constructed module name "\
102 "'%s' from moduleid '%s'." % (moduleid, moduleids[-1]))
103 module = memory_cached_module(moduleid)
104 if module: return module, moduleids
105 moduleids.append(moduleid)
106
107 instant_debug("In instant.check_memory_cache: Failed to find module.")
108 return None, moduleids
109
110
112
113 lock = get_lock(cache_dir, modulename)
114
115
116 cache_dir = validate_cache_dir(cache_dir)
117
118
119 for path in (os.getcwd(), cache_dir):
120 if os.path.isdir(os.path.join(path, modulename)):
121
122 module = import_and_cache_module(path, modulename, moduleids)
123 if module:
124 instant_debug("In instant.check_disk_cache: Imported module "\
125 "'%s' from '%s'." % (modulename, path))
126 release_lock(lock)
127 return module
128 else:
129 instant_debug("In instant.check_disk_cache: Failed to imported "\
130 "module '%s' from '%s'." % (modulename, path))
131
132
133 instant_debug("In instant.check_disk_cache: Can't import module with modulename "\
134 "%r using cache directory %r." % (modulename, cache_dir))
135 release_lock(lock)
136 return None
137
138
140 """Import module from cache given its moduleid and an optional cache directory.
141
142 The moduleid can be either
143 - the module name
144 - a signature string, of which a checksum is taken to look up in the cache
145 - a checksum string, which is used directly to look up in the cache
146 - a hashable non-string object with a function moduleid.signature() which is used to get a signature string
147 The hashable object is used to look up in the memory cache before signature() is called.
148 If the module is found on disk, it is placed in the memory cache.
149 """
150
151 module, moduleids = check_memory_cache(moduleid)
152 if module: return module
153
154
155 modulename = moduleids[-1]
156 return check_disk_cache(modulename, cache_dir, moduleids)
157
158
160 "Return a list with the names of all cached modules."
161 cache_dir = validate_cache_dir(cache_dir)
162 return os.listdir(cache_dir)
163