Clean up tag rendering

This commit is contained in:
Nikhil Rao 2022-11-18 19:59:36 -08:00
parent 3c2a34a2b4
commit 67058b66a4
10 changed files with 67 additions and 50 deletions

View File

@ -131,20 +131,6 @@ EVENT_FN = join(
).format ).format
def format_event_declaration(fn: Callable) -> str:
"""Format an event declaration.
Args:
fn: The function to declare.
Returns:
The compiled event declaration.
"""
name = utils.format_event_fn(fn=fn)
event = utils.to_snake_case(fn.__qualname__)
return f"const {name} = Event('{event}')"
# Effects. # Effects.
ROUTER = constants.ROUTER ROUTER = constants.ROUTER
RESULT = constants.RESULT RESULT = constants.RESULT

View File

@ -137,6 +137,9 @@ class Component(Base, ABC):
Returns: Returns:
The event chain. The event chain.
Raises:
ValueError: If the value is not a valid event chain.
""" """
arg = self.get_controlled_value() arg = self.get_controlled_value()

View File

@ -1,12 +1,9 @@
"""A code component.""" """A code component."""
import json
from typing import Dict from typing import Dict
from pynecone import utils
from pynecone.components.component import Component from pynecone.components.component import Component
from pynecone.components.libs.chakra import ChakraComponent from pynecone.components.libs.chakra import ChakraComponent
from pynecone.components.tags import Tag
from pynecone.var import Var from pynecone.var import Var

View File

@ -65,7 +65,8 @@ class IterTag(Tag):
assert len(args) == 2 assert len(args) == 2
component = render_fn(arg, index) component = render_fn(arg, index)
if component.key is None: if component.key is None:
component.key = utils.wrap(str(index), "{", check_first=False) component.key = index
# component.key = utils.wrap(str(index), "{", check_first=False)
return component return component
def __str__(self) -> str: def __str__(self) -> str:

View File

@ -57,29 +57,19 @@ class Tag(Base):
Returns: Returns:
The formatted prop to display within a tag. The formatted prop to display within a tag.
""" """
def format_fn(value):
args = ",".join([":".join((name, val)) for name, val in value.args])
return f"E(\"{utils.to_snake_case(value.handler.fn.__qualname__)}\", {utils.wrap(args, '{')})"
# Handle var props. # Handle var props.
if isinstance(prop, Var): if isinstance(prop, Var):
if not prop.is_local or prop.is_string: if not prop.is_local or prop.is_string:
return str(prop) return str(prop)
if issubclass(prop.type_, str): if issubclass(prop.type_, str):
prop = json.dumps(prop.full_name) return json.dumps(prop.full_name)
prop = re.sub('"{', "", prop)
prop = re.sub('}"', "", prop)
prop = re.sub('"`', '{"', prop)
prop = re.sub('`"', '"}', prop)
return prop
prop = prop.full_name prop = prop.full_name
# Handle events. # Handle event props.
elif isinstance(prop, EventChain): elif isinstance(prop, EventChain):
local_args = ",".join(prop.events[0].local_args) local_args = ",".join(prop.events[0].local_args)
fns = ",".join([format_fn(event) for event in prop.events]) events = ",".join([utils.format_event(event) for event in prop.events])
prop = f"({local_args}) => Event([{fns}])" prop = f"({local_args}) => Event([{events}])"
# Handle other types. # Handle other types.
elif isinstance(prop, str): elif isinstance(prop, str):
@ -93,19 +83,18 @@ class Tag(Base):
# For dictionaries, convert any properties to strings. # For dictionaries, convert any properties to strings.
else: else:
if isinstance(prop, dict): if isinstance(prop, dict):
prop = json.dumps( # Convert any var keys to strings.
{ prop = {
key: str(val) if isinstance(val, Var) else val key: str(val) if isinstance(val, Var) else val
for key, val in prop.items() for key, val in prop.items()
} }
)
else:
prop = json.dumps(prop)
# Dump the prop as JSON.
prop = json.dumps(prop)
# This substitution is necessary to unwrap var values.
prop = re.sub('"{', "", prop) prop = re.sub('"{', "", prop)
prop = re.sub('}"', "", prop) prop = re.sub('}"', "", prop)
prop = re.sub('"`', '{"', prop)
prop = re.sub('`"', '"}', prop)
# Wrap the variable in braces. # Wrap the variable in braces.
assert isinstance(prop, str), "The prop must be a string." assert isinstance(prop, str), "The prop must be a string."

View File

@ -1,8 +1,10 @@
"""Table components.""" """Table components."""
from typing import List
from pynecone import utils from pynecone import utils
from pynecone.components.component import Component from pynecone.components.component import Component
from pynecone.var import Var from pynecone.var import BaseVar, Var
class Markdown(Component): class Markdown(Component):
@ -55,7 +57,7 @@ class Markdown(Component):
"\n", " " "\n", " "
), ),
}, },
remark_plugins="{{[remarkMath, remarkGfm]}}", remark_plugins=BaseVar(name="[remarkMath, remarkGfm]", type_=List[str]),
rehype_plugins="{{[rehypeKatex]}}", rehype_plugins=BaseVar(name="[rehypeKatex]", type_=List[str]),
src="", src="",
) )

View File

@ -177,6 +177,9 @@ class State(Base, ABC):
Returns: Returns:
The class substate. The class substate.
Raises:
ValueError: If the substate is not found.
""" """
if len(path) == 0: if len(path) == 0:
return cls return cls
@ -198,6 +201,9 @@ class State(Base, ABC):
Returns: Returns:
The class var. The class var.
Raises:
ValueError: If the path is invalid.
""" """
path, name = path[:-1], path[-1] path, name = path[:-1], path[-1]
substate = cls.get_class_substate(tuple(path)) substate = cls.get_class_substate(tuple(path))
@ -247,6 +253,9 @@ class State(Base, ABC):
Returns: Returns:
The attribute. The attribute.
Raises:
Exception: If the attribute is not found.
""" """
# If it is an inherited var, return from the parent state. # If it is an inherited var, return from the parent state.
if name != "inherited_vars" and name in self.inherited_vars: if name != "inherited_vars" and name in self.inherited_vars:
@ -300,6 +309,9 @@ class State(Base, ABC):
Returns: Returns:
The substate. The substate.
Raises:
ValueError: If the substate is not found.
""" """
if len(path) == 0: if len(path) == 0:
return self return self

View File

@ -441,6 +441,9 @@ def get_close_char(open: str, close: Optional[str] = None) -> str:
Returns: Returns:
The close character. The close character.
Raises:
ValueError: If the open character is not a valid brace.
""" """
if close is not None: if close is not None:
return close return close
@ -591,7 +594,20 @@ def format_event_fn(fn: Callable) -> str:
if isinstance(fn, EventHandler): if isinstance(fn, EventHandler):
fn = fn.fn fn = fn.fn
return fn.__qualname__.replace(".", "_") return to_snake_case(fn.__qualname__)
def format_event(event_spec: EventSpec) -> str:
"""Format an event.
Args:
event_spec: The event to format.
Returns:
The compiled event.
"""
args = ",".join([":".join((name, val)) for name, val in event_spec.args])
return f"E(\"{format_event_fn(event_spec.handler.fn)}\", {wrap(args, '{')})"
USED_VARIABLES = set() USED_VARIABLES = set()
@ -633,7 +649,7 @@ def is_dataframe(value: Type) -> bool:
return value.__name__ == "DataFrame" return value.__name__ == "DataFrame"
def format_state(value: Dict) -> Dict: def format_state(value: Any) -> Dict:
"""Recursively format values in the given state. """Recursively format values in the given state.
Args: Args:
@ -724,6 +740,9 @@ def call_event_fn(fn: Callable, arg: Var) -> List[EventSpec]:
Returns: Returns:
The event specs from calling the function. The event specs from calling the function.
Raises:
ValueError: If the lambda has an invalid signature.
""" """
args = inspect.getfullargspec(fn).args args = inspect.getfullargspec(fn).args
if len(args) == 0: if len(args) == 0:
@ -764,6 +783,8 @@ def fix_events(events: Optional[List[Event]], token: str) -> List[Event]:
Returns: Returns:
The fixed events. The fixed events.
""" """
from pynecone.event import Event, EventHandler, EventSpec
# If the event handler returns nothing, return an empty list. # If the event handler returns nothing, return an empty list.
if events is None: if events is None:
return [] return []
@ -786,7 +807,7 @@ def fix_events(events: Optional[List[Event]], token: str) -> List[Event]:
if isinstance(e, EventHandler): if isinstance(e, EventHandler):
e = e() e = e()
assert isinstance(e, EventSpec), f"Unexpected event type, {type(e)}." assert isinstance(e, EventSpec), f"Unexpected event type, {type(e)}."
name = to_snake_case(e.handler.fn.__qualname__) name = format_event_fn(e.handler.fn)
payload = dict(e.args) payload = dict(e.args)
# Create an event and append it to the list. # Create an event and append it to the list.

View File

@ -126,7 +126,7 @@ class Var(ABC):
out = utils.format_string(out) out = utils.format_string(out)
return out return out
def __getitem__(self, i) -> Var: def __getitem__(self, i: Any) -> Var:
"""Index into a var. """Index into a var.
Args: Args:
@ -134,6 +134,9 @@ class Var(ABC):
Returns: Returns:
The indexed var. The indexed var.
Raises:
TypeError: If the var is not indexable.
""" """
# The type of the indexed var. # The type of the indexed var.
type_ = str type_ = str
@ -174,6 +177,9 @@ class Var(ABC):
Returns: Returns:
The var attribute. The var attribute.
Raises:
Exception: If the attribute is not found.
""" """
try: try:
return super().__getattribute__(name) return super().__getattribute__(name)

View File

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "pynecone-io" name = "pynecone-io"
version = "0.1.0" version = "0.1.2"
description = "" description = ""
authors = [ authors = [
"Nikhil Rao <nikhil@pynecone.io>", "Nikhil Rao <nikhil@pynecone.io>",