forked from jurev/knockout
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cachedimport.py
155 lines (128 loc) · 5.4 KB
/
cachedimport.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import urlimport
import logging
logging.basicConfig(level=urlimport.SOURCE)
log = logging.getLogger("cachedimport")
import sys, os, re, shutil
class NotInCacheException(Exception):
pass
class FileCacheImporter(urlimport.UrlImporter):
""" Use filesystem storage as a cache.
"""
CACHE_DIR = "./modules"
SYMLINKS_DIR = None
re_detailedpath = re.compile(''.join([
r'^',
r'(?P<protocol>http|ftp)',
r'://',
r'(?P<host>[^/]+)',
r'(?P<urlpath>.+)',
r'$'
]))
def find_module(self, fullname, mpath=None):
""" Find module in the cache.
"""
for url, path in self.get_candidates(fullname):
try:
localpath = self.translate_fullpath(url)
self.source = self.get_cached_source(localpath)
except Exception, e:
log.debug("find_module: failed to get '%s'. (%s)" % (localpath, e))
else:
log.debug("find_module: got '%s'. mpath=%s" % (localpath, mpath))
self.path = path
self.__file__ = localpath
if fullname == self.package:
self.make_symlink(self.__file__, self.SYMLINKS_DIR)
return self
result = super(FileCacheImporter, self).find_module(fullname, mpath)
if result:
self.put_source(self.translate_fullpath(result.__file__), result.source)
return result
def make_symlink(self, src, dst):
if src and dst:
os.symlink(src, dst)
def translate_fullpath(self, fullpath):
"""Get local path from fullpath.
"""
translated = self.re_detailedpath.match(fullpath)
if not translated:
raise RuntimeError("translate_fullpath: Could not parse the given url: %s" % fullpath)
root, folder, path = self.CACHE_DIR, translated.groupdict()["host"], translated.groupdict()["urlpath"][1:]
localpath = '/'.join([root, folder, path])
return localpath
def get_cached_source(self, localpath):
"""Get the cached source for the given url.
"""
log.debug("get_source: this is my localpath: %s" % localpath)
if os.path.isfile(localpath):
log.debug("get_source: trying to get %s from cache" % localpath)
return open(localpath).read()
raise NotInCacheException("Not in cache: %s" % localpath)
def put_source(self, localpath, source):
"""Put the source obtained from the given url to cache.
"""
dirname = os.path.dirname(localpath)
log.debug("put_source: trying to create %s" % dirname)
if not os.path.isdir(dirname):
os.makedirs(dirname)
log.debug("put_source: trying to write %s" % localpath)
open(localpath, "w").write(source)
log.debug("put_source: wrote %s" % localpath)
class FunkyCacheImporter(urlimport.UrlImporter):
""" Always store python files as packages(something/__init__.py)
"""
CACHE_DIR = "./modules"
re_detailedpath = re.compile(''.join([
r'^',
r'(?P<protocol>http|ftp)',
r'://',
r'(?P<host>[^/]+)',
r'(?P<urlpath>.+)',
r'$'
]))
def find_module(self, fullname, mpath=None):
""" Find module in the cache.
"""
for url, path in self.get_candidates(fullname):
try:
self.source = self.get_cached_source(url)
except Exception, e:
log.debug("find_module: failed to get '%s'. (%s)" % (url, e))
else:
log.debug("find_module: got '%s'. mpath=%s" % (url, mpath))
self.path = path
return self
result = super(FileCacheImporter, self).find_module(fullname, mpath)
if result:
name = fullname.split(".")[-1]
self.put_source(result.location + name + "/__init__.py", result.source)
return result
def translate_fullpath(self, fullpath):
"""Get local path from fullpath.
"""
translated = self.re_detailedpath.match(fullpath)
if not translated:
raise RuntimeError("translate_fullpath: Could not parse the given url: %s" % fullpath)
root, folder, path = self.CACHE_DIR, translated.groupdict()["host"], translated.groupdict()["urlpath"][1:]
localpath = '/'.join([root, folder, path])
return localpath
def get_cached_source(self, url):
"""Get the cached source for the given url.
"""
localpath = self.translate_fullpath(url)
log.debug("get_source: this is my localpath: %s" % localpath)
if os.path.isfile(localpath):
log.debug("get_source: trying to get %s from cache" % localpath)
return open(localpath).read()
raise NotInCacheException
def put_source(self, url, source):
"""Put the source obtained from the given url to cache.
"""
localpath = self.translate_fullpath(url)
dirname = os.path.dirname(localpath)
log.debug("put_source: trying to create %s" % dirname)
if not os.path.isdir(dirname):
os.makedirs(dirname)
log.debug("put_source: trying to write %s" % localpath)
open(localpath, "w").write(source)
log.debug("put_source: wrote %s" % localpath)