11import ast
2+ import re
23from contextlib import contextmanager
34from typing import Any , Iterator , List , Tuple
45
6+ _COMPONENT_DECORATOR_NAME_PATTERN = re .compile (r"^(idom.(\w+\.)*)?component$" )
7+
58
69@contextmanager
710def set_current (obj : Any , ** attrs : Any ) -> Iterator [None ]:
@@ -28,17 +31,25 @@ def is_hook_def(node: ast.FunctionDef) -> bool:
2831
2932
3033def is_component_def (node : ast .FunctionDef ) -> bool :
31- return any (
32- is_idom_component_decorator (decorator ) for decorator in node .decorator_list
33- )
34+ return any (map (_is_component_decorator , node .decorator_list ))
35+
36+
37+ def is_hook_function_name (name : str ) -> bool :
38+ return name .lstrip ("_" ).startswith ("use_" )
3439
3540
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"
41+ def _is_component_decorator (node : ast .AST ) -> bool :
42+ return (
43+ _COMPONENT_DECORATOR_NAME_PATTERN .match (
44+ "." .join (reversed (list (_get_dotted_name (node ))))
45+ )
46+ is not None
4047 )
4148
4249
43- def is_hook_function_name (name : str ) -> bool :
44- return name .lstrip ("_" ).startswith ("use_" )
50+ def _get_dotted_name (node : ast .AST ) -> Iterator [str ]:
51+ while isinstance (node , ast .Attribute ):
52+ yield node .attr
53+ node = node .value
54+ if isinstance (node , ast .Name ):
55+ yield node .id
0 commit comments