Cache ComputedVar fixup for dynamic route vars (#952)
This commit is contained in:
parent
9ea1a64d22
commit
b4e534cc97
@ -484,7 +484,10 @@ class State(Base, ABC, extra=pydantic.Extra.allow):
|
|||||||
func = arglist_factory(param)
|
func = arglist_factory(param)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
cls.computed_vars[param] = func.set_state(cls) # type: ignore
|
# link dynamically created ComputedVar to this state class for dep determination
|
||||||
|
func.__objclass__ = cls
|
||||||
|
func.fget.__name__ = param
|
||||||
|
cls.vars[param] = cls.computed_vars[param] = func.set_state(cls) # type: ignore
|
||||||
setattr(cls, param, func)
|
setattr(cls, param, func)
|
||||||
|
|
||||||
def __getattribute__(self, name: str) -> Any:
|
def __getattribute__(self, name: str) -> Any:
|
||||||
@ -537,7 +540,7 @@ class State(Base, ABC, extra=pydantic.Extra.allow):
|
|||||||
super().__setattr__(name, value)
|
super().__setattr__(name, value)
|
||||||
|
|
||||||
# Add the var to the dirty list.
|
# Add the var to the dirty list.
|
||||||
if name in self.vars:
|
if name in self.vars or name in self.computed_var_dependencies:
|
||||||
self.dirty_vars.add(name)
|
self.dirty_vars.add(name)
|
||||||
self.mark_dirty()
|
self.mark_dirty()
|
||||||
|
|
||||||
|
@ -857,6 +857,10 @@ class ComputedVar(Var, property):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A set of variable names accessed by the given obj.
|
A set of variable names accessed by the given obj.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
RuntimeError: if this ComputedVar does not have a reference to the class
|
||||||
|
it is attached to. (Assign var.__objclass__ manually to workaround.)
|
||||||
"""
|
"""
|
||||||
d = set()
|
d = set()
|
||||||
if obj is None:
|
if obj is None:
|
||||||
@ -876,6 +880,10 @@ class ComputedVar(Var, property):
|
|||||||
if self_is_top_of_stack and instruction.opname == "LOAD_ATTR":
|
if self_is_top_of_stack and instruction.opname == "LOAD_ATTR":
|
||||||
d.add(instruction.argval)
|
d.add(instruction.argval)
|
||||||
elif self_is_top_of_stack and instruction.opname == "LOAD_METHOD":
|
elif self_is_top_of_stack and instruction.opname == "LOAD_METHOD":
|
||||||
|
if not hasattr(self, "__objclass__"):
|
||||||
|
raise RuntimeError(
|
||||||
|
f"ComputedVar {self.name!r} is not bound to a State subclass.",
|
||||||
|
)
|
||||||
d.update(self.deps(obj=getattr(self.__objclass__, instruction.argval)))
|
d.update(self.deps(obj=getattr(self.__objclass__, instruction.argval)))
|
||||||
self_is_top_of_stack = False
|
self_is_top_of_stack = False
|
||||||
return d
|
return d
|
||||||
|
@ -105,6 +105,25 @@ def test_add_page_set_route(app: App, index_page, windows_platform: bool):
|
|||||||
assert set(app.pages.keys()) == {"test"}
|
assert set(app.pages.keys()) == {"test"}
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_page_set_route_dynamic(app: App, index_page, windows_platform: bool):
|
||||||
|
"""Test adding a page with dynamic route variable to an app.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
app: The app to test.
|
||||||
|
index_page: The index page.
|
||||||
|
windows_platform: Whether the system is windows.
|
||||||
|
"""
|
||||||
|
route = "/test/[dynamic]"
|
||||||
|
if windows_platform:
|
||||||
|
route.lstrip("/").replace("/", "\\")
|
||||||
|
assert app.pages == {}
|
||||||
|
app.add_page(index_page, route=route)
|
||||||
|
assert set(app.pages.keys()) == {"test/[dynamic]"}
|
||||||
|
assert "dynamic" in app.state.computed_vars
|
||||||
|
assert app.state.computed_vars["dynamic"].deps() == {"router_data"}
|
||||||
|
assert "router_data" in app.state().computed_var_dependencies
|
||||||
|
|
||||||
|
|
||||||
def test_add_page_set_route_nested(app: App, index_page, windows_platform: bool):
|
def test_add_page_set_route_nested(app: App, index_page, windows_platform: bool):
|
||||||
"""Test adding a page to an app.
|
"""Test adding a page to an app.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user