pulse-framework 0.1.59__tar.gz → 0.1.61__tar.gz

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.
Files changed (125) hide show
  1. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/PKG-INFO +1 -1
  2. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/pyproject.toml +1 -1
  3. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/form.py +2 -1
  4. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/renderer.py +7 -10
  5. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/nodes.py +2 -0
  6. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/vdom.py +2 -1
  7. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/README.md +0 -0
  8. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/__init__.py +0 -0
  9. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/_examples.py +0 -0
  10. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/app.py +0 -0
  11. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/channel.py +0 -0
  12. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/cli/__init__.py +0 -0
  13. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/cli/cmd.py +0 -0
  14. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/cli/dependencies.py +0 -0
  15. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/cli/folder_lock.py +0 -0
  16. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/cli/helpers.py +0 -0
  17. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/cli/logging.py +0 -0
  18. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/cli/models.py +0 -0
  19. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/cli/packages.py +0 -0
  20. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/cli/processes.py +0 -0
  21. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/cli/secrets.py +0 -0
  22. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/cli/uvicorn_log_config.py +0 -0
  23. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/code_analysis.py +0 -0
  24. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/codegen/__init__.py +0 -0
  25. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/codegen/codegen.py +0 -0
  26. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/codegen/templates/__init__.py +0 -0
  27. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/codegen/templates/layout.py +0 -0
  28. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/codegen/templates/route.py +0 -0
  29. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/codegen/templates/routes_ts.py +0 -0
  30. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/codegen/utils.py +0 -0
  31. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/component.py +0 -0
  32. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/components/__init__.py +0 -0
  33. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/components/for_.py +0 -0
  34. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/components/if_.py +0 -0
  35. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/components/react_router.py +0 -0
  36. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/context.py +0 -0
  37. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/cookies.py +0 -0
  38. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/decorators.py +0 -0
  39. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/dom/__init__.py +0 -0
  40. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/dom/elements.py +0 -0
  41. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/dom/events.py +0 -0
  42. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/dom/props.py +0 -0
  43. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/dom/svg.py +0 -0
  44. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/dom/tags.py +0 -0
  45. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/dom/tags.pyi +0 -0
  46. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/env.py +0 -0
  47. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/helpers.py +0 -0
  48. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/hooks/__init__.py +0 -0
  49. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/hooks/core.py +0 -0
  50. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/hooks/effects.py +0 -0
  51. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/hooks/init.py +0 -0
  52. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/hooks/runtime.py +0 -0
  53. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/hooks/setup.py +0 -0
  54. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/hooks/stable.py +0 -0
  55. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/hooks/state.py +0 -0
  56. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/__init__.py +0 -0
  57. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/__init__.pyi +0 -0
  58. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/_types.py +0 -0
  59. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/array.py +0 -0
  60. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/console.py +0 -0
  61. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/date.py +0 -0
  62. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/document.py +0 -0
  63. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/error.py +0 -0
  64. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/json.py +0 -0
  65. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/map.py +0 -0
  66. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/math.py +0 -0
  67. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/navigator.py +0 -0
  68. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/number.py +0 -0
  69. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/obj.py +0 -0
  70. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/object.py +0 -0
  71. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/promise.py +0 -0
  72. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/pulse.py +0 -0
  73. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/react.py +0 -0
  74. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/regexp.py +0 -0
  75. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/set.py +0 -0
  76. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/string.py +0 -0
  77. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/weakmap.py +0 -0
  78. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/weakset.py +0 -0
  79. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/js/window.py +0 -0
  80. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/messages.py +0 -0
  81. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/middleware.py +0 -0
  82. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/plugin.py +0 -0
  83. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/proxy.py +0 -0
  84. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/py.typed +0 -0
  85. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/queries/__init__.py +0 -0
  86. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/queries/client.py +0 -0
  87. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/queries/common.py +0 -0
  88. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/queries/effect.py +0 -0
  89. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/queries/infinite_query.py +0 -0
  90. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/queries/mutation.py +0 -0
  91. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/queries/protocol.py +0 -0
  92. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/queries/query.py +0 -0
  93. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/queries/store.py +0 -0
  94. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/react_component.py +0 -0
  95. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/reactive.py +0 -0
  96. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/reactive_extensions.py +0 -0
  97. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/render_session.py +0 -0
  98. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/request.py +0 -0
  99. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/routing.py +0 -0
  100. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/serializer.py +0 -0
  101. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/state.py +0 -0
  102. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/test_helpers.py +0 -0
  103. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/__init__.py +0 -0
  104. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/assets.py +0 -0
  105. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/builtins.py +0 -0
  106. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/dynamic_import.py +0 -0
  107. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/emit_context.py +0 -0
  108. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/errors.py +0 -0
  109. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/function.py +0 -0
  110. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/id.py +0 -0
  111. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/imports.py +0 -0
  112. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/js_module.py +0 -0
  113. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/modules/__init__.py +0 -0
  114. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/modules/asyncio.py +0 -0
  115. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/modules/json.py +0 -0
  116. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/modules/math.py +0 -0
  117. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/modules/pulse/__init__.py +0 -0
  118. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/modules/pulse/tags.py +0 -0
  119. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/modules/typing.py +0 -0
  120. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/py_module.py +0 -0
  121. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/transpiler/transpiler.py +0 -0
  122. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/types/__init__.py +0 -0
  123. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/types/event_handler.py +0 -0
  124. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/user_session.py +0 -0
  125. {pulse_framework-0.1.59 → pulse_framework-0.1.61}/src/pulse/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pulse-framework
3
- Version: 0.1.59
3
+ Version: 0.1.61
4
4
  Summary: Pulse - Full-stack framework for building real-time React applications in Python
5
5
  Requires-Dist: websockets>=12.0
6
6
  Requires-Dist: fastapi>=0.128.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pulse-framework"
3
- version = "0.1.59"
3
+ version = "0.1.61"
4
4
  description = "Pulse - Full-stack framework for building real-time React applications in Python"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -422,8 +422,9 @@ class ManualForm(Disposable):
422
422
  Returns:
423
423
  Dict with action, method, encType, and onSubmit props.
424
424
  """
425
+ prefix = PulseContext.get().app.api_prefix
425
426
  return {
426
- "action": f"{server_address()}/pulse/forms/{self._render.id}/{self.registration.id}",
427
+ "action": f"{server_address()}{prefix}/forms/{self._render.id}/{self.registration.id}",
427
428
  "method": "POST",
428
429
  "encType": "multipart/form-data",
429
430
  "onSubmit": self._start_submit,
@@ -27,6 +27,7 @@ from pulse.transpiler.vdom import (
27
27
  UpdatePropsDelta,
28
28
  UpdatePropsOperation,
29
29
  VDOMElement,
30
+ VDOMExpr,
30
31
  VDOMNode,
31
32
  VDOMOperation,
32
33
  VDOMPropValue,
@@ -441,21 +442,17 @@ class Renderer:
441
442
  # Expression + tag rendering
442
443
  # ------------------------------------------------------------------
443
444
 
444
- def render_tag(self, tag: str | Expr) -> str:
445
+ def render_tag(self, tag: str | Expr) -> str | VDOMExpr:
445
446
  if isinstance(tag, str):
446
447
  return tag
447
448
 
448
- key = self.register_component_expr(tag)
449
- return f"{MOUNT_PREFIX}{key}"
449
+ return self.register_component_expr(tag)
450
450
 
451
- def register_component_expr(self, expr: Expr) -> str:
451
+ def register_component_expr(self, expr: Expr) -> str | VDOMExpr:
452
452
  ref = registry_ref(expr)
453
- if ref is None:
454
- raise TypeError(
455
- "Component tag expressions must be registry-backed Expr values "
456
- + "(Import/JsFunction/Constant/JsxFunction)."
457
- )
458
- return ref["key"]
453
+ if ref is not None:
454
+ return f"{MOUNT_PREFIX}{ref['key']}"
455
+ return expr.render()
459
456
 
460
457
  # ------------------------------------------------------------------
461
458
  # Unmount helper
@@ -450,6 +450,8 @@ class Jsx(ExprWrapper):
450
450
 
451
451
  for k, v in kwargs.items():
452
452
  if k == "key":
453
+ if v is None:
454
+ continue
453
455
  if not isinstance(v, str):
454
456
  raise ValueError("key must be a string")
455
457
  key = v
@@ -177,9 +177,10 @@ class VDOMElement(TypedDict):
177
177
  Special tags:
178
178
  - "": React Fragment
179
179
  - "$$<ComponentKey>": mount point for client component registry
180
+ - Expr object (VDOMExpr): evaluated on the client for dynamic component tags
180
181
  """
181
182
 
182
- tag: str
183
+ tag: str | VDOMExpr
183
184
  key: NotRequired[str]
184
185
  # Default: plain JSON props (no interpretation).
185
186
  # When `eval` is present, listed keys may contain VDOMExpr / VDOMElement / "$cb:...".