Clean up cond vars (#536)
This commit is contained in:
parent
adf5b7fb1b
commit
47eebe0ea5
@ -10,7 +10,7 @@ from .components.component import custom_component as component
|
|||||||
from .components.graphing.victory import data
|
from .components.graphing.victory import data
|
||||||
from .config import Config
|
from .config import Config
|
||||||
from .constants import Env, Transports
|
from .constants import Env, Transports
|
||||||
from .event import EventChain, console_log, redirect, window_alert
|
from .event import EVENT_ARG, EventChain, console_log, redirect, window_alert
|
||||||
from .middleware import Middleware
|
from .middleware import Middleware
|
||||||
from .model import Model, session
|
from .model import Model, session
|
||||||
from .route import route
|
from .route import route
|
||||||
|
@ -106,11 +106,12 @@ def cond(condition: Any, c1: Any, c2: Any = None):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The conditional component.
|
The conditional component.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the arguments are invalid.
|
||||||
"""
|
"""
|
||||||
# Import here to avoid circular imports.
|
# Import here to avoid circular imports.
|
||||||
from pynecone.var import Var
|
from pynecone.var import BaseVar, Var
|
||||||
|
|
||||||
from .tags.tag import PropCond
|
|
||||||
|
|
||||||
# Convert the condition to a Var.
|
# Convert the condition to a Var.
|
||||||
cond_var = Var.create(condition)
|
cond_var = Var.create(condition)
|
||||||
@ -123,6 +124,20 @@ def cond(condition: Any, c1: Any, c2: Any = None):
|
|||||||
), "Both arguments must be components."
|
), "Both arguments must be components."
|
||||||
return Cond.create(cond_var, c1, c2)
|
return Cond.create(cond_var, c1, c2)
|
||||||
|
|
||||||
# Otherwise, create a PropCond.
|
# Otherwise, create a conditionl Var.
|
||||||
assert not isinstance(c2, Component), "Both arguments must be props."
|
# Check that the second argument is valid.
|
||||||
return PropCond.create(cond_var, c1, c2)
|
if isinstance(c2, Component):
|
||||||
|
raise ValueError("Both arguments must be props.")
|
||||||
|
if c2 is None:
|
||||||
|
raise ValueError("For conditional vars, the second argument must be set.")
|
||||||
|
|
||||||
|
# Create the conditional var.
|
||||||
|
return BaseVar(
|
||||||
|
name=utils.format_cond(
|
||||||
|
cond=cond_var.full_name,
|
||||||
|
true_value=c1,
|
||||||
|
false_value=c2,
|
||||||
|
is_prop=True,
|
||||||
|
),
|
||||||
|
type_=c1.type_ if isinstance(c1, BaseVar) else type(c1),
|
||||||
|
)
|
||||||
|
@ -60,7 +60,6 @@ class Input(ChakraComponent):
|
|||||||
"on_focus": EVENT_ARG.target.value,
|
"on_focus": EVENT_ARG.target.value,
|
||||||
"on_blur": EVENT_ARG.target.value,
|
"on_blur": EVENT_ARG.target.value,
|
||||||
"on_key_down": EVENT_ARG.key,
|
"on_key_down": EVENT_ARG.key,
|
||||||
"on_key_press": EVENT_ARG.key,
|
|
||||||
"on_key_up": EVENT_ARG.key,
|
"on_key_up": EVENT_ARG.key,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,9 @@ class Slider(ChakraComponent):
|
|||||||
# State var to bind the the input.
|
# State var to bind the the input.
|
||||||
value: Var[int]
|
value: Var[int]
|
||||||
|
|
||||||
|
# The color scheme.
|
||||||
|
color_scheme: Var[str]
|
||||||
|
|
||||||
# The placeholder text.
|
# The placeholder text.
|
||||||
default_value: Var[int]
|
default_value: Var[int]
|
||||||
|
|
||||||
|
@ -54,6 +54,5 @@ class TextArea(ChakraComponent):
|
|||||||
"on_focus": EVENT_ARG.target.value,
|
"on_focus": EVENT_ARG.target.value,
|
||||||
"on_blur": EVENT_ARG.target.value,
|
"on_blur": EVENT_ARG.target.value,
|
||||||
"on_key_down": EVENT_ARG.key,
|
"on_key_down": EVENT_ARG.key,
|
||||||
"on_key_press": EVENT_ARG.key,
|
|
||||||
"on_key_up": EVENT_ARG.key,
|
"on_key_up": EVENT_ARG.key,
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ class Tag(Base):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def format_prop(
|
def format_prop(
|
||||||
prop: Union[Var, EventChain, ComponentStyle, PropCond, str],
|
prop: Union[Var, EventChain, ComponentStyle, str],
|
||||||
) -> Union[int, float, str]:
|
) -> Union[int, float, str]:
|
||||||
"""Format a prop.
|
"""Format a prop.
|
||||||
|
|
||||||
@ -71,10 +71,6 @@ class Tag(Base):
|
|||||||
events = ",".join([utils.format_event(event) for event in prop.events])
|
events = ",".join([utils.format_event(event) for event in prop.events])
|
||||||
prop = f"({local_args}) => Event([{events}])"
|
prop = f"({local_args}) => Event([{events}])"
|
||||||
|
|
||||||
# Handle conditional props.
|
|
||||||
elif isinstance(prop, PropCond):
|
|
||||||
return str(prop)
|
|
||||||
|
|
||||||
# Handle other types.
|
# Handle other types.
|
||||||
elif isinstance(prop, str):
|
elif isinstance(prop, str):
|
||||||
if utils.is_wrapped(prop, "{"):
|
if utils.is_wrapped(prop, "{"):
|
||||||
@ -89,7 +85,7 @@ class Tag(Base):
|
|||||||
if isinstance(prop, dict):
|
if isinstance(prop, dict):
|
||||||
# Convert any var keys to strings.
|
# Convert any var keys to strings.
|
||||||
prop = {
|
prop = {
|
||||||
key: str(val) if isinstance(val, (Var, PropCond)) else val
|
key: str(val) if isinstance(val, Var) else val
|
||||||
for key, val in prop.items()
|
for key, val in prop.items()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,54 +184,3 @@ class Tag(Base):
|
|||||||
Whether the prop is valid.
|
Whether the prop is valid.
|
||||||
"""
|
"""
|
||||||
return prop is not None and not (isinstance(prop, dict) and len(prop) == 0)
|
return prop is not None and not (isinstance(prop, dict) and len(prop) == 0)
|
||||||
|
|
||||||
|
|
||||||
class PropCond(Base):
|
|
||||||
"""A conditional prop."""
|
|
||||||
|
|
||||||
# The condition to determine which prop to render.
|
|
||||||
cond: Var[Any]
|
|
||||||
|
|
||||||
# The prop to render if the condition is true.
|
|
||||||
prop1: Any
|
|
||||||
|
|
||||||
# The prop to render if the condition is false.
|
|
||||||
prop2: Any
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def create(cls, cond: Var, prop1: Any, prop2: Any):
|
|
||||||
"""Create a conditional Prop.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
cond: The cond to determine which prop to render.
|
|
||||||
prop1: The prop value to render if the cond is true.
|
|
||||||
prop2: The prop value to render if the cond is false.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The conditional Prop.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
ValueError: If the condition or prop values are not set.
|
|
||||||
"""
|
|
||||||
if cond is None:
|
|
||||||
raise ValueError("The condition must be set.")
|
|
||||||
if prop1 is None or prop2 is None:
|
|
||||||
raise ValueError("Both prop values must be set.")
|
|
||||||
return cls(
|
|
||||||
cond=cond,
|
|
||||||
prop1=prop1,
|
|
||||||
prop2=prop2,
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
"""Render the prop as a React string.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The React code to render the prop.
|
|
||||||
"""
|
|
||||||
return utils.format_cond(
|
|
||||||
cond=self.cond.full_name,
|
|
||||||
true_value=self.prop1,
|
|
||||||
false_value=self.prop2,
|
|
||||||
is_prop=True,
|
|
||||||
)
|
|
||||||
|
@ -24,11 +24,11 @@ def route(
|
|||||||
Note: the decorated functions still need to be imported.
|
Note: the decorated functions still need to be imported.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
route: The route to reach the page. Defaults to None.
|
route: The route to reach the page.
|
||||||
title: The title of the page. Defaults to None.
|
title: The title of the page.
|
||||||
image: The favicon of the page. Defaults to None.
|
image: The favicon of the page.
|
||||||
description: The description of the page. Defaults to None.
|
description: The description of the page
|
||||||
on_load: The event handler called when the page load. Defaults to None.
|
on_load: The event handler called when the page load.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The decorated function.
|
The decorated function.
|
||||||
|
@ -1060,14 +1060,14 @@ def format_cond(
|
|||||||
Returns:
|
Returns:
|
||||||
The formatted conditional expression.
|
The formatted conditional expression.
|
||||||
"""
|
"""
|
||||||
|
# Import here to avoid circular imports.
|
||||||
|
from pynecone.var import Var
|
||||||
|
|
||||||
if is_prop:
|
if is_prop:
|
||||||
if isinstance(true_value, str):
|
prop1 = Var.create(true_value, is_string=type(true_value) == str)
|
||||||
true_value = wrap(true_value, "'")
|
prop2 = Var.create(false_value, is_string=type(false_value) == str)
|
||||||
if isinstance(false_value, str):
|
assert prop1 is not None and prop2 is not None, "Invalid prop values"
|
||||||
false_value = wrap(false_value, "'")
|
expr = f"{cond} ? {prop1} : {prop2}".replace("{", "").replace("}", "")
|
||||||
expr = f"{cond} ? {true_value} : {false_value}".replace("{", "").replace(
|
|
||||||
"}", ""
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
expr = f"{cond} ? {true_value} : {false_value}"
|
expr = f"{cond} ? {true_value} : {false_value}"
|
||||||
|
|
||||||
|
@ -876,7 +876,7 @@ class PCDict(dict):
|
|||||||
self._reassign_field()
|
self._reassign_field()
|
||||||
|
|
||||||
def setdefault(self, *args, **kwargs):
|
def setdefault(self, *args, **kwargs):
|
||||||
"""set default.
|
"""Return value of key if or set default.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args: The args passed.
|
args: The args passed.
|
||||||
@ -901,7 +901,7 @@ class PCDict(dict):
|
|||||||
self._reassign_field()
|
self._reassign_field()
|
||||||
|
|
||||||
def update(self, *args, **kwargs):
|
def update(self, *args, **kwargs):
|
||||||
"""update dict.
|
"""Update the dict with another dict.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args: The args passed.
|
args: The args passed.
|
||||||
@ -911,7 +911,7 @@ class PCDict(dict):
|
|||||||
self._reassign_field()
|
self._reassign_field()
|
||||||
|
|
||||||
def __setitem__(self, *args, **kwargs):
|
def __setitem__(self, *args, **kwargs):
|
||||||
"""set item.
|
"""Set an item in the dict.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args: The args passed.
|
args: The args passed.
|
||||||
@ -921,7 +921,7 @@ class PCDict(dict):
|
|||||||
self._reassign_field() if hasattr(self, "_reassign_field") else None
|
self._reassign_field() if hasattr(self, "_reassign_field") else None
|
||||||
|
|
||||||
def __delitem__(self, *args, **kwargs):
|
def __delitem__(self, *args, **kwargs):
|
||||||
"""delete item.
|
"""Delete an item in the dict.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args: The args passed.
|
args: The args passed.
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import json
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@ -6,8 +7,8 @@ import pynecone as pc
|
|||||||
from pynecone.components import cond
|
from pynecone.components import cond
|
||||||
from pynecone.components.layout.cond import Cond
|
from pynecone.components.layout.cond import Cond
|
||||||
from pynecone.components.layout.fragment import Fragment
|
from pynecone.components.layout.fragment import Fragment
|
||||||
from pynecone.components.tags.tag import PropCond
|
|
||||||
from pynecone.components.typography.text import Text
|
from pynecone.components.typography.text import Text
|
||||||
|
from pynecone.var import Var
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@ -68,10 +69,10 @@ def test_prop_cond(c1: Any, c2: Any):
|
|||||||
c2,
|
c2,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert isinstance(prop_cond, PropCond)
|
assert isinstance(prop_cond, Var)
|
||||||
assert prop_cond.prop1 == c1
|
c1 = json.dumps(c1).replace('"', "`")
|
||||||
assert prop_cond.prop2 == c2
|
c2 = json.dumps(c2).replace('"', "`")
|
||||||
assert prop_cond.cond == True # noqa
|
assert str(prop_cond) == f"{{true ? {c1} : {c2}}}"
|
||||||
|
|
||||||
|
|
||||||
def test_cond_no_else():
|
def test_cond_no_else():
|
||||||
|
@ -3,7 +3,6 @@ from typing import Dict
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from pynecone.components.tags import CondTag, Tag
|
from pynecone.components.tags import CondTag, Tag
|
||||||
from pynecone.components.tags.tag import PropCond
|
|
||||||
from pynecone.event import EventChain, EventHandler, EventSpec
|
from pynecone.event import EventChain, EventHandler, EventSpec
|
||||||
from pynecone.var import BaseVar, Var
|
from pynecone.var import BaseVar, Var
|
||||||
|
|
||||||
@ -40,14 +39,6 @@ def mock_event(arg):
|
|||||||
),
|
),
|
||||||
'{(e) => Event([E("mock_event", {arg:e.target.value})])}',
|
'{(e) => Event([E("mock_event", {arg:e.target.value})])}',
|
||||||
),
|
),
|
||||||
(
|
|
||||||
PropCond.create(
|
|
||||||
cond=BaseVar(name="random_var", type_=str),
|
|
||||||
prop1="true_value",
|
|
||||||
prop2="false_value",
|
|
||||||
),
|
|
||||||
"{random_var ? 'true_value' : 'false_value'}",
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_format_value(prop: Var, formatted: str):
|
def test_format_value(prop: Var, formatted: str):
|
||||||
|
@ -19,7 +19,7 @@ def windows_platform() -> Generator:
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def list_mutation_state():
|
def list_mutation_state():
|
||||||
"""A fixture to create a state with list mutation features.
|
"""Create a state with list mutation features.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A state with list mutation features.
|
A state with list mutation features.
|
||||||
@ -82,7 +82,7 @@ def list_mutation_state():
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def dict_mutation_state():
|
def dict_mutation_state():
|
||||||
"""A fixture to create a state with dict mutation features.
|
"""Create a state with dict mutation features.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A state with dict mutation features.
|
A state with dict mutation features.
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
from typing import Any
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from pynecone.components.tags.tag import PropCond
|
|
||||||
from pynecone.utils import wrap
|
|
||||||
from pynecone.var import BaseVar
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"prop1,prop2",
|
|
||||||
[
|
|
||||||
(1, 3),
|
|
||||||
(1, "text"),
|
|
||||||
("text1", "text2"),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_validate_propcond(prop1: Any, prop2: Any):
|
|
||||||
"""Test the creation of conditional props.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
prop1: truth condition value
|
|
||||||
prop2: false condition value
|
|
||||||
"""
|
|
||||||
prop_cond = PropCond.create(
|
|
||||||
cond=BaseVar(name="cond_state.value", type_=str), prop1=prop1, prop2=prop2
|
|
||||||
)
|
|
||||||
|
|
||||||
expected_prop1 = wrap(prop1, "'") if isinstance(prop1, str) else prop1
|
|
||||||
expected_prop2 = wrap(prop2, "'") if isinstance(prop2, str) else prop2
|
|
||||||
|
|
||||||
assert str(prop_cond) == (
|
|
||||||
"{cond_state.value ? " f"{expected_prop1} : " f"{expected_prop2}" "}"
|
|
||||||
)
|
|
Loading…
Reference in New Issue
Block a user