reflex 0.8.12a1__py3-none-any.whl → 0.8.13a1__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.

@@ -269,25 +269,100 @@ def get_compiled_app(
269
269
  return app_module
270
270
 
271
271
 
272
+ def _can_colorize() -> bool:
273
+ """Check if the output can be colorized.
274
+
275
+ Copied from _colorize.can_colorize.
276
+
277
+ https://raw.githubusercontent.com/python/cpython/refs/heads/main/Lib/_colorize.py
278
+
279
+ Returns:
280
+ If the output can be colorized
281
+ """
282
+ import io
283
+ import os
284
+
285
+ def _safe_getenv(k: str, fallback: str | None = None) -> str | None:
286
+ """Exception-safe environment retrieval. See gh-128636.
287
+
288
+ Args:
289
+ k: The environment variable key.
290
+ fallback: The fallback value if the environment variable is not set.
291
+
292
+ Returns:
293
+ The value of the environment variable or the fallback value.
294
+ """
295
+ try:
296
+ return os.environ.get(k, fallback)
297
+ except Exception:
298
+ return fallback
299
+
300
+ file = sys.stdout
301
+
302
+ if not sys.flags.ignore_environment:
303
+ if _safe_getenv("PYTHON_COLORS") == "0":
304
+ return False
305
+ if _safe_getenv("PYTHON_COLORS") == "1":
306
+ return True
307
+ if _safe_getenv("NO_COLOR"):
308
+ return False
309
+ if _safe_getenv("FORCE_COLOR"):
310
+ return True
311
+ if _safe_getenv("TERM") == "dumb":
312
+ return False
313
+
314
+ if not hasattr(file, "fileno"):
315
+ return False
316
+
317
+ if sys.platform == "win32":
318
+ try:
319
+ import nt
320
+
321
+ if not nt._supports_virtual_terminal():
322
+ return False
323
+ except (ImportError, AttributeError):
324
+ return False
325
+
326
+ try:
327
+ return os.isatty(file.fileno())
328
+ except io.UnsupportedOperation:
329
+ return hasattr(file, "isatty") and file.isatty()
330
+
331
+
272
332
  def compile_or_validate_app(
273
333
  compile: bool = False,
274
334
  check_if_schema_up_to_date: bool = False,
275
335
  prerender_routes: bool = False,
276
- ):
336
+ ) -> bool:
277
337
  """Compile or validate the app module based on the default config.
278
338
 
279
339
  Args:
280
340
  compile: Whether to compile the app.
281
341
  check_if_schema_up_to_date: If True, check if the schema is up to date.
282
342
  prerender_routes: Whether to prerender routes.
343
+
344
+ Returns:
345
+ True if the app was successfully compiled or validated, False otherwise.
283
346
  """
284
- if compile:
285
- get_compiled_app(
286
- check_if_schema_up_to_date=check_if_schema_up_to_date,
287
- prerender_routes=prerender_routes,
288
- )
347
+ try:
348
+ if compile:
349
+ get_compiled_app(
350
+ check_if_schema_up_to_date=check_if_schema_up_to_date,
351
+ prerender_routes=prerender_routes,
352
+ )
353
+ else:
354
+ get_and_validate_app(check_if_schema_up_to_date=check_if_schema_up_to_date)
355
+ except Exception as e:
356
+ import traceback
357
+
358
+ try:
359
+ colorize = _can_colorize()
360
+ traceback.print_exception(e, colorize=colorize) # pyright: ignore[reportCallIssue]
361
+ except Exception:
362
+ traceback.print_exception(e)
363
+ return False
289
364
  else:
290
- get_and_validate_app(check_if_schema_up_to_date=check_if_schema_up_to_date)
365
+ return True
291
366
 
292
367
 
293
368
  def get_redis() -> Redis | None:
@@ -20,7 +20,7 @@ from pydantic import BaseModel as BaseModelV2
20
20
  from pydantic.v1 import BaseModel as BaseModelV1
21
21
 
22
22
  from reflex.base import Base
23
- from reflex.constants.colors import Color, format_color
23
+ from reflex.constants.colors import Color
24
24
  from reflex.utils import console, types
25
25
 
26
26
  # Mapping from type to a serializer.
@@ -413,8 +413,8 @@ def serialize_decimal(value: decimal.Decimal) -> float:
413
413
  return float(value)
414
414
 
415
415
 
416
- @serializer(to=str)
417
- def serialize_color(color: Color) -> str:
416
+ @serializer(to=dict)
417
+ def serialize_color(color: Color) -> dict:
418
418
  """Serialize a color.
419
419
 
420
420
  Args:
@@ -423,7 +423,11 @@ def serialize_color(color: Color) -> str:
423
423
  Returns:
424
424
  The serialized color.
425
425
  """
426
- return format_color(color.color, color.shade, color.alpha)
426
+ return {
427
+ "color": color.color,
428
+ "shade": color.shade,
429
+ "alpha": color.alpha,
430
+ }
427
431
 
428
432
 
429
433
  with contextlib.suppress(ImportError):
@@ -66,6 +66,16 @@ class TokenManager(ABC):
66
66
 
67
67
  return LocalTokenManager()
68
68
 
69
+ async def disconnect_all(self):
70
+ """Disconnect all tracked tokens when the server is going down."""
71
+ token_sid_pairs: set[tuple[str, str]] = set(self.token_to_sid.items())
72
+ token_sid_pairs.update(
73
+ ((token, sid) for sid, token in self.sid_to_token.items())
74
+ )
75
+ # Perform the disconnection logic here
76
+ for token, sid in token_sid_pairs:
77
+ await self.disconnect_token(token, sid)
78
+
69
79
 
70
80
  class LocalTokenManager(TokenManager):
71
81
  """Token manager using local in-memory dictionaries (single worker)."""
reflex/utils/types.py CHANGED
@@ -6,6 +6,7 @@ import dataclasses
6
6
  import sys
7
7
  import types
8
8
  from collections.abc import Callable, Iterable, Mapping, Sequence
9
+ from enum import Enum
9
10
  from functools import cached_property, lru_cache
10
11
  from types import GenericAlias
11
12
  from typing import ( # noqa: UP035
@@ -1241,6 +1242,7 @@ IMMUTABLE_TYPES = (
1241
1242
  frozenset,
1242
1243
  tuple,
1243
1244
  type(None),
1245
+ Enum,
1244
1246
  )
1245
1247
 
1246
1248
 
reflex/vars/__init__.py CHANGED
@@ -1,28 +1,58 @@
1
1
  """Immutable-Based Var System."""
2
2
 
3
- from .base import BaseStateMeta as BaseStateMeta
4
- from .base import EvenMoreBasicBaseState as EvenMoreBasicBaseState
5
- from .base import Field as Field
6
- from .base import LiteralVar as LiteralVar
7
- from .base import Var as Var
8
- from .base import VarData as VarData
9
- from .base import field as field
10
- from .base import get_unique_variable_name as get_unique_variable_name
11
- from .base import get_uuid_string_var as get_uuid_string_var
12
- from .base import var_operation as var_operation
13
- from .base import var_operation_return as var_operation_return
14
- from .datetime import DateTimeVar as DateTimeVar
15
- from .function import FunctionStringVar as FunctionStringVar
16
- from .function import FunctionVar as FunctionVar
17
- from .function import VarOperationCall as VarOperationCall
18
- from .number import BooleanVar as BooleanVar
19
- from .number import LiteralBooleanVar as LiteralBooleanVar
20
- from .number import LiteralNumberVar as LiteralNumberVar
21
- from .number import NumberVar as NumberVar
22
- from .object import LiteralObjectVar as LiteralObjectVar
23
- from .object import ObjectVar as ObjectVar
24
- from .sequence import ArrayVar as ArrayVar
25
- from .sequence import ConcatVarOperation as ConcatVarOperation
26
- from .sequence import LiteralArrayVar as LiteralArrayVar
27
- from .sequence import LiteralStringVar as LiteralStringVar
28
- from .sequence import StringVar as StringVar
3
+ from .base import (
4
+ BaseStateMeta,
5
+ EvenMoreBasicBaseState,
6
+ Field,
7
+ LiteralVar,
8
+ Var,
9
+ VarData,
10
+ field,
11
+ get_unique_variable_name,
12
+ get_uuid_string_var,
13
+ var_operation,
14
+ var_operation_return,
15
+ )
16
+ from .color import ColorVar, LiteralColorVar
17
+ from .datetime import DateTimeVar
18
+ from .function import FunctionStringVar, FunctionVar, VarOperationCall
19
+ from .number import BooleanVar, LiteralBooleanVar, LiteralNumberVar, NumberVar
20
+ from .object import LiteralObjectVar, ObjectVar
21
+ from .sequence import (
22
+ ArrayVar,
23
+ ConcatVarOperation,
24
+ LiteralArrayVar,
25
+ LiteralStringVar,
26
+ StringVar,
27
+ )
28
+
29
+ __all__ = [
30
+ "ArrayVar",
31
+ "BaseStateMeta",
32
+ "BooleanVar",
33
+ "ColorVar",
34
+ "ConcatVarOperation",
35
+ "DateTimeVar",
36
+ "EvenMoreBasicBaseState",
37
+ "Field",
38
+ "FunctionStringVar",
39
+ "FunctionVar",
40
+ "LiteralArrayVar",
41
+ "LiteralBooleanVar",
42
+ "LiteralColorVar",
43
+ "LiteralNumberVar",
44
+ "LiteralObjectVar",
45
+ "LiteralStringVar",
46
+ "LiteralVar",
47
+ "NumberVar",
48
+ "ObjectVar",
49
+ "StringVar",
50
+ "Var",
51
+ "VarData",
52
+ "VarOperationCall",
53
+ "field",
54
+ "get_unique_variable_name",
55
+ "get_uuid_string_var",
56
+ "var_operation",
57
+ "var_operation_return",
58
+ ]
reflex/vars/base.py CHANGED
@@ -18,21 +18,16 @@ from collections.abc import Callable, Coroutine, Iterable, Mapping, Sequence
18
18
  from dataclasses import _MISSING_TYPE, MISSING
19
19
  from decimal import Decimal
20
20
  from types import CodeType, FunctionType
21
- from typing import ( # noqa: UP035
21
+ from typing import (
22
22
  TYPE_CHECKING,
23
23
  Annotated,
24
24
  Any,
25
25
  ClassVar,
26
- Dict,
27
- FrozenSet,
28
26
  Generic,
29
- List,
30
27
  Literal,
31
28
  NoReturn,
32
29
  ParamSpec,
33
30
  Protocol,
34
- Set,
35
- Tuple,
36
31
  TypeGuard,
37
32
  TypeVar,
38
33
  cast,
@@ -78,8 +73,10 @@ from reflex.utils.types import (
78
73
 
79
74
  if TYPE_CHECKING:
80
75
  from reflex.components.component import BaseComponent
76
+ from reflex.constants.colors import Color
81
77
  from reflex.state import BaseState
82
78
 
79
+ from .color import LiteralColorVar
83
80
  from .number import BooleanVar, LiteralBooleanVar, LiteralNumberVar, NumberVar
84
81
  from .object import LiteralObjectVar, ObjectVar
85
82
  from .sequence import ArrayVar, LiteralArrayVar, LiteralStringVar, StringVar
@@ -642,6 +639,14 @@ class Var(Generic[VAR_TYPE], metaclass=MetaclassVar):
642
639
  _var_data: VarData | None = None,
643
640
  ) -> LiteralNumberVar[Decimal]: ...
644
641
 
642
+ @overload
643
+ @classmethod
644
+ def create( # pyright: ignore [reportOverlappingOverload]
645
+ cls,
646
+ value: Color,
647
+ _var_data: VarData | None = None,
648
+ ) -> LiteralColorVar: ...
649
+
645
650
  @overload
646
651
  @classmethod
647
652
  def create( # pyright: ignore [reportOverlappingOverload]
@@ -3080,7 +3085,8 @@ def transform(fn: Callable[[Var], Var]) -> Callable[[Var], Var]:
3080
3085
  TypeError: If the Var return type does not have a generic type.
3081
3086
  ValueError: If a function for the generic type is already registered.
3082
3087
  """
3083
- return_type = fn.__annotations__["return"]
3088
+ types = get_type_hints(fn)
3089
+ return_type = types["return"]
3084
3090
 
3085
3091
  origin = get_origin(return_type)
3086
3092
 
@@ -3105,101 +3111,6 @@ def transform(fn: Callable[[Var], Var]) -> Callable[[Var], Var]:
3105
3111
  return fn
3106
3112
 
3107
3113
 
3108
- def generic_type_to_actual_type_map(
3109
- generic_type: GenericType, actual_type: GenericType
3110
- ) -> dict[TypeVar, GenericType]:
3111
- """Map the generic type to the actual type.
3112
-
3113
- Args:
3114
- generic_type: The generic type.
3115
- actual_type: The actual type.
3116
-
3117
- Returns:
3118
- The mapping of type variables to actual types.
3119
-
3120
- Raises:
3121
- TypeError: If the generic type and actual type do not match.
3122
- TypeError: If the number of generic arguments and actual arguments do not match.
3123
- """
3124
- generic_origin = get_origin(generic_type) or generic_type
3125
- actual_origin = get_origin(actual_type) or actual_type
3126
-
3127
- if generic_origin is not actual_origin:
3128
- if isinstance(generic_origin, TypeVar):
3129
- return {generic_origin: actual_origin}
3130
- msg = f"Type mismatch: expected {generic_origin}, got {actual_origin}."
3131
- raise TypeError(msg)
3132
-
3133
- generic_args = get_args(generic_type)
3134
- actual_args = get_args(actual_type)
3135
-
3136
- if len(generic_args) != len(actual_args):
3137
- msg = f"Number of generic arguments mismatch: expected {len(generic_args)}, got {len(actual_args)}."
3138
- raise TypeError(msg)
3139
-
3140
- # call recursively for nested generic types and merge the results
3141
- return {
3142
- k: v
3143
- for generic_arg, actual_arg in zip(generic_args, actual_args, strict=True)
3144
- for k, v in generic_type_to_actual_type_map(generic_arg, actual_arg).items()
3145
- }
3146
-
3147
-
3148
- def resolve_generic_type_with_mapping(
3149
- generic_type: GenericType, type_mapping: dict[TypeVar, GenericType]
3150
- ):
3151
- """Resolve a generic type with a type mapping.
3152
-
3153
- Args:
3154
- generic_type: The generic type.
3155
- type_mapping: The type mapping.
3156
-
3157
- Returns:
3158
- The resolved generic type.
3159
- """
3160
- if isinstance(generic_type, TypeVar):
3161
- return type_mapping.get(generic_type, generic_type)
3162
-
3163
- generic_origin = get_origin(generic_type) or generic_type
3164
-
3165
- generic_args = get_args(generic_type)
3166
-
3167
- if not generic_args:
3168
- return generic_type
3169
-
3170
- mapping_for_older_python = {
3171
- list: List, # noqa: UP006
3172
- set: Set, # noqa: UP006
3173
- dict: Dict, # noqa: UP006
3174
- tuple: Tuple, # noqa: UP006
3175
- frozenset: FrozenSet, # noqa: UP006
3176
- }
3177
-
3178
- return mapping_for_older_python.get(generic_origin, generic_origin)[
3179
- tuple(
3180
- resolve_generic_type_with_mapping(arg, type_mapping) for arg in generic_args
3181
- )
3182
- ]
3183
-
3184
-
3185
- def resolve_arg_type_from_return_type(
3186
- arg_type: GenericType, return_type: GenericType, actual_return_type: GenericType
3187
- ) -> GenericType:
3188
- """Resolve the argument type from the return type.
3189
-
3190
- Args:
3191
- arg_type: The argument type.
3192
- return_type: The return type.
3193
- actual_return_type: The requested return type.
3194
-
3195
- Returns:
3196
- The argument type without the generics that are resolved.
3197
- """
3198
- return resolve_generic_type_with_mapping(
3199
- arg_type, generic_type_to_actual_type_map(return_type, actual_return_type)
3200
- )
3201
-
3202
-
3203
3114
  def dispatch(
3204
3115
  field_name: str,
3205
3116
  var_data: VarData,
@@ -3227,11 +3138,12 @@ def dispatch(
3227
3138
 
3228
3139
  if result_origin_var_type in dispatchers:
3229
3140
  fn = dispatchers[result_origin_var_type]
3230
- fn_first_arg_type = next(
3231
- iter(inspect.signature(fn).parameters.values())
3232
- ).annotation
3141
+ fn_types = get_type_hints(fn)
3142
+ fn_first_arg_type = fn_types.get(
3143
+ next(iter(inspect.signature(fn).parameters.values())).name, Any
3144
+ )
3233
3145
 
3234
- fn_return = inspect.signature(fn).return_annotation
3146
+ fn_return = fn_types.get("return", Any)
3235
3147
 
3236
3148
  fn_return_origin = get_origin(fn_return) or fn_return
3237
3149
 
@@ -3257,22 +3169,17 @@ def dispatch(
3257
3169
  msg = f"Expected generic type of {fn_first_arg_type} to be a type."
3258
3170
  raise TypeError(msg)
3259
3171
 
3260
- arg_type = arg_generic_args[0]
3261
3172
  fn_return_type = fn_return_generic_args[0]
3262
3173
 
3263
3174
  var = (
3264
3175
  Var(
3265
3176
  field_name,
3266
3177
  _var_data=var_data,
3267
- _var_type=resolve_arg_type_from_return_type(
3268
- arg_type, fn_return_type, result_var_type
3269
- ),
3178
+ _var_type=fn_return_type,
3270
3179
  ).guess_type()
3271
3180
  if existing_var is None
3272
3181
  else existing_var._replace(
3273
- _var_type=resolve_arg_type_from_return_type(
3274
- arg_type, fn_return_type, result_var_type
3275
- ),
3182
+ _var_type=fn_return_type,
3276
3183
  _var_data=var_data,
3277
3184
  _js_expr=field_name,
3278
3185
  ).guess_type()
reflex/vars/color.py ADDED
@@ -0,0 +1,214 @@
1
+ """Vars for colors."""
2
+
3
+ import dataclasses
4
+
5
+ from reflex.constants.colors import Color
6
+ from reflex.vars.base import (
7
+ CachedVarOperation,
8
+ LiteralVar,
9
+ Var,
10
+ VarData,
11
+ cached_property_no_lock,
12
+ get_python_literal,
13
+ transform,
14
+ )
15
+ from reflex.vars.number import BooleanVar, NumberVar, ternary_operation
16
+ from reflex.vars.object import LiteralObjectVar
17
+ from reflex.vars.sequence import ConcatVarOperation, LiteralStringVar, StringVar
18
+
19
+
20
+ @transform
21
+ def evaluate_color(js_dict: Var[dict]) -> Var[Color]:
22
+ """Evaluate a color var.
23
+
24
+ Args:
25
+ js_dict: The color var as a dict.
26
+
27
+ Returns:
28
+ The color var as a string.
29
+ """
30
+ js_color_dict = js_dict.to(dict)
31
+ str_part = ConcatVarOperation.create(
32
+ LiteralStringVar.create("var(--"),
33
+ js_color_dict.color,
34
+ LiteralStringVar.create("-"),
35
+ ternary_operation(
36
+ js_color_dict.alpha,
37
+ LiteralStringVar.create("a"),
38
+ LiteralStringVar.create(""),
39
+ ),
40
+ js_color_dict.shade.to_string(use_json=False),
41
+ LiteralStringVar.create(")"),
42
+ )
43
+ return js_dict._replace(
44
+ _js_expr=f"Object.assign(new String({str_part!s}), {js_dict!s})",
45
+ _var_type=Color,
46
+ )
47
+
48
+
49
+ class ColorVar(StringVar[Color], python_types=Color):
50
+ """Base class for immutable color vars."""
51
+
52
+ @property
53
+ def color(self) -> StringVar:
54
+ """Get the color of the color var.
55
+
56
+ Returns:
57
+ The color of the color var.
58
+ """
59
+ return self.to(dict).color.to(str)
60
+
61
+ @property
62
+ def alpha(self) -> BooleanVar:
63
+ """Get the alpha of the color var.
64
+
65
+ Returns:
66
+ The alpha of the color var.
67
+ """
68
+ return self.to(dict).alpha.to(bool)
69
+
70
+ @property
71
+ def shade(self) -> NumberVar:
72
+ """Get the shade of the color var.
73
+
74
+ Returns:
75
+ The shade of the color var.
76
+ """
77
+ return self.to(dict).shade.to(int)
78
+
79
+
80
+ @dataclasses.dataclass(
81
+ eq=False,
82
+ frozen=True,
83
+ slots=True,
84
+ )
85
+ class LiteralColorVar(CachedVarOperation, LiteralVar, ColorVar):
86
+ """Base class for immutable literal color vars."""
87
+
88
+ _var_value: Color = dataclasses.field(default_factory=lambda: Color(color="black"))
89
+
90
+ @classmethod
91
+ def create(
92
+ cls,
93
+ value: Color,
94
+ _var_type: type[Color] | None = None,
95
+ _var_data: VarData | None = None,
96
+ ) -> ColorVar:
97
+ """Create a var from a string value.
98
+
99
+ Args:
100
+ value: The value to create the var from.
101
+ _var_type: The type of the var.
102
+ _var_data: Additional hooks and imports associated with the Var.
103
+
104
+ Returns:
105
+ The var.
106
+ """
107
+ return cls(
108
+ _js_expr="",
109
+ _var_type=_var_type or Color,
110
+ _var_data=_var_data,
111
+ _var_value=value,
112
+ )
113
+
114
+ def __hash__(self) -> int:
115
+ """Get the hash of the var.
116
+
117
+ Returns:
118
+ The hash of the var.
119
+ """
120
+ return hash(
121
+ (
122
+ self.__class__.__name__,
123
+ self._var_value.color,
124
+ self._var_value.alpha,
125
+ self._var_value.shade,
126
+ )
127
+ )
128
+
129
+ @cached_property_no_lock
130
+ def _cached_var_name(self) -> str:
131
+ """The name of the var.
132
+
133
+ Returns:
134
+ The name of the var.
135
+ """
136
+ alpha = self._var_value.alpha
137
+ alpha = (
138
+ ternary_operation(
139
+ alpha,
140
+ LiteralStringVar.create("a"),
141
+ LiteralStringVar.create(""),
142
+ )
143
+ if isinstance(alpha, Var)
144
+ else LiteralStringVar.create("a" if alpha else "")
145
+ )
146
+
147
+ shade = self._var_value.shade
148
+ shade = (
149
+ shade.to_string(use_json=False)
150
+ if isinstance(shade, Var)
151
+ else LiteralStringVar.create(str(shade))
152
+ )
153
+ string_part = str(
154
+ ConcatVarOperation.create(
155
+ LiteralStringVar.create("var(--"),
156
+ self._var_value.color,
157
+ LiteralStringVar.create("-"),
158
+ alpha,
159
+ shade,
160
+ LiteralStringVar.create(")"),
161
+ )
162
+ )
163
+ dict_part = LiteralObjectVar.create(
164
+ {
165
+ "color": self._var_value.color,
166
+ "alpha": self._var_value.alpha,
167
+ "shade": self._var_value.shade,
168
+ }
169
+ )
170
+ return f"Object.assign(new String({string_part!s}), {dict_part!s})"
171
+
172
+ @cached_property_no_lock
173
+ def _cached_get_all_var_data(self) -> VarData | None:
174
+ """Get all the var data.
175
+
176
+ Returns:
177
+ The var data.
178
+ """
179
+ return VarData.merge(
180
+ *[
181
+ LiteralVar.create(var)._get_all_var_data()
182
+ for var in (
183
+ self._var_value.color,
184
+ self._var_value.alpha,
185
+ self._var_value.shade,
186
+ )
187
+ ],
188
+ self._var_data,
189
+ )
190
+
191
+ def json(self) -> str:
192
+ """Get the JSON representation of the var.
193
+
194
+ Returns:
195
+ The JSON representation of the var.
196
+
197
+ Raises:
198
+ TypeError: If the color is not a valid color.
199
+ """
200
+ color, alpha, shade = map(
201
+ get_python_literal,
202
+ (self._var_value.color, self._var_value.alpha, self._var_value.shade),
203
+ )
204
+ if color is None or alpha is None or shade is None:
205
+ msg = "Cannot serialize color that contains non-literal vars."
206
+ raise TypeError(msg)
207
+ if (
208
+ not isinstance(color, str)
209
+ or not isinstance(alpha, bool)
210
+ or not isinstance(shade, int)
211
+ ):
212
+ msg = "Color is not a valid color."
213
+ raise TypeError(msg)
214
+ return f"var(--{color}-{'a' if alpha else ''}{shade})"
reflex/vars/number.py CHANGED
@@ -909,7 +909,7 @@ def equal_operation(lhs: Var, rhs: Var):
909
909
  Returns:
910
910
  The result of the comparison.
911
911
  """
912
- return f"({lhs} === {rhs})"
912
+ return f"({lhs}?.valueOf?.() === {rhs}?.valueOf?.())"
913
913
 
914
914
 
915
915
  @comparison_operator
@@ -923,7 +923,7 @@ def not_equal_operation(lhs: Var, rhs: Var):
923
923
  Returns:
924
924
  The result of the comparison.
925
925
  """
926
- return f"({lhs} !== {rhs})"
926
+ return f"({lhs}?.valueOf?.() !== {rhs}?.valueOf?.())"
927
927
 
928
928
 
929
929
  @var_operation