pulse-framework 0.1.67__py3-none-any.whl → 0.1.68a1__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.
pulse/app.py CHANGED
@@ -214,6 +214,7 @@ class App:
214
214
  session_timeout: float
215
215
  connection_status: ConnectionStatusConfig
216
216
  render_loop_limit: int
217
+ prerender_queue_timeout: float
217
218
  detach_queue_timeout: float
218
219
  disconnect_queue_timeout: float
219
220
 
@@ -235,6 +236,7 @@ class App:
235
236
  cors: CORSOptions | None = None,
236
237
  fastapi: dict[str, Any] | None = None,
237
238
  session_timeout: float = 60.0,
239
+ prerender_queue_timeout: float = 60.0,
238
240
  detach_queue_timeout: float = 15.0,
239
241
  disconnect_queue_timeout: float = 300.0,
240
242
  connection_status: ConnectionStatusConfig | None = None,
@@ -288,6 +290,7 @@ class App:
288
290
  self._timers = TimerRegistry(tasks=self._tasks, name="app")
289
291
  self._proxy = None
290
292
  self.session_timeout = session_timeout
293
+ self.prerender_queue_timeout = prerender_queue_timeout
291
294
  self.detach_queue_timeout = detach_queue_timeout
292
295
  self.disconnect_queue_timeout = disconnect_queue_timeout
293
296
  self.connection_status = connection_status or ConnectionStatusConfig()
@@ -544,23 +547,10 @@ class App:
544
547
  paths = [ensure_absolute_path(path) for path in paths]
545
548
  payload["paths"] = paths
546
549
  route_info = payload.get("routeInfo")
547
- debug = os.environ.get("PULSE_DEBUG_RENDER")
548
- if debug:
549
- print(
550
- "[PulseDebug][prerender] session=%s header_render_id=%s payload_render_id=%s paths=%s route_info=%s"
551
- % (
552
- session.sid,
553
- request.headers.get("x-pulse-render-id"),
554
- payload.get("renderId"),
555
- paths,
556
- route_info,
557
- )
558
- )
559
550
 
560
551
  client_addr: str | None = get_client_address(request)
561
552
  # Reuse render session from header (set by middleware) or create new one
562
553
  render = PulseContext.get().render
563
- reused = render is not None
564
554
  if render is not None:
565
555
  render_id = render.id
566
556
  else:
@@ -569,12 +559,6 @@ class App:
569
559
  render = self.create_render(
570
560
  render_id, session, client_address=client_addr
571
561
  )
572
- if debug:
573
- print(
574
- "[PulseDebug][prerender] session=%s render=%s reused=%s connected=%s"
575
- % (session.sid, render_id, reused, render.connected)
576
- )
577
-
578
562
  # Schedule cleanup timeout (will cancel/reschedule on activity)
579
563
  if not render.connected:
580
564
  self._schedule_render_cleanup(render_id)
@@ -716,11 +700,6 @@ class App:
716
700
  if cookie is None:
717
701
  raise ConnectionRefusedError("Socket connect missing cookie")
718
702
  session = await self.get_or_create_session(cookie)
719
- debug = os.environ.get("PULSE_DEBUG_RENDER")
720
- if debug:
721
- print(
722
- "[PulseDebug][connect] session=%s render_id=%s" % (session.sid, rid)
723
- )
724
703
 
725
704
  if not rid:
726
705
  # Still refuse connections without a renderId
@@ -732,11 +711,6 @@ class App:
732
711
  render = self.render_sessions.get(rid)
733
712
  if render is None:
734
713
  # The client will try to attach to a non-existing RouteMount, which will cause a reload down the line
735
- if debug:
736
- print(
737
- "[PulseDebug][connect] render_missing session=%s render_id=%s creating=true"
738
- % (session.sid, rid)
739
- )
740
714
  render = self.create_render(
741
715
  rid, session, client_address=get_client_address_socketio(environ)
742
716
  )
@@ -747,11 +721,6 @@ class App:
747
721
  f"Socket connect session mismatch render={render.id} "
748
722
  + f"owner={owner} session={session.sid}"
749
723
  )
750
- if debug:
751
- print(
752
- "[PulseDebug][connect] render_found session=%s render_id=%s owner=%s connected=%s"
753
- % (session.sid, render.id, owner, render.connected)
754
- )
755
724
 
756
725
  def on_message(message: ServerMessage):
757
726
  payload = serialize(message)
@@ -864,22 +833,6 @@ class App:
864
833
  async def _handle_pulse_message(
865
834
  self, render: RenderSession, session: UserSession, msg: ClientPulseMessage
866
835
  ) -> None:
867
- if os.environ.get("PULSE_DEBUG_RENDER") and msg["type"] in (
868
- "attach",
869
- "update",
870
- "detach",
871
- ):
872
- print(
873
- "[PulseDebug][client-message] session=%s render=%s type=%s path=%s route_info=%s"
874
- % (
875
- session.sid,
876
- render.id,
877
- msg["type"],
878
- msg.get("path"),
879
- msg.get("routeInfo"),
880
- )
881
- )
882
-
883
836
  async def _next() -> Ok[None]:
884
837
  if msg["type"] == "attach":
885
838
  render.attach(msg["path"], msg["routeInfo"])
@@ -1058,6 +1011,7 @@ class App:
1058
1011
  self.routes,
1059
1012
  server_address=self.server_address,
1060
1013
  client_address=client_address,
1014
+ prerender_queue_timeout=self.prerender_queue_timeout,
1061
1015
  detach_queue_timeout=self.detach_queue_timeout,
1062
1016
  disconnect_queue_timeout=self.disconnect_queue_timeout,
1063
1017
  render_loop_limit=self.render_loop_limit,
pulse/render_session.py CHANGED
@@ -1,6 +1,5 @@
1
1
  import asyncio
2
2
  import logging
3
- import os
4
3
  import traceback
5
4
  import uuid
6
5
  from asyncio import iscoroutine
@@ -138,11 +137,6 @@ class RouteMount:
138
137
  if self.state != "pending":
139
138
  return
140
139
  action = self.pending_action
141
- if os.environ.get("PULSE_DEBUG_RENDER"):
142
- print(
143
- "[PulseDebug][mount-timeout] render=%s path=%s action=%s state=%s"
144
- % (self.render.id, self.path, action, self.state)
145
- )
146
140
  self.pending_action = None
147
141
  if action == "dispose":
148
142
  self.render.dispose_mount(self.path, self)
@@ -150,11 +144,6 @@ class RouteMount:
150
144
  self.to_idle()
151
145
 
152
146
  def start_pending(self, timeout: float, *, action: PendingAction = "idle") -> None:
153
- if os.environ.get("PULSE_DEBUG_RENDER"):
154
- print(
155
- "[PulseDebug][mount-pending] render=%s path=%s state=%s action=%s timeout=%s"
156
- % (self.render.id, self.path, self.state, action, timeout)
157
- )
158
147
  if self.state == "pending":
159
148
  prev_action = self.pending_action
160
149
  next_action: PendingAction = (
@@ -177,16 +166,6 @@ class RouteMount:
177
166
  )
178
167
 
179
168
  def activate(self, send_message: Callable[[ServerMessage], Any]) -> None:
180
- if os.environ.get("PULSE_DEBUG_RENDER"):
181
- print(
182
- "[PulseDebug][mount-activate] render=%s path=%s state=%s queued=%s"
183
- % (
184
- self.render.id,
185
- self.path,
186
- self.state,
187
- 0 if not self.queue else len(self.queue),
188
- )
189
- )
190
169
  if self.state != "pending":
191
170
  return
192
171
  self._cancel_pending_timeout()
@@ -213,11 +192,6 @@ class RouteMount:
213
192
  def to_idle(self) -> None:
214
193
  if self.state != "pending":
215
194
  return
216
- if os.environ.get("PULSE_DEBUG_RENDER"):
217
- print(
218
- "[PulseDebug][mount-idle] render=%s path=%s"
219
- % (self.render.id, self.path)
220
- )
221
195
  self.state = "idle"
222
196
  self.queue = None
223
197
  self._cancel_pending_timeout()
@@ -294,7 +268,7 @@ class RenderSession:
294
268
  *,
295
269
  server_address: str | None = None,
296
270
  client_address: str | None = None,
297
- prerender_queue_timeout: float = 5.0,
271
+ prerender_queue_timeout: float = 60.0,
298
272
  detach_queue_timeout: float = 15.0,
299
273
  disconnect_queue_timeout: float = 300.0,
300
274
  render_loop_limit: int = 50,
@@ -343,15 +317,11 @@ class RenderSession:
343
317
 
344
318
  def connect(self, send_message: Callable[[ServerMessage], Any]):
345
319
  """WebSocket connected. Set sender, don't auto-flush (attach does that)."""
346
- if os.environ.get("PULSE_DEBUG_RENDER"):
347
- print("[PulseDebug][render-connect] render=%s" % self.id)
348
320
  self._send_message = send_message
349
321
  self.connected = True
350
322
 
351
323
  def disconnect(self):
352
324
  """WebSocket disconnected. Start queuing briefly before pausing."""
353
- if os.environ.get("PULSE_DEBUG_RENDER"):
354
- print("[PulseDebug][render-disconnect] render=%s" % self.id)
355
325
  self._send_message = None
356
326
  self.connected = False
357
327
 
@@ -425,11 +395,6 @@ class RenderSession:
425
395
  - Creates mounts in PENDING state and starts queue
426
396
  """
427
397
  normalized = [ensure_absolute_path(path) for path in paths]
428
- if os.environ.get("PULSE_DEBUG_RENDER"):
429
- print(
430
- "[PulseDebug][prerender] render=%s paths=%s route_info=%s"
431
- % (self.id, normalized, route_info)
432
- )
433
398
 
434
399
  results: dict[str, ServerInitMessage | ServerNavigateToMessage] = {}
435
400
 
@@ -437,12 +402,6 @@ class RenderSession:
437
402
  route = self.routes.find(path)
438
403
  info = route_info or route.default_route_info()
439
404
  mount = self.route_mounts.get(path)
440
- if os.environ.get("PULSE_DEBUG_RENDER"):
441
- route_label = repr(route)
442
- print(
443
- "[PulseDebug][prerender] render=%s path=%s mount_state=%s route=%s"
444
- % (self.id, path, mount.state if mount else None, route_label)
445
- )
446
405
 
447
406
  if mount is None:
448
407
  mount = RouteMount(self, path, route, info)
@@ -481,17 +440,6 @@ class RenderSession:
481
440
  mount = self.route_mounts.get(path)
482
441
 
483
442
  if mount is None or mount.state == "idle":
484
- if os.environ.get("PULSE_DEBUG_RENDER"):
485
- print(
486
- "[PulseDebug][attach] render=%s path=%s mount_state=%s mounts=%s route_info=%s"
487
- % (
488
- self.id,
489
- path,
490
- mount.state if mount else None,
491
- {key: value.state for key, value in self.route_mounts.items()},
492
- route_info,
493
- )
494
- )
495
443
  # Initial render must come from prerender
496
444
  print(f"[DEBUG] Missing or idle route '{path}', reloading")
497
445
  self.send({"type": "reload"})
@@ -500,11 +448,6 @@ class RenderSession:
500
448
  # Update route info for active and pending mounts
501
449
  mount.update_route(route_info)
502
450
  if mount.state == "pending" and self._send_message:
503
- if os.environ.get("PULSE_DEBUG_RENDER"):
504
- print(
505
- "[PulseDebug][attach] render=%s path=%s activating=true"
506
- % (self.id, path)
507
- )
508
451
  mount.activate(self._send_message)
509
452
 
510
453
  def update_route(self, path: str, route_info: RouteInfo):
@@ -520,11 +463,6 @@ class RenderSession:
520
463
  current = self.route_mounts.get(path)
521
464
  if current is not mount:
522
465
  return
523
- if os.environ.get("PULSE_DEBUG_RENDER"):
524
- print(
525
- "[PulseDebug][mount-dispose] render=%s path=%s state=%s"
526
- % (self.id, path, mount.state)
527
- )
528
466
  try:
529
467
  self.route_mounts.pop(path, None)
530
468
  mount.dispose()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pulse-framework
3
- Version: 0.1.67
3
+ Version: 0.1.68a1
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
  pulse/__init__.py,sha256=cXNVXz0aizbkOG1aj2zytgzodyVNv7nNylsXcWmH-Lc,32183
2
2
  pulse/_examples.py,sha256=dFuhD2EVXsbvAeexoG57s4VuN4gWLaTMOEMNYvlPm9A,561
3
- pulse/app.py,sha256=WjQ1ObPwt4GIqvVcuXAjoVg8bKHkmA_T3pigzcrMEns,37195
3
+ pulse/app.py,sha256=TjMP21lpwYpRnkMkeKL8EA22V9xSKTA6_5GQI9Btw_o,36059
4
4
  pulse/channel.py,sha256=ePpvD2mDbddt_LMxxxDjNRgOLbVi8Ed6TmJFgkrALB0,15790
5
5
  pulse/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  pulse/cli/cmd.py,sha256=zh3Ah6c16cNg3o_v_If_S58Qe8rvxNe5M2VrTkwvDU8,15957
@@ -88,7 +88,7 @@ pulse/queries/store.py,sha256=4pWTDSl71LUM7YqhWanKjZkFh3t8F_04o48js_H4ttQ,3728
88
88
  pulse/react_component.py,sha256=8RLg4Bi7IcjqbnbEnp4hJpy8t1UsE7mG0UR1Q655LDk,2332
89
89
  pulse/reactive.py,sha256=GSh9wSH3THCBjDTafwWttyx7djeKBWV_KqjaKRYUNsA,31393
90
90
  pulse/reactive_extensions.py,sha256=yQ1PpdAh4kMvll7R15T72FOg8NFdG_HGBsGc63dawYk,33754
91
- pulse/render_session.py,sha256=6CF6luXFOGyXSommXn2Fsou7N9mwMFw6jYHf-HArd3U,24808
91
+ pulse/render_session.py,sha256=7LmauQSUtRzYLTwwSmG7a6k3Z3u22rjVLpyWUd2iOIM,22808
92
92
  pulse/renderer.py,sha256=fjSsUvCqV12jyN7Y5XspKUfjQJJzKX-Chha5oF5PrAk,16001
93
93
  pulse/request.py,sha256=N0oFOLiGxpbgSgxznjvu64lG3YyOcZPKC8JFyKx6X7w,6023
94
94
  pulse/requirements.py,sha256=nMnE25Uu-TUuQd88jW7m2xwus6fD-HvXxQ9UNb7OOGc,1254
@@ -122,7 +122,7 @@ pulse/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
122
122
  pulse/types/event_handler.py,sha256=psQCydj-WEtBcFU5JU4mDwvyzkW8V2O0g_VFRU2EOHI,1618
123
123
  pulse/user_session.py,sha256=nsnsMgqq2xGJZLpbHRMHUHcLrElMP8WcA4gjGMrcoBk,10208
124
124
  pulse/version.py,sha256=711vaM1jVIQPgkisGgKZqwmw019qZIsc_QTae75K2pg,1895
125
- pulse_framework-0.1.67.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
126
- pulse_framework-0.1.67.dist-info/entry_points.txt,sha256=i7aohd3QaPu5IcuGKKvsQQEiMYMe5HcF56QEsaLVO64,46
127
- pulse_framework-0.1.67.dist-info/METADATA,sha256=0SLAib0uSKvrsTVgt9RN_8qm05KuJOF6qNDgvDOzeEU,8300
128
- pulse_framework-0.1.67.dist-info/RECORD,,
125
+ pulse_framework-0.1.68a1.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
126
+ pulse_framework-0.1.68a1.dist-info/entry_points.txt,sha256=i7aohd3QaPu5IcuGKKvsQQEiMYMe5HcF56QEsaLVO64,46
127
+ pulse_framework-0.1.68a1.dist-info/METADATA,sha256=N5UMIoQUFFEIQVx38-aGoxveGbZkh_JRYwnL3AybWz0,8302
128
+ pulse_framework-0.1.68a1.dist-info/RECORD,,