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