flwr-nightly 1.22.0.dev20250910__py3-none-any.whl → 1.22.0.dev20250912__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.
Files changed (23) hide show
  1. flwr/cli/new/templates/app/code/client.huggingface.py.tpl +68 -30
  2. flwr/cli/new/templates/app/code/client.jax.py.tpl +63 -42
  3. flwr/cli/new/templates/app/code/client.mlx.py.tpl +80 -51
  4. flwr/cli/new/templates/app/code/client.numpy.py.tpl +36 -13
  5. flwr/cli/new/templates/app/code/client.sklearn.py.tpl +75 -30
  6. flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +69 -44
  7. flwr/cli/new/templates/app/code/server.huggingface.py.tpl +23 -19
  8. flwr/cli/new/templates/app/code/server.jax.py.tpl +27 -14
  9. flwr/cli/new/templates/app/code/server.mlx.py.tpl +29 -19
  10. flwr/cli/new/templates/app/code/server.numpy.py.tpl +30 -17
  11. flwr/cli/new/templates/app/code/server.sklearn.py.tpl +29 -21
  12. flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +28 -19
  13. flwr/cli/new/templates/app/code/task.huggingface.py.tpl +16 -20
  14. flwr/cli/new/templates/app/code/task.jax.py.tpl +1 -1
  15. flwr/cli/new/templates/app/code/task.numpy.py.tpl +1 -1
  16. flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +1 -2
  17. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +3 -3
  18. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +1 -1
  19. flwr/serverapp/strategy/fedavg.py +66 -62
  20. {flwr_nightly-1.22.0.dev20250910.dist-info → flwr_nightly-1.22.0.dev20250912.dist-info}/METADATA +1 -1
  21. {flwr_nightly-1.22.0.dev20250910.dist-info → flwr_nightly-1.22.0.dev20250912.dist-info}/RECORD +23 -23
  22. {flwr_nightly-1.22.0.dev20250910.dist-info → flwr_nightly-1.22.0.dev20250912.dist-info}/WHEEL +0 -0
  23. {flwr_nightly-1.22.0.dev20250910.dist-info → flwr_nightly-1.22.0.dev20250912.dist-info}/entry_points.txt +0 -0
@@ -169,56 +169,88 @@ class FedAvg(Strategy):
169
169
  )
170
170
  return self._construct_messages(record, node_ids, MessageType.TRAIN)
171
171
 
172
- def aggregate_train(
173
- self,
174
- server_round: int,
175
- replies: Iterable[Message],
176
- ) -> tuple[Optional[ArrayRecord], Optional[MetricRecord]]:
177
- """Aggregate ArrayRecords and MetricRecords in the received Messages."""
172
+ def _check_and_log_replies(
173
+ self, replies: Iterable[Message], is_train: bool, validate: bool = True
174
+ ) -> tuple[list[Message], list[Message]]:
175
+ """Check replies for errors and log them.
176
+
177
+ Parameters
178
+ ----------
179
+ replies : Iterable[Message]
180
+ Iterable of reply Messages.
181
+ is_train : bool
182
+ Set to True if the replies are from a training round; False otherwise.
183
+ This impacts logging and validation behavior.
184
+ validate : bool (default: True)
185
+ Whether to validate the reply contents for consistency.
186
+
187
+ Returns
188
+ -------
189
+ tuple[list[Message], list[Message]]
190
+ A tuple containing two lists:
191
+ - Messages with valid contents.
192
+ - Messages with errors.
193
+ """
178
194
  if not replies:
179
- return None, None
195
+ return [], []
180
196
 
181
- # Log if any Messages carried errors
182
197
  # Filter messages that carry content
183
- num_errors = 0
184
- replies_with_content = []
198
+ valid_replies: list[Message] = []
199
+ error_replies: list[Message] = []
185
200
  for msg in replies:
186
201
  if msg.has_error():
187
- log(
188
- INFO,
189
- "Received error in reply from node %d: %s",
190
- msg.metadata.src_node_id,
191
- msg.error,
192
- )
193
- num_errors += 1
202
+ error_replies.append(msg)
194
203
  else:
195
- replies_with_content.append(msg.content)
204
+ valid_replies.append(msg)
196
205
 
197
206
  log(
198
207
  INFO,
199
- "aggregate_train: Received %s results and %s failures",
200
- len(replies_with_content),
201
- num_errors,
208
+ "%s: Received %s results and %s failures",
209
+ "aggregate_train" if is_train else "aggregate_evaluate",
210
+ len(valid_replies),
211
+ len(error_replies),
202
212
  )
203
213
 
214
+ # Log errors
215
+ for msg in error_replies:
216
+ log(
217
+ INFO,
218
+ "\t> Received error in reply from node %d: %s",
219
+ msg.metadata.src_node_id,
220
+ msg.error.reason,
221
+ )
222
+
204
223
  # Ensure expected ArrayRecords and MetricRecords are received
205
- validate_message_reply_consistency(
206
- replies=replies_with_content,
207
- weighted_by_key=self.weighted_by_key,
208
- check_arrayrecord=True,
209
- )
224
+ if validate and valid_replies:
225
+ validate_message_reply_consistency(
226
+ replies=[msg.content for msg in valid_replies],
227
+ weighted_by_key=self.weighted_by_key,
228
+ check_arrayrecord=is_train,
229
+ )
230
+
231
+ return valid_replies, error_replies
232
+
233
+ def aggregate_train(
234
+ self,
235
+ server_round: int,
236
+ replies: Iterable[Message],
237
+ ) -> tuple[Optional[ArrayRecord], Optional[MetricRecord]]:
238
+ """Aggregate ArrayRecords and MetricRecords in the received Messages."""
239
+ valid_replies, _ = self._check_and_log_replies(replies, is_train=True)
210
240
 
211
241
  arrays, metrics = None, None
212
- if replies_with_content:
242
+ if valid_replies:
243
+ reply_contents = [msg.content for msg in valid_replies]
244
+
213
245
  # Aggregate ArrayRecords
214
246
  arrays = aggregate_arrayrecords(
215
- replies_with_content,
247
+ reply_contents,
216
248
  self.weighted_by_key,
217
249
  )
218
250
 
219
251
  # Aggregate MetricRecords
220
252
  metrics = self.train_metrics_aggr_fn(
221
- replies_with_content,
253
+ reply_contents,
222
254
  self.weighted_by_key,
223
255
  )
224
256
  return arrays, metrics
@@ -253,43 +285,15 @@ class FedAvg(Strategy):
253
285
  replies: Iterable[Message],
254
286
  ) -> Optional[MetricRecord]:
255
287
  """Aggregate MetricRecords in the received Messages."""
256
- if not replies:
257
- return None
288
+ valid_replies, _ = self._check_and_log_replies(replies, is_train=False)
258
289
 
259
- # Log if any Messages carried errors
260
- # Filter messages that carry content
261
- num_errors = 0
262
- replies_with_content = []
263
- for msg in replies:
264
- if msg.has_error():
265
- log(
266
- INFO,
267
- "Received error in reply from node %d: %s",
268
- msg.metadata.src_node_id,
269
- msg.error,
270
- )
271
- num_errors += 1
272
- else:
273
- replies_with_content.append(msg.content)
274
-
275
- log(
276
- INFO,
277
- "aggregate_evaluate: Received %s results and %s failures",
278
- len(replies_with_content),
279
- num_errors,
280
- )
281
-
282
- # Ensure expected ArrayRecords and MetricRecords are received
283
- validate_message_reply_consistency(
284
- replies=replies_with_content,
285
- weighted_by_key=self.weighted_by_key,
286
- check_arrayrecord=False,
287
- )
288
290
  metrics = None
289
- if replies_with_content:
291
+ if valid_replies:
292
+ reply_contents = [msg.content for msg in valid_replies]
293
+
290
294
  # Aggregate MetricRecords
291
295
  metrics = self.evaluate_metrics_aggr_fn(
292
- replies_with_content,
296
+ reply_contents,
293
297
  self.weighted_by_key,
294
298
  )
295
299
  return metrics
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: flwr-nightly
3
- Version: 1.22.0.dev20250910
3
+ Version: 1.22.0.dev20250912
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
@@ -31,14 +31,14 @@ flwr/cli/new/templates/app/code/__init__.py,sha256=zXa2YU1swzHxOKDQbwlDMEwVPOUsw
31
31
  flwr/cli/new/templates/app/code/__init__.py.tpl,sha256=J0Gn74E7khpLyKJVNqOPu7ev93vkcu1PZugsbxtABMw,52
32
32
  flwr/cli/new/templates/app/code/__init__.pytorch_msg_api.py.tpl,sha256=mKIS8MK_X8T9NlmcX1-_c9Bbexc-ueqDIBI7uN6c4dE,45
33
33
  flwr/cli/new/templates/app/code/client.baseline.py.tpl,sha256=IYlCZqnaxT2ucP1ReffRNohOkYwNrhtrnDoQBBcrThY,1901
34
- flwr/cli/new/templates/app/code/client.huggingface.py.tpl,sha256=ifD08KwjdoGieV26hFCgf3PQB6rMhj_NZLo5iUUndm8,1846
35
- flwr/cli/new/templates/app/code/client.jax.py.tpl,sha256=4EkcGGmbPAa6dgw8GYII-GfrGsu8VU6amRHpJvF0WuA,1319
36
- flwr/cli/new/templates/app/code/client.mlx.py.tpl,sha256=gOxt_QUTfGFpofdNaxdwTSLZlkTWHPYGix2OGHC1hYE,2376
37
- flwr/cli/new/templates/app/code/client.numpy.py.tpl,sha256=DKcnz5-KUf693Va056QTKVofFV3ozJZutK4rQyfvRXc,548
34
+ flwr/cli/new/templates/app/code/client.huggingface.py.tpl,sha256=SIZZ3s-6u8IU8cFfsqu6ZU8zjhfI1m1SWauOSUcW8TA,3015
35
+ flwr/cli/new/templates/app/code/client.jax.py.tpl,sha256=uFCIPwAHYiRAgh2W3nRni_Oig02ZzRF-ofUG5O19zcE,2125
36
+ flwr/cli/new/templates/app/code/client.mlx.py.tpl,sha256=CHU2IBIzI2YENZZuvTsAlSdL94DK19wMYMIhr-JgwZ8,3422
37
+ flwr/cli/new/templates/app/code/client.numpy.py.tpl,sha256=1_WEoOPe9jJeK-7FZgYuDUqY8mC0vxgqA83d-h201Gk,1381
38
38
  flwr/cli/new/templates/app/code/client.pytorch.py.tpl,sha256=fuxVmZpjHIueNy_aHWF81531vmi8DGu4CYjYDqmUwWo,1705
39
39
  flwr/cli/new/templates/app/code/client.pytorch_msg_api.py.tpl,sha256=fYoh-dTu07LkqNYvwcxQnbgVvH4Yo4eiGEcyHECbsnU,2473
40
- flwr/cli/new/templates/app/code/client.sklearn.py.tpl,sha256=MfhMN-hayGCc3cZ1XpN0A6f67GRveI_tGbq5kjOeP0Q,1871
41
- flwr/cli/new/templates/app/code/client.tensorflow.py.tpl,sha256=yBiiU7B9Kf70U52cPkNs_dUpYrrTwbUi2os-PAyheaM,1680
40
+ flwr/cli/new/templates/app/code/client.sklearn.py.tpl,sha256=0qqEe-RRjkHGOH8gsD9e83ae-kyyYixhyBgzVHjYpzk,3500
41
+ flwr/cli/new/templates/app/code/client.tensorflow.py.tpl,sha256=8o55KXpsbF_rv6o98ZNYJDCazjwMp_RPTaSzDfT7Qlw,2682
42
42
  flwr/cli/new/templates/app/code/dataset.baseline.py.tpl,sha256=jbd_exHAk2-Blu_kVutjPO6a_dkJQWb232zxSeXIZ1k,1453
43
43
  flwr/cli/new/templates/app/code/flwr_tune/__init__.py,sha256=Xq5fEn5yZkw6HAJi10T_3HRBoqN5_5pNqJHY4wXvD5k,748
44
44
  flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl,sha256=vJ-cbxwaNmDr9eDAVINy_qUJzA2FirSXKsrkUnlFWYU,3759
@@ -48,29 +48,29 @@ flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl,sha256=xkmmBKr0oGmew
48
48
  flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl,sha256=BhiqRg9w1MGuU5h2_vrLhRc0oHItYzE69qX_JI411k8,2754
49
49
  flwr/cli/new/templates/app/code/model.baseline.py.tpl,sha256=zJklLwH4vPx7rruzhzbAGdInxjjJw-djHCuCx5wshVA,2575
50
50
  flwr/cli/new/templates/app/code/server.baseline.py.tpl,sha256=rBB-DKEuA2SG1DGLW8uSHUg-GydEgb-7NHEclsC2X2g,1539
51
- flwr/cli/new/templates/app/code/server.huggingface.py.tpl,sha256=0PJmnZvR9_VPLSak1yVfkOx3dmqo6cynhY1l2s4AZrE,1158
52
- flwr/cli/new/templates/app/code/server.jax.py.tpl,sha256=IHk57syZhvO4nWVHGxE9S8f5DTxRKIrTitDufF4RhMY,828
53
- flwr/cli/new/templates/app/code/server.mlx.py.tpl,sha256=GAqalaI-U2uRdttNeRn75k1FzdEW3rmgT-ywuKkFdK4,988
54
- flwr/cli/new/templates/app/code/server.numpy.py.tpl,sha256=xbQlLCKutnOqlbLQPZsaL9WM7vnebTceiU8a0HaUcZk,740
51
+ flwr/cli/new/templates/app/code/server.huggingface.py.tpl,sha256=_2Mv-SqGSMf7sMdbMEmvROzedvNaVHvhIIO3eYAhVYU,1252
52
+ flwr/cli/new/templates/app/code/server.jax.py.tpl,sha256=RW-rh7ogcJ3_BD66bJxTw-ZoP7c-4SK8hVHc-e0SSVY,1029
53
+ flwr/cli/new/templates/app/code/server.mlx.py.tpl,sha256=J8rIe6RL2ndODVJD79xShRKBH70HljFSCi4s_RJ-xLQ,1200
54
+ flwr/cli/new/templates/app/code/server.numpy.py.tpl,sha256=T3hcKbPw3uL5lXEP-MuVJXIBXjzva5sWJXfpQqarUwA,955
55
55
  flwr/cli/new/templates/app/code/server.pytorch.py.tpl,sha256=gvBsGA_Jg9kAH8xTxjzTjMcvBtciuccOwQFbO7ey8tU,916
56
56
  flwr/cli/new/templates/app/code/server.pytorch_msg_api.py.tpl,sha256=epARqfcQ-EQsdZwaaaUp5y4OSTBT6CiFGlNRocw-23A,1158
57
- flwr/cli/new/templates/app/code/server.sklearn.py.tpl,sha256=JoDYjPU99aKTTfjKsCtKHzMICiOR9pi8JGVBsxFpWO4,1133
58
- flwr/cli/new/templates/app/code/server.tensorflow.py.tpl,sha256=xMhQ7AumowgLkgUilgjVK7IbpRhPjslhVJU-vID6NY8,856
57
+ flwr/cli/new/templates/app/code/server.sklearn.py.tpl,sha256=ehQ5VRgBn92WeFl6kupwJnuxSNkKvE-EvKde6A9mNQo,1377
58
+ flwr/cli/new/templates/app/code/server.tensorflow.py.tpl,sha256=2-WTOPd-ewdLd9QmSlflIH7ix7zxAzPEOZoyiPBOy8c,1010
59
59
  flwr/cli/new/templates/app/code/strategy.baseline.py.tpl,sha256=YkHAgppUeD2BnBoGfVB6dEvBfjuIPGsU1gw4CiUi3qA,40
60
- flwr/cli/new/templates/app/code/task.huggingface.py.tpl,sha256=ua6cAhJYPUCwML20DEucM0F4ZzzsEVQLYrRvhQ7CGRE,3347
61
- flwr/cli/new/templates/app/code/task.jax.py.tpl,sha256=jK03Y0HUvVFjUB-cYnvYB-WCRdr451aYklP1o6G5rx8,1530
60
+ flwr/cli/new/templates/app/code/task.huggingface.py.tpl,sha256=piBbY3Dg60bQnCg15uzMw0QiL5SDOYX4YhQouy-X2zI,3164
61
+ flwr/cli/new/templates/app/code/task.jax.py.tpl,sha256=Fb0XgdTAQplM-ZCusI081XA9asO3gHptH772S-Xcyy8,1525
62
62
  flwr/cli/new/templates/app/code/task.mlx.py.tpl,sha256=YxH5z4s5kOh5_9DIY9pvzqURckLDfgdanTA68_iM_Wo,2946
63
- flwr/cli/new/templates/app/code/task.numpy.py.tpl,sha256=MsjJK8DAvM3ex6JTfZuBVqoBKJfCCjIHMUOPkspiSQ0,124
63
+ flwr/cli/new/templates/app/code/task.numpy.py.tpl,sha256=CwUJPnN3z6GjP8-KVGWzx7RYRJsl0wLFZ72xscvl3RM,126
64
64
  flwr/cli/new/templates/app/code/task.pytorch.py.tpl,sha256=XlJqA4Ix_PloO_zJLhjiN5vDj16w3I4CPVGdmbe8asE,3800
65
65
  flwr/cli/new/templates/app/code/task.pytorch_msg_api.py.tpl,sha256=RKA5lV6O6OnVKZ2r75pbzwy9arg5o2lzXqG2kNrLIUU,3446
66
66
  flwr/cli/new/templates/app/code/task.sklearn.py.tpl,sha256=vHdhtMp0FHxbYafXyhDT9aKmmmA0Jvpx5Oum1Yu9lWY,1850
67
- flwr/cli/new/templates/app/code/task.tensorflow.py.tpl,sha256=SKXAZdgBnPpbAbJ90Rb7oQ5ilnopBx_j_JNFoUDeEAI,1732
67
+ flwr/cli/new/templates/app/code/task.tensorflow.py.tpl,sha256=impgWN7MfztmcWF4xh1llcZGsgTvrb1HD5ZE0t-8U08,1731
68
68
  flwr/cli/new/templates/app/code/utils.baseline.py.tpl,sha256=YkHAgppUeD2BnBoGfVB6dEvBfjuIPGsU1gw4CiUi3qA,40
69
69
  flwr/cli/new/templates/app/pyproject.baseline.toml.tpl,sha256=eoRhBN5n00LQu2y4o29JUw3T03CasO5S1HMxHrnyWWQ,3180
70
70
  flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl,sha256=oVq52gXoPT69jHji75FSOYZ978xwIG-AVCha-LyuG7k,2497
71
- flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl,sha256=lqWlKcwE7n7OFdqNDOrpi759HZuWFLEtkPvSL7jIkZI,2019
71
+ flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl,sha256=xHGF38i7oFpvnFvqfqLdtc08CkHRYsenbLz3q1dhCXk,2020
72
72
  flwr/cli/new/templates/app/pyproject.jax.toml.tpl,sha256=fdDhwmPoMirJ095cU_vFCBf0ILQlAoa1fdnHb2LM1yk,1471
73
- flwr/cli/new/templates/app/pyproject.mlx.toml.tpl,sha256=aTvHNL9X3rAiHNgXzDoMbt2UA3xRvVVdga461D59ZPM,1542
73
+ flwr/cli/new/templates/app/pyproject.mlx.toml.tpl,sha256=PAjPT2v06sBZxacNiyMJloDwocCK5tFcGQmMXOoBqc8,1542
74
74
  flwr/cli/new/templates/app/pyproject.numpy.toml.tpl,sha256=Kb_O2iQfzwc6FTy3fWqtQYc3FwY6x9SUgQPGqZR_ILg,1409
75
75
  flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl,sha256=docQbs3MuRR-yT24lVz7N2sQL3Sj49EHuOCuRj_0djQ,1508
76
76
  flwr/cli/new/templates/app/pyproject.pytorch_msg_api.toml.tpl,sha256=SE4H23OFkQbqNU64nYf38igqrT4cJGA7XxEtSnNxJqg,1490
@@ -336,7 +336,7 @@ flwr/serverapp/strategy/__init__.py,sha256=yAYBZUkp4aNmcTLsvormEc9HyO34oEoFN45Li
336
336
  flwr/serverapp/strategy/dp_fixed_clipping.py,sha256=wbP4W7CaUHXdll8ZSVUnTBSEWrnWM00CGk63rOR-Q2s,12133
337
337
  flwr/serverapp/strategy/fedadagrad.py,sha256=fD65P6OEERa_pxq847e1UZpA083AcWR44XavYB0naGM,6343
338
338
  flwr/serverapp/strategy/fedadam.py,sha256=s3xPIqhopy6yPTeFxevSPnc7a6BcKnKsvo2AaO6Z_xs,7138
339
- flwr/serverapp/strategy/fedavg.py,sha256=C8UUvLTjodMpGRb4PNej5gW2cPbXsPKebGX1zPfAMUo,11020
339
+ flwr/serverapp/strategy/fedavg.py,sha256=53L06lZLkbGV0TRZrUWvPaocvFTT1PAhTvu9UkKq1zE,11294
340
340
  flwr/serverapp/strategy/fedopt.py,sha256=kqT0uV2IUE93O72XEVa1JJo61dcwbZEoT9KmYTjR2tE,8477
341
341
  flwr/serverapp/strategy/fedyogi.py,sha256=1Ripr4Hi2cdeTOLiFOXtMKvOxR3BsUQwc7bbTrXN4LM,6653
342
342
  flwr/serverapp/strategy/result.py,sha256=E0Hl2VLnZAgQJjE2GDoKsK7JX-kPPU2KXc47Axt6hGw,4295
@@ -403,7 +403,7 @@ flwr/supernode/servicer/__init__.py,sha256=lucTzre5WPK7G1YLCfaqg3rbFWdNSb7ZTt-ca
403
403
  flwr/supernode/servicer/clientappio/__init__.py,sha256=7Oy62Y_oijqF7Dxi6tpcUQyOpLc_QpIRZ83NvwmB0Yg,813
404
404
  flwr/supernode/servicer/clientappio/clientappio_servicer.py,sha256=nIHRu38EWK-rpNOkcgBRAAKwYQQWFeCwu0lkO7OPZGQ,10239
405
405
  flwr/supernode/start_client_internal.py,sha256=Y9S1-QlO2WP6eo4JvWzIpfaCoh2aoE7bjEYyxNNnlyg,20777
406
- flwr_nightly-1.22.0.dev20250910.dist-info/METADATA,sha256=7KsUFI_mYiRdZsLQ8_3IDEu9hn_ysW_R_r3H5Iz_I5g,15967
407
- flwr_nightly-1.22.0.dev20250910.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
408
- flwr_nightly-1.22.0.dev20250910.dist-info/entry_points.txt,sha256=hxHD2ixb_vJFDOlZV-zB4Ao32_BQlL34ftsDh1GXv14,420
409
- flwr_nightly-1.22.0.dev20250910.dist-info/RECORD,,
406
+ flwr_nightly-1.22.0.dev20250912.dist-info/METADATA,sha256=OP6fAr3TSMpa-fjeKWdOOmeQDsuogn0nPjWVodf3vCg,15967
407
+ flwr_nightly-1.22.0.dev20250912.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
408
+ flwr_nightly-1.22.0.dev20250912.dist-info/entry_points.txt,sha256=hxHD2ixb_vJFDOlZV-zB4Ao32_BQlL34ftsDh1GXv14,420
409
+ flwr_nightly-1.22.0.dev20250912.dist-info/RECORD,,