reflex 0.8.7a1__py3-none-any.whl → 0.8.8a1__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 (67) hide show
  1. reflex/app.py +13 -5
  2. reflex/app_mixins/lifespan.py +8 -2
  3. reflex/compiler/compiler.py +12 -12
  4. reflex/compiler/templates.py +629 -102
  5. reflex/compiler/utils.py +29 -20
  6. reflex/components/base/bare.py +17 -0
  7. reflex/components/component.py +37 -33
  8. reflex/components/core/cond.py +6 -12
  9. reflex/components/core/foreach.py +1 -1
  10. reflex/components/core/match.py +83 -60
  11. reflex/components/dynamic.py +3 -3
  12. reflex/components/el/elements/forms.py +31 -14
  13. reflex/components/el/elements/forms.pyi +0 -5
  14. reflex/components/lucide/icon.py +2 -1
  15. reflex/components/lucide/icon.pyi +2 -1
  16. reflex/components/markdown/markdown.py +2 -2
  17. reflex/components/radix/primitives/accordion.py +1 -1
  18. reflex/components/radix/primitives/drawer.py +1 -1
  19. reflex/components/radix/primitives/form.py +1 -1
  20. reflex/components/radix/primitives/slider.py +1 -1
  21. reflex/components/tags/cond_tag.py +14 -5
  22. reflex/components/tags/iter_tag.py +0 -26
  23. reflex/components/tags/match_tag.py +15 -6
  24. reflex/components/tags/tag.py +3 -6
  25. reflex/components/tags/tagless.py +14 -0
  26. reflex/constants/base.py +0 -2
  27. reflex/constants/installer.py +4 -4
  28. reflex/custom_components/custom_components.py +202 -15
  29. reflex/experimental/client_state.py +1 -1
  30. reflex/istate/manager.py +2 -1
  31. reflex/plugins/shared_tailwind.py +87 -62
  32. reflex/plugins/tailwind_v3.py +2 -2
  33. reflex/plugins/tailwind_v4.py +4 -4
  34. reflex/state.py +5 -1
  35. reflex/utils/format.py +2 -3
  36. reflex/utils/frontend_skeleton.py +2 -2
  37. reflex/utils/imports.py +18 -0
  38. reflex/utils/pyi_generator.py +10 -2
  39. reflex/utils/telemetry.py +4 -1
  40. reflex/utils/templates.py +1 -6
  41. {reflex-0.8.7a1.dist-info → reflex-0.8.8a1.dist-info}/METADATA +3 -4
  42. {reflex-0.8.7a1.dist-info → reflex-0.8.8a1.dist-info}/RECORD +45 -67
  43. reflex/.templates/jinja/app/rxconfig.py.jinja2 +0 -9
  44. reflex/.templates/jinja/custom_components/README.md.jinja2 +0 -9
  45. reflex/.templates/jinja/custom_components/__init__.py.jinja2 +0 -1
  46. reflex/.templates/jinja/custom_components/demo_app.py.jinja2 +0 -39
  47. reflex/.templates/jinja/custom_components/pyproject.toml.jinja2 +0 -25
  48. reflex/.templates/jinja/custom_components/src.py.jinja2 +0 -57
  49. reflex/.templates/jinja/web/package.json.jinja2 +0 -27
  50. reflex/.templates/jinja/web/pages/_app.js.jinja2 +0 -62
  51. reflex/.templates/jinja/web/pages/_document.js.jinja2 +0 -9
  52. reflex/.templates/jinja/web/pages/base_page.js.jinja2 +0 -21
  53. reflex/.templates/jinja/web/pages/component.js.jinja2 +0 -2
  54. reflex/.templates/jinja/web/pages/custom_component.js.jinja2 +0 -22
  55. reflex/.templates/jinja/web/pages/index.js.jinja2 +0 -18
  56. reflex/.templates/jinja/web/pages/macros.js.jinja2 +0 -38
  57. reflex/.templates/jinja/web/pages/stateful_component.js.jinja2 +0 -15
  58. reflex/.templates/jinja/web/pages/stateful_components.js.jinja2 +0 -5
  59. reflex/.templates/jinja/web/pages/utils.js.jinja2 +0 -93
  60. reflex/.templates/jinja/web/styles/styles.css.jinja2 +0 -6
  61. reflex/.templates/jinja/web/utils/context.js.jinja2 +0 -129
  62. reflex/.templates/jinja/web/utils/theme.js.jinja2 +0 -1
  63. reflex/.templates/jinja/web/vite.config.js.jinja2 +0 -74
  64. reflex/components/core/client_side_routing.pyi +0 -68
  65. {reflex-0.8.7a1.dist-info → reflex-0.8.8a1.dist-info}/WHEEL +0 -0
  66. {reflex-0.8.7a1.dist-info → reflex-0.8.8a1.dist-info}/entry_points.txt +0 -0
  67. {reflex-0.8.7a1.dist-info → reflex-0.8.8a1.dist-info}/licenses/LICENSE +0 -0
reflex/app.py CHANGED
@@ -12,6 +12,7 @@ import inspect
12
12
  import io
13
13
  import json
14
14
  import sys
15
+ import time
15
16
  import traceback
16
17
  import urllib.parse
17
18
  from collections.abc import (
@@ -1582,7 +1583,10 @@ class App(MiddlewareMixin, LifespanMixin):
1582
1583
  sid=state.router.session.session_id,
1583
1584
  )
1584
1585
 
1585
- task = asyncio.create_task(_coro())
1586
+ task = asyncio.create_task(
1587
+ _coro(),
1588
+ name=f"reflex_background_task|{event.name}|{time.time()}|{event.token}",
1589
+ )
1586
1590
  self._background_tasks.add(task)
1587
1591
  # Clean up task from background_tasks set when complete.
1588
1592
  task.add_done_callback(self._background_tasks.discard)
@@ -1727,7 +1731,8 @@ async def process(
1727
1731
  "reload",
1728
1732
  data=event,
1729
1733
  to=sid,
1730
- )
1734
+ ),
1735
+ name=f"reflex_emit_reload|{event.name}|{time.time()}|{event.token}",
1731
1736
  )
1732
1737
  return
1733
1738
  # re-assign only when the value is different
@@ -2028,7 +2033,8 @@ class EventNamespace(AsyncNamespace):
2028
2033
  if disconnect_token:
2029
2034
  # Use async cleanup through token manager
2030
2035
  task = asyncio.create_task(
2031
- self._token_manager.disconnect_token(disconnect_token, sid)
2036
+ self._token_manager.disconnect_token(disconnect_token, sid),
2037
+ name=f"reflex_disconnect_token|{disconnect_token}|{time.time()}",
2032
2038
  )
2033
2039
  # Don't await to avoid blocking disconnect, but handle potential errors
2034
2040
  task.add_done_callback(
@@ -2047,12 +2053,14 @@ class EventNamespace(AsyncNamespace):
2047
2053
  # If the sid is None, we are not connected to a client. Prevent sending
2048
2054
  # updates to all clients.
2049
2055
  return
2050
- if sid not in self.sid_to_token:
2056
+ token = self.sid_to_token.get(sid)
2057
+ if token is None:
2051
2058
  console.warn(f"Attempting to send delta to disconnected websocket {sid}")
2052
2059
  return
2053
2060
  # Creating a task prevents the update from being blocked behind other coroutines.
2054
2061
  await asyncio.create_task(
2055
- self.emit(str(constants.SocketEvent.EVENT), update, to=sid)
2062
+ self.emit(str(constants.SocketEvent.EVENT), update, to=sid),
2063
+ name=f"reflex_emit_event|{token}|{sid}|{time.time()}",
2056
2064
  )
2057
2065
 
2058
2066
  async def on_event(self, sid: str, data: Any):
@@ -7,6 +7,7 @@ import contextlib
7
7
  import dataclasses
8
8
  import functools
9
9
  import inspect
10
+ import time
10
11
  from collections.abc import Callable, Coroutine
11
12
 
12
13
  from starlette.applications import Starlette
@@ -36,6 +37,7 @@ class LifespanMixin(AppMixin):
36
37
  if isinstance(task, asyncio.Task):
37
38
  running_tasks.append(task)
38
39
  else:
40
+ task_name = task.__name__
39
41
  signature = inspect.signature(task)
40
42
  if "app" in signature.parameters:
41
43
  task = functools.partial(task, app=app)
@@ -44,7 +46,10 @@ class LifespanMixin(AppMixin):
44
46
  await stack.enter_async_context(_t)
45
47
  console.debug(run_msg.format(type="asynccontextmanager"))
46
48
  elif isinstance(_t, Coroutine):
47
- task_ = asyncio.create_task(_t)
49
+ task_ = asyncio.create_task(
50
+ _t,
51
+ name=f"reflex_lifespan_task|{task_name}|{time.time()}",
52
+ )
48
53
  task_.add_done_callback(lambda t: t.result())
49
54
  running_tasks.append(task_)
50
55
  console.debug(run_msg.format(type="coroutine"))
@@ -70,9 +75,10 @@ class LifespanMixin(AppMixin):
70
75
  msg = f"Task {task.__name__} of type generator must be decorated with contextlib.asynccontextmanager."
71
76
  raise InvalidLifespanTaskTypeError(msg)
72
77
 
78
+ task_name = task.__name__ # pyright: ignore [reportAttributeAccessIssue]
73
79
  if task_kwargs:
74
80
  original_task = task
75
81
  task = functools.partial(task, **task_kwargs) # pyright: ignore [reportArgumentType]
76
82
  functools.update_wrapper(task, original_task) # pyright: ignore [reportArgumentType]
77
83
  self.lifespan_tasks.add(task)
78
- console.debug(f"Registered lifespan task: {task.__name__}") # pyright: ignore [reportAttributeAccessIssue]
84
+ console.debug(f"Registered lifespan task: {task_name}")
@@ -53,7 +53,7 @@ def _compile_document_root(root: Component) -> str:
53
53
  """
54
54
  document_root_imports = root._get_all_imports()
55
55
  _apply_common_imports(document_root_imports)
56
- return templates.DOCUMENT_ROOT.render(
56
+ return templates.document_root_template(
57
57
  imports=utils.compile_imports(document_root_imports),
58
58
  document=root.render(),
59
59
  )
@@ -93,7 +93,7 @@ def _compile_app(app_root: Component) -> str:
93
93
  app_root_imports = app_root._get_all_imports()
94
94
  _apply_common_imports(app_root_imports)
95
95
 
96
- return templates.APP_ROOT.render(
96
+ return templates.app_root_template(
97
97
  imports=utils.compile_imports(app_root_imports),
98
98
  custom_codes=app_root._get_all_custom_code(),
99
99
  hooks=app_root._get_all_hooks(),
@@ -112,7 +112,7 @@ def _compile_theme(theme: str) -> str:
112
112
  Returns:
113
113
  The compiled theme.
114
114
  """
115
- return templates.THEME.render(theme=theme)
115
+ return templates.theme_template(theme=theme)
116
116
 
117
117
 
118
118
  def _compile_contexts(state: type[BaseState] | None, theme: Component | None) -> str:
@@ -130,17 +130,17 @@ def _compile_contexts(state: type[BaseState] | None, theme: Component | None) ->
130
130
  appearance = LiteralVar.create(SYSTEM_COLOR_MODE)
131
131
 
132
132
  return (
133
- templates.CONTEXT.render(
133
+ templates.context_template(
134
134
  initial_state=utils.compile_state(state),
135
135
  state_name=state.get_name(),
136
136
  client_storage=utils.compile_client_storage(state),
137
137
  is_dev_mode=not is_prod_mode(),
138
- default_color_mode=appearance,
138
+ default_color_mode=str(appearance),
139
139
  )
140
140
  if state
141
- else templates.CONTEXT.render(
141
+ else templates.context_template(
142
142
  is_dev_mode=not is_prod_mode(),
143
- default_color_mode=appearance,
143
+ default_color_mode=str(appearance),
144
144
  )
145
145
  )
146
146
 
@@ -159,7 +159,7 @@ def _compile_page(component: BaseComponent) -> str:
159
159
  imports = utils.compile_imports(imports)
160
160
 
161
161
  # Compile the code to render the component.
162
- return templates.PAGE.render(
162
+ return templates.page_template(
163
163
  imports=imports,
164
164
  dynamic_imports=component._get_all_dynamic_imports(),
165
165
  custom_codes=component._get_all_custom_code(),
@@ -321,7 +321,7 @@ def _compile_root_stylesheet(stylesheets: list[str], reset_style: bool = True) -
321
321
  'The `libsass` package is required to compile sass/scss stylesheet files. Run `pip install "libsass>=0.23.0"`.'
322
322
  )
323
323
 
324
- return templates.STYLE.render(stylesheets=sheets)
324
+ return templates.styles_template(stylesheets=sheets)
325
325
 
326
326
 
327
327
  def _compile_component(component: Component | StatefulComponent) -> str:
@@ -333,7 +333,7 @@ def _compile_component(component: Component | StatefulComponent) -> str:
333
333
  Returns:
334
334
  The compiled component.
335
335
  """
336
- return templates.COMPONENT.render(component=component)
336
+ return templates.component_template(component=component)
337
337
 
338
338
 
339
339
  def _compile_components(
@@ -376,7 +376,7 @@ def _compile_components(
376
376
 
377
377
  # Compile the components page.
378
378
  return (
379
- templates.COMPONENTS.render(
379
+ templates.custom_component_template(
380
380
  imports=utils.compile_imports(imports),
381
381
  components=component_renders,
382
382
  dynamic_imports=dynamic_imports,
@@ -456,7 +456,7 @@ def _compile_stateful_components(
456
456
  if rendered_components:
457
457
  _apply_common_imports(all_imports)
458
458
 
459
- return templates.STATEFUL_COMPONENTS.render(
459
+ return templates.stateful_components_template(
460
460
  imports=utils.compile_imports(all_imports),
461
461
  memoized_code="\n".join(rendered_components),
462
462
  )