summaryrefslogtreecommitdiff
path: root/lbup/_path.py
diff options
context:
space:
mode:
Diffstat (limited to 'lbup/_path.py')
-rw-r--r--lbup/_path.py57
1 files changed, 57 insertions, 0 deletions
diff --git a/lbup/_path.py b/lbup/_path.py
new file mode 100644
index 0000000..26c67f8
--- /dev/null
+++ b/lbup/_path.py
@@ -0,0 +1,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('/')