summaryrefslogtreecommitdiff
path: root/lbup/_path.py
blob: 26c67f89e08d6c4506fd4e63a27897bef21ca18f (plain)
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
class AbsPath:
    _components = None

    def __init__(self, path = None, components = None):
        if path is not None and components is not None:
            raise ValueError('Both path and components provided')

        if path is not None:
            if isinstance(path, str):
                path = path.encode('utf-8')
            if len(path) < 1 or not path.startswith(b'/'):
                raise ValueError('Path does not look like valid absolute path', path)
            components = list(filter(lambda x: len(x) > 0 and x != b'.', path[1:].split(b'/')))
            if b'..' in components:
                raise ValueError('Parent references are not allowed', path)

        self._components = components

    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)

    @property
    def path(self):
        return b'/' + b'/'.join(self.components)

    @property
    def components(self):
        """
        Return a list of path components.

        Note that root does not count as a component, so a path of b'/' returns
        an empty list.
        """
        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('/')