فهرست منبع

don't treat name with - differently (#5291)

* don't treat name with - differently

* ok i got things very wrong

* improve performance

* simplify even more code

* fix the test
Khaleel Al-Adhami 4 روز پیش
والد
کامیت
e81bab7e59
4فایلهای تغییر یافته به همراه56 افزوده شده و 91 حذف شده
  1. 26 60
      reflex/components/component.py
  2. 12 6
      reflex/constants/compiler.py
  3. 4 11
      reflex/utils/format.py
  4. 14 14
      tests/units/components/test_component.py

+ 26 - 60
reflex/components/component.py

@@ -58,7 +58,7 @@ from reflex.vars.base import (
 )
 )
 from reflex.vars.function import ArgsFunctionOperation, FunctionStringVar, FunctionVar
 from reflex.vars.function import ArgsFunctionOperation, FunctionStringVar, FunctionVar
 from reflex.vars.number import ternary_operation
 from reflex.vars.number import ternary_operation
-from reflex.vars.object import LiteralObjectVar, ObjectVar
+from reflex.vars.object import ObjectVar
 from reflex.vars.sequence import LiteralArrayVar, LiteralStringVar, StringVar
 from reflex.vars.sequence import LiteralArrayVar, LiteralStringVar, StringVar
 
 
 
 
@@ -500,36 +500,16 @@ class Component(BaseComponent, ABC):
             else:
             else:
                 continue
                 continue
 
 
-            def determine_key(value: Any):
-                # Try to create a var from the value
-                key = value if isinstance(value, Var) else LiteralVar.create(value)
-
-                # Check that the var type is not None.
-                if key is None:
-                    raise TypeError
-
-                return key
-
             # Check whether the key is a component prop.
             # Check whether the key is a component prop.
             if is_var:
             if is_var:
                 try:
                 try:
-                    kwargs[key] = determine_key(value)
+                    kwargs[key] = LiteralVar.create(value)
 
 
+                    # Get the passed type and the var type.
+                    passed_type = kwargs[key]._var_type
                     expected_type = types.get_args(
                     expected_type = types.get_args(
                         types.get_field_type(type(self), key)
                         types.get_field_type(type(self), key)
                     )[0]
                     )[0]
-
-                    # validate literal fields.
-                    types.validate_literal(
-                        key, value, expected_type, type(self).__name__
-                    )
-                    # Get the passed type and the var type.
-                    passed_type = kwargs[key]._var_type
-                    expected_type = (
-                        type(expected_type.__args__[0])
-                        if types.is_literal(expected_type)
-                        else expected_type
-                    )
                 except TypeError:
                 except TypeError:
                     # If it is not a valid var, check the base types.
                     # If it is not a valid var, check the base types.
                     passed_type = type(value)
                     passed_type = type(value)
@@ -561,15 +541,19 @@ class Component(BaseComponent, ABC):
             kwargs.pop(key, None)
             kwargs.pop(key, None)
 
 
         # Place data_ and aria_ attributes into custom_attrs
         # Place data_ and aria_ attributes into custom_attrs
-        special_attributes = tuple(
+        special_attributes = [
             key
             key
             for key in kwargs
             for key in kwargs
             if key not in fields and SpecialAttributes.is_special(key)
             if key not in fields and SpecialAttributes.is_special(key)
-        )
+        ]
         if special_attributes:
         if special_attributes:
             custom_attrs = kwargs.setdefault("custom_attrs", {})
             custom_attrs = kwargs.setdefault("custom_attrs", {})
-            for key in special_attributes:
-                custom_attrs[format.to_kebab_case(key)] = kwargs.pop(key)
+            custom_attrs.update(
+                {
+                    format.to_kebab_case(key): kwargs.pop(key)
+                    for key in special_attributes
+                }
+            )
 
 
         # Add style props to the component.
         # Add style props to the component.
         style = kwargs.get("style", {})
         style = kwargs.get("style", {})
@@ -805,6 +789,18 @@ class Component(BaseComponent, ABC):
             for component in _components_from(value)
             for component in _components_from(value)
         ]
         ]
 
 
+    @classmethod
+    def _validate_children(cls, children: tuple | list):
+        from reflex.utils.exceptions import ChildrenTypeError
+
+        for child in children:
+            if isinstance(child, (tuple, list)):
+                cls._validate_children(child)
+
+            # Make sure the child is a valid type.
+            if isinstance(child, dict) or not isinstance(child, ComponentChildTypes):
+                raise ChildrenTypeError(component=cls.__name__, child=child)
+
     @classmethod
     @classmethod
     def create(cls: type[T], *children, **props) -> T:
     def create(cls: type[T], *children, **props) -> T:
         """Create the component.
         """Create the component.
@@ -819,24 +815,12 @@ class Component(BaseComponent, ABC):
         # Import here to avoid circular imports.
         # Import here to avoid circular imports.
         from reflex.components.base.bare import Bare
         from reflex.components.base.bare import Bare
         from reflex.components.base.fragment import Fragment
         from reflex.components.base.fragment import Fragment
-        from reflex.utils.exceptions import ChildrenTypeError
 
 
         # Filter out None props
         # Filter out None props
         props = {key: value for key, value in props.items() if value is not None}
         props = {key: value for key, value in props.items() if value is not None}
 
 
-        def validate_children(children: tuple | list):
-            for child in children:
-                if isinstance(child, (tuple, list)):
-                    validate_children(child)
-
-                # Make sure the child is a valid type.
-                if isinstance(child, dict) or not isinstance(
-                    child, ComponentChildTypes
-                ):
-                    raise ChildrenTypeError(component=cls.__name__, child=child)
-
         # Validate all the children.
         # Validate all the children.
-        validate_children(children)
+        cls._validate_children(children)
 
 
         children_normalized = [
         children_normalized = [
             (
             (
@@ -2577,25 +2561,7 @@ def render_dict_to_var(tag: dict | Component | str, imported_names: set[str]) ->
             else LiteralNoneVar.create(),
             else LiteralNoneVar.create(),
         )
         )
 
 
-    props = {}
-
-    special_props = []
-
-    for prop_str in tag["props"]:
-        if ":" not in prop_str:
-            special_props.append(Var(prop_str).to(ObjectVar))
-            continue
-        prop = prop_str.index(":")
-        key = prop_str[:prop]
-        value = prop_str[prop + 1 :]
-        props[key] = value
-
-    props = LiteralObjectVar.create(
-        {LiteralStringVar.create(k): Var(v) for k, v in props.items()}
-    )
-
-    for prop in special_props:
-        props = props.merge(prop)
+    props = Var("({" + ",".join(tag["props"]) + "})")
 
 
     contents = tag["contents"] if tag["contents"] else None
     contents = tag["contents"] if tag["contents"] else None
 
 

+ 12 - 6
reflex/constants/compiler.py

@@ -171,6 +171,12 @@ class MemoizationMode:
     recursive: bool = True
     recursive: bool = True
 
 
 
 
+DATA_UNDERSCORE = "data_"
+DATA_DASH = "data-"
+ARIA_UNDERSCORE = "aria_"
+ARIA_DASH = "aria-"
+
+
 class SpecialAttributes(enum.Enum):
 class SpecialAttributes(enum.Enum):
     """Special attributes for components.
     """Special attributes for components.
 
 
@@ -178,11 +184,6 @@ class SpecialAttributes(enum.Enum):
     to a style prop.
     to a style prop.
     """
     """
 
 
-    DATA_UNDERSCORE = "data_"
-    DATA_DASH = "data-"
-    ARIA_UNDERSCORE = "aria_"
-    ARIA_DASH = "aria-"
-
     @classmethod
     @classmethod
     def is_special(cls, attr: str) -> bool:
     def is_special(cls, attr: str) -> bool:
         """Check if the attribute is special.
         """Check if the attribute is special.
@@ -193,4 +194,9 @@ class SpecialAttributes(enum.Enum):
         Returns:
         Returns:
             True if the attribute is special.
             True if the attribute is special.
         """
         """
-        return any(attr.startswith(value.value) for value in cls)
+        return (
+            attr.startswith(DATA_UNDERSCORE)
+            or attr.startswith(DATA_DASH)
+            or attr.startswith(ARIA_UNDERSCORE)
+            or attr.startswith(ARIA_DASH)
+        )

+ 4 - 11
reflex/utils/format.py

@@ -436,19 +436,12 @@ def format_props(*single_props, **key_value_props) -> list[str]:
         The formatted props list.
         The formatted props list.
     """
     """
     # Format all the props.
     # Format all the props.
-    from reflex.vars.base import LiteralVar, Var
+    from reflex.vars import LiteralStringVar, LiteralVar, Var
 
 
     return [
     return [
-        ":".join(
-            [
-                str(name if "-" not in name else LiteralVar.create(name)),
-                str(
-                    format_prop(
-                        prop if isinstance(prop, Var) else LiteralVar.create(prop)
-                    )
-                ),
-            ]
-        )
+        (str(LiteralStringVar.create(name)) if "-" in name else name)
+        + ":"
+        + str(format_prop(prop if isinstance(prop, Var) else LiteralVar.create(prop)))
         for name, prop in sorted(key_value_props.items())
         for name, prop in sorted(key_value_props.items())
         if prop is not None
         if prop is not None
     ] + [(f"...{LiteralVar.create(prop)!s}") for prop in single_props]
     ] + [(f"...{LiteralVar.create(prop)!s}") for prop in single_props]

+ 14 - 14
tests/units/components/test_component.py

@@ -1221,10 +1221,10 @@ def test_stateful_banner():
     assert isinstance(stateful_component, StatefulComponent)
     assert isinstance(stateful_component, StatefulComponent)
 
 
 
 
-TEST_VAR = LiteralVar.create("test")._replace(
+TEST_VAR = LiteralVar.create("p")._replace(
     merge_var_data=VarData(
     merge_var_data=VarData(
         hooks={"useTest": None},
         hooks={"useTest": None},
-        imports={"test": [ImportVar(tag="test")]},
+        imports={"test": [ImportVar(tag="p")]},
         state="Test",
         state="Test",
     )
     )
 )
 )
@@ -1233,31 +1233,31 @@ STYLE_VAR = TEST_VAR._replace(_js_expr="style")
 EVENT_CHAIN_VAR = TEST_VAR.to(EventChain)
 EVENT_CHAIN_VAR = TEST_VAR.to(EventChain)
 ARG_VAR = Var(_js_expr="arg")
 ARG_VAR = Var(_js_expr="arg")
 
 
-TEST_VAR_DICT_OF_DICT = LiteralVar.create({"a": {"b": "test"}})._replace(
+TEST_VAR_DICT_OF_DICT = LiteralVar.create({"a": {"b": "p"}})._replace(
+    merge_var_data=TEST_VAR._var_data
+)
+FORMATTED_TEST_VAR_DICT_OF_DICT = LiteralVar.create({"a": {"b": "foopbar"}})._replace(
     merge_var_data=TEST_VAR._var_data
     merge_var_data=TEST_VAR._var_data
 )
 )
-FORMATTED_TEST_VAR_DICT_OF_DICT = LiteralVar.create(
-    {"a": {"b": "footestbar"}}
-)._replace(merge_var_data=TEST_VAR._var_data)
 
 
-TEST_VAR_LIST_OF_LIST = LiteralVar.create([["test"]])._replace(
+TEST_VAR_LIST_OF_LIST = LiteralVar.create([["p"]])._replace(
     merge_var_data=TEST_VAR._var_data
     merge_var_data=TEST_VAR._var_data
 )
 )
-FORMATTED_TEST_VAR_LIST_OF_LIST = LiteralVar.create([["footestbar"]])._replace(
+FORMATTED_TEST_VAR_LIST_OF_LIST = LiteralVar.create([["foopbar"]])._replace(
     merge_var_data=TEST_VAR._var_data
     merge_var_data=TEST_VAR._var_data
 )
 )
 
 
-TEST_VAR_LIST_OF_LIST_OF_LIST = LiteralVar.create([[["test"]]])._replace(
+TEST_VAR_LIST_OF_LIST_OF_LIST = LiteralVar.create([[["p"]]])._replace(
+    merge_var_data=TEST_VAR._var_data
+)
+FORMATTED_TEST_VAR_LIST_OF_LIST_OF_LIST = LiteralVar.create([[["foopbar"]]])._replace(
     merge_var_data=TEST_VAR._var_data
     merge_var_data=TEST_VAR._var_data
 )
 )
-FORMATTED_TEST_VAR_LIST_OF_LIST_OF_LIST = LiteralVar.create(
-    [[["footestbar"]]]
-)._replace(merge_var_data=TEST_VAR._var_data)
 
 
-TEST_VAR_LIST_OF_DICT = LiteralVar.create([{"a": "test"}])._replace(
+TEST_VAR_LIST_OF_DICT = LiteralVar.create([{"a": "p"}])._replace(
     merge_var_data=TEST_VAR._var_data
     merge_var_data=TEST_VAR._var_data
 )
 )
-FORMATTED_TEST_VAR_LIST_OF_DICT = LiteralVar.create([{"a": "footestbar"}])._replace(
+FORMATTED_TEST_VAR_LIST_OF_DICT = LiteralVar.create([{"a": "foopbar"}])._replace(
     merge_var_data=TEST_VAR._var_data
     merge_var_data=TEST_VAR._var_data
 )
 )