Add state name into compiler
This commit is contained in:
parent
03d0aca366
commit
705557b484
@ -56,9 +56,7 @@ def format_import(lib: str, default: str = "", rest: Optional[Set[str]] = None)
|
||||
DOCUMENT_ROOT = join(
|
||||
[
|
||||
"{imports}",
|
||||
"",
|
||||
"export default function Document() {{",
|
||||
"",
|
||||
"return (",
|
||||
"{document}",
|
||||
")",
|
||||
@ -74,17 +72,11 @@ COMPONENT = join(
|
||||
[
|
||||
"{imports}",
|
||||
"{custom_code}",
|
||||
"",
|
||||
"{constants}",
|
||||
"",
|
||||
"export default function Component() {{",
|
||||
"",
|
||||
"{state}",
|
||||
"",
|
||||
"{events}",
|
||||
"",
|
||||
"{effects}",
|
||||
"",
|
||||
"return (",
|
||||
"{render}",
|
||||
")",
|
||||
@ -155,22 +147,28 @@ def format_event_declaration(fn: Callable) -> str:
|
||||
|
||||
|
||||
# Effects.
|
||||
ROUTER = constants.ROUTER
|
||||
RESULT = constants.RESULT
|
||||
PROCESSING = constants.PROCESSING
|
||||
STATE = constants.STATE
|
||||
EVENTS = constants.EVENTS
|
||||
SET_RESULT = format_state_setter(RESULT)
|
||||
USE_EFFECT = join(
|
||||
[
|
||||
"useEffect(() => {{",
|
||||
" const update = async () => {{",
|
||||
" if (result.state != null) {{",
|
||||
" setState({{",
|
||||
" ...result.state,",
|
||||
" events: [...state.events, ...result.events],",
|
||||
f" if ({RESULT}.{STATE} != null) {{{{",
|
||||
f" {{set_state}}({{{{",
|
||||
f" ...{RESULT}.{STATE},",
|
||||
f" events: [...{{state}}.{EVENTS}, ...{RESULT}.{EVENTS}],",
|
||||
" }})",
|
||||
" setResult({{",
|
||||
" ...result,",
|
||||
" state: null,",
|
||||
" processing: false,",
|
||||
f" {SET_RESULT}({{{{",
|
||||
f" ...{RESULT},",
|
||||
f" {{state}}: null,",
|
||||
f" {PROCESSING}: false,",
|
||||
" }})",
|
||||
" }}",
|
||||
f" await updateState({{state}}, {{result}}, {{set_result}}, {EVENT_ENDPOINT}, {constants.ROUTER})",
|
||||
f" await updateState({{state}}, {RESULT}, {SET_RESULT}, {EVENT_ENDPOINT}, {ROUTER})",
|
||||
" }}",
|
||||
" update()",
|
||||
"}})",
|
||||
|
@ -115,9 +115,9 @@ def compile_state(state: Type[State]) -> str:
|
||||
state=state.get_name(), initial_state=json.dumps(initial_state)
|
||||
)
|
||||
initial_result = {
|
||||
"state": None,
|
||||
"events": [],
|
||||
"processing": False,
|
||||
constants.STATE: None,
|
||||
constants.EVENTS: [],
|
||||
constants.PROCESSING: False,
|
||||
}
|
||||
result = templates.format_state(
|
||||
state="result",
|
||||
@ -151,11 +151,8 @@ def compile_effects(state: Type[State]) -> str:
|
||||
A string of the compiled effects for the component.
|
||||
"""
|
||||
state_name = state.get_name()
|
||||
result_name = "result"
|
||||
set_result = templates.format_state_setter(result_name)
|
||||
return templates.USE_EFFECT(
|
||||
state=state_name, result=result_name, set_result=set_result
|
||||
)
|
||||
set_state = templates.format_state_setter(state_name)
|
||||
return templates.USE_EFFECT(state=state_name, set_state=set_state)
|
||||
|
||||
|
||||
def compile_render(component: Component) -> str:
|
||||
|
@ -5,7 +5,7 @@ from __future__ import annotations
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
from typing import Any, Dict, Optional, Union
|
||||
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
|
||||
|
||||
from plotly.graph_objects import Figure
|
||||
from plotly.io import to_json
|
||||
@ -15,6 +15,9 @@ from pynecone.base import Base
|
||||
from pynecone.event import EventChain
|
||||
from pynecone.var import Var
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pynecone.components.component import ComponentStyle
|
||||
|
||||
|
||||
class Tag(Base):
|
||||
"""A React tag."""
|
||||
@ -43,87 +46,86 @@ class Tag(Base):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
def format_attr_value(
|
||||
value: Union[Var, EventChain, Dict[str, Var], str],
|
||||
def format_prop(
|
||||
prop: Union[Var, EventChain, ComponentStyle, str],
|
||||
) -> Union[int, float, str]:
|
||||
"""Format an attribute value.
|
||||
"""Format a prop.
|
||||
|
||||
Args:
|
||||
value: The value of the attribute
|
||||
prop: The prop to format.
|
||||
|
||||
Returns:
|
||||
The formatted value to display within the 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 attributes.
|
||||
if isinstance(value, Var):
|
||||
if not value.is_local or value.is_string:
|
||||
return str(value)
|
||||
if issubclass(value.type_, str):
|
||||
value = json.dumps(value.full_name)
|
||||
value = re.sub('"{', "", value)
|
||||
value = re.sub('}"', "", value)
|
||||
value = re.sub('"`', '{"', value)
|
||||
value = re.sub('`"', '"}', value)
|
||||
return value
|
||||
value = value.full_name
|
||||
# Handle var props.
|
||||
if isinstance(prop, Var):
|
||||
if not prop.is_local or prop.is_string:
|
||||
return str(prop)
|
||||
if issubclass(prop.type_, str):
|
||||
prop = 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
|
||||
|
||||
# Handle events.
|
||||
elif isinstance(value, EventChain):
|
||||
local_args = ",".join(value.events[0].local_args)
|
||||
fns = ",".join([format_fn(event) for event in value.events])
|
||||
value = f"({local_args}) => Event([{fns}])"
|
||||
elif isinstance(prop, EventChain):
|
||||
local_args = ",".join(prop.events[0].local_args)
|
||||
fns = ",".join([format_fn(event) for event in prop.events])
|
||||
prop = f"({local_args}) => Event([{fns}])"
|
||||
|
||||
# Handle other types.
|
||||
elif isinstance(value, str):
|
||||
if utils.is_wrapped(value, "{"):
|
||||
return value
|
||||
return json.dumps(value)
|
||||
elif isinstance(prop, str):
|
||||
if utils.is_wrapped(prop, "{"):
|
||||
return prop
|
||||
return json.dumps(prop)
|
||||
|
||||
elif isinstance(value, Figure):
|
||||
value = json.loads(to_json(value))["data"]
|
||||
elif isinstance(prop, Figure):
|
||||
prop = json.loads(to_json(prop))["data"]
|
||||
|
||||
# For dictionaries, convert any properties to strings.
|
||||
else:
|
||||
if isinstance(value, dict):
|
||||
value = json.dumps(
|
||||
if isinstance(prop, dict):
|
||||
prop = json.dumps(
|
||||
{
|
||||
key: str(val) if isinstance(val, Var) else val
|
||||
for key, val in value.items()
|
||||
for key, val in prop.items()
|
||||
}
|
||||
)
|
||||
else:
|
||||
value = json.dumps(value)
|
||||
prop = json.dumps(prop)
|
||||
|
||||
value = re.sub('"{', "", value)
|
||||
value = re.sub('}"', "", value)
|
||||
value = re.sub('"`', '{"', value)
|
||||
value = re.sub('`"', '"}', value)
|
||||
prop = re.sub('"{', "", prop)
|
||||
prop = re.sub('}"', "", prop)
|
||||
prop = re.sub('"`', '{"', prop)
|
||||
prop = re.sub('`"', '"}', prop)
|
||||
|
||||
# Wrap the variable in braces.
|
||||
assert isinstance(value, str), "The value must be a string."
|
||||
return utils.wrap(value, "{", check_first=False)
|
||||
assert isinstance(prop, str), "The prop must be a string."
|
||||
return utils.wrap(prop, "{", check_first=False)
|
||||
|
||||
def format_props(self) -> str:
|
||||
"""Format a dictionary of attributes.
|
||||
"""Format the tag's props.
|
||||
|
||||
Returns:
|
||||
The formatted attributes.
|
||||
The formatted props.
|
||||
"""
|
||||
# If there are no attributes, return an empty string.
|
||||
# If there are no props, return an empty string.
|
||||
if len(self.props) == 0:
|
||||
return ""
|
||||
|
||||
# Get the string representation of all the attributes joined.
|
||||
# We need a space at the beginning for formatting.
|
||||
# Format all the props.
|
||||
return os.linesep.join(
|
||||
f"{name}={self.format_attr_value(value)}"
|
||||
for name, value in self.props.items()
|
||||
if value is not None
|
||||
f"{name}={self.format_prop(prop)}"
|
||||
for name, prop in self.props.items()
|
||||
if prop is not None
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
@ -132,7 +134,7 @@ class Tag(Base):
|
||||
Returns:
|
||||
The React code to render the tag.
|
||||
"""
|
||||
# Get the tag attributes.
|
||||
# Get the tag props.
|
||||
props_str = self.format_props()
|
||||
if len(props_str) > 0:
|
||||
props_str = " " + props_str
|
||||
@ -149,33 +151,33 @@ class Tag(Base):
|
||||
return tag_str
|
||||
|
||||
def add_props(self, **kwargs: Optional[Any]) -> Tag:
|
||||
"""Add attributes to the tag.
|
||||
"""Add props to the tag.
|
||||
|
||||
Args:
|
||||
**kwargs: The attributes to add.
|
||||
**kwargs: The props to add.
|
||||
|
||||
Returns:
|
||||
The tag with the attributes added.
|
||||
The tag with the props added.
|
||||
"""
|
||||
self.props.update(
|
||||
{
|
||||
utils.to_camel_case(name): attr
|
||||
if utils._isinstance(attr, Union[EventChain, dict])
|
||||
else Var.create(attr)
|
||||
for name, attr in kwargs.items()
|
||||
if self.is_valid_attr(attr)
|
||||
utils.to_camel_case(name): prop
|
||||
if utils._isinstance(prop, Union[EventChain, dict])
|
||||
else Var.create(prop)
|
||||
for name, prop in kwargs.items()
|
||||
if self.is_valid_prop(prop)
|
||||
}
|
||||
)
|
||||
return self
|
||||
|
||||
def remove_props(self, *args: str) -> Tag:
|
||||
"""Remove attributes from the tag.
|
||||
"""Remove props from the tag.
|
||||
|
||||
Args:
|
||||
*args: The attributes to remove.
|
||||
*args: The props to remove.
|
||||
|
||||
Returns:
|
||||
The tag with the attributes removed.
|
||||
The tag with the props removed.
|
||||
"""
|
||||
for name in args:
|
||||
if name in self.props:
|
||||
@ -183,13 +185,13 @@ class Tag(Base):
|
||||
return self
|
||||
|
||||
@staticmethod
|
||||
def is_valid_attr(attr: Optional[Var]) -> bool:
|
||||
"""Check if the attr is valid.
|
||||
def is_valid_prop(prop: Optional[Var]) -> bool:
|
||||
"""Check if the prop is valid.
|
||||
|
||||
Args:
|
||||
attr: The value to check.
|
||||
prop: The prop to check.
|
||||
|
||||
Returns:
|
||||
Whether the value is valid.
|
||||
Whether the prop is valid.
|
||||
"""
|
||||
return attr is not None and not (isinstance(attr, dict) and len(attr) == 0)
|
||||
return prop is not None and not (isinstance(prop, dict) and len(prop) == 0)
|
||||
|
@ -70,6 +70,14 @@ APP_VAR = "app"
|
||||
API_VAR = "api"
|
||||
# The name of the router variable.
|
||||
ROUTER = "router"
|
||||
# The name of the variable to hold API results.
|
||||
RESULT = "result"
|
||||
# The name of the process variable.
|
||||
PROCESSING = "processing"
|
||||
# The name of the state variable.
|
||||
STATE = "state"
|
||||
# The name of the events variable.
|
||||
EVENTS = "events"
|
||||
# The name of the initial hydrate event.
|
||||
HYDRATE = "hydrate"
|
||||
# The name of the index page.
|
||||
|
Loading…
Reference in New Issue
Block a user