reflex 0.5.8a1__py3-none-any.whl → 0.5.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of reflex might be problematic. Click here for more details.

@@ -23,7 +23,12 @@ export const useClientSideRouting = () => {
23
23
  router.replace({
24
24
  pathname: window.location.pathname,
25
25
  query: window.location.search.slice(1),
26
- })
26
+ }).then(()=>{
27
+ // Check if the current route is /404
28
+ if (router.pathname === '/404') {
29
+ setRouteNotFound(true); // Mark as an actual 404
30
+ }
31
+ })
27
32
  .catch((e) => {
28
33
  setRouteNotFound(true) // navigation failed, so this is a real 404
29
34
  })
@@ -647,7 +647,12 @@ export const useEventLoop = (
647
647
  const [connectErrors, setConnectErrors] = useState([]);
648
648
 
649
649
  // Function to add new events to the event queue.
650
- const addEvents = (events, _e, event_actions) => {
650
+ const addEvents = (events, args, event_actions) => {
651
+ if (!(args instanceof Array)) {
652
+ args = [args];
653
+ }
654
+ const _e = args.filter((o) => o?.preventDefault !== undefined)[0]
655
+
651
656
  if (event_actions?.preventDefault && _e?.preventDefault) {
652
657
  _e.preventDefault();
653
658
  }
@@ -777,7 +782,7 @@ export const useEventLoop = (
777
782
  // Route after the initial page hydration.
778
783
  useEffect(() => {
779
784
  const change_start = () => {
780
- const main_state_dispatch = dispatch["state"]
785
+ const main_state_dispatch = dispatch["reflex___state____state"]
781
786
  if (main_state_dispatch !== undefined) {
782
787
  main_state_dispatch({ is_hydrated: false })
783
788
  }
@@ -24,6 +24,7 @@ from typing import (
24
24
  import reflex.state
25
25
  from reflex.base import Base
26
26
  from reflex.compiler.templates import STATEFUL_COMPONENT
27
+ from reflex.components.core.breakpoints import Breakpoints
27
28
  from reflex.components.tags import Tag
28
29
  from reflex.constants import (
29
30
  Dirs,
@@ -466,6 +467,12 @@ class Component(BaseComponent, ABC):
466
467
  # Merge styles, the later ones overriding keys in the earlier ones.
467
468
  style = {k: v for style_dict in style for k, v in style_dict.items()}
468
469
 
470
+ if isinstance(style, Breakpoints):
471
+ style = {
472
+ # Assign the Breakpoints to the self-referential selector to avoid squashing down to a regular dict.
473
+ "&": style,
474
+ }
475
+
469
476
  kwargs["style"] = Style(
470
477
  {
471
478
  **self.get_fields()["style"].default,
@@ -29,24 +29,49 @@ class Link(BaseHTML): # noqa: E742
29
29
 
30
30
  tag = "link"
31
31
 
32
+ # Specifies the CORS settings for the linked resource
32
33
  cross_origin: Var[Union[str, int, bool]]
34
+
35
+ # Specifies the URL of the linked document/resource
33
36
  href: Var[Union[str, int, bool]]
37
+
38
+ # Specifies the language of the text in the linked document
34
39
  href_lang: Var[Union[str, int, bool]]
40
+
41
+ # Allows a browser to check the fetched link for integrity
35
42
  integrity: Var[Union[str, int, bool]]
43
+
44
+ # Specifies on what device the linked document will be displayed
36
45
  media: Var[Union[str, int, bool]]
46
+
47
+ # Specifies the referrer policy of the linked document
37
48
  referrer_policy: Var[Union[str, int, bool]]
49
+
50
+ # Specifies the relationship between the current document and the linked one
38
51
  rel: Var[Union[str, int, bool]]
52
+
53
+ # Specifies the sizes of icons for visual media
39
54
  sizes: Var[Union[str, int, bool]]
55
+
56
+ # Specifies the MIME type of the linked document
40
57
  type: Var[Union[str, int, bool]]
41
58
 
42
59
 
43
60
  class Meta(BaseHTML): # Inherits common attributes from BaseHTML
44
61
  """Display the meta element."""
45
62
 
46
- tag = "meta"
63
+ tag = "meta" # The HTML tag for this element is <meta>
64
+
65
+ # Specifies the character encoding for the HTML document
47
66
  char_set: Var[Union[str, int, bool]]
67
+
68
+ # Defines the content of the metadata
48
69
  content: Var[Union[str, int, bool]]
70
+
71
+ # Provides an HTTP header for the information/value of the content attribute
49
72
  http_equiv: Var[Union[str, int, bool]]
73
+
74
+ # Specifies a name for the metadata
50
75
  name: Var[Union[str, int, bool]]
51
76
 
52
77
 
@@ -346,6 +346,15 @@ class Link(BaseHTML):
346
346
 
347
347
  Args:
348
348
  *children: The children of the component.
349
+ cross_origin: Specifies the CORS settings for the linked resource
350
+ href: Specifies the URL of the linked document/resource
351
+ href_lang: Specifies the language of the text in the linked document
352
+ integrity: Allows a browser to check the fetched link for integrity
353
+ media: Specifies on what device the linked document will be displayed
354
+ referrer_policy: Specifies the referrer policy of the linked document
355
+ rel: Specifies the relationship between the current document and the linked one
356
+ sizes: Specifies the sizes of icons for visual media
357
+ type: Specifies the MIME type of the linked document
349
358
  access_key: Provides a hint for generating a keyboard shortcut for the current element.
350
359
  auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
351
360
  content_editable: Indicates whether the element's content is editable.
@@ -466,6 +475,10 @@ class Meta(BaseHTML):
466
475
 
467
476
  Args:
468
477
  *children: The children of the component.
478
+ char_set: Specifies the character encoding for the HTML document
479
+ content: Defines the content of the metadata
480
+ http_equiv: Provides an HTTP header for the information/value of the content attribute
481
+ name: Specifies a name for the metadata
469
482
  access_key: Provides a hint for generating a keyboard shortcut for the current element.
470
483
  auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
471
484
  content_editable: Indicates whether the element's content is editable.
@@ -1,9 +1,7 @@
1
1
  """Experimental Immutable-Based Var System."""
2
2
 
3
3
  from .base import ImmutableVar as ImmutableVar
4
- from .base import LiteralObjectVar as LiteralObjectVar
5
4
  from .base import LiteralVar as LiteralVar
6
- from .base import ObjectVar as ObjectVar
7
5
  from .base import var_operation as var_operation
8
6
  from .function import FunctionStringVar as FunctionStringVar
9
7
  from .function import FunctionVar as FunctionVar
@@ -12,6 +10,8 @@ from .number import BooleanVar as BooleanVar
12
10
  from .number import LiteralBooleanVar as LiteralBooleanVar
13
11
  from .number import LiteralNumberVar as LiteralNumberVar
14
12
  from .number import NumberVar as NumberVar
13
+ from .object import LiteralObjectVar as LiteralObjectVar
14
+ from .object import ObjectVar as ObjectVar
15
15
  from .sequence import ArrayJoinOperation as ArrayJoinOperation
16
16
  from .sequence import ArrayVar as ArrayVar
17
17
  from .sequence import ConcatVarOperation as ConcatVarOperation
@@ -4,18 +4,25 @@ from __future__ import annotations
4
4
 
5
5
  import dataclasses
6
6
  import functools
7
+ import inspect
7
8
  import sys
8
9
  from typing import (
10
+ TYPE_CHECKING,
9
11
  Any,
10
12
  Callable,
11
13
  Dict,
14
+ Generic,
15
+ List,
12
16
  Optional,
17
+ Set,
18
+ Tuple,
13
19
  Type,
14
20
  TypeVar,
15
21
  Union,
22
+ overload,
16
23
  )
17
24
 
18
- from typing_extensions import ParamSpec
25
+ from typing_extensions import ParamSpec, get_origin
19
26
 
20
27
  from reflex import constants
21
28
  from reflex.base import Base
@@ -30,20 +37,33 @@ from reflex.vars import (
30
37
  _global_vars,
31
38
  )
32
39
 
40
+ if TYPE_CHECKING:
41
+ from .function import FunctionVar, ToFunctionOperation
42
+ from .number import (
43
+ BooleanVar,
44
+ NumberVar,
45
+ ToBooleanVarOperation,
46
+ ToNumberVarOperation,
47
+ )
48
+ from .object import ObjectVar, ToObjectOperation
49
+ from .sequence import ArrayVar, StringVar, ToArrayOperation, ToStringOperation
50
+
51
+ VAR_TYPE = TypeVar("VAR_TYPE")
52
+
33
53
 
34
54
  @dataclasses.dataclass(
35
55
  eq=False,
36
56
  frozen=True,
37
57
  **{"slots": True} if sys.version_info >= (3, 10) else {},
38
58
  )
39
- class ImmutableVar(Var):
59
+ class ImmutableVar(Var, Generic[VAR_TYPE]):
40
60
  """Base class for immutable vars."""
41
61
 
42
62
  # The name of the var.
43
63
  _var_name: str = dataclasses.field()
44
64
 
45
65
  # The type of the var.
46
- _var_type: Type = dataclasses.field(default=Any)
66
+ _var_type: types.GenericType = dataclasses.field(default=Any)
47
67
 
48
68
  # Extra metadata associated with the Var
49
69
  _var_data: Optional[ImmutableVarData] = dataclasses.field(default=None)
@@ -265,9 +285,140 @@ class ImmutableVar(Var):
265
285
  # Encode the _var_data into the formatted output for tracking purposes.
266
286
  return f"{constants.REFLEX_VAR_OPENING_TAG}{hashed_var}{constants.REFLEX_VAR_CLOSING_TAG}{self._var_name}"
267
287
 
288
+ @overload
289
+ def to(
290
+ self, output: Type[NumberVar], var_type: type[int] | type[float] = float
291
+ ) -> ToNumberVarOperation: ...
292
+
293
+ @overload
294
+ def to(self, output: Type[BooleanVar]) -> ToBooleanVarOperation: ...
295
+
296
+ @overload
297
+ def to(
298
+ self,
299
+ output: Type[ArrayVar],
300
+ var_type: type[list] | type[tuple] | type[set] = list,
301
+ ) -> ToArrayOperation: ...
302
+
303
+ @overload
304
+ def to(self, output: Type[StringVar]) -> ToStringOperation: ...
305
+
306
+ @overload
307
+ def to(
308
+ self, output: Type[ObjectVar], var_type: types.GenericType = dict
309
+ ) -> ToObjectOperation: ...
310
+
311
+ @overload
312
+ def to(
313
+ self, output: Type[FunctionVar], var_type: Type[Callable] = Callable
314
+ ) -> ToFunctionOperation: ...
315
+
316
+ @overload
317
+ def to(
318
+ self, output: Type[OUTPUT], var_type: types.GenericType | None = None
319
+ ) -> OUTPUT: ...
320
+
321
+ def to(
322
+ self, output: Type[OUTPUT], var_type: types.GenericType | None = None
323
+ ) -> Var:
324
+ """Convert the var to a different type.
325
+
326
+ Args:
327
+ output: The output type.
328
+ var_type: The type of the var.
329
+
330
+ Raises:
331
+ TypeError: If the var_type is not a supported type for the output.
332
+
333
+ Returns:
334
+ The converted var.
335
+ """
336
+ from .number import (
337
+ BooleanVar,
338
+ NumberVar,
339
+ ToBooleanVarOperation,
340
+ ToNumberVarOperation,
341
+ )
342
+
343
+ fixed_type = (
344
+ var_type
345
+ if var_type is None or inspect.isclass(var_type)
346
+ else get_origin(var_type)
347
+ )
348
+
349
+ if issubclass(output, NumberVar):
350
+ if fixed_type is not None and not issubclass(fixed_type, (int, float)):
351
+ raise TypeError(
352
+ f"Unsupported type {var_type} for NumberVar. Must be int or float."
353
+ )
354
+ return ToNumberVarOperation(self, var_type or float)
355
+ if issubclass(output, BooleanVar):
356
+ return ToBooleanVarOperation(self)
357
+
358
+ from .sequence import ArrayVar, StringVar, ToArrayOperation, ToStringOperation
359
+
360
+ if issubclass(output, ArrayVar):
361
+ if fixed_type is not None and not issubclass(
362
+ fixed_type, (list, tuple, set)
363
+ ):
364
+ raise TypeError(
365
+ f"Unsupported type {var_type} for ArrayVar. Must be list, tuple, or set."
366
+ )
367
+ return ToArrayOperation(self, var_type or list)
368
+ if issubclass(output, StringVar):
369
+ return ToStringOperation(self)
370
+
371
+ from .object import ObjectVar, ToObjectOperation
372
+
373
+ if issubclass(output, ObjectVar):
374
+ return ToObjectOperation(self, var_type or dict)
375
+
376
+ from .function import FunctionVar, ToFunctionOperation
377
+
378
+ if issubclass(output, FunctionVar):
379
+ if fixed_type is not None and not issubclass(fixed_type, Callable):
380
+ raise TypeError(
381
+ f"Unsupported type {var_type} for FunctionVar. Must be Callable."
382
+ )
383
+ return ToFunctionOperation(self, var_type or Callable)
384
+
385
+ return output(
386
+ _var_name=self._var_name,
387
+ _var_type=self._var_type if var_type is None else var_type,
388
+ _var_data=self._var_data,
389
+ )
390
+
391
+ def guess_type(self) -> ImmutableVar:
392
+ """Guess the type of the var.
393
+
394
+ Returns:
395
+ The guessed type.
396
+ """
397
+ from .number import NumberVar
398
+ from .object import ObjectVar
399
+ from .sequence import ArrayVar, StringVar
400
+
401
+ if self._var_type is Any:
402
+ return self
403
+
404
+ var_type = self._var_type
405
+
406
+ fixed_type = var_type if inspect.isclass(var_type) else get_origin(var_type)
407
+
408
+ if issubclass(fixed_type, (int, float)):
409
+ return self.to(NumberVar, var_type)
410
+ if issubclass(fixed_type, dict):
411
+ return self.to(ObjectVar, var_type)
412
+ if issubclass(fixed_type, (list, tuple, set)):
413
+ return self.to(ArrayVar, var_type)
414
+ if issubclass(fixed_type, str):
415
+ return self.to(StringVar)
416
+ if issubclass(fixed_type, Base):
417
+ return self.to(ObjectVar, var_type)
418
+ return self
268
419
 
269
- class ObjectVar(ImmutableVar):
270
- """Base class for immutable object vars."""
420
+
421
+ OUTPUT = TypeVar("OUTPUT", bound=ImmutableVar)
271
422
 
272
423
 
273
424
  class LiteralVar(ImmutableVar):
@@ -299,6 +450,8 @@ class LiteralVar(ImmutableVar):
299
450
  if value is None:
300
451
  return ImmutableVar.create_safe("null", _var_data=_var_data)
301
452
 
453
+ from .object import LiteralObjectVar
454
+
302
455
  if isinstance(value, Base):
303
456
  return LiteralObjectVar(
304
457
  value.dict(), _var_type=type(value), _var_data=_var_data
@@ -330,103 +483,16 @@ class LiteralVar(ImmutableVar):
330
483
  def __post_init__(self):
331
484
  """Post-initialize the var."""
332
485
 
486
+ def json(self) -> str:
487
+ """Serialize the var to a JSON string.
333
488
 
334
- @dataclasses.dataclass(
335
- eq=False,
336
- frozen=True,
337
- **{"slots": True} if sys.version_info >= (3, 10) else {},
338
- )
339
- class LiteralObjectVar(LiteralVar):
340
- """Base class for immutable literal object vars."""
341
-
342
- _var_value: Dict[Union[Var, Any], Union[Var, Any]] = dataclasses.field(
343
- default_factory=dict
344
- )
345
-
346
- def __init__(
347
- self,
348
- _var_value: dict[Var | Any, Var | Any],
349
- _var_type: Type = dict,
350
- _var_data: VarData | None = None,
351
- ):
352
- """Initialize the object var.
353
-
354
- Args:
355
- _var_value: The value of the var.
356
- _var_data: Additional hooks and imports associated with the Var.
357
- """
358
- super(LiteralObjectVar, self).__init__(
359
- _var_name="",
360
- _var_type=_var_type,
361
- _var_data=ImmutableVarData.merge(_var_data),
362
- )
363
- object.__setattr__(
364
- self,
365
- "_var_value",
366
- _var_value,
367
- )
368
- object.__delattr__(self, "_var_name")
369
-
370
- def __getattr__(self, name):
371
- """Get an attribute of the var.
372
-
373
- Args:
374
- name: The name of the attribute.
375
-
376
- Returns:
377
- The attribute of the var.
378
- """
379
- if name == "_var_name":
380
- return self._cached_var_name
381
- return super(type(self), self).__getattr__(name)
382
-
383
- @functools.cached_property
384
- def _cached_var_name(self) -> str:
385
- """The name of the var.
386
-
387
- Returns:
388
- The name of the var.
389
- """
390
- return (
391
- "{ "
392
- + ", ".join(
393
- [
394
- f"[{str(LiteralVar.create(key))}] : {str(LiteralVar.create(value))}"
395
- for key, value in self._var_value.items()
396
- ]
397
- )
398
- + " }"
399
- )
400
-
401
- @functools.cached_property
402
- def _cached_get_all_var_data(self) -> ImmutableVarData | None:
403
- """Get all VarData associated with the Var.
404
-
405
- Returns:
406
- The VarData of the components and all of its children.
489
+ Raises:
490
+ NotImplementedError: If the method is not implemented.
407
491
  """
408
- return ImmutableVarData.merge(
409
- *[
410
- value._get_all_var_data()
411
- for key, value in self._var_value
412
- if isinstance(value, Var)
413
- ],
414
- *[
415
- key._get_all_var_data()
416
- for key, value in self._var_value
417
- if isinstance(key, Var)
418
- ],
419
- self._var_data,
492
+ raise NotImplementedError(
493
+ "LiteralVar subclasses must implement the json method."
420
494
  )
421
495
 
422
- def _get_all_var_data(self) -> ImmutableVarData | None:
423
- """Wrapper method for cached property.
424
-
425
- Returns:
426
- The VarData of the components and all of its children.
427
- """
428
- return self._cached_get_all_var_data
429
-
430
496
 
431
497
  P = ParamSpec("P")
432
498
  T = TypeVar("T", bound=ImmutableVar)
@@ -475,3 +541,43 @@ def var_operation(*, output: Type[T]) -> Callable[[Callable[P, str]], Callable[P
475
541
  return wrapper
476
542
 
477
543
  return decorator
544
+
545
+
546
+ def unionize(*args: Type) -> Type:
547
+ """Unionize the types.
548
+
549
+ Args:
550
+ args: The types to unionize.
551
+
552
+ Returns:
553
+ The unionized types.
554
+ """
555
+ if not args:
556
+ return Any
557
+ first, *rest = args
558
+ if not rest:
559
+ return first
560
+ return Union[first, unionize(*rest)]
561
+
562
+
563
+ def figure_out_type(value: Any) -> Type:
564
+ """Figure out the type of the value.
565
+
566
+ Args:
567
+ value: The value to figure out the type of.
568
+
569
+ Returns:
570
+ The type of the value.
571
+ """
572
+ if isinstance(value, list):
573
+ return List[unionize(*(figure_out_type(v) for v in value))]
574
+ if isinstance(value, set):
575
+ return Set[unionize(*(figure_out_type(v) for v in value))]
576
+ if isinstance(value, tuple):
577
+ return Tuple[unionize(*(figure_out_type(v) for v in value)), ...]
578
+ if isinstance(value, dict):
579
+ return Dict[
580
+ unionize(*(figure_out_type(k) for k in value)),
581
+ unionize(*(figure_out_type(v) for v in value.values())),
582
+ ]
583
+ return type(value)
@@ -5,13 +5,13 @@ from __future__ import annotations
5
5
  import dataclasses
6
6
  import sys
7
7
  from functools import cached_property
8
- from typing import Any, Callable, Optional, Tuple, Union
8
+ from typing import Any, Callable, Optional, Tuple, Type, Union
9
9
 
10
10
  from reflex.experimental.vars.base import ImmutableVar, LiteralVar
11
11
  from reflex.vars import ImmutableVarData, Var, VarData
12
12
 
13
13
 
14
- class FunctionVar(ImmutableVar):
14
+ class FunctionVar(ImmutableVar[Callable]):
15
15
  """Base class for immutable function vars."""
16
16
 
17
17
  def __call__(self, *args: Var | Any) -> ArgsFunctionOperation:
@@ -212,3 +212,79 @@ class ArgsFunctionOperation(FunctionVar):
212
212
 
213
213
  def __post_init__(self):
214
214
  """Post-initialize the var."""
215
+
216
+
217
+ @dataclasses.dataclass(
218
+ eq=False,
219
+ frozen=True,
220
+ **{"slots": True} if sys.version_info >= (3, 10) else {},
221
+ )
222
+ class ToFunctionOperation(FunctionVar):
223
+ """Base class of converting a var to a function."""
224
+
225
+ _original_var: Var = dataclasses.field(
226
+ default_factory=lambda: LiteralVar.create(None)
227
+ )
228
+
229
+ def __init__(
230
+ self,
231
+ original_var: Var,
232
+ _var_type: Type[Callable] = Callable,
233
+ _var_data: VarData | None = None,
234
+ ) -> None:
235
+ """Initialize the function with arguments var.
236
+
237
+ Args:
238
+ original_var: The original var to convert to a function.
239
+ _var_type: The type of the function.
240
+ _var_data: Additional hooks and imports associated with the Var.
241
+ """
242
+ super(ToFunctionOperation, self).__init__(
243
+ _var_name=f"",
244
+ _var_type=_var_type,
245
+ _var_data=ImmutableVarData.merge(_var_data),
246
+ )
247
+ object.__setattr__(self, "_original_var", original_var)
248
+ object.__delattr__(self, "_var_name")
249
+
250
+ def __getattr__(self, name):
251
+ """Get an attribute of the var.
252
+
253
+ Args:
254
+ name: The name of the attribute.
255
+
256
+ Returns:
257
+ The attribute of the var.
258
+ """
259
+ if name == "_var_name":
260
+ return self._cached_var_name
261
+ return super(type(self), self).__getattr__(name)
262
+
263
+ @cached_property
264
+ def _cached_var_name(self) -> str:
265
+ """The name of the var.
266
+
267
+ Returns:
268
+ The name of the var.
269
+ """
270
+ return str(self._original_var)
271
+
272
+ @cached_property
273
+ def _cached_get_all_var_data(self) -> ImmutableVarData | None:
274
+ """Get all VarData associated with the Var.
275
+
276
+ Returns:
277
+ The VarData of the components and all of its children.
278
+ """
279
+ return ImmutableVarData.merge(
280
+ self._original_var._get_all_var_data(),
281
+ self._var_data,
282
+ )
283
+
284
+ def _get_all_var_data(self) -> ImmutableVarData | None:
285
+ """Wrapper method for cached property.
286
+
287
+ Returns:
288
+ The VarData of the components and all of its children.
289
+ """
290
+ return self._cached_get_all_var_data