Add better error messages (#18)

This commit is contained in:
Nikhil Rao 2022-11-29 19:22:48 -08:00 committed by GitHub
parent f710fc1a82
commit f0355e7f39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 4 deletions

View File

@ -253,10 +253,22 @@ class Component(Base, ABC):
Returns:
The component.
Raises:
TypeError: If an invalid child is passed.
"""
# Import here to avoid circular imports.
from pynecone.components.base.bare import Bare
# Validate all the children.
for child in children:
if not utils._isinstance(child, ComponentChild):
raise TypeError(
"Children of Pynecone components must be other components, "
"state vars, or primitive Python types. "
f"Got child of type {type(child)}.",
)
children = [
Bare.create(contents=Var.create(child, is_string=True))
if not isinstance(child, Component)
@ -348,3 +360,4 @@ class Component(Base, ABC):
# Map from component to styling.
ComponentStyle = Dict[Union[str, Type[Component]], Any]
ComponentChild = Union[utils.PrimitiveType, Var, Component]

View File

@ -10,7 +10,7 @@ from typing import Any, Callable, ClassVar, Dict, List, Optional, Sequence, Set,
from pynecone import constants, utils
from pynecone.base import Base
from pynecone.event import Event, EventHandler, EventSpec, window_alert
from pynecone.event import Event, EventHandler, window_alert
from pynecone.var import BaseVar, ComputedVar, Var
Delta = Dict[str, Any]
@ -70,6 +70,9 @@ class State(Base, ABC):
Args:
**kwargs: The kwargs to pass to the pydantic init_subclass method.
Raises:
TypeError: If the class has a var with an invalid type.
"""
super().__init_subclass__(**kwargs)
@ -103,6 +106,13 @@ class State(Base, ABC):
# Setup the base vars at the class level.
for prop in cls.base_vars.values():
if not utils._issubclass(prop.type_, utils.StateVar):
raise TypeError(
"State vars must be primitive Python types, "
"Plotly figures, Pandas dataframes, "
"or subclasses of pc.Base. "
f'Found var "{prop.name}" with type {prop.type_}.'
)
cls._set_var(prop)
cls._create_setter(prop)
cls._set_default_value(prop)

View File

@ -32,6 +32,8 @@ from plotly.io import to_json
from rich.console import Console
from pynecone import constants
from pynecone.base import Base
if TYPE_CHECKING:
from pynecone.components.component import ImportDict
@ -49,6 +51,10 @@ console = Console()
# Union of generic types.
GenericType = Union[Type, _GenericAlias]
# Valid state var types.
PrimitiveType = Union[int, float, bool, str, list, dict, tuple]
StateVar = Union[PrimitiveType, Base, None]
def get_args(alias: _GenericAlias) -> Tuple[Type, ...]:
"""Get the arguments of a type alias.
@ -703,17 +709,33 @@ def format_state(value: Any) -> Dict:
Returns:
The formatted state.
Raises:
TypeError: If the given value is not a valid state.
"""
if isinstance(value, go.Figure):
# Convert plotly figures to JSON.
if _isinstance(value, go.Figure):
return json.loads(to_json(value))["data"]
# Convert pandas dataframes to JSON.
if is_dataframe(type(value)):
return {
"columns": value.columns.tolist(),
"data": value.values.tolist(),
}
if isinstance(value, dict):
# Handle dicts.
if _isinstance(value, dict):
return {k: format_state(v) for k, v in value.items()}
# Make sure the value is JSON serializable.
if not _isinstance(value, StateVar):
raise TypeError(
"State vars must be primitive Python types, "
"or subclasses of pc.Base. "
f"Got var of type {type(value)}."
)
return value

View File

@ -30,7 +30,7 @@ plotly = "^5.10.0"
pydantic = "1.10.2"
requests = "^2.28.1"
sqlmodel = "^0.0.8"
typer = "^0.7.0"
typer = "0.4.2"
uvicorn = "^0.20.0"
rich = "^12.6.0"
redis = "^4.3.5"