96 lines
2.7 KiB
Python
96 lines
2.7 KiB
Python
import py
|
|
import os
|
|
html = py.xml.html
|
|
|
|
def getrelfspath(dotted_name):
|
|
# XXX need to make sure its imported on non-py lib
|
|
return eval(dotted_name, {"py": py})
|
|
|
|
class LazyHref(object):
|
|
def __init__(self, linker, linkid):
|
|
self._linker = linker
|
|
self._linkid = linkid
|
|
|
|
def __unicode__(self):
|
|
return unicode(self._linker.get_target(self._linkid))
|
|
|
|
class Linker(object):
|
|
fromlocation = None
|
|
|
|
def __init__(self):
|
|
self._linkid2target = {}
|
|
|
|
def get_lazyhref(self, linkid):
|
|
return LazyHref(self, linkid)
|
|
|
|
def set_link(self, linkid, target):
|
|
assert (linkid not in self._linkid2target,
|
|
'linkid %r already used' % (linkid,))
|
|
self._linkid2target[linkid] = target
|
|
|
|
def get_target(self, linkid):
|
|
linktarget = self._linkid2target[linkid]
|
|
if self.fromlocation is not None:
|
|
linktarget = relpath(self.fromlocation, linktarget)
|
|
return linktarget
|
|
|
|
def call_withbase(self, base, func, *args, **kwargs):
|
|
assert self.fromlocation is None
|
|
self.fromlocation = base
|
|
try:
|
|
return func(*args, **kwargs)
|
|
finally:
|
|
del self.fromlocation
|
|
|
|
def relpath(p1, p2, sep='/', back='..', normalize=True):
|
|
""" create a relative path from p1 to p2
|
|
|
|
sep is the seperator used for input and (depending
|
|
on the setting of 'normalize', see below) output
|
|
|
|
back is the string used to indicate the parent directory
|
|
|
|
when 'normalize' is True, any backslashes (\) in the path
|
|
will be replaced with forward slashes, resulting in a consistent
|
|
output on Windows and the rest of the world
|
|
|
|
paths to directories must end on a / (URL style)
|
|
"""
|
|
if normalize:
|
|
p1 = p1.replace(sep, '/')
|
|
p2 = p2.replace(sep, '/')
|
|
sep = '/'
|
|
# XXX would be cool to be able to do long filename expansion and drive
|
|
# letter fixes here, and such... iow: windows sucks :(
|
|
if (p1.startswith(sep) ^ p2.startswith(sep)):
|
|
raise ValueError("mixed absolute relative path: %r -> %r" %(p1, p2))
|
|
fromlist = p1.split(sep)
|
|
tolist = p2.split(sep)
|
|
|
|
# AA
|
|
# AA BB -> AA/BB
|
|
#
|
|
# AA BB
|
|
# AA CC -> CC
|
|
#
|
|
# AA BB
|
|
# AA -> ../AA
|
|
|
|
diffindex = 0
|
|
for x1, x2 in zip(fromlist, tolist):
|
|
if x1 != x2:
|
|
break
|
|
diffindex += 1
|
|
commonindex = diffindex - 1
|
|
|
|
fromlist_diff = fromlist[diffindex:]
|
|
tolist_diff = tolist[diffindex:]
|
|
|
|
if not fromlist_diff:
|
|
return sep.join(tolist[commonindex:])
|
|
backcount = len(fromlist_diff)
|
|
if tolist_diff:
|
|
return sep.join([back,]*(backcount-1) + tolist_diff)
|
|
return sep.join([back,]*(backcount) + tolist[commonindex:])
|
|
|