verysimpletree 1.0__tar.gz → 1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: verysimpletree
3
- Version: 1.0
3
+ Version: 1.2
4
4
  Summary: lightweight tree data structure for musicxml and musicscore
5
5
  Home-page: https://github.com/alexgorji/verysimpletree.git
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name="verysimpletree"
3
- version="1.0"
3
+ version="1.2"
4
4
  description = "lightweight tree data structure for musicxml and musicscore"
5
5
  authors = ["Alex Gorji <aligorji@hotmail.com>"]
6
6
  license = "MIT"
@@ -15,8 +15,8 @@ class BContent:
15
15
 
16
16
 
17
17
  class A(Tree[Any]):
18
- def __init__(self, name, parent=None, *args, **keyword):
19
- super().__init__(*args, **keyword)
18
+ def __init__(self, name, parent=None, *args, **kwargs):
19
+ super().__init__(*args, **kwargs)
20
20
  self._children = []
21
21
  self._parent = parent
22
22
  self.name = name
@@ -35,8 +35,8 @@ class A(Tree[Any]):
35
35
 
36
36
 
37
37
  class B(Tree[Any]):
38
- def __init__(self, name, *args, **keyword):
39
- super().__init__(*args, **keyword)
38
+ def __init__(self, name, *args, **kwargs):
39
+ super().__init__(*args, **kwargs)
40
40
  self.name = name
41
41
  self.content = BContent(value=10)
42
42
 
@@ -44,8 +44,17 @@ class B(Tree[Any]):
44
44
  if not isinstance(child, Tree):
45
45
  raise TypeError
46
46
 
47
+ class C(Tree[Any]):
48
+ def __init__(self, name, value, *args, **kwargs):
49
+ super().__init__(*args, **kwargs)
50
+ self.name = name
51
+ self.value = value
47
52
 
48
- class TestTree(TestCase):
53
+ def _check_child_to_be_added(self, child): # pragma: no cover
54
+ if not isinstance(child, Tree):
55
+ raise TypeError
56
+
57
+ class TreeTestCase(TestCase):
49
58
  def setUp(self) -> None:
50
59
  self.root = A(name='root')
51
60
  self.child1 = self.root.add_child_by_name('child1')
@@ -57,6 +66,7 @@ class TestTree(TestCase):
57
66
  self.grandchild3 = self.child4.add_child_by_name('grandchild3')
58
67
  self.greatgrandchild1 = self.grandchild2.add_child_by_name('greatgrandchild1')
59
68
 
69
+ class Test(TreeTestCase):
60
70
  def test_is_last_child(self):
61
71
  t = self.root
62
72
  for node in t.traverse():
@@ -206,6 +216,52 @@ class TestTree(TestCase):
206
216
  with self.assertRaises(ValueError):
207
217
  self.root.get_tree_representation(space=0)
208
218
 
219
+ def test_get_tree_representation(self):
220
+ expected = """└── root
221
+ ├── child1
222
+ ├── child2
223
+ │ ├── grandchild1
224
+ │ └── grandchild2
225
+ │ └── greatgrandchild1
226
+ ├── child3
227
+ └── child4
228
+ └── grandchild3
229
+ """
230
+
231
+ assert self.root.get_tree_representation() == expected
232
+
233
+
234
+ class TreeListRepresentationTestCase(TreeTestCase):
235
+
236
+ def test_get_list_representation_all(self):
237
+ assert self.root.get_list_representation(key=lambda node: node.name) == ['root', ['child1'], ['child2', ['grandchild1'], ['grandchild2', ['greatgrandchild1']]], ['child3'], ['child4', ['grandchild3']]]
238
+
239
+ def test_get_list_representation_only_root(self):
240
+ a = A(name='root')
241
+ assert a.get_list_representation(key=lambda node: node.name) == ['root']
242
+
243
+ def test_create_tree_from_list(self):
244
+ tree = A.create_tree_from_list(self.root.get_list_representation(key=lambda node: node.name), 'name')
245
+ assert tree.get_list_representation(key=lambda node: node.name) == self.root.get_list_representation(key=lambda node: node.name)
246
+
247
+ def test_create_tree_from_list_only_root(self):
248
+ tree = A.create_tree_from_list(self.root.get_list_representation(key=lambda node: node.name), 'name')
249
+ assert tree.get_list_representation(key=lambda node: node.name) == self.root.get_list_representation(key=lambda node: node.name)
250
+
251
+ def test_create_tree_from_list_with_name_and_value(self):
252
+ def _copy_node(node, current_value):
253
+ copied = C(name=node.name, value=current_value)
254
+ current_value += 1
255
+ for child in node.get_children():
256
+ copied.add_child(_copy_node(child, current_value=current_value))
257
+ return copied
258
+
259
+ copied_c = _copy_node(self.root, 0)
260
+ representation = copied_c.get_list_representation(key=lambda node: [node.name, node.value])
261
+ assert representation == [['root', 0], [['child1', 1]], [['child2', 1], [['grandchild1', 2]], [['grandchild2', 2], [['greatgrandchild1', 3]]]], [['child3', 1]], [['child4', 1], [['grandchild3', 2]]]]
262
+ tree = C.create_tree_from_list(representation, ['name', 'value'])
263
+ assert tree.get_list_representation(key=lambda node: [node.name, node.value]) == copied_c.get_list_representation(key=lambda node: [node.name, node.value])
264
+
209
265
 
210
266
  class TestNodeReturnValue(TestCase):
211
267
 
@@ -1,6 +1,8 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from typing import Optional, Callable, Iterator, TypeVar, Any, Generic, cast, Union
3
3
 
4
+ from verysimpletree.util import make_list
5
+
4
6
 
5
7
  class TreeException(Exception):
6
8
  pass
@@ -41,7 +43,7 @@ class Tree(ABC, Generic[T]):
41
43
 
42
44
  def _raw_traverse(self: T) -> Iterator[T]:
43
45
  yield self
44
- for child in self.get_children():
46
+ for child in self._children:
45
47
  for node in child._raw_traverse():
46
48
  yield node
47
49
 
@@ -74,7 +76,7 @@ class Tree(ABC, Generic[T]):
74
76
  def is_first_child(self) -> bool:
75
77
  if self.is_root:
76
78
  return True
77
- if cast(T, self.up).get_children()[0] == self:
79
+ if cast(T, self.up)._children[0] == self:
78
80
  return True
79
81
  return False
80
82
 
@@ -90,7 +92,7 @@ class Tree(ABC, Generic[T]):
90
92
  """
91
93
  if self.is_root:
92
94
  return True
93
- if cast(T, self.up).get_children()[-1] == self:
95
+ if cast(T, self.up)._children[-1] == self:
94
96
  return True
95
97
  return False
96
98
 
@@ -122,8 +124,8 @@ class Tree(ABC, Generic[T]):
122
124
  :return: next sibling. ``None`` if this is the last current child of the parent.
123
125
  :rtype: :obj:`~tree.tree.Tree`
124
126
  """
125
- if self.up and self != self.up.get_children()[-1]:
126
- return cast(T, self.up.get_children()[self.up.get_children().index(self) + 1])
127
+ if self.up and self != self.up._children[-1]:
128
+ return cast(T, self.up._children[self.up._children.index(self) + 1])
127
129
  else:
128
130
  return None
129
131
 
@@ -135,8 +137,8 @@ class Tree(ABC, Generic[T]):
135
137
  :return: previous sibling. ``None`` if this is the first child of the parent.
136
138
  :rtype: :obj:`~tree.tree.Tree`
137
139
  """
138
- if self.up and self != self.up.get_children()[0]:
139
- return cast(T, self.up.get_children()[self.up.get_children().index(self) - 1])
140
+ if self.up and self != self.up._children[0]:
141
+ return cast(T, self.up._children[self.up._children.index(self) - 1])
140
142
  else:
141
143
  return None
142
144
 
@@ -167,7 +169,22 @@ class Tree(ABC, Generic[T]):
167
169
  if self._is_leaf is True:
168
170
  self._is_leaf = False
169
171
  return child
170
-
172
+
173
+ # typing with T and Generic[T] etc. seems to be faulty. Return value of _create_node is Tree[T].
174
+ @classmethod
175
+ def create_tree_from_list(cls, tree_list_representation: list[list[Any]], represented_attribute_names: list[str]) -> T:
176
+ represented_attribute_names = make_list(represented_attribute_names)
177
+ def _create_node(represented_values: list[Any]) -> T:
178
+ if len(represented_values) != len(represented_attribute_names):
179
+ raise ValueError(f'create_tree_from_list: represented_attribute_names must be of length {len(represented_values)}.')
180
+ root_kwargs = {attr:val for attr, val in zip(represented_attribute_names, represented_values)}
181
+ return cast(T, cls(**root_kwargs))
182
+ node = _create_node(make_list(tree_list_representation[0]))
183
+ for child_list_representation in tree_list_representation [1:]:
184
+ child = cls.create_tree_from_list(child_list_representation, represented_attribute_names)
185
+ node.add_child(child)
186
+ return node
187
+
171
188
  def get_children(self: T) -> list[T]:
172
189
  """
173
190
  :obj:`~tree.tree.Tree` method
@@ -183,7 +200,7 @@ class Tree(ABC, Generic[T]):
183
200
  :return: list of added children of type.d
184
201
  :rtype: list[:obj:`~tree.tree.Tree`]
185
202
  """
186
- return [cast(T, ch) for ch in self.get_children() if isinstance(ch, type_)]
203
+ return [cast(T, ch) for ch in self._children if isinstance(ch, type_)]
187
204
 
188
205
  def get_distance(self, reference: Optional[T] = None) -> int:
189
206
  """
@@ -233,14 +250,14 @@ class Tree(ABC, Generic[T]):
233
250
  if level == 0:
234
251
  output = [self]
235
252
  elif level == 1:
236
- output = self.get_children()
253
+ output = self._children
237
254
  else:
238
255
  output = []
239
256
  for child in self.get_layer(level - 1):
240
257
  if child.is_leaf:
241
258
  output.append(child)
242
259
  else:
243
- output.extend(child.get_children())
260
+ output.extend(child._children)
244
261
 
245
262
  if key is None:
246
263
  return output
@@ -262,7 +279,7 @@ class Tree(ABC, Generic[T]):
262
279
  """
263
280
  output: list[Union[Any, list[Any]]] = []
264
281
  child: T
265
- for child in self.get_children():
282
+ for child in self._children:
266
283
  if not child.is_leaf:
267
284
  output.append(child.get_leaves(key=key))
268
285
  else:
@@ -333,9 +350,9 @@ class Tree(ABC, Generic[T]):
333
350
  if parent is None:
334
351
  return '0'
335
352
  elif self.get_level() == 1:
336
- return str(parent.get_children().index(self) + 1)
353
+ return str(parent._children.index(self) + 1)
337
354
  else:
338
- return f"{parent.get_position_in_tree()}.{parent.get_children().index(self) + 1}"
355
+ return f"{parent.get_position_in_tree()}.{parent._children.index(self) + 1}"
339
356
 
340
357
  def get_reversed_path_to_root(self) -> list[T]:
341
358
  """
@@ -406,6 +423,12 @@ class Tree(ABC, Generic[T]):
406
423
  if key:
407
424
  tree_representation.key = cast(Callable[[Tree[Any]], Any], key)
408
425
  return tree_representation.get_representation()
426
+
427
+ def get_list_representation(self, key: Callable[["Tree[T]"], Any]) -> list[list[Any]]:
428
+ result: list[list[Any]] = [key(self)]
429
+ for child in self._children:
430
+ result.append(child.get_list_representation(key=key))
431
+ return result
409
432
 
410
433
  def get_number_of_layers(self) -> int:
411
434
  """
@@ -453,10 +476,10 @@ class Tree(ABC, Generic[T]):
453
476
  :param child:
454
477
  :return: None
455
478
  """
456
- if child not in self.get_children():
479
+ if child not in self._children:
457
480
  raise ChildNotFoundError
458
481
  child._parent = None
459
- self.get_children().remove(child)
482
+ self._children.remove(child)
460
483
  self._reset_iterators()
461
484
 
462
485
  def remove_children(self) -> None:
@@ -467,7 +490,7 @@ class Tree(ABC, Generic[T]):
467
490
 
468
491
  :return: None
469
492
  """
470
- for child in self.get_children()[:]:
493
+ for child in self._children[:]:
471
494
  parent = child.get_parent()
472
495
  if parent is not None:
473
496
  parent.remove(child)
@@ -482,16 +505,16 @@ class Tree(ABC, Generic[T]):
482
505
  :return: None
483
506
  """
484
507
  if hasattr(old, '__call__'):
485
- list_of_olds = [ch for ch in self.get_children() if old(ch)]
508
+ list_of_olds = [ch for ch in self._children if old(ch)]
486
509
  else:
487
- list_of_olds = [ch for ch in self.get_children() if ch == old]
510
+ list_of_olds = [ch for ch in self._children if ch == old]
488
511
  if not list_of_olds:
489
512
  raise ValueError(f"{old} not in list.")
490
513
  self._check_child_to_be_added(new)
491
- old_index = self.get_children().index(list_of_olds[index])
492
- old_child = self.get_children()[old_index]
493
- self.get_children().remove(old_child)
494
- self.get_children().insert(old_index, new)
514
+ old_index = self._children.index(list_of_olds[index])
515
+ old_child = self._children[old_index]
516
+ self._children.remove(old_child)
517
+ self._children.insert(old_index, new)
495
518
  old_child._parent = None
496
519
  self._reset_iterators()
497
520
  new._parent = self
@@ -0,0 +1,12 @@
1
+ from typing import Any
2
+
3
+
4
+ def make_list(input: Any) -> list[Any]:
5
+ if isinstance(input, list):
6
+ return input
7
+ if isinstance(input, str):
8
+ return [input]
9
+ try:
10
+ return list(input)
11
+ except TypeError:
12
+ return [input]
File without changes