phml.utils.locate.index

 1# pylint: disable=missing-module-docstring
 2from typing import Callable, Optional
 3
 4from phml.nodes import AST, Element, Root
 5from phml.utils.validate.test import Test
 6
 7
 8class Index:
 9    """Uses the given key or key generator and creates a mutable dict of key value pairs
10    that can be easily indexed.
11
12    Nodes that don't match the condition or don't have a valid key are not indexed.
13    """
14
15    indexed_tree: dict[str, list[Element]]
16    """The indexed collection of elements"""
17
18    def __init__(
19        self, key: str | Callable, start: AST | Root | Element, condition: Optional[Test] = None
20    ):
21        """
22        Args:
23            `key` (str | Callable): Str represents the property to use as an index. Callable
24            represents a function to call on each element to generate a key. The returned key
25            must be able to be converted to a string. If none then element is skipped.
26            `start` (AST | Root | Element): The root or node to start at while indexing
27            `test` (Test): The test to apply to each node. Only valid/passing nodes
28            will be indexed
29        """
30        from phml.utils import test, walk  # pylint: disable=import-outside-toplevel
31
32        self.indexed_tree = {}
33        self.key = key
34
35        for node in walk(start):
36            if isinstance(node, Element):
37                if condition is not None:
38                    if test(node, condition):
39                        self.add(node)
40                else:
41                    self.add(node)
42
43    def add(self, node: Element):
44        """Adds element to indexed collection if not already there."""
45
46        key = node.properties[self.key] if isinstance(self.key, str) else self.key(node)
47        if key not in self.indexed_tree:
48            self.indexed_tree[key] = [node]
49
50        if node not in self.indexed_tree[key]:
51            self.indexed_tree[key].append(node)
52
53    def remove(self, node: Element):
54        """Removes element from indexed collection if there."""
55
56        key = node.properties[self.key] if isinstance(self.key, str) else self.key(node)
57        if key in self.indexed_tree and node in self.indexed_tree[key]:
58            self.indexed_tree[key].remove(node)
59
60    def get(self, _key: str) -> Optional[list[Element]]:
61        """Get a specific index from the indexed tree."""
62        return self.indexed_tree.get(_key)
63
64    def map(self, modifier: Callable) -> list:
65        """Applies the passed modifier to each index.
66
67        Returns:
68            list of results generated by the modifier applied
69            to each index.
70        """
71        result = []
72        for value in self.indexed_tree.values():
73            result.extend([modifier(v) for v in value])
74        return result
class Index:
 9class Index:
10    """Uses the given key or key generator and creates a mutable dict of key value pairs
11    that can be easily indexed.
12
13    Nodes that don't match the condition or don't have a valid key are not indexed.
14    """
15
16    indexed_tree: dict[str, list[Element]]
17    """The indexed collection of elements"""
18
19    def __init__(
20        self, key: str | Callable, start: AST | Root | Element, condition: Optional[Test] = None
21    ):
22        """
23        Args:
24            `key` (str | Callable): Str represents the property to use as an index. Callable
25            represents a function to call on each element to generate a key. The returned key
26            must be able to be converted to a string. If none then element is skipped.
27            `start` (AST | Root | Element): The root or node to start at while indexing
28            `test` (Test): The test to apply to each node. Only valid/passing nodes
29            will be indexed
30        """
31        from phml.utils import test, walk  # pylint: disable=import-outside-toplevel
32
33        self.indexed_tree = {}
34        self.key = key
35
36        for node in walk(start):
37            if isinstance(node, Element):
38                if condition is not None:
39                    if test(node, condition):
40                        self.add(node)
41                else:
42                    self.add(node)
43
44    def add(self, node: Element):
45        """Adds element to indexed collection if not already there."""
46
47        key = node.properties[self.key] if isinstance(self.key, str) else self.key(node)
48        if key not in self.indexed_tree:
49            self.indexed_tree[key] = [node]
50
51        if node not in self.indexed_tree[key]:
52            self.indexed_tree[key].append(node)
53
54    def remove(self, node: Element):
55        """Removes element from indexed collection if there."""
56
57        key = node.properties[self.key] if isinstance(self.key, str) else self.key(node)
58        if key in self.indexed_tree and node in self.indexed_tree[key]:
59            self.indexed_tree[key].remove(node)
60
61    def get(self, _key: str) -> Optional[list[Element]]:
62        """Get a specific index from the indexed tree."""
63        return self.indexed_tree.get(_key)
64
65    def map(self, modifier: Callable) -> list:
66        """Applies the passed modifier to each index.
67
68        Returns:
69            list of results generated by the modifier applied
70            to each index.
71        """
72        result = []
73        for value in self.indexed_tree.values():
74            result.extend([modifier(v) for v in value])
75        return result

Uses the given key or key generator and creates a mutable dict of key value pairs that can be easily indexed.

Nodes that don't match the condition or don't have a valid key are not indexed.

Index( key: Union[str, Callable], start: phml.nodes.AST.AST | phml.nodes.root.Root | phml.nodes.element.Element, condition: Union[NoneType, str, list, dict, Callable] = None)
19    def __init__(
20        self, key: str | Callable, start: AST | Root | Element, condition: Optional[Test] = None
21    ):
22        """
23        Args:
24            `key` (str | Callable): Str represents the property to use as an index. Callable
25            represents a function to call on each element to generate a key. The returned key
26            must be able to be converted to a string. If none then element is skipped.
27            `start` (AST | Root | Element): The root or node to start at while indexing
28            `test` (Test): The test to apply to each node. Only valid/passing nodes
29            will be indexed
30        """
31        from phml.utils import test, walk  # pylint: disable=import-outside-toplevel
32
33        self.indexed_tree = {}
34        self.key = key
35
36        for node in walk(start):
37            if isinstance(node, Element):
38                if condition is not None:
39                    if test(node, condition):
40                        self.add(node)
41                else:
42                    self.add(node)
Args
  • key (str | Callable): Str represents the property to use as an index. Callable
  • represents a function to call on each element to generate a key. The returned key
  • must be able to be converted to a string. If none then element is skipped.
  • start (AST | Root | Element): The root or node to start at while indexing
  • test (Test): The test to apply to each node. Only valid/passing nodes
  • will be indexed
indexed_tree: dict[str, list[phml.nodes.element.Element]]

The indexed collection of elements

def add(self, node: phml.nodes.element.Element):
44    def add(self, node: Element):
45        """Adds element to indexed collection if not already there."""
46
47        key = node.properties[self.key] if isinstance(self.key, str) else self.key(node)
48        if key not in self.indexed_tree:
49            self.indexed_tree[key] = [node]
50
51        if node not in self.indexed_tree[key]:
52            self.indexed_tree[key].append(node)

Adds element to indexed collection if not already there.

def remove(self, node: phml.nodes.element.Element):
54    def remove(self, node: Element):
55        """Removes element from indexed collection if there."""
56
57        key = node.properties[self.key] if isinstance(self.key, str) else self.key(node)
58        if key in self.indexed_tree and node in self.indexed_tree[key]:
59            self.indexed_tree[key].remove(node)

Removes element from indexed collection if there.

def get(self, _key: str) -> Optional[list[phml.nodes.element.Element]]:
61    def get(self, _key: str) -> Optional[list[Element]]:
62        """Get a specific index from the indexed tree."""
63        return self.indexed_tree.get(_key)

Get a specific index from the indexed tree.

def map(self, modifier: Callable) -> list:
65    def map(self, modifier: Callable) -> list:
66        """Applies the passed modifier to each index.
67
68        Returns:
69            list of results generated by the modifier applied
70            to each index.
71        """
72        result = []
73        for value in self.indexed_tree.values():
74            result.extend([modifier(v) for v in value])
75        return result

Applies the passed modifier to each index.

Returns

list of results generated by the modifier applied to each index.