1+ import re
12import ast
23from contextlib import contextmanager
34from typing import Any , Iterator , List , Tuple
45
56
7+ _COMPONENT_DECORATOR_NAME_PATTERN = re .compile ("^(idom.(\w+\.)*)?component$" )
8+
9+
610@contextmanager
711def set_current (obj : Any , ** attrs : Any ) -> Iterator [None ]:
812 old_attrs = {k : getattr (obj , f"_current_{ k } " ) for k in attrs }
@@ -28,17 +32,25 @@ def is_hook_def(node: ast.FunctionDef) -> bool:
2832
2933
3034def 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 ))
3436
3537
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
4048 )
4149
4250
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