From 2543e48a308cb8ca49b2449f27ef508adee984a5 Mon Sep 17 00:00:00 2001 From: Nikhil Rao Date: Wed, 4 Jan 2023 15:41:05 -0800 Subject: [PATCH] Access parent state vars from substate (#207) --- poetry.lock | 6 +++--- pynecone/components/component.py | 2 +- pynecone/state.py | 25 ++++++++++++++++++++++++- tests/test_state.py | 18 ++++++++++++++++-- 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index 5ec162efa..6265169f7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -605,14 +605,14 @@ plugins = ["importlib-metadata"] [[package]] name = "pyright" -version = "1.1.286" +version = "1.1.287" description = "Command line wrapper for pyright" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pyright-1.1.286-py3-none-any.whl", hash = "sha256:b80761f303bf437d764b2d194b06f07fb4ed38960d7f3a8b2f7f41da37aced70"}, - {file = "pyright-1.1.286.tar.gz", hash = "sha256:2bbf82114ac3838c31c91d1c32abe4858259bff094465cadff55eac465250f1b"}, + {file = "pyright-1.1.287-py3-none-any.whl", hash = "sha256:0c760edbd40eb4f763027f742de2cb29c1d8320880e5f6ad85fc89db43fe6871"}, + {file = "pyright-1.1.287.tar.gz", hash = "sha256:806a4af328dc1f2b6688147528c71393f0cf241eb1214d6e9a7fb1ef5caa2327"}, ] [package.dependencies] diff --git a/pynecone/components/component.py b/pynecone/components/component.py index 3797a2176..98bd77a2c 100644 --- a/pynecone/components/component.py +++ b/pynecone/components/component.py @@ -443,7 +443,7 @@ class CustomComponent(Component): value = Var.create(value, is_string=type(value) is str) self.props[utils.to_camel_case(key)] = value - def __eq__(self, other) -> bool: + def __eq__(self, other: Any) -> bool: """Check if the component is equal to another. Args: diff --git a/pynecone/state.py b/pynecone/state.py index 6aa985a09..0c1270865 100644 --- a/pynecone/state.py +++ b/pynecone/state.py @@ -30,7 +30,7 @@ class State(Base, ABC): # The computed vars of the class. computed_vars: ClassVar[Dict[str, ComputedVar]] = {} - # vars inherited by the parent state. + # Vars inherited by the parent state. inherited_vars: ClassVar[Dict[str, Var]] = {} # The parent state. @@ -257,13 +257,36 @@ class State(Base, ABC): field.required = False field.default = default_value + def __getattribute__(self, name: str) -> Any: + """Get the state var. + + If the var is inherited, get the var from the parent state. + + Args: + name: The name of the var. + + Returns: + The value of the var. + """ + # Get the var from the parent state. + if name in super().__getattribute__("inherited_vars"): + return getattr(super().__getattribute__("parent_state"), name) + return super().__getattribute__(name) + def __setattr__(self, name: str, value: Any): """Set the attribute. + If the attribute is inherited, set the attribute on the parent state. + Args: name: The name of the attribute. value: The value of the attribute. """ + # Set the var on the parent state. + if name in self.inherited_vars: + setattr(self.parent_state, name, value) + return + # Set the attribute. super().__setattr__(name, value) diff --git a/tests/test_state.py b/tests/test_state.py index 3206ac84e..ad60322ee 100644 --- a/tests/test_state.py +++ b/tests/test_state.py @@ -405,10 +405,24 @@ def test_set_child_attribute(test_state, child_state, grandchild_state): """ test_state.num1 = 10 assert test_state.num1 == 10 + assert child_state.num1 == 10 + assert grandchild_state.num1 == 10 + + grandchild_state.num1 = 5 + assert test_state.num1 == 5 + assert child_state.num1 == 5 + assert grandchild_state.num1 == 5 + child_state.value = "test" assert child_state.value == "test" - grandchild_state.value2 = "test2" - assert grandchild_state.value2 == "test2" + assert grandchild_state.value == "test" + + grandchild_state.value = "test2" + assert child_state.value == "test2" + assert grandchild_state.value == "test2" + + grandchild_state.value2 = "test3" + assert grandchild_state.value2 == "test3" def test_get_substate(test_state, child_state, child_state2, grandchild_state):