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
71
72
73
74
75
76
77
78
|
"""Tree data structure for ls command to work with OpenAPI specification."""
class Node(object):
def __init__(self, name, data=None, parent=None):
if name in ('.', '..'):
raise ValueError("name cannot be '.' or '..'")
self.name = name
self.data = data or {}
self.parent = parent
self.children = set()
def __str__(self):
return self.name
def __repr__(self):
return "Node('{}', '{}')".format(self.name, self.data.get('type'))
def __lt__(self, other):
ta = self.data.get('type')
tb = other.data.get('type')
if ta != tb:
return ta < tb
return self.name < other.name
def __eq__(self, other):
return self.name == other.name and self.data == other.data
def __hash__(self):
return hash((self.name, self.data.get('type')))
def add_path(self, *path, **kwargs):
node_type = kwargs.get('node_type', 'dir')
name = path[0]
tail = path[1:]
child = self.find_child(name, wildcard=False)
if not child:
data = {'type': 'dir' if tail else node_type}
child = Node(name, data=data, parent=self)
self.children.add(child)
if tail:
child.add_path(*tail, node_type=node_type)
def find_child(self, name, wildcard=True):
for child in self.children:
if child.name == name:
return child
# Attempt to match wildcard like /users/{user_id}
if wildcard:
for child in self.children:
if child.name.startswith('{') and child.name.endswith('}'):
return child
return None
def ls(self, *path):
success = True
cur = self
for name in path:
if not name or name == '.':
continue
elif name == '..':
if cur.parent:
cur = cur.parent
else:
child = cur.find_child(name)
if child:
cur = child
else:
success = False
break
if success:
for node in sorted(cur.children):
yield node
|