Coverage for phml\utilities\validate\check.py: 100%
16 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-04-06 15:56 -0500
« prev ^ index » next coverage.py v6.5.0, created at 2023-04-06 15:56 -0500
1"""phml.utilities.validate.test
3Logic that allows nodes to be tested against a series of conditions.
4"""
6from __future__ import annotations
8from typing import Callable
10from phml.nodes import Element, Node
12Test = list | str | dict | Callable[[Node], bool]
15def check(
16 node: Node,
17 _test: Test,
18 strict: bool = True,
19) -> bool:
20 """Test if a node passes the given test(s).
22 Test Types:
23 - `None`: Just checks that the node is a valid node.
24 - `str`: Checks that the node is an element and the condition == node.tag.
25 - `dict`: Checks all items are valid attributes on the node.
26 and that the values are strictly equal.
27 - `Callable`: Passes the given function the node and it's index, if provided,
28 and checks if the callable returned true.
29 - `list[Test]`: Apply all the rules above for each Test in the list.
31 If the `parent` arg is passed so should the `index` arg.
33 Args:
34 node (Node): Node to test. Can be any phml node.
35 test (Test): Test to apply to the node. See previous section
36 for more info.
38 Returns:
39 True if all tests pass.
40 """
42 if isinstance(_test, str):
43 return isinstance(node, Element) and node.tag == _test
45 if isinstance(_test, dict):
46 # If dict validate all items with properties are the same
47 # Either in attributes or in
48 if strict:
49 return bool(
50 isinstance(node, Element)
51 and all(
52 (key in node and (value is True or value == node[key]))
53 for key, value in _test.items()
54 ),
55 )
56 return bool(
57 isinstance(node, Element)
58 and any(
59 (key in node and (value is True or value == node[key]))
60 for key, value in _test.items()
61 ),
62 )
64 if isinstance(_test, list):
65 # If list then recursively apply tests
66 if strict:
67 return bool(
68 all(isinstance(cond, Test) and check(node, cond) for cond in _test),
69 )
71 return bool(
72 any(isinstance(cond, Test) and check(node, cond) for cond in _test),
73 )
75 if isinstance(_test, Callable):
76 # If callable return result of collable after passing node, index, and parent
77 return _test(node)
79 raise TypeError(f"Invalid test condition: {_test}")