flwr-nightly 1.20.0.dev20250717__py3-none-any.whl → 1.20.0.dev20250718__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.
@@ -18,6 +18,8 @@
18
18
  from typing import Callable
19
19
 
20
20
  from flwr.proto.message_pb2 import ( # pylint: disable=E0611
21
+ ConfirmMessageReceivedRequest,
22
+ ConfirmMessageReceivedResponse,
21
23
  PullObjectRequest,
22
24
  PullObjectResponse,
23
25
  PushObjectRequest,
@@ -27,6 +29,10 @@ from flwr.proto.node_pb2 import Node # pylint: disable=E0611
27
29
 
28
30
  from .inflatable_utils import ObjectIdNotPreregisteredError, ObjectUnavailableError
29
31
 
32
+ ConfirmMessageReceivedProtobuf = Callable[
33
+ [ConfirmMessageReceivedRequest], ConfirmMessageReceivedResponse
34
+ ]
35
+
30
36
 
31
37
  def make_pull_object_fn_protobuf(
32
38
  pull_object_protobuf: Callable[[PullObjectRequest], PullObjectResponse],
@@ -99,3 +105,37 @@ def make_push_object_fn_protobuf(
99
105
  raise ObjectIdNotPreregisteredError(object_id)
100
106
 
101
107
  return push_object_fn
108
+
109
+
110
+ def make_confirm_message_received_fn_protobuf(
111
+ confirm_message_received_protobuf: ConfirmMessageReceivedProtobuf,
112
+ node: Node,
113
+ run_id: int,
114
+ ) -> Callable[[str], None]:
115
+ """Create a confirm message received function that uses protobuf.
116
+
117
+ Parameters
118
+ ----------
119
+ confirm_message_received_protobuf : ConfirmMessageReceivedProtobuf
120
+ A callable that takes a `ConfirmMessageReceivedRequest` and returns a
121
+ `ConfirmMessageReceivedResponse`, confirming message receipt.
122
+ This function is typically backed by a gRPC client stub.
123
+ node : Node
124
+ The node making the request.
125
+ run_id : int
126
+ The run ID for the current message.
127
+
128
+ Returns
129
+ -------
130
+ Callable[[str], None]
131
+ A wrapper function that takes an object ID and confirms that
132
+ the message has been received.
133
+ """
134
+
135
+ def confirm_message_received_fn(object_id: str) -> None:
136
+ request = ConfirmMessageReceivedRequest(
137
+ node=node, run_id=run_id, message_object_id=object_id
138
+ )
139
+ confirm_message_received_protobuf(request)
140
+
141
+ return confirm_message_received_fn
@@ -19,7 +19,9 @@ import os
19
19
  import random
20
20
  import threading
21
21
  import time
22
- from typing import Callable, Optional
22
+ from typing import Callable, Optional, TypeVar
23
+
24
+ from flwr.proto.message_pb2 import ObjectTree # pylint: disable=E0611
23
25
 
24
26
  from .constant import (
25
27
  HEAD_BODY_DIVIDER,
@@ -38,6 +40,7 @@ from .inflatable import (
38
40
  get_object_head_values_from_object_content,
39
41
  get_object_id,
40
42
  is_valid_sha256_hash,
43
+ iterate_object_tree,
41
44
  )
42
45
  from .message import Message
43
46
  from .record import Array, ArrayRecord, ConfigRecord, MetricRecord, RecordDict
@@ -54,6 +57,8 @@ inflatable_class_registry: dict[str, type[InflatableObject]] = {
54
57
  RecordDict.__qualname__: RecordDict,
55
58
  }
56
59
 
60
+ T = TypeVar("T", bound=InflatableObject)
61
+
57
62
 
58
63
  class ObjectUnavailableError(Exception):
59
64
  """Exception raised when an object has been pre-registered but is not yet
@@ -348,3 +353,75 @@ def validate_object_content(content: bytes) -> None:
348
353
  raise UnexpectedObjectContentError(
349
354
  object_id=get_object_id(content), reason=str(err)
350
355
  ) from err
356
+
357
+
358
+ def pull_and_inflate_object_from_tree( # pylint: disable=R0913
359
+ object_tree: ObjectTree,
360
+ pull_object_fn: Callable[[str], bytes],
361
+ confirm_object_received_fn: Callable[[str], None],
362
+ *,
363
+ return_type: type[T] = InflatableObject, # type: ignore
364
+ max_concurrent_pulls: int = MAX_CONCURRENT_PULLS,
365
+ max_time: Optional[float] = PULL_MAX_TIME,
366
+ max_tries_per_object: Optional[int] = PULL_MAX_TRIES_PER_OBJECT,
367
+ initial_backoff: float = PULL_INITIAL_BACKOFF,
368
+ backoff_cap: float = PULL_BACKOFF_CAP,
369
+ ) -> T:
370
+ """Pull and inflate the head object from the provided object tree.
371
+
372
+ Parameters
373
+ ----------
374
+ object_tree : ObjectTree
375
+ The object tree containing the object ID and its descendants.
376
+ pull_object_fn : Callable[[str], bytes]
377
+ A function that takes an object ID and returns the object content as bytes.
378
+ confirm_object_received_fn : Callable[[str], None]
379
+ A function to confirm that the object has been received.
380
+ return_type : type[T] (default: InflatableObject)
381
+ The type of the object to return. Must be a subclass of `InflatableObject`.
382
+ max_concurrent_pulls : int (default: MAX_CONCURRENT_PULLS)
383
+ The maximum number of concurrent pulls to perform.
384
+ max_time : Optional[float] (default: PULL_MAX_TIME)
385
+ The maximum time to wait for all pulls to complete. If `None`, waits
386
+ indefinitely.
387
+ max_tries_per_object : Optional[int] (default: PULL_MAX_TRIES_PER_OBJECT)
388
+ The maximum number of attempts to pull each object. If `None`, pulls
389
+ indefinitely until the object is available.
390
+ initial_backoff : float (default: PULL_INITIAL_BACKOFF)
391
+ The initial backoff time in seconds for retrying pulls after an
392
+ `ObjectUnavailableError`.
393
+ backoff_cap : float (default: PULL_BACKOFF_CAP)
394
+ The maximum backoff time in seconds. Backoff times will not exceed this value.
395
+
396
+ Returns
397
+ -------
398
+ T
399
+ An instance of the specified return type containing the inflated object.
400
+ """
401
+ # Pull the main object and all its descendants
402
+ pulled_object_contents = pull_objects(
403
+ [tree.object_id for tree in iterate_object_tree(object_tree)],
404
+ pull_object_fn,
405
+ max_concurrent_pulls=max_concurrent_pulls,
406
+ max_time=max_time,
407
+ max_tries_per_object=max_tries_per_object,
408
+ initial_backoff=initial_backoff,
409
+ backoff_cap=backoff_cap,
410
+ )
411
+
412
+ # Confirm that all objects were pulled
413
+ confirm_object_received_fn(object_tree.object_id)
414
+
415
+ # Inflate the main object
416
+ inflated_object = inflate_object_from_contents(
417
+ object_tree.object_id, pulled_object_contents, keep_object_contents=False
418
+ )
419
+
420
+ # Check if the inflated object is of the expected type
421
+ if not isinstance(inflated_object, return_type):
422
+ raise TypeError(
423
+ f"Expected object of type {return_type.__name__}, "
424
+ f"but got {type(inflated_object).__name__}."
425
+ )
426
+
427
+ return inflated_object
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: flwr-nightly
3
- Version: 1.20.0.dev20250717
3
+ Version: 1.20.0.dev20250718
4
4
  Summary: Flower: A Friendly Federated AI Framework
5
5
  License: Apache-2.0
6
6
  Keywords: Artificial Intelligence,Federated AI,Federated Analytics,Federated Evaluation,Federated Learning,Flower,Machine Learning
@@ -123,8 +123,8 @@ flwr/common/exit_handlers.py,sha256=IaqJ60fXZuu7McaRYnoYKtlbH9t4Yl9goNExKqtmQbs,
123
123
  flwr/common/grpc.py,sha256=y70hUFvXkIf3l03xOhlb7qhS6W1UJZRSZqCdB0ir0v8,10381
124
124
  flwr/common/heartbeat.py,sha256=SyEpNDnmJ0lni0cWO67rcoJVKasCLmkNHm3dKLeNrLU,5749
125
125
  flwr/common/inflatable.py,sha256=GDL9oBKs16_yyVdlH6kBf493O5xll_h9V7XB5Mpx1Hc,9524
126
- flwr/common/inflatable_protobuf_utils.py,sha256=lvKR5jD5P8AlpknD_1BlvUoTuT6Iyd8oodXfUQvjDRU,3746
127
- flwr/common/inflatable_utils.py,sha256=yew5VU8po8yZsmoTVxg-tB5vrvnb2mvBAE55qjiOAq8,12840
126
+ flwr/common/inflatable_protobuf_utils.py,sha256=JtRqp-fV47goDM2y8JRQ7AmwwjeGaWexwoMWLcxX5gE,5056
127
+ flwr/common/inflatable_utils.py,sha256=kJnLBQEaByrJPGg0O2saExjLf_GPNqFlGOt0nOc3ZUw,15982
128
128
  flwr/common/logger.py,sha256=JbRf6E2vQxXzpDBq1T8IDUJo_usu3gjWEBPQ6uKcmdg,13049
129
129
  flwr/common/message.py,sha256=xAL7iZN5-n-xPQpgoSFvxNrzs8fmiiPfoU0DjNQEhRw,19953
130
130
  flwr/common/object_ref.py,sha256=p3SfTeqo3Aj16SkB-vsnNn01zswOPdGNBitcbRnqmUk,9134
@@ -369,7 +369,7 @@ flwr/supernode/servicer/__init__.py,sha256=lucTzre5WPK7G1YLCfaqg3rbFWdNSb7ZTt-ca
369
369
  flwr/supernode/servicer/clientappio/__init__.py,sha256=7Oy62Y_oijqF7Dxi6tpcUQyOpLc_QpIRZ83NvwmB0Yg,813
370
370
  flwr/supernode/servicer/clientappio/clientappio_servicer.py,sha256=OclO38I6NhKwM2ZnHz9NjrxW4RA4_v8M4GkLzsReG2c,9477
371
371
  flwr/supernode/start_client_internal.py,sha256=_ZqSfL_j4qn6Cg-P6sv3k_n1ZG62J_teokBxnWrXrPE,18772
372
- flwr_nightly-1.20.0.dev20250717.dist-info/METADATA,sha256=VlPfht2YzCaqiIBeDUy6f8p4AHm88CNaVCeEh8tGhMA,15966
373
- flwr_nightly-1.20.0.dev20250717.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
374
- flwr_nightly-1.20.0.dev20250717.dist-info/entry_points.txt,sha256=jNpDXGBGgs21RqUxelF_jwGaxtqFwm-MQyfz-ZqSjrA,367
375
- flwr_nightly-1.20.0.dev20250717.dist-info/RECORD,,
372
+ flwr_nightly-1.20.0.dev20250718.dist-info/METADATA,sha256=GVGToag6Bdk8OT-FHN7080UDdDwbCEnMA3tlR7L0ZwQ,15966
373
+ flwr_nightly-1.20.0.dev20250718.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
374
+ flwr_nightly-1.20.0.dev20250718.dist-info/entry_points.txt,sha256=jNpDXGBGgs21RqUxelF_jwGaxtqFwm-MQyfz-ZqSjrA,367
375
+ flwr_nightly-1.20.0.dev20250718.dist-info/RECORD,,