flwr-nightly 1.20.0.dev20250721__py3-none-any.whl → 1.20.0.dev20250722__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.
flwr/common/constant.py CHANGED
@@ -123,7 +123,7 @@ AUTHZ_TYPE_YAML_KEY = "authz_type" # For key name in YAML file
123
123
  PUBLIC_KEY_HEADER = "flwr-public-key-bin" # Must end with "-bin" for binary data
124
124
  SIGNATURE_HEADER = "flwr-signature-bin" # Must end with "-bin" for binary data
125
125
  TIMESTAMP_HEADER = "flwr-timestamp"
126
- TIMESTAMP_TOLERANCE = 10 # General tolerance for timestamp verification
126
+ TIMESTAMP_TOLERANCE = 300 # General tolerance for timestamp verification
127
127
  SYSTEM_TIME_TOLERANCE = 5 # Allowance for system time drift
128
128
 
129
129
  # Constants for grpc retry
@@ -264,14 +264,22 @@ class Array(InflatableObject):
264
264
 
265
265
  def slice_array(self) -> list[tuple[str, InflatableObject]]:
266
266
  """Slice Array data and construct a list of ArrayChunks."""
267
- children: list[tuple[str, InflatableObject]] = []
267
+ # Return cached chunks if they exist
268
+ if "_chunks" in self.__dict__:
269
+ return cast(list[tuple[str, InflatableObject]], self.__dict__["_chunks"])
270
+
271
+ # Chunks are not children as some of them may be identical
272
+ chunks: list[tuple[str, InflatableObject]] = []
268
273
  # memoryview allows for zero-copy slicing
269
274
  data_view = memoryview(self.data)
270
275
  for start in range(0, len(data_view), MAX_ARRAY_CHUNK_SIZE):
271
276
  end = min(start + MAX_ARRAY_CHUNK_SIZE, len(data_view))
272
277
  ac = ArrayChunk(data_view[start:end])
273
- children.append((ac.object_id, ac))
274
- return children
278
+ chunks.append((ac.object_id, ac))
279
+
280
+ # Cache the chunks for future use
281
+ self.__dict__["_chunks"] = chunks
282
+ return chunks
275
283
 
276
284
  def deflate(self) -> bytes:
277
285
  """Deflate the Array."""
@@ -386,4 +394,9 @@ class Array(InflatableObject):
386
394
  if name in ("dtype", "shape", "stype", "data"):
387
395
  # Mark as dirty if any of the main attributes are set
388
396
  self.is_dirty = True
397
+ # Clear cached object ID
398
+ self.__dict__.pop("_object_id", None)
399
+ # Clear cached chunks if data is set
400
+ if name == "data":
401
+ self.__dict__.pop("_chunks", None)
389
402
  super().__setattr__(name, value)
@@ -28,9 +28,6 @@ class ArrayChunk(InflatableObject):
28
28
 
29
29
  data: memoryview
30
30
 
31
- def __init__(self, data: bytes) -> None:
32
- self.data = memoryview(data)
33
-
34
31
  def deflate(self) -> bytes:
35
32
  """Deflate the ArrayChunk."""
36
33
  return add_header_to_object_body(object_body=self.data, obj=self)
@@ -99,8 +99,10 @@ class ObjectStore(abc.ABC):
99
99
 
100
100
  Returns
101
101
  -------
102
- bytes
103
- The object stored under the given object_id.
102
+ Optional[bytes]
103
+ The object stored under the given object_id if it exists, else None.
104
+ The returned bytes will be b"" if the object is not yet available,
105
+ but has been preregistered.
104
106
  """
105
107
 
106
108
  @abc.abstractmethod
@@ -23,7 +23,7 @@ from contextlib import contextmanager
23
23
  from functools import partial
24
24
  from logging import INFO, WARN
25
25
  from pathlib import Path
26
- from typing import Callable, Optional, Union
26
+ from typing import Callable, Optional, Union, cast
27
27
 
28
28
  import grpc
29
29
  from cryptography.hazmat.primitives.asymmetric import ec
@@ -384,23 +384,29 @@ def _push_messages(
384
384
 
385
385
  # Define the iterator for yielding object contents
386
386
  # This will yield (object_id, content) pairs
387
- def yield_object_contents(_obj_tree: ObjectTree) -> Iterator[tuple[str, bytes]]:
387
+ def yield_object_contents(
388
+ _obj_tree: ObjectTree, obj_id_set: set[str]
389
+ ) -> Iterator[tuple[str, bytes]]:
388
390
  for tree in iterate_object_tree(_obj_tree):
389
- while (content := object_store.get(tree.object_id)) is None:
391
+ if tree.object_id not in obj_id_set:
392
+ continue
393
+ while (content := object_store.get(tree.object_id)) == b"":
390
394
  # Wait for the content to be available
391
395
  time.sleep(0.5)
392
-
393
- yield tree.object_id, content
396
+ # At this point, content is guaranteed to be available
397
+ # therefore we can yield it after casting it to bytes
398
+ yield tree.object_id, cast(bytes, content)
394
399
 
395
400
  # Send the message
396
401
  try:
397
402
  # Send the reply message with its ObjectTree
398
- send(message, object_tree)
403
+ # Get the IDs of objects to send
404
+ ids_obj_to_send = send(message, object_tree)
399
405
 
400
406
  # Push object contents from the ObjectStore
401
407
  run_id = message.metadata.run_id
402
408
  push_object_contents_from_iterable(
403
- yield_object_contents(object_tree),
409
+ yield_object_contents(object_tree, ids_obj_to_send),
404
410
  # Use functools.partial to bind run_id explicitly,
405
411
  # avoiding late binding issues and satisfying flake8 (B023)
406
412
  # Equivalent to:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: flwr-nightly
3
- Version: 1.20.0.dev20250721
3
+ Version: 1.20.0.dev20250722
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
@@ -108,7 +108,7 @@ flwr/common/args.py,sha256=-aX_jVnSaDrJR2KZ8Wq0Y3dQHII4R4MJtJOIXzVUA0c,5417
108
108
  flwr/common/auth_plugin/__init__.py,sha256=3rzPkVLn9WyB5n7HLk1XGDw3SLCqRWAU1_CnglcWPfw,970
109
109
  flwr/common/auth_plugin/auth_plugin.py,sha256=kXx5o39vJchaPv28sK9qO6H_UXSWym6zRBbCa7sUwtQ,4825
110
110
  flwr/common/config.py,sha256=glcZDjco-amw1YfQcYTFJ4S1pt9APoexT-mf1QscuHs,13960
111
- flwr/common/constant.py,sha256=HMLDvtiWGcGUfHpyyMx1rau34eXdMuBsvn-koRD8-pQ,8234
111
+ flwr/common/constant.py,sha256=7BHHSoeNlOzweYyacI1DPLfyPhzN24C7VCA8j9pgA2A,8235
112
112
  flwr/common/context.py,sha256=Be8obQR_OvEDy1OmshuUKxGRQ7Qx89mf5F4xlhkR10s,2407
113
113
  flwr/common/date.py,sha256=1ZT2cRSpC2DJqprOVTLXYCR_O2_OZR0zXO_brJ3LqWc,1554
114
114
  flwr/common/differential_privacy.py,sha256=FdlpdpPl_H_2HJa8CQM1iCUGBBQ5Dc8CzxmHERM-EoE,6148
@@ -131,8 +131,8 @@ flwr/common/object_ref.py,sha256=p3SfTeqo3Aj16SkB-vsnNn01zswOPdGNBitcbRnqmUk,913
131
131
  flwr/common/parameter.py,sha256=UVw6sOgehEFhFs4uUCMl2kfVq1PD6ncmWgPLMsZPKPE,2095
132
132
  flwr/common/pyproject.py,sha256=2SU6yJW7059SbMXgzjOdK1GZRWO6AixDH7BmdxbMvHI,1386
133
133
  flwr/common/record/__init__.py,sha256=cNGccdDoxttqgnUgyKRIqLWULjW-NaSmOufVxtXq-sw,1197
134
- flwr/common/record/array.py,sha256=50WACrlTRbGOnRpw5Qqt-5_u4TroVl-7jRHCx_CQ35o,14503
135
- flwr/common/record/arraychunk.py,sha256=2ubMzsRNZFL4cc-wXNrJkcTSJUD3nL8CeX5PZpEhNSo,2019
134
+ flwr/common/record/array.py,sha256=6ybCfUZ13zI_CZKETUAVhIwlmbEGj4k6JazvVX5rOPw,15038
135
+ flwr/common/record/arraychunk.py,sha256=gU5h6uP7H_06Z14wNixtwH2FvepQkl9FpALXg9qcbhM,1936
136
136
  flwr/common/record/arrayrecord.py,sha256=CpoqYXM6Iv4XEc9SryCMYmw-bIvP8ut6xWJzRwYJzdU,18008
137
137
  flwr/common/record/configrecord.py,sha256=G7U0q39kB0Kyi0zMxFmPxcVemL9NgwVS1qjvI4BRQuU,9763
138
138
  flwr/common/record/conversion_utils.py,sha256=wbNCzy7oAqaA3-arhls_EqRZYXRC4YrWIoE-Gy82fJ0,1191
@@ -341,7 +341,7 @@ flwr/supercore/license_plugin/__init__.py,sha256=d8OgHTn2BwjoNSPy8jQQxTC_iT3-ENL
341
341
  flwr/supercore/license_plugin/license_plugin.py,sha256=BFhlCH5v9KKuY7crVCsi8fuYe98SJfnGxRS0CVc_Y5I,948
342
342
  flwr/supercore/object_store/__init__.py,sha256=cdfPAmjINY6iOp8oI_LdcVh2simg469Mkdl4LLV4kHI,911
343
343
  flwr/supercore/object_store/in_memory_object_store.py,sha256=CGY43syxDGrUPcdOzRH3hNrfeqmoTOY_wjo3qaAHuNk,9612
344
- flwr/supercore/object_store/object_store.py,sha256=wC6Pxq89a7FwmIMJE3ZLPPy2i7Gdss7-8RUapECCAPY,5099
344
+ flwr/supercore/object_store/object_store.py,sha256=J-rI3X7ET-F6dqOyM-UfHKCCQtPJ_EnYW62H_1txts0,5252
345
345
  flwr/supercore/object_store/object_store_factory.py,sha256=QVwE2ywi7vsj2iKfvWWnNw3N_I7Rz91NUt2RpcbJ7iM,1527
346
346
  flwr/supercore/object_store/utils.py,sha256=-WwBa6ejMNm9ahmNZP39IHutS0cwingmeqCoxTmATQM,1845
347
347
  flwr/supercore/utils.py,sha256=ebuHMbeA8eXisX0oMPqBK3hk7uVnIE_yiqWVz8YbkpQ,1324
@@ -369,8 +369,8 @@ flwr/supernode/runtime/run_clientapp.py,sha256=woAO8rXclt5eZeNHokhBChgxMf-TAzqWn
369
369
  flwr/supernode/servicer/__init__.py,sha256=lucTzre5WPK7G1YLCfaqg3rbFWdNSb7ZTt-ca8gxdEo,717
370
370
  flwr/supernode/servicer/clientappio/__init__.py,sha256=7Oy62Y_oijqF7Dxi6tpcUQyOpLc_QpIRZ83NvwmB0Yg,813
371
371
  flwr/supernode/servicer/clientappio/clientappio_servicer.py,sha256=SOx719uqdkIHryBri-XpuYpALQE__hxNtDjSAdeUtug,10059
372
- flwr/supernode/start_client_internal.py,sha256=Sa9HT-YrS_RPkY44Dv6X-EZOX8HGupJyS4EY_e0x8u8,21367
373
- flwr_nightly-1.20.0.dev20250721.dist-info/METADATA,sha256=leBKwaZsOax_yJrfB6silj5VVDX6i3Oe_GHSF2D3yV0,15966
374
- flwr_nightly-1.20.0.dev20250721.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
375
- flwr_nightly-1.20.0.dev20250721.dist-info/entry_points.txt,sha256=jNpDXGBGgs21RqUxelF_jwGaxtqFwm-MQyfz-ZqSjrA,367
376
- flwr_nightly-1.20.0.dev20250721.dist-info/RECORD,,
372
+ flwr/supernode/start_client_internal.py,sha256=j0tGOaki1LNNMKzvnb2h8mGM0nE3ys-GzwAh0r6rgWI,21731
373
+ flwr_nightly-1.20.0.dev20250722.dist-info/METADATA,sha256=nF2Mzn-x3-xwXJ-gLIXU9zZgS7XXOIrU1_MUkX-MpiY,15966
374
+ flwr_nightly-1.20.0.dev20250722.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
375
+ flwr_nightly-1.20.0.dev20250722.dist-info/entry_points.txt,sha256=jNpDXGBGgs21RqUxelF_jwGaxtqFwm-MQyfz-ZqSjrA,367
376
+ flwr_nightly-1.20.0.dev20250722.dist-info/RECORD,,