reflex 0.7.3a1__py3-none-any.whl → 0.7.4__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.

Files changed (50) hide show
  1. reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +9 -1
  2. reflex/.templates/web/utils/state.js +1 -1
  3. reflex/app.py +21 -5
  4. reflex/app_mixins/middleware.py +2 -3
  5. reflex/base.py +3 -3
  6. reflex/compiler/compiler.py +68 -8
  7. reflex/components/component.py +6 -3
  8. reflex/components/core/client_side_routing.py +3 -3
  9. reflex/components/core/cond.py +20 -12
  10. reflex/components/core/upload.py +1 -1
  11. reflex/components/dynamic.py +2 -4
  12. reflex/components/lucide/icon.py +20 -27
  13. reflex/components/plotly/plotly.py +9 -9
  14. reflex/components/recharts/recharts.py +2 -2
  15. reflex/components/sonner/toast.py +1 -1
  16. reflex/config.py +23 -23
  17. reflex/constants/__init__.py +1 -2
  18. reflex/constants/base.py +3 -0
  19. reflex/constants/installer.py +8 -105
  20. reflex/custom_components/custom_components.py +8 -3
  21. reflex/reflex.py +22 -4
  22. reflex/state.py +9 -1
  23. reflex/testing.py +7 -1
  24. reflex/utils/build.py +3 -4
  25. reflex/utils/exec.py +156 -75
  26. reflex/utils/net.py +107 -18
  27. reflex/utils/path_ops.py +15 -25
  28. reflex/utils/prerequisites.py +225 -189
  29. reflex/utils/processes.py +70 -35
  30. reflex/utils/redir.py +3 -1
  31. reflex/utils/registry.py +16 -8
  32. reflex/vars/base.py +2 -38
  33. reflex/vars/datetime.py +10 -34
  34. reflex/vars/number.py +16 -112
  35. reflex/vars/sequence.py +99 -108
  36. {reflex-0.7.3a1.dist-info → reflex-0.7.4.dist-info}/METADATA +32 -23
  37. {reflex-0.7.3a1.dist-info → reflex-0.7.4.dist-info}/RECORD +58 -68
  38. {reflex-0.7.3a1.dist-info → reflex-0.7.4.dist-info}/WHEEL +1 -1
  39. {reflex-0.7.3a1.dist-info → reflex-0.7.4.dist-info}/entry_points.txt +0 -3
  40. benchmarks/__init__.py +0 -3
  41. benchmarks/benchmark_compile_times.py +0 -147
  42. benchmarks/benchmark_imports.py +0 -128
  43. benchmarks/benchmark_lighthouse.py +0 -75
  44. benchmarks/benchmark_package_size.py +0 -135
  45. benchmarks/benchmark_web_size.py +0 -106
  46. benchmarks/conftest.py +0 -20
  47. benchmarks/lighthouse.sh +0 -77
  48. benchmarks/utils.py +0 -74
  49. reflex/app_module_for_backend.py +0 -33
  50. {reflex-0.7.3a1.dist-info → reflex-0.7.4.dist-info}/licenses/LICENSE +0 -0
reflex/utils/processes.py CHANGED
@@ -10,7 +10,7 @@ import signal
10
10
  import subprocess
11
11
  from concurrent import futures
12
12
  from pathlib import Path
13
- from typing import Callable, Generator, Tuple
13
+ from typing import Any, Callable, Generator, Literal, Sequence, Tuple, overload
14
14
 
15
15
  import psutil
16
16
  import typer
@@ -142,12 +142,30 @@ def handle_port(service_name: str, port: int, auto_increment: bool) -> int:
142
142
  raise typer.Exit()
143
143
 
144
144
 
145
+ @overload
146
+ def new_process(
147
+ args: str | list[str] | list[str | None] | list[str | Path | None],
148
+ run: Literal[False] = False,
149
+ show_logs: bool = False,
150
+ **kwargs,
151
+ ) -> subprocess.Popen[str]: ...
152
+
153
+
154
+ @overload
155
+ def new_process(
156
+ args: str | list[str] | list[str | None] | list[str | Path | None],
157
+ run: Literal[True],
158
+ show_logs: bool = False,
159
+ **kwargs,
160
+ ) -> subprocess.CompletedProcess[str]: ...
161
+
162
+
145
163
  def new_process(
146
164
  args: str | list[str] | list[str | None] | list[str | Path | None],
147
165
  run: bool = False,
148
166
  show_logs: bool = False,
149
167
  **kwargs,
150
- ):
168
+ ) -> subprocess.CompletedProcess[str] | subprocess.Popen[str]:
151
169
  """Wrapper over subprocess.Popen to unify the launch of child processes.
152
170
 
153
171
  Args:
@@ -163,7 +181,8 @@ def new_process(
163
181
  Exit: When attempting to run a command with a None value.
164
182
  """
165
183
  # Check for invalid command first.
166
- if isinstance(args, list) and None in args:
184
+ non_empty_args = list(filter(None, args)) if isinstance(args, list) else [args]
185
+ if isinstance(args, list) and len(non_empty_args) != len(args):
167
186
  console.error(f"Invalid command: {args}")
168
187
  raise typer.Exit(1)
169
188
 
@@ -171,14 +190,9 @@ def new_process(
171
190
 
172
191
  # Add node_bin_path to the PATH environment variable.
173
192
  if not environment.REFLEX_BACKEND_ONLY.get():
174
- node_bin_path = str(path_ops.get_node_bin_path())
175
- if not node_bin_path and not prerequisites.CURRENTLY_INSTALLING_NODE:
176
- console.warn(
177
- "The path to the Node binary could not be found. Please ensure that Node is properly "
178
- "installed and added to your system's PATH environment variable or try running "
179
- "`reflex init` again."
180
- )
181
- path_env = os.pathsep.join([node_bin_path, path_env])
193
+ node_bin_path = path_ops.get_node_bin_path()
194
+ if node_bin_path:
195
+ path_env = os.pathsep.join([str(node_bin_path), path_env])
182
196
 
183
197
  env: dict[str, str] = {
184
198
  **os.environ,
@@ -195,14 +209,20 @@ def new_process(
195
209
  "errors": "replace", # Avoid UnicodeDecodeError in unknown command output
196
210
  **kwargs,
197
211
  }
198
- console.debug(f"Running command: {args}")
199
- fn = subprocess.run if run else subprocess.Popen
200
- return fn(args, **kwargs) # pyright: ignore [reportCallIssue, reportArgumentType]
212
+ console.debug(f"Running command: {non_empty_args}")
213
+
214
+ def subprocess_p_open(args: subprocess._CMD, **kwargs):
215
+ return subprocess.Popen(args, **kwargs)
216
+
217
+ fn: Callable[..., subprocess.CompletedProcess[str] | subprocess.Popen[str]] = (
218
+ subprocess.run if run else subprocess_p_open
219
+ )
220
+ return fn(non_empty_args, **kwargs)
201
221
 
202
222
 
203
223
  @contextlib.contextmanager
204
224
  def run_concurrently_context(
205
- *fns: Callable | Tuple,
225
+ *fns: Callable[..., Any] | tuple[Callable[..., Any], ...],
206
226
  ) -> Generator[list[futures.Future], None, None]:
207
227
  """Run functions concurrently in a thread pool.
208
228
 
@@ -218,14 +238,14 @@ def run_concurrently_context(
218
238
  return
219
239
 
220
240
  # Convert the functions to tuples.
221
- fns = [fn if isinstance(fn, tuple) else (fn,) for fn in fns] # pyright: ignore [reportAssignmentType]
241
+ fns = tuple(fn if isinstance(fn, tuple) else (fn,) for fn in fns)
222
242
 
223
243
  # Run the functions concurrently.
224
244
  executor = None
225
245
  try:
226
246
  executor = futures.ThreadPoolExecutor(max_workers=len(fns))
227
247
  # Submit the tasks.
228
- tasks = [executor.submit(*fn) for fn in fns] # pyright: ignore [reportArgumentType]
248
+ tasks = [executor.submit(*fn) for fn in fns]
229
249
 
230
250
  # Yield control back to the main thread while tasks are running.
231
251
  yield tasks
@@ -316,6 +336,7 @@ def show_status(
316
336
  process: subprocess.Popen,
317
337
  suppress_errors: bool = False,
318
338
  analytics_enabled: bool = False,
339
+ prior_processes: Tuple[subprocess.Popen, ...] = (),
319
340
  ):
320
341
  """Show the status of a process.
321
342
 
@@ -324,15 +345,17 @@ def show_status(
324
345
  process: The process.
325
346
  suppress_errors: If True, do not exit if errors are encountered (for fallback).
326
347
  analytics_enabled: Whether analytics are enabled for this command.
348
+ prior_processes: The prior processes that have been run.
327
349
  """
328
- with console.status(message) as status:
329
- for line in stream_logs(
330
- message,
331
- process,
332
- suppress_errors=suppress_errors,
333
- analytics_enabled=analytics_enabled,
334
- ):
335
- status.update(f"{message} {line}")
350
+ for one_process in (*prior_processes, process):
351
+ with console.status(message) as status:
352
+ for line in stream_logs(
353
+ message,
354
+ one_process,
355
+ suppress_errors=suppress_errors,
356
+ analytics_enabled=analytics_enabled,
357
+ ):
358
+ status.update(f"{message} {line}")
336
359
 
337
360
 
338
361
  def show_progress(message: str, process: subprocess.Popen, checkpoints: list[str]):
@@ -380,12 +403,13 @@ def get_command_with_loglevel(command: list[str]) -> list[str]:
380
403
  return command
381
404
 
382
405
 
383
- def run_process_with_fallback(
406
+ def run_process_with_fallbacks(
384
407
  args: list[str],
385
408
  *,
386
409
  show_status_message: str,
387
- fallback: str | list | None = None,
410
+ fallbacks: str | Sequence[str] | Sequence[Sequence[str]] | None = None,
388
411
  analytics_enabled: bool = False,
412
+ prior_processes: Tuple[subprocess.Popen, ...] = (),
389
413
  **kwargs,
390
414
  ):
391
415
  """Run subprocess and retry using fallback command if initial command fails.
@@ -393,32 +417,43 @@ def run_process_with_fallback(
393
417
  Args:
394
418
  args: A string, or a sequence of program arguments.
395
419
  show_status_message: The status message to be displayed in the console.
396
- fallback: The fallback command to run.
420
+ fallbacks: The fallback command to run if the initial command fails.
397
421
  analytics_enabled: Whether analytics are enabled for this command.
398
- kwargs: Kwargs to pass to new_process function.
422
+ prior_processes: The prior processes that have been run.
423
+ **kwargs: Kwargs to pass to new_process function.
399
424
  """
400
425
  process = new_process(get_command_with_loglevel(args), **kwargs)
401
- if fallback is None:
426
+ if not fallbacks:
402
427
  # No fallback given, or this _is_ the fallback command.
403
428
  show_status(
404
429
  show_status_message,
405
430
  process,
406
431
  analytics_enabled=analytics_enabled,
432
+ prior_processes=prior_processes,
407
433
  )
408
434
  else:
409
435
  # Suppress errors for initial command, because we will try to fallback
410
436
  show_status(show_status_message, process, suppress_errors=True)
437
+
438
+ current_fallback = fallbacks[0] if not isinstance(fallbacks, str) else fallbacks
439
+ next_fallbacks = fallbacks[1:] if not isinstance(fallbacks, str) else None
440
+
411
441
  if process.returncode != 0:
412
442
  # retry with fallback command.
413
- fallback_args = [fallback, *args[1:]]
443
+ fallback_with_args = (
444
+ [current_fallback, *args[1:]]
445
+ if isinstance(current_fallback, str)
446
+ else [*current_fallback, *args[1:]]
447
+ )
414
448
  console.warn(
415
- f"There was an error running command: {args}. Falling back to: {fallback_args}."
449
+ f"There was an error running command: {args}. Falling back to: {fallback_with_args}."
416
450
  )
417
- run_process_with_fallback(
418
- fallback_args,
451
+ run_process_with_fallbacks(
452
+ fallback_with_args,
419
453
  show_status_message=show_status_message,
420
- fallback=None,
454
+ fallbacks=next_fallbacks,
421
455
  analytics_enabled=analytics_enabled,
456
+ prior_processes=(*prior_processes, process),
422
457
  **kwargs,
423
458
  )
424
459
 
reflex/utils/redir.py CHANGED
@@ -5,6 +5,8 @@ import webbrowser
5
5
 
6
6
  import httpx
7
7
 
8
+ from reflex.utils import net
9
+
8
10
  from .. import constants
9
11
  from . import console
10
12
 
@@ -38,7 +40,7 @@ def open_browser_and_wait(
38
40
  console.info("[b]Complete the workflow in the browser to continue.[/b]")
39
41
  while True:
40
42
  try:
41
- response = httpx.get(poll_url, follow_redirects=True)
43
+ response = net.get(poll_url, follow_redirects=True)
42
44
  if response.is_success:
43
45
  break
44
46
  except httpx.RequestError as err:
reflex/utils/registry.py CHANGED
@@ -16,10 +16,13 @@ def latency(registry: str) -> int:
16
16
  int: The latency of the registry in microseconds.
17
17
  """
18
18
  try:
19
- return net.get(registry).elapsed.microseconds
19
+ time_to_respond = net.get(registry, timeout=2).elapsed.microseconds
20
20
  except httpx.HTTPError:
21
21
  console.info(f"Failed to connect to {registry}.")
22
22
  return 10_000_000
23
+ else:
24
+ console.debug(f"Latency of {registry}: {time_to_respond}")
25
+ return time_to_respond
23
26
 
24
27
 
25
28
  def average_latency(registry: str, attempts: int = 3) -> int:
@@ -32,27 +35,32 @@ def average_latency(registry: str, attempts: int = 3) -> int:
32
35
  Returns:
33
36
  The average latency of the registry in microseconds.
34
37
  """
35
- return sum(latency(registry) for _ in range(attempts)) // attempts
38
+ registry_latency = sum(latency(registry) for _ in range(attempts)) // attempts
39
+ console.debug(f"Average latency of {registry}: {registry_latency}")
40
+ return registry_latency
36
41
 
37
42
 
38
- def get_best_registry() -> str:
43
+ def _get_best_registry() -> str:
39
44
  """Get the best registry based on latency.
40
45
 
41
46
  Returns:
42
- str: The best registry.
47
+ The best registry.
43
48
  """
49
+ console.debug("Getting best registry...")
44
50
  registries = [
45
51
  "https://registry.npmjs.org",
46
52
  "https://r.cnpmjs.org",
47
53
  ]
48
54
 
49
- return min(registries, key=average_latency)
55
+ best_registry = min(registries, key=average_latency)
56
+ console.debug(f"Best registry: {best_registry}")
57
+ return best_registry
50
58
 
51
59
 
52
- def _get_npm_registry() -> str:
60
+ def get_npm_registry() -> str:
53
61
  """Get npm registry. If environment variable is set, use it first.
54
62
 
55
63
  Returns:
56
- str:
64
+ The npm registry.
57
65
  """
58
- return environment.NPM_CONFIG_REGISTRY.get() or get_best_registry()
66
+ return environment.NPM_CONFIG_REGISTRY.get() or _get_best_registry()
reflex/vars/base.py CHANGED
@@ -160,7 +160,7 @@ class VarData:
160
160
  if isinstance(hooks, str):
161
161
  hooks = [hooks]
162
162
  if not isinstance(hooks, dict):
163
- hooks = {hook: None for hook in (hooks or [])}
163
+ hooks = dict.fromkeys(hooks or [])
164
164
  immutable_imports: ImmutableParsedImportDict = tuple(
165
165
  (k, tuple(v)) for k, v in parse_imports(imports or {}).items()
166
166
  )
@@ -1791,8 +1791,7 @@ class cached_property: # noqa: N801
1791
1791
  if original_del is not None:
1792
1792
  original_del(this)
1793
1793
  return
1794
- if unique_id in GLOBAL_CACHE:
1795
- del GLOBAL_CACHE[unique_id]
1794
+ GLOBAL_CACHE.pop(unique_id, None)
1796
1795
 
1797
1796
  if original_del is not None:
1798
1797
  original_del(this)
@@ -3017,41 +3016,6 @@ _decode_var_pattern = re.compile(_decode_var_pattern_re, flags=re.DOTALL)
3017
3016
  _global_vars: dict[int, Var] = {}
3018
3017
 
3019
3018
 
3020
- def _extract_var_data(value: Iterable) -> list[VarData | None]:
3021
- """Extract the var imports and hooks from an iterable containing a Var.
3022
-
3023
- Args:
3024
- value: The iterable to extract the VarData from
3025
-
3026
- Returns:
3027
- The extracted VarDatas.
3028
- """
3029
- from reflex.style import Style
3030
- from reflex.vars import Var
3031
-
3032
- var_datas = []
3033
- with contextlib.suppress(TypeError):
3034
- for sub in value:
3035
- if isinstance(sub, Var):
3036
- var_datas.append(sub._var_data)
3037
- elif not isinstance(sub, str):
3038
- # Recurse into dict values.
3039
- if hasattr(sub, "values") and callable(sub.values):
3040
- var_datas.extend(_extract_var_data(sub.values())) # pyright: ignore [reportArgumentType]
3041
- # Recurse into iterable values (or dict keys).
3042
- var_datas.extend(_extract_var_data(sub))
3043
-
3044
- # Style objects should already have _var_data.
3045
- if isinstance(value, Style):
3046
- var_datas.append(value._var_data)
3047
- else:
3048
- # Recurse when value is a dict itself.
3049
- values = getattr(value, "values", None)
3050
- if callable(values):
3051
- var_datas.extend(_extract_var_data(values())) # pyright: ignore [reportArgumentType]
3052
- return var_datas
3053
-
3054
-
3055
3019
  dispatchers: dict[GenericType, Callable[[Var], Var]] = {}
3056
3020
 
3057
3021
 
reflex/vars/datetime.py CHANGED
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import dataclasses
6
6
  from datetime import date, datetime
7
- from typing import Any, NoReturn, TypeVar, overload
7
+ from typing import Any, TypeVar
8
8
 
9
9
  from reflex.utils.exceptions import VarTypeError
10
10
  from reflex.vars.number import BooleanVar
@@ -35,13 +35,7 @@ def raise_var_type_error():
35
35
  class DateTimeVar(Var[DATETIME_T], python_types=(datetime, date)):
36
36
  """A variable that holds a datetime or date object."""
37
37
 
38
- @overload
39
- def __lt__(self, other: datetime_types) -> BooleanVar: ...
40
-
41
- @overload
42
- def __lt__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
43
-
44
- def __lt__(self, other: Any):
38
+ def __lt__(self, other: datetime_types | DateTimeVar) -> BooleanVar:
45
39
  """Less than comparison.
46
40
 
47
41
  Args:
@@ -54,13 +48,7 @@ class DateTimeVar(Var[DATETIME_T], python_types=(datetime, date)):
54
48
  raise_var_type_error()
55
49
  return date_lt_operation(self, other)
56
50
 
57
- @overload
58
- def __le__(self, other: datetime_types) -> BooleanVar: ...
59
-
60
- @overload
61
- def __le__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
62
-
63
- def __le__(self, other: Any):
51
+ def __le__(self, other: datetime_types | DateTimeVar) -> BooleanVar:
64
52
  """Less than or equal comparison.
65
53
 
66
54
  Args:
@@ -73,13 +61,7 @@ class DateTimeVar(Var[DATETIME_T], python_types=(datetime, date)):
73
61
  raise_var_type_error()
74
62
  return date_le_operation(self, other)
75
63
 
76
- @overload
77
- def __gt__(self, other: datetime_types) -> BooleanVar: ...
78
-
79
- @overload
80
- def __gt__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
81
-
82
- def __gt__(self, other: Any):
64
+ def __gt__(self, other: datetime_types | DateTimeVar) -> BooleanVar:
83
65
  """Greater than comparison.
84
66
 
85
67
  Args:
@@ -92,13 +74,7 @@ class DateTimeVar(Var[DATETIME_T], python_types=(datetime, date)):
92
74
  raise_var_type_error()
93
75
  return date_gt_operation(self, other)
94
76
 
95
- @overload
96
- def __ge__(self, other: datetime_types) -> BooleanVar: ...
97
-
98
- @overload
99
- def __ge__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
100
-
101
- def __ge__(self, other: Any):
77
+ def __ge__(self, other: datetime_types | DateTimeVar) -> BooleanVar:
102
78
  """Greater than or equal comparison.
103
79
 
104
80
  Args:
@@ -113,7 +89,7 @@ class DateTimeVar(Var[DATETIME_T], python_types=(datetime, date)):
113
89
 
114
90
 
115
91
  @var_operation
116
- def date_gt_operation(lhs: Var | Any, rhs: Var | Any) -> CustomVarOperationReturn:
92
+ def date_gt_operation(lhs: DateTimeVar | Any, rhs: DateTimeVar | Any):
117
93
  """Greater than comparison.
118
94
 
119
95
  Args:
@@ -127,7 +103,7 @@ def date_gt_operation(lhs: Var | Any, rhs: Var | Any) -> CustomVarOperationRetur
127
103
 
128
104
 
129
105
  @var_operation
130
- def date_lt_operation(lhs: Var | Any, rhs: Var | Any) -> CustomVarOperationReturn:
106
+ def date_lt_operation(lhs: DateTimeVar | Any, rhs: DateTimeVar | Any):
131
107
  """Less than comparison.
132
108
 
133
109
  Args:
@@ -141,7 +117,7 @@ def date_lt_operation(lhs: Var | Any, rhs: Var | Any) -> CustomVarOperationRetur
141
117
 
142
118
 
143
119
  @var_operation
144
- def date_le_operation(lhs: Var | Any, rhs: Var | Any) -> CustomVarOperationReturn:
120
+ def date_le_operation(lhs: DateTimeVar | Any, rhs: DateTimeVar | Any):
145
121
  """Less than or equal comparison.
146
122
 
147
123
  Args:
@@ -155,7 +131,7 @@ def date_le_operation(lhs: Var | Any, rhs: Var | Any) -> CustomVarOperationRetur
155
131
 
156
132
 
157
133
  @var_operation
158
- def date_ge_operation(lhs: Var | Any, rhs: Var | Any) -> CustomVarOperationReturn:
134
+ def date_ge_operation(lhs: DateTimeVar | Any, rhs: DateTimeVar | Any):
159
135
  """Greater than or equal comparison.
160
136
 
161
137
  Args:
@@ -172,7 +148,7 @@ def date_compare_operation(
172
148
  lhs: DateTimeVar[DATETIME_T] | Any,
173
149
  rhs: DateTimeVar[DATETIME_T] | Any,
174
150
  strict: bool = False,
175
- ) -> CustomVarOperationReturn:
151
+ ) -> CustomVarOperationReturn[bool]:
176
152
  """Check if the value is less than the other value.
177
153
 
178
154
  Args:
reflex/vars/number.py CHANGED
@@ -61,13 +61,7 @@ def raise_unsupported_operand_types(
61
61
  class NumberVar(Var[NUMBER_T], python_types=(int, float)):
62
62
  """Base class for immutable number vars."""
63
63
 
64
- @overload
65
- def __add__(self, other: number_types) -> NumberVar: ...
66
-
67
- @overload
68
- def __add__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
69
-
70
- def __add__(self, other: Any):
64
+ def __add__(self, other: number_types) -> NumberVar:
71
65
  """Add two numbers.
72
66
 
73
67
  Args:
@@ -80,13 +74,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
80
74
  raise_unsupported_operand_types("+", (type(self), type(other)))
81
75
  return number_add_operation(self, +other)
82
76
 
83
- @overload
84
- def __radd__(self, other: number_types) -> NumberVar: ...
85
-
86
- @overload
87
- def __radd__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
88
-
89
- def __radd__(self, other: Any):
77
+ def __radd__(self, other: number_types) -> NumberVar:
90
78
  """Add two numbers.
91
79
 
92
80
  Args:
@@ -99,13 +87,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
99
87
  raise_unsupported_operand_types("+", (type(other), type(self)))
100
88
  return number_add_operation(+other, self)
101
89
 
102
- @overload
103
- def __sub__(self, other: number_types) -> NumberVar: ...
104
-
105
- @overload
106
- def __sub__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
107
-
108
- def __sub__(self, other: Any):
90
+ def __sub__(self, other: number_types) -> NumberVar:
109
91
  """Subtract two numbers.
110
92
 
111
93
  Args:
@@ -119,13 +101,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
119
101
 
120
102
  return number_subtract_operation(self, +other)
121
103
 
122
- @overload
123
- def __rsub__(self, other: number_types) -> NumberVar: ...
124
-
125
- @overload
126
- def __rsub__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
127
-
128
- def __rsub__(self, other: Any):
104
+ def __rsub__(self, other: number_types) -> NumberVar:
129
105
  """Subtract two numbers.
130
106
 
131
107
  Args:
@@ -201,13 +177,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
201
177
 
202
178
  return number_multiply_operation(+other, self)
203
179
 
204
- @overload
205
- def __truediv__(self, other: number_types) -> NumberVar: ...
206
-
207
- @overload
208
- def __truediv__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
209
-
210
- def __truediv__(self, other: Any):
180
+ def __truediv__(self, other: number_types) -> NumberVar:
211
181
  """Divide two numbers.
212
182
 
213
183
  Args:
@@ -221,13 +191,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
221
191
 
222
192
  return number_true_division_operation(self, +other)
223
193
 
224
- @overload
225
- def __rtruediv__(self, other: number_types) -> NumberVar: ...
226
-
227
- @overload
228
- def __rtruediv__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
229
-
230
- def __rtruediv__(self, other: Any):
194
+ def __rtruediv__(self, other: number_types) -> NumberVar:
231
195
  """Divide two numbers.
232
196
 
233
197
  Args:
@@ -241,13 +205,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
241
205
 
242
206
  return number_true_division_operation(+other, self)
243
207
 
244
- @overload
245
- def __floordiv__(self, other: number_types) -> NumberVar: ...
246
-
247
- @overload
248
- def __floordiv__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
249
-
250
- def __floordiv__(self, other: Any):
208
+ def __floordiv__(self, other: number_types) -> NumberVar:
251
209
  """Floor divide two numbers.
252
210
 
253
211
  Args:
@@ -261,13 +219,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
261
219
 
262
220
  return number_floor_division_operation(self, +other)
263
221
 
264
- @overload
265
- def __rfloordiv__(self, other: number_types) -> NumberVar: ...
266
-
267
- @overload
268
- def __rfloordiv__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
269
-
270
- def __rfloordiv__(self, other: Any):
222
+ def __rfloordiv__(self, other: number_types) -> NumberVar:
271
223
  """Floor divide two numbers.
272
224
 
273
225
  Args:
@@ -281,13 +233,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
281
233
 
282
234
  return number_floor_division_operation(+other, self)
283
235
 
284
- @overload
285
- def __mod__(self, other: number_types) -> NumberVar: ...
286
-
287
- @overload
288
- def __mod__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
289
-
290
- def __mod__(self, other: Any):
236
+ def __mod__(self, other: number_types) -> NumberVar:
291
237
  """Modulo two numbers.
292
238
 
293
239
  Args:
@@ -301,13 +247,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
301
247
 
302
248
  return number_modulo_operation(self, +other)
303
249
 
304
- @overload
305
- def __rmod__(self, other: number_types) -> NumberVar: ...
306
-
307
- @overload
308
- def __rmod__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
309
-
310
- def __rmod__(self, other: Any):
250
+ def __rmod__(self, other: number_types) -> NumberVar:
311
251
  """Modulo two numbers.
312
252
 
313
253
  Args:
@@ -321,13 +261,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
321
261
 
322
262
  return number_modulo_operation(+other, self)
323
263
 
324
- @overload
325
- def __pow__(self, other: number_types) -> NumberVar: ...
326
-
327
- @overload
328
- def __pow__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
329
-
330
- def __pow__(self, other: Any):
264
+ def __pow__(self, other: number_types) -> NumberVar:
331
265
  """Exponentiate two numbers.
332
266
 
333
267
  Args:
@@ -341,13 +275,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
341
275
 
342
276
  return number_exponent_operation(self, +other)
343
277
 
344
- @overload
345
- def __rpow__(self, other: number_types) -> NumberVar: ...
346
-
347
- @overload
348
- def __rpow__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
349
-
350
- def __rpow__(self, other: Any):
278
+ def __rpow__(self, other: number_types) -> NumberVar:
351
279
  """Exponentiate two numbers.
352
280
 
353
281
  Args:
@@ -417,13 +345,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
417
345
  """
418
346
  return number_trunc_operation(self)
419
347
 
420
- @overload
421
- def __lt__(self, other: number_types) -> BooleanVar: ...
422
-
423
- @overload
424
- def __lt__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
425
-
426
- def __lt__(self, other: Any):
348
+ def __lt__(self, other: number_types) -> BooleanVar:
427
349
  """Less than comparison.
428
350
 
429
351
  Args:
@@ -436,13 +358,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
436
358
  raise_unsupported_operand_types("<", (type(self), type(other)))
437
359
  return less_than_operation(+self, +other)
438
360
 
439
- @overload
440
- def __le__(self, other: number_types) -> BooleanVar: ...
441
-
442
- @overload
443
- def __le__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
444
-
445
- def __le__(self, other: Any):
361
+ def __le__(self, other: number_types) -> BooleanVar:
446
362
  """Less than or equal comparison.
447
363
 
448
364
  Args:
@@ -481,13 +397,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
481
397
  return not_equal_operation(+self, +other)
482
398
  return not_equal_operation(self, other)
483
399
 
484
- @overload
485
- def __gt__(self, other: number_types) -> BooleanVar: ...
486
-
487
- @overload
488
- def __gt__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
489
-
490
- def __gt__(self, other: Any):
400
+ def __gt__(self, other: number_types) -> BooleanVar:
491
401
  """Greater than comparison.
492
402
 
493
403
  Args:
@@ -500,13 +410,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
500
410
  raise_unsupported_operand_types(">", (type(self), type(other)))
501
411
  return greater_than_operation(+self, +other)
502
412
 
503
- @overload
504
- def __ge__(self, other: number_types) -> BooleanVar: ...
505
-
506
- @overload
507
- def __ge__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
508
-
509
- def __ge__(self, other: Any):
413
+ def __ge__(self, other: number_types) -> BooleanVar:
510
414
  """Greater than or equal comparison.
511
415
 
512
416
  Args: