Skip to content

Commit

Permalink
fully migrate vars into new system (#3743)
Browse files Browse the repository at this point in the history
* fully migrate vars into new system

* i hate rufffff (no i don't)

* fix silly pright issues (except colormode and state)

* remove all instances of Var.create

* create immutable callable var and get rid of more base vars

* implement hash for all functions

* get reflex-web to compile

* get it to compile reflex-web successfully

* fix tests

* fix pyi

* use override from typing_extension

* put plotly inside of a catch

* dicts are unusable sadly

* fix silly mistake

* overload equals to special case immutable var

* improve test_cond

* solve more CI issues, down to 94 failures

* down to 20 errors

* down to 13 errors

* pass all testcases

* fix pyright issues

* reorder things

* use get origin more

* use fixed_type logic

* various optimizations

* go back to passing test cases

* use less boilerplate

* remove unnecessary print message

* remove weird comment

* add test for html issue

* add type ignore

* fix another silly issue

* override get all var data for var operations call

* make integration tests pass

* fix immutable call var

* better logic for finding parent class

* use even better logic for finding state wrt computedvar

* only choose the ones that are defined in the same module

* small dict to large dict

* [REF-3591] Remove chakra-related files from immutable vars PR (#3821)

* Add comments to html metadata component (#3731)

* fix: add verification for path /404 (#3723)

Co-authored-by: coolstorm <manas.gupta@fampay.in>

* Use the new state name when setting `is_hydrated` to false (#3738)

* Use `._is_mutable()` to account for parent state proxy (#3739)

When a parent state proxy is set, also allow child StateProxy._self_mutable to
override the parent's `_is_mutable()`.

* bump to 0.5.9 (#3746)

* add message when installing requirements.txt is needed for chosen template during init (#3750)

* #3752 bugfix add domain for XAxis (#3764)

* fix appharness app_source typing (#3777)

* fix import clash between connectionToaster and hooks.useState (#3749)

* use different registry when in china, fixes #3700 (#3702)

* do not reload compilation if using local app in AppHarness (#3790)

* do not reload if using local app

* Update reflex/testing.py

Co-authored-by: Masen Furer <m_github@0x26.net>

---------

Co-authored-by: Masen Furer <m_github@0x26.net>

* Bump memory on relevant actions (#3781)

Co-authored-by: Alek Petuskey <alekpetuskey@Aleks-MacBook-Pro.local>

* [REF-3334] Validate Toast Props (#3793)

* [REF-3536][REF-3537][REF-3541] Move chakra components into its repo(reflex-chakra) (#3798)

* fix get_uuid_string_var (#3795)

* minor State cleanup (#3768)

* Fix code wrap in markdown (#3755)

---------

Co-authored-by: Alek Petuskey <alek@pynecone.io>
Co-authored-by: Manas Gupta <53006261+Manas1820@users.noreply.github.com>
Co-authored-by: coolstorm <manas.gupta@fampay.in>
Co-authored-by: Thomas Brandého <thomas.brandeho@gmail.com>
Co-authored-by: Shubhankar Dimri <dimrishubhi@gmail.com>
Co-authored-by: benedikt-bartscher <31854409+benedikt-bartscher@users.noreply.github.com>
Co-authored-by: Khaleel Al-Adhami <khaleel.aladhami@gmail.com>
Co-authored-by: Alek Petuskey <alekpetuskey@Aleks-MacBook-Pro.local>
Co-authored-by: Elijah Ahianyo <elijahahianyo@gmail.com>

* pyproject.toml: bump to 0.6.0a1

* pyproject.toml: depend on reflex-chakra>=0.6.0a

New Var system support in reflex-chakra 0.6.0a1

* poetry.lock: relock dependencies

* integration: bump listening timeout to 1200 seconds

* integration: bump listening timeout to 1800 seconds

* Use cached_var_no_lock to avoid ImmutableVar deadlocks (#3835)

* Use cached_var_no_lock to avoid ImmutableVar deadlocks

ImmutableVar subclasses will always return the same value for a _var_name or
_get_all_var_data so there is no need to use a per-class lock to protect a
cached attribute on an instance, and doing so actually is observed to cause
deadlocks when a particular _cached_var_name creates new LiteralVar instances
and attempts to serialize them.

* remove unused module global

---------

Co-authored-by: Masen Furer <m_github@0x26.net>
Co-authored-by: Alek Petuskey <alek@pynecone.io>
Co-authored-by: Manas Gupta <53006261+Manas1820@users.noreply.github.com>
Co-authored-by: coolstorm <manas.gupta@fampay.in>
Co-authored-by: Thomas Brandého <thomas.brandeho@gmail.com>
Co-authored-by: Shubhankar Dimri <dimrishubhi@gmail.com>
Co-authored-by: benedikt-bartscher <31854409+benedikt-bartscher@users.noreply.github.com>
Co-authored-by: Alek Petuskey <alekpetuskey@Aleks-MacBook-Pro.local>
Co-authored-by: Elijah Ahianyo <elijahahianyo@gmail.com>
  • Loading branch information
10 people authored Aug 26, 2024
1 parent a265fb4 commit ea15b18
Show file tree
Hide file tree
Showing 189 changed files with 11,537 additions and 14,807 deletions.
2 changes: 2 additions & 0 deletions integration/test_form_submit.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ async def get_form_data():

form_data = format.collect_form_dict_names(form_data)

print(form_data)

assert form_data["name_input"] == "foo"
assert form_data["pin_input"] == pin_values
assert form_data["number_input"] == "-3"
Expand Down
2 changes: 1 addition & 1 deletion integration/test_tailwind.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def test_tailwind_app(tailwind_app: AppHarness, tailwind_disabled: bool):
assert len(paragraphs) == 3
for p in paragraphs:
assert tailwind_app.poll_for_content(p, exp_not_equal="") == PARAGRAPH_TEXT
assert p.value_of_css_property("font-family") == "monospace"
assert p.value_of_css_property("font-family") == '"monospace"'
if tailwind_disabled:
# expect default color, not "text-red-500" from tailwind utility class
assert p.value_of_css_property("color") not in TEXT_RED_500_COLOR
Expand Down
23 changes: 13 additions & 10 deletions integration/test_var_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ def VarOperations():
import reflex_chakra as rc

import reflex as rx
from reflex.ivars.base import LiteralVar
from reflex.ivars.sequence import ArrayVar

class VarOperationState(rx.State):
int_var1: int = 10
Expand All @@ -31,8 +33,8 @@ class VarOperationState(rx.State):
str_var2: str = "second"
str_var3: str = "ThIrD"
str_var4: str = "a long string"
dict1: Dict = {1: 2}
dict2: Dict = {3: 4}
dict1: Dict[int, int] = {1: 2}
dict2: Dict[int, int] = {3: 4}
html_str: str = "<div>hello</div>"

app = rx.App(state=rx.State)
Expand Down Expand Up @@ -549,29 +551,29 @@ def index():
"second",
query=[VarOperationState.str_var2],
),
rx.text(rx.Var.range(2, 5).join(","), id="list_join_range1"),
rx.text(rx.Var.range(2, 10, 2).join(","), id="list_join_range2"),
rx.text(rx.Var.range(5, 0, -1).join(","), id="list_join_range3"),
rx.text(rx.Var.range(0, 3).join(","), id="list_join_range4"),
rx.text(ArrayVar.range(2, 5).join(","), id="list_join_range1"),
rx.text(ArrayVar.range(2, 10, 2).join(","), id="list_join_range2"),
rx.text(ArrayVar.range(5, 0, -1).join(","), id="list_join_range3"),
rx.text(ArrayVar.range(0, 3).join(","), id="list_join_range4"),
rx.box(
rx.foreach(
rx.Var.range(0, 2),
ArrayVar.range(0, 2),
lambda x: rx.text(VarOperationState.list1[x], as_="p"),
),
id="foreach_list_arg",
),
rx.box(
rx.foreach(
rx.Var.range(0, 2),
ArrayVar.range(0, 2),
lambda x, ix: rx.text(VarOperationState.list1[ix], as_="p"),
),
id="foreach_list_ix",
),
rx.box(
rx.foreach(
rx.Var.create_safe(list(range(0, 3))).to(List[int]),
LiteralVar.create(list(range(0, 3))).to(ArrayVar, List[int]),
lambda x: rx.foreach(
rx.Var.range(x),
ArrayVar.range(x),
lambda y: rx.text(VarOperationState.list1[y], as_="p"),
),
),
Expand Down Expand Up @@ -785,6 +787,7 @@ def test_var_operations(driver, var_operations: AppHarness):
]

for tag, expected in tests:
print(tag)
assert driver.find_element(By.ID, tag).text == expected

# Highlight component with var query (does not plumb ID)
Expand Down
18 changes: 9 additions & 9 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "reflex"
version = "0.5.9"
version = "0.6.0a1"
description = "Web apps in pure Python."
license = "Apache-2.0"
authors = [
Expand Down Expand Up @@ -61,7 +61,7 @@ httpx = ">=0.25.1,<1.0"
twine = ">=4.0.0,<6.0"
tomlkit = ">=0.12.4,<1.0"
lazy_loader = ">=0.4"
reflex-chakra = ">=0.1.1a1,<0.6"
reflex-chakra = ">=0.6.0a"

[tool.poetry.group.dev.dependencies]
pytest = ">=7.1.2,<8.0"
Expand Down
3 changes: 2 additions & 1 deletion reflex/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@
"style": ["Style", "toggle_color_mode"],
"utils.imports": ["ImportVar"],
"utils.serializers": ["serializer"],
"vars": ["cached_var", "Var"],
"vars": ["Var"],
}

_SUBMODULES: set[str] = {
Expand All @@ -338,6 +338,7 @@
"testing",
"utils",
"vars",
"ivars",
"config",
"compiler",
}
Expand Down
2 changes: 1 addition & 1 deletion reflex/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ from . import compiler as compiler
from . import components as components
from . import config as config
from . import event as event
from . import ivars as ivars
from . import model as model
from . import style as style
from . import testing as testing
Expand Down Expand Up @@ -189,7 +190,6 @@ from .style import toggle_color_mode as toggle_color_mode
from .utils.imports import ImportVar as ImportVar
from .utils.serializers import serializer as serializer
from .vars import Var as Var
from .vars import cached_var as cached_var

del compat
RADIX_THEMES_MAPPING: dict
Expand Down
8 changes: 5 additions & 3 deletions reflex/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ def _generate_component(component: Component | ComponentCallable) -> Component:
raise
except TypeError as e:
message = str(e)
if "BaseVar" in message or "ComputedVar" in message:
if "Var" in message:
raise VarOperationTypeError(
"You may be trying to use an invalid Python function on a state var. "
"When referencing a var inside your render code, only limited var operations are supported. "
Expand Down Expand Up @@ -527,9 +527,10 @@ def add_page(
self._enable_state()
else:
for var in component._get_vars(include_children=True):
if not var._var_data:
var_data = var._get_all_var_data()
if not var_data:
continue
if not var._var_data.state:
if not var_data.state:
continue
self._enable_state()
break
Expand Down Expand Up @@ -1113,6 +1114,7 @@ def _process_background(
Task if the event was backgroundable, otherwise None
"""
substate, handler = state._get_event_handler(event)

if not handler.is_background:
return None

Expand Down
5 changes: 3 additions & 2 deletions reflex/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,15 @@ def add_field(cls, var: Any, default_value: Any):
var: The variable to add a pydantic field for.
default_value: The default value of the field
"""
var_name = var._var_name.split(".")[-1]
new_field = ModelField.infer(
name=var._var_name,
name=var_name,
value=default_value,
annotation=var._var_type,
class_validators=None,
config=cls.__config__, # type: ignore
)
cls.__fields__.update({var._var_name: new_field})
cls.__fields__.update({var_name: new_field})

def get_value(self, key: str) -> Any:
"""Get the value of a field.
Expand Down
3 changes: 2 additions & 1 deletion reflex/compiler/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
StatefulComponent,
)
from reflex.config import get_config
from reflex.ivars.base import ImmutableVar
from reflex.state import BaseState
from reflex.style import SYSTEM_COLOR_MODE
from reflex.utils.exec import is_prod_mode
Expand Down Expand Up @@ -80,7 +81,7 @@ def _compile_contexts(state: Optional[Type[BaseState]], theme: Component | None)
The compiled context file.
"""
appearance = getattr(theme, "appearance", None)
if appearance is None or Var.create_safe(appearance)._var_name == "inherit":
if appearance is None or str(ImmutableVar.create_safe(appearance)) == "inherit":
appearance = SYSTEM_COLOR_MODE

last_compiled_time = str(datetime.now())
Expand Down
6 changes: 2 additions & 4 deletions reflex/components/base/app_wrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from reflex.components.base.fragment import Fragment
from reflex.components.component import Component
from reflex.vars import Var
from reflex.ivars.base import ImmutableVar


class AppWrap(Fragment):
Expand All @@ -15,6 +15,4 @@ def create(cls) -> Component:
Returns:
A new AppWrap component containing {children}.
"""
return super().create(
Var.create("{children}", _var_is_local=False, _var_is_string=False)
)
return super().create(ImmutableVar.create("children"))
42 changes: 16 additions & 26 deletions reflex/components/base/app_wrap.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ from typing import Any, Callable, Dict, Optional, Union, overload
from reflex.components.base.fragment import Fragment
from reflex.event import EventHandler, EventSpec
from reflex.style import Style
from reflex.vars import BaseVar, Var
from reflex.vars import Var

class AppWrap(Fragment):
@overload
Expand All @@ -22,50 +22,40 @@ class AppWrap(Fragment):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
on_blur: Optional[
Union[EventHandler, EventSpec, list, Callable, BaseVar]
] = None,
on_click: Optional[
Union[EventHandler, EventSpec, list, Callable, BaseVar]
] = None,
on_blur: Optional[Union[EventHandler, EventSpec, list, Callable, Var]] = None,
on_click: Optional[Union[EventHandler, EventSpec, list, Callable, Var]] = None,
on_context_menu: Optional[
Union[EventHandler, EventSpec, list, Callable, BaseVar]
Union[EventHandler, EventSpec, list, Callable, Var]
] = None,
on_double_click: Optional[
Union[EventHandler, EventSpec, list, Callable, BaseVar]
] = None,
on_focus: Optional[
Union[EventHandler, EventSpec, list, Callable, BaseVar]
] = None,
on_mount: Optional[
Union[EventHandler, EventSpec, list, Callable, BaseVar]
Union[EventHandler, EventSpec, list, Callable, Var]
] = None,
on_focus: Optional[Union[EventHandler, EventSpec, list, Callable, Var]] = None,
on_mount: Optional[Union[EventHandler, EventSpec, list, Callable, Var]] = None,
on_mouse_down: Optional[
Union[EventHandler, EventSpec, list, Callable, BaseVar]
Union[EventHandler, EventSpec, list, Callable, Var]
] = None,
on_mouse_enter: Optional[
Union[EventHandler, EventSpec, list, Callable, BaseVar]
Union[EventHandler, EventSpec, list, Callable, Var]
] = None,
on_mouse_leave: Optional[
Union[EventHandler, EventSpec, list, Callable, BaseVar]
Union[EventHandler, EventSpec, list, Callable, Var]
] = None,
on_mouse_move: Optional[
Union[EventHandler, EventSpec, list, Callable, BaseVar]
Union[EventHandler, EventSpec, list, Callable, Var]
] = None,
on_mouse_out: Optional[
Union[EventHandler, EventSpec, list, Callable, BaseVar]
Union[EventHandler, EventSpec, list, Callable, Var]
] = None,
on_mouse_over: Optional[
Union[EventHandler, EventSpec, list, Callable, BaseVar]
Union[EventHandler, EventSpec, list, Callable, Var]
] = None,
on_mouse_up: Optional[
Union[EventHandler, EventSpec, list, Callable, BaseVar]
] = None,
on_scroll: Optional[
Union[EventHandler, EventSpec, list, Callable, BaseVar]
Union[EventHandler, EventSpec, list, Callable, Var]
] = None,
on_scroll: Optional[Union[EventHandler, EventSpec, list, Callable, Var]] = None,
on_unmount: Optional[
Union[EventHandler, EventSpec, list, Callable, BaseVar]
Union[EventHandler, EventSpec, list, Callable, Var]
] = None,
**props,
) -> "AppWrap":
Expand Down
9 changes: 7 additions & 2 deletions reflex/components/base/bare.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
from reflex.components.component import Component
from reflex.components.tags import Tag
from reflex.components.tags.tagless import Tagless
from reflex.ivars.base import ImmutableVar
from reflex.vars import Var


class Bare(Component):
"""A component with no tag."""

contents: Var[str]
contents: Var[Any]

@classmethod
def create(cls, contents: Any) -> Component:
Expand All @@ -25,13 +26,17 @@ def create(cls, contents: Any) -> Component:
Returns:
The component.
"""
if isinstance(contents, Var) and contents._var_data:
if isinstance(contents, ImmutableVar):
return cls(contents=contents)
if isinstance(contents, Var) and contents._get_all_var_data():
contents = contents.to(str)
else:
contents = str(contents) if contents is not None else ""
return cls(contents=contents) # type: ignore

def _render(self) -> Tag:
if isinstance(self.contents, ImmutableVar):
return Tagless(contents=f"{{{str(self.contents)}}}")
return Tagless(contents=str(self.contents))

def _get_vars(self, include_children: bool = False) -> Iterator[Var]:
Expand Down
Loading

0 comments on commit ea15b18

Please sign in to comment.