dara-core 1.21.12__py3-none-any.whl → 1.21.13__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.
@@ -68,7 +68,7 @@ def store_in_shared_memory(content: Any) -> SharedMemoryPointer:
68
68
  data_size = len(pickled_args)
69
69
 
70
70
  shared_mem = SharedMemory(create=True, size=data_size)
71
-
71
+ assert shared_mem.buf
72
72
  shared_mem.buf[0:data_size] = pickled_args
73
73
  shared_mem.close()
74
74
 
@@ -88,6 +88,7 @@ def read_from_shared_memory(pointer: SharedMemoryPointer) -> Any:
88
88
 
89
89
  # Read from memory
90
90
  shared_mem = SharedMemory(name=shared_mem_name)
91
+ assert shared_mem.buf
91
92
  data = shared_mem.buf[:data_size]
92
93
 
93
94
  # Unpickle and deepcopy
@@ -19,7 +19,7 @@ import contextlib
19
19
  import inspect
20
20
  import math
21
21
  from collections.abc import Awaitable
22
- from typing import Any, Callable, Dict, List, Optional, Set, Union, overload
22
+ from typing import Any, Callable, Dict, List, Optional, Set, Union, cast, overload
23
23
 
24
24
  from anyio import (
25
25
  BrokenResourceError,
@@ -453,8 +453,8 @@ class TaskManager:
453
453
 
454
454
  # Notify channels that this specific task was cancelled
455
455
  if notify:
456
- await self._send_notification_for_pending_task(
457
- pending_task=pending_task,
456
+ await self._send_notification_for_task(
457
+ task=pending_task,
458
458
  messages=[{'status': 'CANCELED', 'task_id': task_id_to_cancel}],
459
459
  )
460
460
 
@@ -556,12 +556,14 @@ class TaskManager:
556
556
 
557
557
  return task_ids
558
558
 
559
- async def _multicast_notification(self, task_id: str, messages: List[dict]):
559
+ async def _multicast_notification(self, task_id: str, messages: List[dict], variable_task_id: bool = True):
560
560
  """
561
561
  Send notifications to all task IDs that are related to a given task
562
562
 
563
563
  :param task: the task the notifications are related to
564
564
  :param messages: List of message dictionaries to send to all related tasks
565
+ :param variable_task_id: whether the task_id in messages should be replaced with the task being notified
566
+ or if False, the task_id should be left as is
565
567
  """
566
568
  # prevent cancellation, we need the notifications to be sent
567
569
  with CancelScope(shield=True):
@@ -581,28 +583,33 @@ class TaskManager:
581
583
  if pending_task_id not in self.tasks:
582
584
  continue
583
585
  pending_task = self.tasks[pending_task_id]
584
- task_tg.start_soon(self._send_notification_for_pending_task, pending_task, messages)
586
+ task_tg.start_soon(self._send_notification_for_task, pending_task, messages, variable_task_id)
585
587
 
586
- async def _send_notification_for_pending_task(self, pending_task: PendingTask, messages: List[dict]):
588
+ async def _send_notification_for_task(self, task: BaseTask, messages: List[dict], variable_task_id: bool = True):
587
589
  """
588
590
  Send notifications for a specific PendingTask
589
591
 
590
592
  :param pending_task: The PendingTask to send notifications for
591
593
  :param messages: The messages to send
594
+ :param variable_task_id: whether the task_id in messages should be replaced with the task being notified
592
595
  """
593
596
  # Collect channels for this PendingTask
594
- channels_to_notify = set(pending_task.notify_channels)
595
- channels_to_notify.update(pending_task.task_def.notify_channels)
597
+ channels_to_notify = set(task.notify_channels)
598
+ if isinstance(task, PendingTask):
599
+ channels_to_notify.update(task.task_def.notify_channels)
596
600
 
597
601
  if not channels_to_notify:
598
602
  return
599
603
 
600
- # Send to all channels for this PendingTask in parallel
604
+ # Send to all channels for this Task in parallel
601
605
  async def _send_to_channel(channel: str):
602
606
  async with create_task_group() as channel_tg:
603
607
  for message in messages:
604
- # Create message with this PendingTask's task_id (if message has task_id)
605
- message_for_task = {**message, 'task_id': pending_task.task_id} if 'task_id' in message else message
608
+ if variable_task_id:
609
+ # Create message with this Task's task_id (if message has task_id)
610
+ message_for_task = {**message, 'task_id': task.task_id} if 'task_id' in message else message
611
+ else:
612
+ message_for_task = message
606
613
  channel_tg.start_soon(self.ws_manager.send_message, channel, message_for_task)
607
614
 
608
615
  async with create_task_group() as channel_tg:
@@ -633,13 +640,18 @@ class TaskManager:
633
640
  async for message in receive_stream:
634
641
  if isinstance(message, TaskProgressUpdate):
635
642
  # Send progress notifications to related tasks
636
- progress_message = {
637
- 'task_id': message.task_id, # Will be updated per task ID in multicast
638
- 'status': 'PROGRESS',
639
- 'progress': message.progress,
640
- 'message': message.message,
641
- }
642
- await self._multicast_notification(message.task_id, [progress_message])
643
+ await self._multicast_notification(
644
+ task_id=message.task_id,
645
+ messages=[
646
+ {
647
+ # Will be updated per task ID in multicast
648
+ 'task_id': message.task_id,
649
+ 'status': 'PROGRESS',
650
+ 'progress': message.progress,
651
+ 'message': message.message,
652
+ }
653
+ ],
654
+ )
643
655
  if isinstance(task, Task) and task.on_progress:
644
656
  await run_user_handler(task.on_progress, args=(message,))
645
657
  elif isinstance(message, TaskResult):
@@ -659,10 +671,17 @@ class TaskManager:
659
671
  # Set final result
660
672
  await self.set_result(message.task_id, message.result)
661
673
 
662
- # Notify all PendingTasks that depend on this specific task
674
+ # NOTE: this is still multicasting to all related channels to ensure
675
+ # all interested parties are notified, but notably we use `variable_task_id=False`
676
+ # to only notify about the task that actually completed,
677
+ # as opposed to e.g. progress, errors and cancellations which
678
+ # we 'bubble up' by updating the task_id in the message to the respective related task
663
679
  await self._multicast_notification(
664
680
  task_id=message.task_id,
665
- messages=[{'result': message.result, 'status': 'COMPLETE', 'task_id': message.task_id}],
681
+ messages=[
682
+ {'result': message.result, 'status': 'COMPLETE', 'task_id': message.task_id},
683
+ ],
684
+ variable_task_id=False,
666
685
  )
667
686
 
668
687
  # Remove the task from the registered tasks - it finished running
@@ -726,7 +745,8 @@ class TaskManager:
726
745
  eng_logger.info(f'TaskManager finished task {task.task_id}', {'result': result})
727
746
  finally:
728
747
  with CancelScope(shield=True):
729
- # pyright: ignore[reportUnreachable]
748
+ # cast explicitly as otherwise pyright thinks it's always None here
749
+ task_error = cast(Optional[ExceptionGroup], task_error)
730
750
  if task_error is not None:
731
751
  err = task_error
732
752
  # Mark pending task as failed
@@ -755,8 +775,8 @@ class TaskManager:
755
775
  error = get_error_for_channel(err)
756
776
  message = {'status': 'ERROR', 'task_id': task.task_id, 'error': error['error']}
757
777
  # Notify about this task failing, and a server broadcast error
758
- await self._send_notification_for_pending_task(
759
- pending_task=pending_task,
778
+ await self._send_notification_for_task(
779
+ task=pending_task,
760
780
  messages=[message, error],
761
781
  )
762
782
  # notify related tasks
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dara-core
3
- Version: 1.21.12
3
+ Version: 1.21.13
4
4
  Summary: Dara Framework Core
5
5
  Home-page: https://dara.causalens.com/
6
6
  License: Apache-2.0
@@ -21,10 +21,10 @@ Requires-Dist: cachetools (>=5.0.0,<6.0.0)
21
21
  Requires-Dist: certifi (>=2024.7.4)
22
22
  Requires-Dist: click (==8.1.3)
23
23
  Requires-Dist: colorama (>=0.4.6,<0.5.0)
24
- Requires-Dist: create-dara-app (==1.21.12)
24
+ Requires-Dist: create-dara-app (==1.21.13)
25
25
  Requires-Dist: croniter (>=1.0.15,<3.0.0)
26
26
  Requires-Dist: cryptography (>=42.0.4)
27
- Requires-Dist: dara-components (==1.21.12) ; extra == "all"
27
+ Requires-Dist: dara-components (==1.21.13) ; extra == "all"
28
28
  Requires-Dist: exceptiongroup (>=1.1.3,<2.0.0)
29
29
  Requires-Dist: fastapi (>=0.115.0,<0.116.0)
30
30
  Requires-Dist: fastapi_vite_dara (==0.4.0)
@@ -55,7 +55,7 @@ Description-Content-Type: text/markdown
55
55
 
56
56
  # Dara Application Framework
57
57
 
58
- <img src="https://github.com/causalens/dara/blob/v1.21.12/img/dara_light.svg?raw=true">
58
+ <img src="https://github.com/causalens/dara/blob/v1.21.13/img/dara_light.svg?raw=true">
59
59
 
60
60
  ![Master tests](https://github.com/causalens/dara/actions/workflows/tests.yml/badge.svg?branch=master)
61
61
  [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
@@ -100,7 +100,7 @@ source .venv/bin/activate
100
100
  dara start
101
101
  ```
102
102
 
103
- ![Dara App](https://github.com/causalens/dara/blob/v1.21.12/img/components_gallery.png?raw=true)
103
+ ![Dara App](https://github.com/causalens/dara/blob/v1.21.13/img/components_gallery.png?raw=true)
104
104
 
105
105
  Note: `pip` installation uses [PEP 660](https://peps.python.org/pep-0660/) `pyproject.toml`-based editable installs which require `pip >= 21.3` and `setuptools >= 64.0.0`. You can upgrade both with:
106
106
 
@@ -117,9 +117,9 @@ Explore some of our favorite apps - a great way of getting started and getting t
117
117
 
118
118
  | Dara App | Description |
119
119
  | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
120
- | ![Large Language Model](https://github.com/causalens/dara/blob/v1.21.12/img/llm.png?raw=true) | Demonstrates how to use incorporate a LLM chat box into your decision app to understand model insights |
121
- | ![Plot Interactivity](https://github.com/causalens/dara/blob/v1.21.12/img/plot_interactivity.png?raw=true) | Demonstrates how to enable the user to interact with plots, trigger actions based on clicks, mouse movements and other interactions with `Bokeh` or `Plotly` plots |
122
- | ![Graph Editor](https://github.com/causalens/dara/blob/v1.21.12/img/graph_viewer.png?raw=true) | Demonstrates how to use the `CausalGraphViewer` component to display your graphs or networks, customising the displayed information through colors and tooltips, and updating the page based on user interaction. |
120
+ | ![Large Language Model](https://github.com/causalens/dara/blob/v1.21.13/img/llm.png?raw=true) | Demonstrates how to use incorporate a LLM chat box into your decision app to understand model insights |
121
+ | ![Plot Interactivity](https://github.com/causalens/dara/blob/v1.21.13/img/plot_interactivity.png?raw=true) | Demonstrates how to enable the user to interact with plots, trigger actions based on clicks, mouse movements and other interactions with `Bokeh` or `Plotly` plots |
122
+ | ![Graph Editor](https://github.com/causalens/dara/blob/v1.21.13/img/graph_viewer.png?raw=true) | Demonstrates how to use the `CausalGraphViewer` component to display your graphs or networks, customising the displayed information through colors and tooltips, and updating the page based on user interaction. |
123
123
 
124
124
  Check out our [App Gallery](https://dara.causalens.com/gallery) for more inspiration!
125
125
 
@@ -146,9 +146,9 @@ And the supporting UI packages and tools.
146
146
  - `ui-utils` - miscellaneous utility functions
147
147
  - `ui-widgets` - widget components
148
148
 
149
- More information on the repository structure can be found in the [CONTRIBUTING.md](https://github.com/causalens/dara/blob/v1.21.12/CONTRIBUTING.md) file.
149
+ More information on the repository structure can be found in the [CONTRIBUTING.md](https://github.com/causalens/dara/blob/v1.21.13/CONTRIBUTING.md) file.
150
150
 
151
151
  ## License
152
152
 
153
- Dara is open-source and licensed under the [Apache 2.0 License](https://github.com/causalens/dara/blob/v1.21.12/LICENSE).
153
+ Dara is open-source and licensed under the [Apache 2.0 License](https://github.com/causalens/dara/blob/v1.21.13/LICENSE).
154
154
 
@@ -55,7 +55,7 @@ dara/core/internal/pool/__init__.py,sha256=pBbXE5GR3abVC9Lg3i0QxfdmsrBDMJUYAYb0S
55
55
  dara/core/internal/pool/channel.py,sha256=TbyIE-PnfzzsQYhl3INOs5UIHHbF_h9bMFne5FjbWlQ,4948
56
56
  dara/core/internal/pool/definitions.py,sha256=27dtsyHsztc7zgr2axMWCn1O9pBNI_VKByGxjvKHBGc,4649
57
57
  dara/core/internal/pool/task_pool.py,sha256=MqzUtoGEjeXdpCdTmBXQmQt582u0suiL5vwrsj1slhY,17780
58
- dara/core/internal/pool/utils.py,sha256=HoNlHy2V0VmX5Xm2cqsFbPIOV74E2MslzTFgyNRmiB0,5411
58
+ dara/core/internal/pool/utils.py,sha256=7M8A3lYfp3TVB6yPf-6-nnSr5j6TCqHzdT9I639lUS0,5470
59
59
  dara/core/internal/pool/worker.py,sha256=eBi3FS652goZxu9chaRT89eHDvqJW0aHjt8I5UgyESA,6808
60
60
  dara/core/internal/port_utils.py,sha256=3NN94CubNrIYQKmPM4SEwstY-UMqsbbe1M_JhyPcncA,1654
61
61
  dara/core/internal/registries.py,sha256=1lY9xrggiyUlM32pPyzFEfflW3_37QGOxTDrfWQ4CN4,3659
@@ -65,7 +65,7 @@ dara/core/internal/routing.py,sha256=El2rRuJODoTuZvyay1LSbxCX8IvGDos3dwXYn1RIHZs
65
65
  dara/core/internal/scheduler.py,sha256=rmj-NnHHToWBPuteKlf0RmKcav2Hz0Z9-l4uyrAGKSI,13069
66
66
  dara/core/internal/settings.py,sha256=DxRvXcelawaKemTcX6JIVIilibn0XO5Bd98dCXau4zg,3937
67
67
  dara/core/internal/store.py,sha256=Z4EUMwHR0DR-TVCL9csSGYE3toxh15iRpBP2c7MUgr8,6442
68
- dara/core/internal/tasks.py,sha256=LVRrcK_cuJ7fujSUb8S6xSkPLYmxrAcnXKxEvo7G3l0,34814
68
+ dara/core/internal/tasks.py,sha256=84-87FtxsoCp-SrhE3w-rcMuj-yiaNs2itPYt0n-0dQ,36098
69
69
  dara/core/internal/utils.py,sha256=nUnwy1BLW9HUQro9ASAYb-AlNJkbaT_bQ1bE2e1q1wo,9088
70
70
  dara/core/internal/websocket.py,sha256=rcipt5XY48akMuLHFdvUUIgNLqzJx7ovLeiPsYVMELM,21953
71
71
  dara/core/jinja/index.html,sha256=5Sq_FwXn0F4dOyRFprfoh_tn0GUq6_aLYyYdpzQLdeM,3312
@@ -120,8 +120,8 @@ dara/core/visual/themes/__init__.py,sha256=aM4mgoIYo2neBSw5FRzswsht7PUKjLthiHLmF
120
120
  dara/core/visual/themes/dark.py,sha256=UQGDooOc8ric73eHs9E0ltYP4UCrwqQ3QxqN_fb4PwY,1942
121
121
  dara/core/visual/themes/definitions.py,sha256=5g83t24w8Ar51Cl9REBJfCU7_DtlashBQeUTKDg3D1M,2862
122
122
  dara/core/visual/themes/light.py,sha256=-Tviq8oEwGbdFULoDOqPuHO0UpAZGsBy8qFi0kAGolQ,1944
123
- dara_core-1.21.12.dist-info/LICENSE,sha256=r9u1w2RvpLMV6YjuXHIKXRBKzia3fx_roPwboGcLqCc,10944
124
- dara_core-1.21.12.dist-info/METADATA,sha256=grTJrNqVMQk1Da7XU6IVNt7Jrf1TidbxBbRnISdHPn8,7544
125
- dara_core-1.21.12.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
126
- dara_core-1.21.12.dist-info/entry_points.txt,sha256=H__D5sNIGuPIhVam0DChNL-To5k8Y7nY7TAFz9Mz6cc,139
127
- dara_core-1.21.12.dist-info/RECORD,,
123
+ dara_core-1.21.13.dist-info/LICENSE,sha256=r9u1w2RvpLMV6YjuXHIKXRBKzia3fx_roPwboGcLqCc,10944
124
+ dara_core-1.21.13.dist-info/METADATA,sha256=TrgbUFRw_sb5zVZux8BKLvN_iDKIhlg-gx3hBBepjfA,7544
125
+ dara_core-1.21.13.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
126
+ dara_core-1.21.13.dist-info/entry_points.txt,sha256=H__D5sNIGuPIhVam0DChNL-To5k8Y7nY7TAFz9Mz6cc,139
127
+ dara_core-1.21.13.dist-info/RECORD,,