phml.utils.validate.test
Logic that allows nodes to be tested against a series of conditions.
1"""phml.utils.validate.test 2 3Logic that allows nodes to be tested against a series of conditions. 4""" 5 6from __future__ import annotations 7 8from typing import TYPE_CHECKING, Callable, Optional 9 10from phml.nodes import Element 11 12if TYPE_CHECKING: 13 from phml.nodes import All_Nodes, Root 14 15Test = None | str | list | dict | Callable 16 17 18def test( 19 node: All_Nodes, 20 _test: Test, 21 index: Optional[int] = None, 22 parent: Optional[Root | Element] = None, 23) -> bool: 24 """Test if a node passes the given test(s). 25 26 Test Types: 27 - `None`: Just checks that the node is a valid node. 28 - `str`: Checks that the test value is == the `node.type`. 29 - `dict`: Checks all items are valid attributes on the node. 30 and that the values are strictly equal. 31 - `Callable`: Passes the given function the node and it's index, if provided, 32 and checks if the callable returned true. 33 - `list[Test]`: Apply all the rules above for each Test in the list. 34 35 If the `parent` arg is passed so should the `index` arg. 36 37 Args: 38 node (All_Nodes): Node to test. Can be any phml node. 39 test (Test): Test to apply to the node. See previous section 40 for more info. 41 index (Optional[int], optional): Index in the parent where the 42 node exists. Defaults to None. 43 parent (Optional[Root | Element], optional): The nodes parent. Defaults to None. 44 45 Returns: 46 True if all tests pass. 47 """ 48 49 if parent is not None: 50 # If parent is given then index has to be also. 51 # Validate index is correct in parent.children 52 if index is None or parent.children[index] != node: 53 return False 54 55 if isinstance(_test, str): 56 # If string then validate that the type is the same 57 return hasattr(node, "type") and node.type == _test 58 59 if isinstance(_test, dict): 60 # If dict validate all items with properties are the same 61 # Either in attributes or in 62 return bool( 63 isinstance(node, Element) 64 and all( 65 (hasattr(node, key) and value == getattr(node, key)) 66 or ( 67 hasattr(node, "properties") 68 and key in node.properties 69 and value == node.properties[key] 70 ) 71 for key, value in _test.items() 72 ) 73 ) 74 75 if isinstance(_test, list): 76 # If list then recursively apply tests 77 return bool( 78 all(isinstance(cond, Test) and test(node, cond, index, parent) for cond in _test) 79 ) 80 81 if isinstance(_test, Callable): 82 # If callable return result of collable after passing node, index, and parent 83 return _test(node, index, node.parent) 84 85 raise Exception("Invalid test condition")
def
test( node: phml.nodes.root.Root | phml.nodes.element.Element | phml.nodes.text.Text | phml.nodes.comment.Comment | phml.nodes.doctype.DocType | phml.nodes.parent.Parent | phml.nodes.node.Node | phml.nodes.literal.Literal, _test: Union[NoneType, str, list, dict, Callable], index: Optional[int] = None, parent: Union[phml.nodes.element.Element, phml.nodes.root.Root, NoneType] = None) -> bool:
19def test( 20 node: All_Nodes, 21 _test: Test, 22 index: Optional[int] = None, 23 parent: Optional[Root | Element] = None, 24) -> bool: 25 """Test if a node passes the given test(s). 26 27 Test Types: 28 - `None`: Just checks that the node is a valid node. 29 - `str`: Checks that the test value is == the `node.type`. 30 - `dict`: Checks all items are valid attributes on the node. 31 and that the values are strictly equal. 32 - `Callable`: Passes the given function the node and it's index, if provided, 33 and checks if the callable returned true. 34 - `list[Test]`: Apply all the rules above for each Test in the list. 35 36 If the `parent` arg is passed so should the `index` arg. 37 38 Args: 39 node (All_Nodes): Node to test. Can be any phml node. 40 test (Test): Test to apply to the node. See previous section 41 for more info. 42 index (Optional[int], optional): Index in the parent where the 43 node exists. Defaults to None. 44 parent (Optional[Root | Element], optional): The nodes parent. Defaults to None. 45 46 Returns: 47 True if all tests pass. 48 """ 49 50 if parent is not None: 51 # If parent is given then index has to be also. 52 # Validate index is correct in parent.children 53 if index is None or parent.children[index] != node: 54 return False 55 56 if isinstance(_test, str): 57 # If string then validate that the type is the same 58 return hasattr(node, "type") and node.type == _test 59 60 if isinstance(_test, dict): 61 # If dict validate all items with properties are the same 62 # Either in attributes or in 63 return bool( 64 isinstance(node, Element) 65 and all( 66 (hasattr(node, key) and value == getattr(node, key)) 67 or ( 68 hasattr(node, "properties") 69 and key in node.properties 70 and value == node.properties[key] 71 ) 72 for key, value in _test.items() 73 ) 74 ) 75 76 if isinstance(_test, list): 77 # If list then recursively apply tests 78 return bool( 79 all(isinstance(cond, Test) and test(node, cond, index, parent) for cond in _test) 80 ) 81 82 if isinstance(_test, Callable): 83 # If callable return result of collable after passing node, index, and parent 84 return _test(node, index, node.parent) 85 86 raise Exception("Invalid test condition")
Test if a node passes the given test(s).
Test Types
None
: Just checks that the node is a valid node.str
: Checks that the test value is == thenode.type
.dict
: Checks all items are valid attributes on the node. and that the values are strictly equal.Callable
: Passes the given function the node and it's index, if provided, and checks if the callable returned true.list[Test]
: Apply all the rules above for each Test in the list.
If the parent
arg is passed so should the index
arg.
Args
- node (All_Nodes): Node to test. Can be any phml node.
- test (Test): Test to apply to the node. See previous section
- for more info.
- index (Optional[int], optional): Index in the parent where the
- node exists. Defaults to None.
- parent (Optional[Root | Element], optional): The nodes parent. Defaults to None.
Returns
True if all tests pass.