New Features
Make Var System Expandable
A new dispatch mechanism for converting python values into Var and LiteralVar subclasses. This allows component authors and downstream applications to better support custom frontend operations on Python values converted to Javascript values
<details>
<summary>See Example</summary>
This example allows for near drop-in support for working with SQLAlchemy `DeclarativeBase` models and will likely be included in a future release:
python
from collections.abc import Mapping, MutableSet, Sequence
from typing import TypeVar
import dataclasses
import sys
import reflex as rx
import sqlalchemy
import sqlalchemy.orm.exc
from sqlalchemy.orm import DeclarativeBase
class DeclarativeBaseVar(rx.vars.ObjectVar, python_types=DeclarativeBase):
pass
dataclasses.dataclass(
eq=False,
frozen=True,
**{"slots": True} if sys.version_info >= (3, 10) else {},
)
class LiteralDeclarativeBaseVar(rx.vars.LiteralObjectVar, DeclarativeBaseVar):
_var_value: DeclarativeBase | None = None
T = TypeVar("T")
K = TypeVar("K")
V = TypeVar("V")
rx.serializer
def serialize_Sequence(s: Sequence[T] | MutableSet[T]) -> list[T]:
return list(s)
rx.serializer
def serialize_Mapping(m: Mapping[K, V]) -> dict[K, V]:
return dict(m)
rx.serializer
def serialize_DeclarativeBase(obj: DeclarativeBase) -> dict[str, str]:
s = {}
for attr in sqlalchemy.inspect(type(obj)).all_orm_descriptors.keys():
try:
s[attr] = getattr(obj, attr)
except sqlalchemy.orm.exc.DetachedInstanceError:
This happens when the relationship was never loaded and the session is closed.
continue
return s
</details>
* make var system expandable by adhami3310 in https://github.com/reflex-dev/reflex/pull/4175
`max-requests` support to gunicorn (fixed memory leak)
This is a new configurable option in the rx.config but also now has default values.
`gunicorn_max_requests` - ( gunicorn / uvicorn )max requests per worker
Defaults value - `100`
`gunicorn_max_requests_jitter` - (gunicorn only) variance in the max request limit. To prevent all workers restarting at same time
Defaults value - `25`
What is `max_requests`?
`max_requests` is a the maximum number of requests a worker can serve before the manager will kill the worker and restart.
Why is this needed?
gunicorn workers don't release memory after a request. This can cause for a workers to hold on to more and more memory over time. Setting this flag means that after serving N requests the worker is killed, thus releasing the memory, and a new worker is spun up.
How to configure
python
rx.config(
...
gunicorn_max_requests=50
...
)
Experimental Shiki Codeblock
python
rx._x.code_block(
"""
print("Original text") [!code --]
print("Replace original with this") [!code ++]
name = "John Doe" [!code highlight]
""",
language="python",
theme="dracula",
use_transformers=True,
can_copy=True,
show_line_numbers=True
)
* [ENG-3848][ENG-3861]Shiki Code block Experimental by ElijahAhianyo in https://github.com/reflex-dev/reflex/pull/4030
`dotenv` support added
To use this feature, you must install `python-dotenv` separately from reflex.
python
import reflex as rx
config = rx.Config(
app_name="mycoolapp",
env_file=".env",
)
* HOS-93: add support for .env file by Kastier1 in https://github.com/reflex-dev/reflex/pull/4219
* make python-dotenv optional by Lendemor in https://github.com/reflex-dev/reflex/pull/4222
New `rx.dynamic` decorator
Unlike normal UI functions, this decorator allows UI code to directly access State instance values, Python-only APIs, and typical `for` and `if` statements.
<details>
<summary>See Example</summary>
We can implement a simple Reflex fiddle, that evaluates component strings into UI components and render them. This was previously difficult, as all UI had to compile into react code in the `.web` folder. This works by dynamically compiling a JavaScript module using in-window react.
python
import reflex as rx
class State(rx.State):
component_str = "rx.button('login')"
rx.dynamic
def evaluated_component(state: State):
try:
component = eval(
state.component_str,
{
"rx": rx,
"State": State,
},
)
except Exception as e:
return rx.text(f"Error: {e}")
if not isinstance(component, rx.Component):
return rx.text("Invalid component")
return component
def index():
return (
rx.hstack(
rx.text_area(
value=State.component_str,
on_change=State.set_component_str,
height="100%",
flex="1",
),
rx.card(evaluated_component(), height="100%", flex="1"),
height="100vh",
padding="1rem",
box_size="border-box",
),
)
</details>
* implement rx dynamic by adhami3310 in https://github.com/reflex-dev/reflex/pull/4195
Improvements
Better Type Hinting for Built in Components
* add type hinting to error boundary by adhami3310 in https://github.com/reflex-dev/reflex/pull/4182
* add event types to suneditor by adhami3310 in https://github.com/reflex-dev/reflex/pull/4209
* Add type hinting to dataeditor events by adhami3310 in https://github.com/reflex-dev/reflex/pull/4210
* Add on progress typing to react player by adhami3310 in https://github.com/reflex-dev/reflex/pull/4211
* add additional typing for calling events by adhami3310 in https://github.com/reflex-dev/reflex/pull/4218
Other Improvements
* allow setting run mode via env, add helpers to determine it by benedikt-bartscher in https://github.com/reflex-dev/reflex/pull/4168
* Raise TypeError when `ComputedVar.__init__` gets bad kwargs by masenf in https://github.com/reflex-dev/reflex/pull/4199
* move all environment variables to the same place by adhami3310 in https://github.com/reflex-dev/reflex/pull/4192
* add existing path subclass for env checks by adhami3310 in 4260
* port enum env var support from 4248 by benedikt-bartscher in 4251
* [ENG-3970] When normal pickle fails, try dill by masenf in https://github.com/reflex-dev/reflex/pull/4239
Bug Fixes
* use larger or equal for node version check by adhami3310 in https://github.com/reflex-dev/reflex/pull/4189
* check for none before returning which by adhami3310 in https://github.com/reflex-dev/reflex/pull/4187
* fix and test bug in config env loading by benedikt-bartscher in https://github.com/reflex-dev/reflex/pull/4205
* fix inverted alembic file check by adhami3310 in https://github.com/reflex-dev/reflex/pull/4238
* fix: async default setters break setvar by benedikt-bartscher in https://github.com/reflex-dev/reflex/pull/4169
* Fix 'enter_key_submit=True' on 'rx.text_area' by carrying custom_code on debounce by masenf in https://github.com/reflex-dev/reflex/pull/4142
* Handle props annotated as list/dict of EventHandler (4257)
Version Bumps
* upgrade node to latest lts by adhami3310 in https://github.com/reflex-dev/reflex/pull/4191
* versions bump before 0.6.4 by Lendemor in https://github.com/reflex-dev/reflex/pull/4208
* bump ruff to 0.7.0 by Lendemor in https://github.com/reflex-dev/reflex/pull/4213
Other Changes
* pin AppHarness tests to ubuntu-22.04 runner by masenf in https://github.com/reflex-dev/reflex/pull/4173
* Remove demo command by Alek99 in https://github.com/reflex-dev/reflex/pull/4176
* move client storage classes to their own file by Lendemor in https://github.com/reflex-dev/reflex/pull/4216
* use $ syntax by adhami3310 in https://github.com/reflex-dev/reflex/pull/4237
* test for stateless apps by Lendemor in https://github.com/reflex-dev/reflex/pull/3816
**Full Changelog**: https://github.com/reflex-dev/reflex/compare/v0.6.3.post1...v0.6.4