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

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 Callable 

9 

10from phml.nodes import Element, Node 

11 

12Test = list | str | dict | Callable[[Node], bool] 

13 

14 

15def check( 

16 node: Node, 

17 _test: Test, 

18 strict: bool = True, 

19) -> bool: 

20 """Test if a node passes the given test(s). 

21 

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. 

30 

31 If the `parent` arg is passed so should the `index` arg. 

32 

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. 

37 

38 Returns: 

39 True if all tests pass. 

40 """ 

41 

42 if isinstance(_test, str): 

43 return isinstance(node, Element) and node.tag == _test 

44 

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 ) 

63 

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 ) 

70 

71 return bool( 

72 any(isinstance(cond, Test) and check(node, cond) for cond in _test), 

73 ) 

74 

75 if isinstance(_test, Callable): 

76 # If callable return result of collable after passing node, index, and parent 

77 return _test(node) 

78 

79 raise TypeError(f"Invalid test condition: {_test}")