diff --git a/pynecone/compiler/templates.py b/pynecone/compiler/templates.py index 48a27a1ae..5cc4a384a 100644 --- a/pynecone/compiler/templates.py +++ b/pynecone/compiler/templates.py @@ -131,20 +131,6 @@ EVENT_FN = join( ).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. ROUTER = constants.ROUTER RESULT = constants.RESULT diff --git a/pynecone/components/component.py b/pynecone/components/component.py index ed6c0bd41..5b8959c2b 100644 --- a/pynecone/components/component.py +++ b/pynecone/components/component.py @@ -137,6 +137,9 @@ class Component(Base, ABC): Returns: The event chain. + + Raises: + ValueError: If the value is not a valid event chain. """ arg = self.get_controlled_value() diff --git a/pynecone/components/datadisplay/code.py b/pynecone/components/datadisplay/code.py index 8c4104ac2..fa6c2f888 100644 --- a/pynecone/components/datadisplay/code.py +++ b/pynecone/components/datadisplay/code.py @@ -1,12 +1,9 @@ """A code component.""" -import json from typing import Dict -from pynecone import utils from pynecone.components.component import Component from pynecone.components.libs.chakra import ChakraComponent -from pynecone.components.tags import Tag from pynecone.var import Var diff --git a/pynecone/components/tags/iter_tag.py b/pynecone/components/tags/iter_tag.py index f4da3e23a..d2887d445 100644 --- a/pynecone/components/tags/iter_tag.py +++ b/pynecone/components/tags/iter_tag.py @@ -65,7 +65,8 @@ class IterTag(Tag): assert len(args) == 2 component = render_fn(arg, index) 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 def __str__(self) -> str: diff --git a/pynecone/components/tags/tag.py b/pynecone/components/tags/tag.py index 1d4d4c47d..633a9997f 100644 --- a/pynecone/components/tags/tag.py +++ b/pynecone/components/tags/tag.py @@ -57,29 +57,19 @@ class Tag(Base): Returns: 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. 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 + return json.dumps(prop.full_name) prop = prop.full_name - # Handle events. + # Handle event props. 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}])" + events = ",".join([utils.format_event(event) for event in prop.events]) + prop = f"({local_args}) => Event([{events}])" # Handle other types. elif isinstance(prop, str): @@ -93,19 +83,18 @@ class Tag(Base): # For dictionaries, convert any properties to strings. else: if isinstance(prop, dict): - prop = json.dumps( - { - key: str(val) if isinstance(val, Var) else val - for key, val in prop.items() - } - ) - else: - prop = json.dumps(prop) + # Convert any var keys to strings. + prop = { + key: str(val) if isinstance(val, Var) else val + for key, val in prop.items() + } + # 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) # Wrap the variable in braces. assert isinstance(prop, str), "The prop must be a string." diff --git a/pynecone/components/typography/markdown.py b/pynecone/components/typography/markdown.py index 701949f4e..dbdf7582a 100644 --- a/pynecone/components/typography/markdown.py +++ b/pynecone/components/typography/markdown.py @@ -1,8 +1,10 @@ """Table components.""" +from typing import List + from pynecone import utils from pynecone.components.component import Component -from pynecone.var import Var +from pynecone.var import BaseVar, Var class Markdown(Component): @@ -55,7 +57,7 @@ class Markdown(Component): "\n", " " ), }, - remark_plugins="{{[remarkMath, remarkGfm]}}", - rehype_plugins="{{[rehypeKatex]}}", + remark_plugins=BaseVar(name="[remarkMath, remarkGfm]", type_=List[str]), + rehype_plugins=BaseVar(name="[rehypeKatex]", type_=List[str]), src="", ) diff --git a/pynecone/state.py b/pynecone/state.py index c7cae1dbd..e2cdef779 100644 --- a/pynecone/state.py +++ b/pynecone/state.py @@ -177,6 +177,9 @@ class State(Base, ABC): Returns: The class substate. + + Raises: + ValueError: If the substate is not found. """ if len(path) == 0: return cls @@ -198,6 +201,9 @@ class State(Base, ABC): Returns: The class var. + + Raises: + ValueError: If the path is invalid. """ path, name = path[:-1], path[-1] substate = cls.get_class_substate(tuple(path)) @@ -247,6 +253,9 @@ class State(Base, ABC): Returns: The attribute. + + Raises: + Exception: If the attribute is not found. """ # If it is an inherited var, return from the parent state. if name != "inherited_vars" and name in self.inherited_vars: @@ -300,6 +309,9 @@ class State(Base, ABC): Returns: The substate. + + Raises: + ValueError: If the substate is not found. """ if len(path) == 0: return self diff --git a/pynecone/utils.py b/pynecone/utils.py index 87d6a41fb..bc380a35c 100644 --- a/pynecone/utils.py +++ b/pynecone/utils.py @@ -441,6 +441,9 @@ def get_close_char(open: str, close: Optional[str] = None) -> str: Returns: The close character. + + Raises: + ValueError: If the open character is not a valid brace. """ if close is not None: return close @@ -591,7 +594,20 @@ def format_event_fn(fn: Callable) -> str: if isinstance(fn, EventHandler): 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() @@ -633,7 +649,7 @@ def is_dataframe(value: Type) -> bool: return value.__name__ == "DataFrame" -def format_state(value: Dict) -> Dict: +def format_state(value: Any) -> Dict: """Recursively format values in the given state. Args: @@ -724,6 +740,9 @@ def call_event_fn(fn: Callable, arg: Var) -> List[EventSpec]: Returns: The event specs from calling the function. + + Raises: + ValueError: If the lambda has an invalid signature. """ args = inspect.getfullargspec(fn).args if len(args) == 0: @@ -764,6 +783,8 @@ def fix_events(events: Optional[List[Event]], token: str) -> List[Event]: Returns: The fixed events. """ + from pynecone.event import Event, EventHandler, EventSpec + # If the event handler returns nothing, return an empty list. if events is None: return [] @@ -786,7 +807,7 @@ def fix_events(events: Optional[List[Event]], token: str) -> List[Event]: if isinstance(e, EventHandler): e = 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) # Create an event and append it to the list. diff --git a/pynecone/var.py b/pynecone/var.py index 5222e3a53..cffb48905 100644 --- a/pynecone/var.py +++ b/pynecone/var.py @@ -126,7 +126,7 @@ class Var(ABC): out = utils.format_string(out) return out - def __getitem__(self, i) -> Var: + def __getitem__(self, i: Any) -> Var: """Index into a var. Args: @@ -134,6 +134,9 @@ class Var(ABC): Returns: The indexed var. + + Raises: + TypeError: If the var is not indexable. """ # The type of the indexed var. type_ = str @@ -174,6 +177,9 @@ class Var(ABC): Returns: The var attribute. + + Raises: + Exception: If the attribute is not found. """ try: return super().__getattribute__(name) diff --git a/pyproject.toml b/pyproject.toml index 51c195ba8..345727f69 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pynecone-io" -version = "0.1.0" +version = "0.1.2" description = "" authors = [ "Nikhil Rao ",