move client storage classes to their own file (#4216)
* move client storage classes to their own file * fix 3.9 annotations
This commit is contained in:
parent
0aca89781f
commit
13591793de
@ -320,13 +320,15 @@ _MAPPING: dict = {
|
|||||||
"upload_files",
|
"upload_files",
|
||||||
"window_alert",
|
"window_alert",
|
||||||
],
|
],
|
||||||
|
"istate.storage": [
|
||||||
|
"Cookie",
|
||||||
|
"LocalStorage",
|
||||||
|
"SessionStorage",
|
||||||
|
],
|
||||||
"middleware": ["middleware", "Middleware"],
|
"middleware": ["middleware", "Middleware"],
|
||||||
"model": ["session", "Model"],
|
"model": ["session", "Model"],
|
||||||
"state": [
|
"state": [
|
||||||
"var",
|
"var",
|
||||||
"Cookie",
|
|
||||||
"LocalStorage",
|
|
||||||
"SessionStorage",
|
|
||||||
"ComponentState",
|
"ComponentState",
|
||||||
"State",
|
"State",
|
||||||
],
|
],
|
||||||
|
@ -174,15 +174,15 @@ from .event import stop_propagation as stop_propagation
|
|||||||
from .event import upload_files as upload_files
|
from .event import upload_files as upload_files
|
||||||
from .event import window_alert as window_alert
|
from .event import window_alert as window_alert
|
||||||
from .experimental import _x as _x
|
from .experimental import _x as _x
|
||||||
|
from .istate.storage import Cookie as Cookie
|
||||||
|
from .istate.storage import LocalStorage as LocalStorage
|
||||||
|
from .istate.storage import SessionStorage as SessionStorage
|
||||||
from .middleware import Middleware as Middleware
|
from .middleware import Middleware as Middleware
|
||||||
from .middleware import middleware as middleware
|
from .middleware import middleware as middleware
|
||||||
from .model import Model as Model
|
from .model import Model as Model
|
||||||
from .model import session as session
|
from .model import session as session
|
||||||
from .page import page as page
|
from .page import page as page
|
||||||
from .state import ComponentState as ComponentState
|
from .state import ComponentState as ComponentState
|
||||||
from .state import Cookie as Cookie
|
|
||||||
from .state import LocalStorage as LocalStorage
|
|
||||||
from .state import SessionStorage as SessionStorage
|
|
||||||
from .state import State as State
|
from .state import State as State
|
||||||
from .state import var as var
|
from .state import var as var
|
||||||
from .style import Style as Style
|
from .style import Style as Style
|
||||||
|
@ -28,7 +28,8 @@ from reflex.components.base import (
|
|||||||
Title,
|
Title,
|
||||||
)
|
)
|
||||||
from reflex.components.component import Component, ComponentStyle, CustomComponent
|
from reflex.components.component import Component, ComponentStyle, CustomComponent
|
||||||
from reflex.state import BaseState, Cookie, LocalStorage, SessionStorage
|
from reflex.istate.storage import Cookie, LocalStorage, SessionStorage
|
||||||
|
from reflex.state import BaseState
|
||||||
from reflex.style import Style
|
from reflex.style import Style
|
||||||
from reflex.utils import console, format, imports, path_ops
|
from reflex.utils import console, format, imports, path_ops
|
||||||
from reflex.utils.imports import ImportVar, ParsedImportDict
|
from reflex.utils.imports import ImportVar, ParsedImportDict
|
||||||
|
144
reflex/istate/storage.py
Normal file
144
reflex/istate/storage.py
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
"""Client-side storage classes for reflex state variables."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from reflex.utils import format
|
||||||
|
|
||||||
|
|
||||||
|
class ClientStorageBase:
|
||||||
|
"""Base class for client-side storage."""
|
||||||
|
|
||||||
|
def options(self) -> dict[str, Any]:
|
||||||
|
"""Get the options for the storage.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
All set options for the storage (not None).
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
format.to_camel_case(k): v for k, v in vars(self).items() if v is not None
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Cookie(ClientStorageBase, str):
|
||||||
|
"""Represents a state Var that is stored as a cookie in the browser."""
|
||||||
|
|
||||||
|
name: str | None
|
||||||
|
path: str
|
||||||
|
max_age: int | None
|
||||||
|
domain: str | None
|
||||||
|
secure: bool | None
|
||||||
|
same_site: str
|
||||||
|
|
||||||
|
def __new__(
|
||||||
|
cls,
|
||||||
|
object: Any = "",
|
||||||
|
encoding: str | None = None,
|
||||||
|
errors: str | None = None,
|
||||||
|
/,
|
||||||
|
name: str | None = None,
|
||||||
|
path: str = "/",
|
||||||
|
max_age: int | None = None,
|
||||||
|
domain: str | None = None,
|
||||||
|
secure: bool | None = None,
|
||||||
|
same_site: str = "lax",
|
||||||
|
):
|
||||||
|
"""Create a client-side Cookie (str).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
object: The initial object.
|
||||||
|
encoding: The encoding to use.
|
||||||
|
errors: The error handling scheme to use.
|
||||||
|
name: The name of the cookie on the client side.
|
||||||
|
path: Cookie path. Use / as the path if the cookie should be accessible on all pages.
|
||||||
|
max_age: Relative max age of the cookie in seconds from when the client receives it.
|
||||||
|
domain: Domain for the cookie (sub.domain.com or .allsubdomains.com).
|
||||||
|
secure: Is the cookie only accessible through HTTPS?
|
||||||
|
same_site: Whether the cookie is sent with third party requests.
|
||||||
|
One of (true|false|none|lax|strict)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The client-side Cookie object.
|
||||||
|
|
||||||
|
Note: expires (absolute Date) is not supported at this time.
|
||||||
|
"""
|
||||||
|
if encoding or errors:
|
||||||
|
inst = super().__new__(cls, object, encoding or "utf-8", errors or "strict")
|
||||||
|
else:
|
||||||
|
inst = super().__new__(cls, object)
|
||||||
|
inst.name = name
|
||||||
|
inst.path = path
|
||||||
|
inst.max_age = max_age
|
||||||
|
inst.domain = domain
|
||||||
|
inst.secure = secure
|
||||||
|
inst.same_site = same_site
|
||||||
|
return inst
|
||||||
|
|
||||||
|
|
||||||
|
class LocalStorage(ClientStorageBase, str):
|
||||||
|
"""Represents a state Var that is stored in localStorage in the browser."""
|
||||||
|
|
||||||
|
name: str | None
|
||||||
|
sync: bool = False
|
||||||
|
|
||||||
|
def __new__(
|
||||||
|
cls,
|
||||||
|
object: Any = "",
|
||||||
|
encoding: str | None = None,
|
||||||
|
errors: str | None = None,
|
||||||
|
/,
|
||||||
|
name: str | None = None,
|
||||||
|
sync: bool = False,
|
||||||
|
) -> "LocalStorage":
|
||||||
|
"""Create a client-side localStorage (str).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
object: The initial object.
|
||||||
|
encoding: The encoding to use.
|
||||||
|
errors: The error handling scheme to use.
|
||||||
|
name: The name of the storage key on the client side.
|
||||||
|
sync: Whether changes should be propagated to other tabs.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The client-side localStorage object.
|
||||||
|
"""
|
||||||
|
if encoding or errors:
|
||||||
|
inst = super().__new__(cls, object, encoding or "utf-8", errors or "strict")
|
||||||
|
else:
|
||||||
|
inst = super().__new__(cls, object)
|
||||||
|
inst.name = name
|
||||||
|
inst.sync = sync
|
||||||
|
return inst
|
||||||
|
|
||||||
|
|
||||||
|
class SessionStorage(ClientStorageBase, str):
|
||||||
|
"""Represents a state Var that is stored in sessionStorage in the browser."""
|
||||||
|
|
||||||
|
name: str | None
|
||||||
|
|
||||||
|
def __new__(
|
||||||
|
cls,
|
||||||
|
object: Any = "",
|
||||||
|
encoding: str | None = None,
|
||||||
|
errors: str | None = None,
|
||||||
|
/,
|
||||||
|
name: str | None = None,
|
||||||
|
) -> "SessionStorage":
|
||||||
|
"""Create a client-side sessionStorage (str).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
object: The initial object.
|
||||||
|
encoding: The encoding to use.
|
||||||
|
errors: The error handling scheme to use
|
||||||
|
name: The name of the storage on the client side
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The client-side sessionStorage object.
|
||||||
|
"""
|
||||||
|
if encoding or errors:
|
||||||
|
inst = super().__new__(cls, object, encoding or "utf-8", errors or "strict")
|
||||||
|
else:
|
||||||
|
inst = super().__new__(cls, object)
|
||||||
|
inst.name = name
|
||||||
|
return inst
|
140
reflex/state.py
140
reflex/state.py
@ -42,6 +42,9 @@ from typing_extensions import Self
|
|||||||
from reflex import event
|
from reflex import event
|
||||||
from reflex.config import get_config
|
from reflex.config import get_config
|
||||||
from reflex.istate.data import RouterData
|
from reflex.istate.data import RouterData
|
||||||
|
from reflex.istate.storage import (
|
||||||
|
ClientStorageBase,
|
||||||
|
)
|
||||||
from reflex.vars.base import (
|
from reflex.vars.base import (
|
||||||
ComputedVar,
|
ComputedVar,
|
||||||
DynamicRouteVar,
|
DynamicRouteVar,
|
||||||
@ -3349,143 +3352,6 @@ def get_state_manager() -> StateManager:
|
|||||||
return app.state_manager
|
return app.state_manager
|
||||||
|
|
||||||
|
|
||||||
class ClientStorageBase:
|
|
||||||
"""Base class for client-side storage."""
|
|
||||||
|
|
||||||
def options(self) -> dict[str, Any]:
|
|
||||||
"""Get the options for the storage.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
All set options for the storage (not None).
|
|
||||||
"""
|
|
||||||
return {
|
|
||||||
format.to_camel_case(k): v for k, v in vars(self).items() if v is not None
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class Cookie(ClientStorageBase, str):
|
|
||||||
"""Represents a state Var that is stored as a cookie in the browser."""
|
|
||||||
|
|
||||||
name: str | None
|
|
||||||
path: str
|
|
||||||
max_age: int | None
|
|
||||||
domain: str | None
|
|
||||||
secure: bool | None
|
|
||||||
same_site: str
|
|
||||||
|
|
||||||
def __new__(
|
|
||||||
cls,
|
|
||||||
object: Any = "",
|
|
||||||
encoding: str | None = None,
|
|
||||||
errors: str | None = None,
|
|
||||||
/,
|
|
||||||
name: str | None = None,
|
|
||||||
path: str = "/",
|
|
||||||
max_age: int | None = None,
|
|
||||||
domain: str | None = None,
|
|
||||||
secure: bool | None = None,
|
|
||||||
same_site: str = "lax",
|
|
||||||
):
|
|
||||||
"""Create a client-side Cookie (str).
|
|
||||||
|
|
||||||
Args:
|
|
||||||
object: The initial object.
|
|
||||||
encoding: The encoding to use.
|
|
||||||
errors: The error handling scheme to use.
|
|
||||||
name: The name of the cookie on the client side.
|
|
||||||
path: Cookie path. Use / as the path if the cookie should be accessible on all pages.
|
|
||||||
max_age: Relative max age of the cookie in seconds from when the client receives it.
|
|
||||||
domain: Domain for the cookie (sub.domain.com or .allsubdomains.com).
|
|
||||||
secure: Is the cookie only accessible through HTTPS?
|
|
||||||
same_site: Whether the cookie is sent with third party requests.
|
|
||||||
One of (true|false|none|lax|strict)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The client-side Cookie object.
|
|
||||||
|
|
||||||
Note: expires (absolute Date) is not supported at this time.
|
|
||||||
"""
|
|
||||||
if encoding or errors:
|
|
||||||
inst = super().__new__(cls, object, encoding or "utf-8", errors or "strict")
|
|
||||||
else:
|
|
||||||
inst = super().__new__(cls, object)
|
|
||||||
inst.name = name
|
|
||||||
inst.path = path
|
|
||||||
inst.max_age = max_age
|
|
||||||
inst.domain = domain
|
|
||||||
inst.secure = secure
|
|
||||||
inst.same_site = same_site
|
|
||||||
return inst
|
|
||||||
|
|
||||||
|
|
||||||
class LocalStorage(ClientStorageBase, str):
|
|
||||||
"""Represents a state Var that is stored in localStorage in the browser."""
|
|
||||||
|
|
||||||
name: str | None
|
|
||||||
sync: bool = False
|
|
||||||
|
|
||||||
def __new__(
|
|
||||||
cls,
|
|
||||||
object: Any = "",
|
|
||||||
encoding: str | None = None,
|
|
||||||
errors: str | None = None,
|
|
||||||
/,
|
|
||||||
name: str | None = None,
|
|
||||||
sync: bool = False,
|
|
||||||
) -> "LocalStorage":
|
|
||||||
"""Create a client-side localStorage (str).
|
|
||||||
|
|
||||||
Args:
|
|
||||||
object: The initial object.
|
|
||||||
encoding: The encoding to use.
|
|
||||||
errors: The error handling scheme to use.
|
|
||||||
name: The name of the storage key on the client side.
|
|
||||||
sync: Whether changes should be propagated to other tabs.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The client-side localStorage object.
|
|
||||||
"""
|
|
||||||
if encoding or errors:
|
|
||||||
inst = super().__new__(cls, object, encoding or "utf-8", errors or "strict")
|
|
||||||
else:
|
|
||||||
inst = super().__new__(cls, object)
|
|
||||||
inst.name = name
|
|
||||||
inst.sync = sync
|
|
||||||
return inst
|
|
||||||
|
|
||||||
|
|
||||||
class SessionStorage(ClientStorageBase, str):
|
|
||||||
"""Represents a state Var that is stored in sessionStorage in the browser."""
|
|
||||||
|
|
||||||
name: str | None
|
|
||||||
|
|
||||||
def __new__(
|
|
||||||
cls,
|
|
||||||
object: Any = "",
|
|
||||||
encoding: str | None = None,
|
|
||||||
errors: str | None = None,
|
|
||||||
/,
|
|
||||||
name: str | None = None,
|
|
||||||
) -> "SessionStorage":
|
|
||||||
"""Create a client-side sessionStorage (str).
|
|
||||||
|
|
||||||
Args:
|
|
||||||
object: The initial object.
|
|
||||||
encoding: The encoding to use.
|
|
||||||
errors: The error handling scheme to use
|
|
||||||
name: The name of the storage on the client side
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The client-side sessionStorage object.
|
|
||||||
"""
|
|
||||||
if encoding or errors:
|
|
||||||
inst = super().__new__(cls, object, encoding or "utf-8", errors or "strict")
|
|
||||||
else:
|
|
||||||
inst = super().__new__(cls, object)
|
|
||||||
inst.name = name
|
|
||||||
return inst
|
|
||||||
|
|
||||||
|
|
||||||
class MutableProxy(wrapt.ObjectProxy):
|
class MutableProxy(wrapt.ObjectProxy):
|
||||||
"""A proxy for a mutable object that tracks changes."""
|
"""A proxy for a mutable object that tracks changes."""
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user