1
+ import re
1
2
import ast
2
3
from contextlib import contextmanager
3
4
from typing import Any , Iterator , List , Tuple
4
5
5
6
7
+ _COMPONENT_DECORATOR_NAME_PATTERN = re .compile ("^(idom.(\w+\.)*)?component$" )
8
+
9
+
6
10
@contextmanager
7
11
def set_current (obj : Any , ** attrs : Any ) -> Iterator [None ]:
8
12
old_attrs = {k : getattr (obj , f"_current_{ k } " ) for k in attrs }
@@ -28,17 +32,25 @@ def is_hook_def(node: ast.FunctionDef) -> bool:
28
32
29
33
30
34
def is_component_def (node : ast .FunctionDef ) -> bool :
31
- return any (
32
- is_idom_component_decorator (decorator ) for decorator in node .decorator_list
33
- )
35
+ return any (map (_is_component_decorator , node .decorator_list ))
34
36
35
37
36
- def is_idom_component_decorator (node : Any ) -> bool :
37
- return getattr (node , "id" , None ) == "component" or (
38
- getattr (getattr (node , "value" , None ), "id" , None ) == "idom"
39
- and getattr (node , "attr" , None ) == "component"
38
+ def is_hook_function_name (name : str ) -> bool :
39
+ return name .lstrip ("_" ).startswith ("use_" )
40
+
41
+
42
+ def _is_component_decorator (node : ast .AST ) -> bool :
43
+ return (
44
+ _COMPONENT_DECORATOR_NAME_PATTERN .match (
45
+ "." .join (reversed (list (_get_dotted_name (node ))))
46
+ )
47
+ is not None
40
48
)
41
49
42
50
43
- def is_hook_function_name (name : str ) -> bool :
44
- return name .lstrip ("_" ).startswith ("use_" )
51
+ def _get_dotted_name (node : ast .AST ) -> Iterator [str ]:
52
+ while isinstance (node , ast .Attribute ):
53
+ yield node .attr
54
+ node = node .value
55
+ if isinstance (node , ast .Name ):
56
+ yield node .id
0 commit comments