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