Skip to content

Instantly share code, notes, and snippets.

@jaraco
Created August 9, 2024 18:36
Show Gist options
  • Save jaraco/a37365872703163393b44793cda34ad2 to your computer and use it in GitHub Desktop.
Save jaraco/a37365872703163393b44793cda34ad2 to your computer and use it in GitHub Desktop.
from typing import Iterable
def unique(items):
return list(dict.fromkeys(items))
class Tree:
def __init__(self, paths, at=""):
self.paths = tuple(paths)
self.at = at
@property
def name(self):
rest, sep, name = self.at.rpartition("/")
return name
@property
def children(self):
return unique(
Tree(self.paths, "/".join((self.at, self._child_name(path))).lstrip("/"))
for path in self.paths
if self._child_name(path)
)
def __hash__(self):
return hash(tuple(vars(self).values()))
def __eq__(self, other):
return vars(self) == vars(other)
def _child_name(self, path):
path = path.strip("/")
name, sep, rest = path.removeprefix(self.at).strip("/").partition("/")
return self._is_subpath(path) and name
def _is_subpath(self, path):
"""
Is path a subpath of self.at
"""
return (
not self.at
or len(self.at) <= len(path)
and all(
left == right
for left, right in zip(path.split("/"), self.at.split("/"))
)
)
def __repr__(self):
return f"Tree(at={self.at!r})"
def generate_tree(paths: list[str]) -> None:
"""
Don't support non-root elements without a leading slash. (a/b)
"""
paths.sort()
render_level(Tree(paths).children)
def render_level(trees: Iterable[Tree], level=0):
for item in trees:
print(" " * level, f"-- {item.name}", sep="")
render_level(item.children, level=level + 1)
inputs = [
"/a/b",
"/a/b/c",
"/a/b/c1.jpg",
"/d/e/",
"p1.png",
"p2.png",
"/a/b/fff",
"/b/a",
]
__name__ == "__main__" and generate_tree(inputs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment