Coverage for phml\compiler\steps\base.py: 100%

5 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-04-12 14:26 -0500

1from functools import wraps 

2from typing import Any, Callable 

3 

4from phml.components import ComponentManager 

5from phml.nodes import AST, Parent 

6 

7__all__ = ["scoped_step", "setup_step", "post_step"] 

8 

9 

10def scoped_step( 

11 func: Callable[[Parent, ComponentManager, dict[str, Any]], None] 

12): # pragma: no cover 

13 """Wrapper for compilation steps. This wraps a function that takes a parent node, 

14 the current context, and component manager. The function is expected to mutate the children nodes. 

15 It is also expected that the function is not recursive and only mutates the direct children of the node 

16 passed in. 

17 

18 Args: 

19 Node (Parent): The parent node that is the current scope 

20 components (ComponentManager): The manager instance for the components 

21 context (dict[str, Any]): Additional global context from parent objects 

22 

23 Note: 

24 There may be any combination of arguments, keyword only arguments, or catch alls with *arg and **kwarg. 

25 This wrapper will predictably and automatically pass the arguments that are specified. 

26 """ 

27 

28 @wraps(func) 

29 def inner( 

30 node: Parent, 

31 components: ComponentManager, 

32 context: dict[str, Any], 

33 ): 

34 if not isinstance(node, Parent): 

35 raise TypeError( 

36 f"Expected node to be a parent for step {func.__name__!r}." 

37 + "Maybe try putting the step into the scoped steps with add_step(<step>, 'scoped')" 

38 ) 

39 return func(node, components, context) 

40 

41 return inner 

42 

43 

44def setup_step( 

45 func: Callable[[AST, ComponentManager, dict[str, Any]], None] 

46): # pragma: no cover 

47 """Wrapper for setup compile processes. This wraps a function that takes an AST node, 

48 the current context, and the component manager. The funciton is expected to mutate the AST recursively 

49 

50 Args: 

51 Node (Parent): The parent node that is the current scope 

52 components (ComponentManager): The manager instance for the components 

53 context (dict[str, Any]): Additional global context from parent objects 

54 

55 Note: 

56 There may be any combination of arguments, keyword only arguments, or catch alls with *arg and **kwarg. 

57 This wrapper will predictably and automatically pass the arguments that are specified. 

58 """ 

59 

60 @wraps(func) 

61 def inner( 

62 node: AST, 

63 components: ComponentManager, 

64 context: dict[str, Any], 

65 ): 

66 if not isinstance(node, AST): 

67 raise TypeError( 

68 f"Expected node to be an AST for step {func.__name__!r}." 

69 + "Maybe try putting the step into the setup steps with add_step(<step>, 'setup')" 

70 ) 

71 return func(node, components, context) 

72 

73 return inner 

74 

75 

76def post_step( 

77 func: Callable[[AST, ComponentManager, dict[str, Any]], None] 

78): # pragma: no cover 

79 """Wrapper for post compile processes. This wraps a function that takes an AST node, 

80 the current context, and the component manager. The funciton is expected to mutate the AST recursively 

81 

82 Args: 

83 Node (Parent): The parent node that is the current scope 

84 components (ComponentManager): The manager instance for the components 

85 context (dict[str, Any]): Additional global context from parent objects 

86 

87 Note: 

88 There may be any combination of arguments, keyword only arguments, or catch alls with *arg and **kwarg. 

89 This wrapper will predictably and automatically pass the arguments that are specified. 

90 """ 

91 

92 @wraps(func) 

93 def inner( 

94 node: AST, 

95 components: ComponentManager, 

96 context: dict[str, Any], 

97 ): 

98 if not isinstance(node, AST): 

99 raise TypeError( 

100 f"Expected node to be an AST for step {func.__name__!r}." 

101 + "Maybe try putting the step into the post steps with add_step(<step>, 'post')" 

102 ) 

103 return func(node, components, context) 

104 

105 return inner