From 2008417bd7e1f40094efd00521f56e6f535ce8ed Mon Sep 17 00:00:00 2001 From: Nikhil Rao Date: Fri, 18 Nov 2022 13:04:16 -0800 Subject: [PATCH] Clean up tags. --- pynecone/components/base/link.py | 2 +- pynecone/components/component.py | 20 ++++++----- pynecone/components/layout/box.py | 2 +- pynecone/components/tags/tag.py | 39 +++++++++++----------- pynecone/components/typography/markdown.py | 2 +- tests/components/test_tag.py | 4 +-- 6 files changed, 35 insertions(+), 34 deletions(-) diff --git a/pynecone/components/base/link.py b/pynecone/components/base/link.py index 485b0e825..159af1946 100644 --- a/pynecone/components/base/link.py +++ b/pynecone/components/base/link.py @@ -15,7 +15,7 @@ class Link(Component): rel: Var[str] def _render(self) -> Tag: - return Tag(name="link").add_attrs( + return Tag(name="link").add_props( href=self.href, rel=self.rel, ) diff --git a/pynecone/components/component.py b/pynecone/components/component.py index ca31945a7..ed560eef2 100644 --- a/pynecone/components/component.py +++ b/pynecone/components/component.py @@ -30,7 +30,7 @@ class Component(Base, ABC): # The style of the component. style: Style = Style() - # A mapping of event chains to event triggers. + # A mapping from event triggers to event chains. event_triggers: Dict[str, EventChain] = {} # The library that the component is based on. @@ -114,10 +114,9 @@ class Component(Base, ABC): del kwargs[key] # Add style props to the component. - style = kwargs["style"] if "style" in kwargs else {} kwargs["style"] = Style( { - **style, + **kwargs.get("style", {}), **{attr: value for attr, value in kwargs.items() if attr not in fields}, } ) @@ -220,14 +219,17 @@ class Component(Base, ABC): Returns: The tag to render. """ - tag = Tag(name=self.tag).add_attrs( - **{attr: getattr(self, attr) for attr in self.get_props()} - ) + # Create the base tag. + tag = Tag(name=self.tag) + # Add component props to the tag. + props = {attr: getattr(self, attr) for attr in self.get_props()} + # Special case for props named `type_`. if hasattr(self, "type_"): - tag.add_attrs(type=getattr(self, "type_")) - return tag + props["type"] = getattr(self, "type_") + + return tag.add_props(**props) @classmethod def get_props(cls) -> Set[str]: @@ -297,7 +299,7 @@ class Component(Base, ABC): """ tag = self._render() return str( - tag.add_attrs(**self.event_triggers, key=self.key, sx=self.style).set( + tag.add_props(**self.event_triggers, key=self.key, sx=self.style).set( contents=utils.join( [str(tag.contents)] + [child.render() for child in self.children] ), diff --git a/pynecone/components/layout/box.py b/pynecone/components/layout/box.py index 00317c362..cf67b99b9 100644 --- a/pynecone/components/layout/box.py +++ b/pynecone/components/layout/box.py @@ -17,7 +17,7 @@ class Box(ChakraComponent): return ( super() ._render() - .add_attrs( + .add_props( **{ "as": self.element, } diff --git a/pynecone/components/tags/tag.py b/pynecone/components/tags/tag.py index 77a7ff0be..26c70993f 100644 --- a/pynecone/components/tags/tag.py +++ b/pynecone/components/tags/tag.py @@ -7,7 +7,6 @@ import os import re from typing import Any, Dict, Optional, Union -import pydantic from plotly.graph_objects import Figure from plotly.io import to_json @@ -23,8 +22,8 @@ class Tag(Base): # The name of the tag. name: str = "" - # The attributes of the tag. - attrs: Dict[str, Any] = {} + # The props of the tag. + props: Dict[str, Any] = {} # The inner contents of the tag. contents: str = "" @@ -36,10 +35,10 @@ class Tag(Base): *args: Args to initialize the tag. **kwargs: Kwargs to initialize the tag. """ - # Convert any attrs to properties. - if "attrs" in kwargs: - kwargs["attrs"] = { - name: Var.create(value) for name, value in kwargs["attrs"].items() + # Convert any props to vars. + if "props" in kwargs: + kwargs["props"] = { + name: Var.create(value) for name, value in kwargs["props"].items() } super().__init__(*args, **kwargs) @@ -109,21 +108,21 @@ class Tag(Base): assert isinstance(value, str), "The value must be a string." return utils.wrap(value, "{", check_first=False) - def format_attrs(self) -> str: + def format_props(self) -> str: """Format a dictionary of attributes. Returns: The formatted attributes. """ # If there are no attributes, return an empty string. - if len(self.attrs) == 0: + if len(self.props) == 0: return "" # Get the string representation of all the attributes joined. # We need a space at the beginning for formatting. return os.linesep.join( f"{name}={self.format_attr_value(value)}" - for name, value in self.attrs.items() + for name, value in self.props.items() if value is not None ) @@ -134,22 +133,22 @@ class Tag(Base): The React code to render the tag. """ # Get the tag attributes. - attrs_str = self.format_attrs() - if len(attrs_str) > 0: - attrs_str = " " + attrs_str + props_str = self.format_props() + if len(props_str) > 0: + props_str = " " + props_str if len(self.contents) == 0: # If there is no inner content, we don't need a closing tag. - tag_str = utils.wrap(f"{self.name}{attrs_str}/", "<") + tag_str = utils.wrap(f"{self.name}{props_str}/", "<") else: # Otherwise wrap it in opening and closing tags. - open = utils.wrap(f"{self.name}{attrs_str}", "<") + open = utils.wrap(f"{self.name}{props_str}", "<") close = utils.wrap(f"/{self.name}", "<") tag_str = utils.wrap(self.contents, open, close) return tag_str - def add_attrs(self, **kwargs: Optional[Any]) -> Tag: + def add_props(self, **kwargs: Optional[Any]) -> Tag: """Add attributes to the tag. Args: @@ -158,7 +157,7 @@ class Tag(Base): Returns: The tag with the attributes added. """ - self.attrs.update( + self.props.update( { utils.to_camel_case(name): attr if utils._isinstance(attr, Union[EventChain, dict]) @@ -169,7 +168,7 @@ class Tag(Base): ) return self - def remove_attrs(self, *args: str) -> Tag: + def remove_props(self, *args: str) -> Tag: """Remove attributes from the tag. Args: @@ -179,8 +178,8 @@ class Tag(Base): The tag with the attributes removed. """ for name in args: - if name in self.attrs: - del self.attrs[name] + if name in self.props: + del self.props[name] return self @staticmethod diff --git a/pynecone/components/typography/markdown.py b/pynecone/components/typography/markdown.py index 6a62922eb..701949f4e 100644 --- a/pynecone/components/typography/markdown.py +++ b/pynecone/components/typography/markdown.py @@ -28,7 +28,7 @@ class Markdown(Component): def _render(self): tag = super()._render() - return tag.add_attrs( + return tag.add_props( children=utils.wrap(str(self.src).strip(), "`"), components={ "h1": "{({node, ...props}) => }", diff --git a/tests/components/test_tag.py b/tests/components/test_tag.py index 1d18c2df0..200f721da 100644 --- a/tests/components/test_tag.py +++ b/tests/components/test_tag.py @@ -111,9 +111,9 @@ def test_is_valid_attr(attr: Var, valid: bool): assert Tag.is_valid_attr(attr) == valid -def test_add_attrs(): +def test_add_props(): """Test that the attributes are added.""" - tag = Tag().add_attrs(key="value", key2=42, invalid=None, invalid2={}) + tag = Tag().add_props(key="value", key2=42, invalid=None, invalid2={}) assert tag.attrs["key"] == Var.create("value") assert tag.attrs["key2"] == Var.create(42) assert "invalid" not in tag.attrs