31
35
entity_re = re.compile("&(#?)(\d{1,5}|\w{1,8});")
32
36
return entity_re.subn(substitute_entity, string)[0]
38
def cacheable_download(url, cachefile):
39
"""Download url to cachefile if it's modified since cachefile.
40
Specify cachefile in the form pluginname/cachefile.
41
Returns complete path to downloaded file."""
43
# We do allow absolute paths, for people who know what they are doing,
44
# but the common use case should be pluginname/cachefile.
45
if cachefile[0] not in (os.sep, os.altsep):
46
cachedir = ibid.config.plugins['cachedir']
48
cachedir = os.path.join(ibid.options['base'], 'cache')
49
elif cachedir[0] == "~":
50
cachedir = os.path.expanduser(cachedir)
52
plugindir = os.path.join(cachedir, os.path.dirname(cachefile))
53
if not os.path.isdir(plugindir):
54
os.makedirs(plugindir)
56
cachefile = os.path.join(cachedir, cachefile)
58
exists = os.path.isfile(cachefile)
60
req = urllib2.Request(url)
63
modified = os.path.getmtime(cachefile)
64
modified = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(modified))
65
req.add_header("If-Modified-Since", modified)
68
connection = urllib2.urlopen(req)
69
except urllib2.HTTPError, e:
70
if e.code == 304 and exists:
75
# Download into a temporary file, in case something goes wrong
76
downloadfile = os.path.join(plugindir, ".download." + os.path.basename(cachefile))
77
outfile = file(downloadfile, "wb")
80
buf = connection.read(1024)
86
os.rename(downloadfile, cachefile)
88
# Are we on a system that doesn't support atomic renames?
90
os.rename(downloadfile, cachefile)
34
94
def file_in_path(program):
35
95
path = os.environ.get("PATH", os.defpath).split(os.pathsep)
36
96
path = [os.path.join(dir, program) for dir in path]