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
|
class AbsPath:
_components = None
def __init__(self, path = None, components = None):
if (path is None) == (components is None):
raise ValueError('Exactly one of path or components must be provided')
if path is not None:
if isinstance(path, str):
path = path.encode('utf-8')
else:
path = bytes(path)
if len(path) < 1 or not path.startswith(b'/'):
raise ValueError('Path does not look like valid absolute path', path)
components = filter(lambda x: len(x) > 0 and x != b'.', path[1:].split(b'/'))
self._components = tuple(components)
if b'..' in self.components:
raise ValueError('Parent references are not allowed: %s' % self)
def __bytes__(self):
return self.path
def __repr__(self):
return self.path.decode('utf-8', errors = 'backslashreplace')
def __contains__(self, item):
c = self.components
ci = item.components
if len(ci) >= len(c) and ci[:len(c)] == c:
return True
return False
def __eq__(self, other):
return self.components == other.components
def __len__(self):
return len(self.components)
def __add__(self, other):
if isinstance(other, str):
other = other.encode('utf-8')
if isinstance(other, bytes):
other = self.__class__(b'/' + other)
return self.__class__(components = self.components + other.components)
@property
def path(self):
return b'/' + b'/'.join(self.components)
@property
def components(self):
"""
A tuple of path components.
Note that root does not count as a component, so for a path of b'/' this
is an empty tuple.
"""
return self._components
def reparent(self, src, dst):
if not self in src:
raise ValueError('Path not in parent', self, src)
tail = self.components[len(src):]
return AbsPath(components = dst.components + tail)
ROOT = AbsPath('/')
|