flwr-nightly 1.21.0.dev20250907__py3-none-any.whl → 1.21.0.dev20250909__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/app/__init__.py CHANGED
@@ -15,19 +15,28 @@
15
15
  """Public Flower App APIs."""
16
16
 
17
17
 
18
+ from flwr.common.constant import MessageType
18
19
  from flwr.common.context import Context
19
20
  from flwr.common.message import Message
20
- from flwr.common.record import ArrayRecord, ConfigRecord, MetricRecord, RecordDict
21
+ from flwr.common.record import (
22
+ Array,
23
+ ArrayRecord,
24
+ ConfigRecord,
25
+ MetricRecord,
26
+ RecordDict,
27
+ )
21
28
 
22
29
  from .error import Error
23
30
  from .metadata import Metadata
24
31
 
25
32
  __all__ = [
33
+ "Array",
26
34
  "ArrayRecord",
27
35
  "ConfigRecord",
28
36
  "Context",
29
37
  "Error",
30
38
  "Message",
39
+ "MessageType",
31
40
  "Metadata",
32
41
  "MetricRecord",
33
42
  "RecordDict",
flwr/cli/utils.py CHANGED
@@ -32,6 +32,7 @@ from flwr.common.constant import (
32
32
  AUTH_TYPE_JSON_KEY,
33
33
  CREDENTIALS_DIR,
34
34
  FLWR_DIR,
35
+ NO_USER_AUTH_MESSAGE,
35
36
  RUN_ID_NOT_FOUND_MESSAGE,
36
37
  )
37
38
  from flwr.common.grpc import (
@@ -312,11 +313,21 @@ def flwr_cli_grpc_exc_handler() -> Iterator[None]:
312
313
  )
313
314
  raise typer.Exit(code=1) from None
314
315
  if e.code() == grpc.StatusCode.UNIMPLEMENTED:
315
- typer.secho(
316
- "❌ User authentication is not enabled on this SuperLink.",
317
- fg=typer.colors.RED,
318
- bold=True,
319
- )
316
+ if e.details() == NO_USER_AUTH_MESSAGE: # pylint: disable=E1101
317
+ typer.secho(
318
+ "❌ User authentication is not enabled on this SuperLink.",
319
+ fg=typer.colors.RED,
320
+ bold=True,
321
+ )
322
+ else:
323
+ typer.secho(
324
+ "❌ The SuperLink cannot process this request. Please verify that "
325
+ "you set the address to its Control API endpoint correctly in your "
326
+ "`pyproject.toml`, and ensure that the Flower versions used by "
327
+ "the CLI and SuperLink are compatible.",
328
+ fg=typer.colors.RED,
329
+ bold=True,
330
+ )
320
331
  raise typer.Exit(code=1) from None
321
332
  if e.code() == grpc.StatusCode.PERMISSION_DENIED:
322
333
  typer.secho(
@@ -324,7 +335,7 @@ def flwr_cli_grpc_exc_handler() -> Iterator[None]:
324
335
  fg=typer.colors.RED,
325
336
  bold=True,
326
337
  )
327
- # pylint: disable=E1101
338
+ # pylint: disable-next=E1101
328
339
  typer.secho(e.details(), fg=typer.colors.RED, bold=True)
329
340
  raise typer.Exit(code=1) from None
330
341
  if e.code() == grpc.StatusCode.UNAVAILABLE:
@@ -337,7 +348,7 @@ def flwr_cli_grpc_exc_handler() -> Iterator[None]:
337
348
  raise typer.Exit(code=1) from None
338
349
  if (
339
350
  e.code() == grpc.StatusCode.NOT_FOUND
340
- and e.details() == RUN_ID_NOT_FOUND_MESSAGE
351
+ and e.details() == RUN_ID_NOT_FOUND_MESSAGE # pylint: disable=E1101
341
352
  ):
342
353
  typer.secho(
343
354
  "❌ Run ID not found.",
@@ -15,13 +15,11 @@
15
15
  """Public Flower ClientApp APIs."""
16
16
 
17
17
 
18
- from flwr.client import mod
19
18
  from flwr.client.client_app import ClientApp
20
19
 
21
- from .centraldp_mods import fixedclipping_mod
20
+ from . import mod
22
21
 
23
22
  __all__ = [
24
23
  "ClientApp",
25
- "fixedclipping_mod",
26
24
  "mod",
27
25
  ]
@@ -0,0 +1,26 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Flower Built-in Mods."""
16
+
17
+
18
+ from flwr.client.mod.comms_mods import arrays_size_mod, message_size_mod
19
+
20
+ from .centraldp_mods import fixedclipping_mod
21
+
22
+ __all__ = [
23
+ "arrays_size_mod",
24
+ "fixedclipping_mod",
25
+ "message_size_mod",
26
+ ]
flwr/common/constant.py CHANGED
@@ -154,6 +154,7 @@ PULL_BACKOFF_CAP = 10 # Maximum backoff time for pulling objects
154
154
 
155
155
  # ControlServicer constants
156
156
  RUN_ID_NOT_FOUND_MESSAGE = "Run ID not found"
157
+ NO_USER_AUTH_MESSAGE = "ControlServicer initialized without user authentication"
157
158
 
158
159
 
159
160
  class MessageType:
@@ -21,6 +21,8 @@ from logging import INFO
21
21
  from time import sleep
22
22
  from typing import Optional, cast
23
23
 
24
+ import numpy as np
25
+
24
26
  from flwr.common import (
25
27
  Array,
26
28
  ArrayRecord,
@@ -99,7 +101,7 @@ def aggregate_arrayrecords(
99
101
  aggregated_np_arrays[key] += value.numpy() * weight
100
102
 
101
103
  return ArrayRecord(
102
- OrderedDict({k: Array(v) for k, v in aggregated_np_arrays.items()})
104
+ OrderedDict({k: Array(np.asarray(v)) for k, v in aggregated_np_arrays.items()})
103
105
  )
104
106
 
105
107
 
@@ -22,8 +22,8 @@ import pytest
22
22
  from parameterized import parameterized
23
23
 
24
24
  from flwr.common import Array, ArrayRecord, ConfigRecord, MetricRecord, RecordDict
25
+ from flwr.serverapp.exception import InconsistentMessageReplies
25
26
 
26
- from ..exception import InconsistentMessageReplies
27
27
  from .strategy_utils import (
28
28
  aggregate_arrayrecords,
29
29
  aggregate_metricrecords,
@@ -71,6 +71,33 @@ def test_arrayrecords_aggregation() -> None:
71
71
  assert aggrd.object_id == ArrayRecord(avg_list).object_id
72
72
 
73
73
 
74
+ def test_arrayrecords_aggregation_with_ndim_zero() -> None:
75
+ """Test aggregation of ArrayRecords with 0-dim arrays."""
76
+ num_replies = 3
77
+ weights = [0.25, 0.4, 0.35]
78
+ np_arrays = [np.array(np.random.randn()) for _ in range(num_replies)]
79
+
80
+ # For 0-dimensional arrays, we just compute the weighted average directly
81
+ avg_list = [np.average(np_arrays, axis=0, weights=weights)]
82
+
83
+ # Construct RecordDicts (mimicing replies)
84
+ records = [
85
+ RecordDict(
86
+ {
87
+ "arrays": ArrayRecord([np_arrays[i]]),
88
+ "metrics": MetricRecord({"weight": weights[i]}),
89
+ }
90
+ )
91
+ for i in range(num_replies)
92
+ ]
93
+ # Execute aggregate
94
+ aggrd = aggregate_arrayrecords(records, weighting_metric_name="weight")
95
+
96
+ # Assert consistency
97
+ assert np.isclose(aggrd.to_numpy_ndarrays()[0], avg_list[0])
98
+ assert aggrd.object_id == ArrayRecord([np.array(avg_list[0])]).object_id
99
+
100
+
74
101
  def test_metricrecords_aggregation() -> None:
75
102
  """Test aggregation of MetricRecords."""
76
103
  num_replies = 3
@@ -17,6 +17,7 @@
17
17
 
18
18
  import argparse
19
19
  from logging import INFO
20
+ from typing import Optional
20
21
 
21
22
  from flwr.common import EventType, event
22
23
  from flwr.common.constant import ExecPluginType
@@ -34,6 +35,25 @@ from flwr.supercore.superexec.plugin import (
34
35
  )
35
36
  from flwr.supercore.superexec.run_superexec import run_superexec
36
37
 
38
+ try:
39
+ from flwr.ee.constant import ExecEePluginType
40
+ from flwr.ee.exec_plugin import get_ee_plugin_and_stub_class
41
+ except ImportError:
42
+
43
+ class ExecEePluginType: # type: ignore[no-redef]
44
+ """SuperExec EE plugin types."""
45
+
46
+ @staticmethod
47
+ def all() -> list[str]:
48
+ """Return all SuperExec EE plugin types."""
49
+ return []
50
+
51
+ def get_ee_plugin_and_stub_class( # pylint: disable=unused-argument
52
+ plugin_type: str,
53
+ ) -> Optional[tuple[type[ExecPlugin], type[object]]]:
54
+ """Get the EE plugin class and stub class based on the plugin type."""
55
+ return None
56
+
37
57
 
38
58
  def flower_superexec() -> None:
39
59
  """Run `flower-superexec` command."""
@@ -73,7 +93,7 @@ def _parse_args() -> argparse.ArgumentParser:
73
93
  parser.add_argument(
74
94
  "--plugin-type",
75
95
  type=str,
76
- choices=ExecPluginType.all(),
96
+ choices=ExecPluginType.all() + ExecEePluginType.all(),
77
97
  required=True,
78
98
  help="The type of plugin to use.",
79
99
  )
@@ -116,4 +136,6 @@ def _get_plugin_and_stub_class(
116
136
  return ServerAppExecPlugin, ServerAppIoStub
117
137
  if plugin_type == ExecPluginType.SIMULATION:
118
138
  return SimulationExecPlugin, SimulationIoStub
139
+ if ret := get_ee_plugin_and_stub_class(plugin_type):
140
+ return ret # type: ignore[no-any-return]
119
141
  raise ValueError(f"Unknown plugin type: {plugin_type}")
@@ -29,6 +29,7 @@ from flwr.common.auth_plugin import ControlAuthPlugin
29
29
  from flwr.common.constant import (
30
30
  FAB_MAX_SIZE,
31
31
  LOG_STREAM_INTERVAL,
32
+ NO_USER_AUTH_MESSAGE,
32
33
  RUN_ID_NOT_FOUND_MESSAGE,
33
34
  Status,
34
35
  SubStatus,
@@ -291,7 +292,7 @@ class ControlServicer(control_pb2_grpc.ControlServicer):
291
292
  if self.auth_plugin is None:
292
293
  context.abort(
293
294
  grpc.StatusCode.UNIMPLEMENTED,
294
- "ControlServicer initialized without user authentication",
295
+ NO_USER_AUTH_MESSAGE,
295
296
  )
296
297
  raise grpc.RpcError() # This line is unreachable
297
298
 
@@ -318,7 +319,7 @@ class ControlServicer(control_pb2_grpc.ControlServicer):
318
319
  if self.auth_plugin is None:
319
320
  context.abort(
320
321
  grpc.StatusCode.UNIMPLEMENTED,
321
- "ControlServicer initialized without user authentication",
322
+ NO_USER_AUTH_MESSAGE,
322
323
  )
323
324
  raise grpc.RpcError() # This line is unreachable
324
325
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: flwr-nightly
3
- Version: 1.21.0.dev20250907
3
+ Version: 1.21.0.dev20250909
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
@@ -1,5 +1,5 @@
1
1
  flwr/__init__.py,sha256=CXTKPZSm83CVKTxw9j_ge6AEVnqgd1rlcsm_2kPoVkU,1009
2
- flwr/app/__init__.py,sha256=msr0FM9Iz56oZgWU3jjP58BKHxvo9tiDeiGLEbPWWeY,1086
2
+ flwr/app/__init__.py,sha256=Pqg1iWx_TiBuGYeGJnS1QgYYWcAnPnZ2h4Y5iacNSls,1195
3
3
  flwr/app/error.py,sha256=0PwA-E_CAs5P_nWAA0kksVO1A44t4CNLEf7u-Su-uJ0,2342
4
4
  flwr/app/exception.py,sha256=dAKSNrdh9YqKZTdYaN8hts4dAMVZHfNDV-ytzYby0LQ,1246
5
5
  flwr/app/metadata.py,sha256=rdMBn0zhIOYmCvmGENQWSQqDwcxwsMJzCle4PQdlc_Y,7331
@@ -79,7 +79,7 @@ flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl,sha256=mK8wOWqoQOVxZG6-
79
79
  flwr/cli/run/__init__.py,sha256=RPyB7KbYTFl6YRiilCch6oezxrLQrl1kijV7BMGkLbA,790
80
80
  flwr/cli/run/run.py,sha256=ECa0kup9dn15O70H74QdgUsEaeErbzDqVX_U0zZO5IM,8173
81
81
  flwr/cli/stop.py,sha256=TR9F61suTxNUzGIktUdoBhXwdRtCdvzGhy3qCuvcfBg,5000
82
- flwr/cli/utils.py,sha256=fkyiWXWfXo5fS_sACw8Rg9wweq3RQ7XvEUEAa_caqkE,12349
82
+ flwr/cli/utils.py,sha256=tTI8PyJdA8BU1PoTS8ZItdCM5EVTeze_Z1zumffYY6A,12963
83
83
  flwr/client/__init__.py,sha256=boIhKaK6I977zrILmoTutNx94x5jB0e6F1gnAjaRJnI,1250
84
84
  flwr/client/client.py,sha256=3HAchxvknKG9jYbB7swNyDj-e5vUWDuMKoLvbT7jCVM,7895
85
85
  flwr/client/client_app.py,sha256=zVhi-l3chAb06ozFsKwix3hU_RpOLjST13Ha50AVIPE,16918
@@ -107,15 +107,16 @@ flwr/client/rest_client/__init__.py,sha256=MBiuK62hj439m9rtwSwI184Hth6Tt5GbmpNMy
107
107
  flwr/client/rest_client/connection.py,sha256=fyiS1aXTv71jWczx7mSco94LYJTBXgTF-p2PnAk3CL8,15784
108
108
  flwr/client/run_info_store.py,sha256=MaJ3UQ-07hWtK67wnWu0zR29jrk0fsfgJX506dvEOfE,4042
109
109
  flwr/client/typing.py,sha256=Jw3rawDzI_-ZDcRmEQcs5gZModY7oeQlEeltYsdOhlU,1048
110
- flwr/clientapp/__init__.py,sha256=m_5SENAoZN7G1q7EgBEM4uYb7D90b4CvQe-bOZAN2QY,909
111
- flwr/clientapp/centraldp_mods.py,sha256=M8vvdrjfLVsFLMd9JXqD_-P08q9jsNOgu_4AAs-X9Zk,4626
110
+ flwr/clientapp/__init__.py,sha256=uoTjvIynfGvMhsmc7iYK-5qJ0AdKKjCbx7WTKc0KeSk,828
111
+ flwr/clientapp/mod/__init__.py,sha256=o8bbHMYb_aiPbGp6guRA-I_gCJaJQ6mCqSRZdfBYYrs,920
112
+ flwr/clientapp/mod/centraldp_mods.py,sha256=M8vvdrjfLVsFLMd9JXqD_-P08q9jsNOgu_4AAs-X9Zk,4626
112
113
  flwr/common/__init__.py,sha256=5GCLVk399Az_rTJHNticRlL0Sl_oPw_j5_LuFKfX7-M,4171
113
114
  flwr/common/address.py,sha256=9JucdTwlc-jpeJkRKeUboZoacUtErwSVtnDR9kAtLqE,4119
114
115
  flwr/common/args.py,sha256=Nq2u4yePbkSY0CWFamn0hZY6Rms8G1xYDeDGIcLIITE,5849
115
116
  flwr/common/auth_plugin/__init__.py,sha256=DktrRcGZrRarLf7Jb_UlHtOyLp9_-kEplyq6PS5-vOA,988
116
117
  flwr/common/auth_plugin/auth_plugin.py,sha256=mM7SuphO4OsVAVJR1GErYVgYT83ZjxDzS_gha12bT9E,4855
117
118
  flwr/common/config.py,sha256=glcZDjco-amw1YfQcYTFJ4S1pt9APoexT-mf1QscuHs,13960
118
- flwr/common/constant.py,sha256=0w5GCaW078GMj_VMQX-Lb7OQDnA70GmWZMzufDvGv6E,8769
119
+ flwr/common/constant.py,sha256=FXG5HqwQG-mQXgfptHn4jTaXD4Y_kyDA1ntTKcp0qfs,8850
119
120
  flwr/common/context.py,sha256=Be8obQR_OvEDy1OmshuUKxGRQ7Qx89mf5F4xlhkR10s,2407
120
121
  flwr/common/date.py,sha256=1ZT2cRSpC2DJqprOVTLXYCR_O2_OZR0zXO_brJ3LqWc,1554
121
122
  flwr/common/differential_privacy.py,sha256=FdlpdpPl_H_2HJa8CQM1iCUGBBQ5Dc8CzxmHERM-EoE,6148
@@ -340,8 +341,8 @@ flwr/serverapp/strategy/fedopt.py,sha256=kqT0uV2IUE93O72XEVa1JJo61dcwbZEoT9KmYTj
340
341
  flwr/serverapp/strategy/fedyogi.py,sha256=1Ripr4Hi2cdeTOLiFOXtMKvOxR3BsUQwc7bbTrXN4LM,6653
341
342
  flwr/serverapp/strategy/result.py,sha256=E0Hl2VLnZAgQJjE2GDoKsK7JX-kPPU2KXc47Axt6hGw,4295
342
343
  flwr/serverapp/strategy/strategy.py,sha256=8uJGGm1ROLZERQ_dkRS7Z_rs-yK6XCE0UxXtIdFiEWk,10789
343
- flwr/serverapp/strategy/strategy_utils.py,sha256=o_1ksJsIQr6KgSQS_SOz3ZjarjnhwQBYzA6L0z171uI,9214
344
- flwr/serverapp/strategy/strategy_utils_tests.py,sha256=5aJE3qXG0QuIHskPI2H0L3I5an-7yHLrcjcjDYJIK3A,9251
344
+ flwr/serverapp/strategy/strategy_utils.py,sha256=9ga93Se21I_k7zYiw343EMC2qCTQ8rUG5ZEm8HVEuFs,9246
345
+ flwr/serverapp/strategy/strategy_utils_tests.py,sha256=o32XHujd9PLCB-YZMI2AttWLlvUXHe9yuxgiCrCkpgU,10209
345
346
  flwr/simulation/__init__.py,sha256=Gg6OsP1Z-ixc3-xxzvl7j7rz2Fijy9rzyEPpxgAQCeM,1556
346
347
  flwr/simulation/app.py,sha256=LbGLMvN9Ap119yBqsUcNNmVLRnCySnr4VechqcQ1hpA,10401
347
348
  flwr/simulation/legacy_app.py,sha256=nMISQqW0otJL1-2Kfd94O6BLlGS2IEmEPKTM2WGKrIs,15861
@@ -354,7 +355,7 @@ flwr/simulation/simulationio_connection.py,sha256=mzS1C6EEREwQDPceDo30anAasmTDLb
354
355
  flwr/supercore/__init__.py,sha256=pqkFoow_E6UhbBlhmoD1gmTH-33yJRhBsIZqxRPFZ7U,755
355
356
  flwr/supercore/app_utils.py,sha256=K76Zt6R670b1hUmxOsNc1WUCVYvF7lejXPcCO9K0Q0g,1753
356
357
  flwr/supercore/cli/__init__.py,sha256=EDl2aO-fuQfxSbL-T1W9RAfA2N0hpWHmqX_GSwblJbQ,845
357
- flwr/supercore/cli/flower_superexec.py,sha256=6fbzv71VYZ7nqrJQG8ZUKYVgL9LPIFFDw7uvDlkCd-o,4225
358
+ flwr/supercore/cli/flower_superexec.py,sha256=kov4uEeihf7QEUAfHEgdEvsL_8nL_fzQI9EePnRM1Ww,5012
358
359
  flwr/supercore/corestate/__init__.py,sha256=Vau6-L_JG5QzNqtCTa9xCKGGljc09wY8avZmIjSJemg,774
359
360
  flwr/supercore/corestate/corestate.py,sha256=rDAWWeG5DcpCyQso9Z3RhwL4zr2IroPlRMcDzqoSu8s,2328
360
361
  flwr/supercore/ffs/__init__.py,sha256=U3KXwG_SplEvchat27K0LYPoPHzh-cwwT_NHsGlYMt8,908
@@ -386,7 +387,7 @@ flwr/superlink/servicer/control/__init__.py,sha256=qhUTMt_Mg4lxslCJYn5hDSrA-lXf5
386
387
  flwr/superlink/servicer/control/control_event_log_interceptor.py,sha256=HauUd7Xq-b1TFZmZVl9wpBITfDttn8-1_KhlEq-HJ8M,5966
387
388
  flwr/superlink/servicer/control/control_grpc.py,sha256=DUGArJvH3oZasutEU55NtYm0ZukPEO92UKhzOGu3qu8,4079
388
389
  flwr/superlink/servicer/control/control_license_interceptor.py,sha256=T3AzmRt-PPwyTq3hrdpmZHQd5_CpPOk7TtnFZrB-JRY,3349
389
- flwr/superlink/servicer/control/control_servicer.py,sha256=5GMGcq5_Hvac7DpVg8TWUZbjVibS2B-yRlcSX2U6zeM,13962
390
+ flwr/superlink/servicer/control/control_servicer.py,sha256=RFttpc1O0pYBaru1SXE6v3hUoNfgR3_ijN02bSVhDsM,13914
390
391
  flwr/superlink/servicer/control/control_user_auth_interceptor.py,sha256=9Aqhrt_UX80FXbIQVXUrqDHs5rD5CA7vEn0Bh-zPiYU,6232
391
392
  flwr/supernode/__init__.py,sha256=KgeCaVvXWrU3rptNR1y0oBp4YtXbAcrnCcJAiOoWkI4,707
392
393
  flwr/supernode/cli/__init__.py,sha256=JuEMr0-s9zv-PEWKuLB9tj1ocNfroSyNJ-oyv7ati9A,887
@@ -402,7 +403,7 @@ flwr/supernode/servicer/__init__.py,sha256=lucTzre5WPK7G1YLCfaqg3rbFWdNSb7ZTt-ca
402
403
  flwr/supernode/servicer/clientappio/__init__.py,sha256=7Oy62Y_oijqF7Dxi6tpcUQyOpLc_QpIRZ83NvwmB0Yg,813
403
404
  flwr/supernode/servicer/clientappio/clientappio_servicer.py,sha256=nIHRu38EWK-rpNOkcgBRAAKwYQQWFeCwu0lkO7OPZGQ,10239
404
405
  flwr/supernode/start_client_internal.py,sha256=Y9S1-QlO2WP6eo4JvWzIpfaCoh2aoE7bjEYyxNNnlyg,20777
405
- flwr_nightly-1.21.0.dev20250907.dist-info/METADATA,sha256=aXiTtgUb9RiTyRE9PmLM1etPKZRJ2B_1DbRko2ZfS54,15967
406
- flwr_nightly-1.21.0.dev20250907.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
407
- flwr_nightly-1.21.0.dev20250907.dist-info/entry_points.txt,sha256=hxHD2ixb_vJFDOlZV-zB4Ao32_BQlL34ftsDh1GXv14,420
408
- flwr_nightly-1.21.0.dev20250907.dist-info/RECORD,,
406
+ flwr_nightly-1.21.0.dev20250909.dist-info/METADATA,sha256=tbQEPnXrFuNmo3xiiqjL2PPpZASd8ZkhdcrhjGIKbXU,15967
407
+ flwr_nightly-1.21.0.dev20250909.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
408
+ flwr_nightly-1.21.0.dev20250909.dist-info/entry_points.txt,sha256=hxHD2ixb_vJFDOlZV-zB4Ao32_BQlL34ftsDh1GXv14,420
409
+ flwr_nightly-1.21.0.dev20250909.dist-info/RECORD,,