flwr-nightly 1.20.0.dev20250722__py3-none-any.whl → 1.20.0.dev20250723__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.
@@ -31,6 +31,7 @@ class ExitCode:
31
31
  SUPERLINK_THREAD_CRASH = 100
32
32
  SUPERLINK_LICENSE_INVALID = 101
33
33
  SUPERLINK_LICENSE_MISSING = 102
34
+ SUPERLINK_LICENSE_URL_INVALID = 103
34
35
 
35
36
  # ServerApp-specific exit codes (200-299)
36
37
 
@@ -70,6 +71,10 @@ EXIT_CODE_HELP = {
70
71
  "The license is missing. Please specify the license key by setting the "
71
72
  "environment variable `FLWR_LICENSE_KEY`."
72
73
  ),
74
+ ExitCode.SUPERLINK_LICENSE_URL_INVALID: (
75
+ "The license URL is invalid. Please ensure that the `FLWR_LICENSE_URL` "
76
+ "environment variable is set to a valid URL."
77
+ ),
73
78
  # ServerApp-specific exit codes (200-299)
74
79
  # SuperNode-specific exit codes (300-399)
75
80
  ExitCode.SUPERNODE_REST_ADDRESS_INVALID: (
@@ -260,15 +260,15 @@ class GrpcGrid(Grid):
260
260
  run_id = cast(Run, self._run).run_id
261
261
  message_ids: list[str] = []
262
262
  try:
263
- for msg in messages:
264
- # Populate metadata
265
- msg.metadata.__dict__["_run_id"] = run_id
266
- msg.metadata.__dict__["_src_node_id"] = self.node.node_id
267
- msg.metadata.__dict__["_message_id"] = msg.object_id
268
- # Check message
269
- self._check_message(msg)
270
- # Try pushing message and its objects
271
- with no_object_id_recompute():
263
+ with no_object_id_recompute():
264
+ for msg in messages:
265
+ # Populate metadata
266
+ msg.metadata.__dict__["_run_id"] = run_id
267
+ msg.metadata.__dict__["_src_node_id"] = self.node.node_id
268
+ msg.metadata.__dict__["_message_id"] = msg.object_id
269
+ # Check message
270
+ self._check_message(msg)
271
+ # Try pushing message and its objects
272
272
  message_ids.append(self._try_push_message(run_id, msg))
273
273
 
274
274
  except grpc.RpcError as e:
@@ -0,0 +1,22 @@
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 App Scheduler."""
16
+
17
+
18
+ from .plugin import SchedulerPlugin
19
+
20
+ __all__ = [
21
+ "SchedulerPlugin",
22
+ ]
@@ -0,0 +1,71 @@
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
+ """Abstract base class SchedulerPlugin."""
16
+
17
+
18
+ from abc import ABC, abstractmethod
19
+ from collections.abc import Sequence
20
+ from typing import Callable, Optional
21
+
22
+ from flwr.common.typing import Run
23
+
24
+
25
+ class SchedulerPlugin(ABC):
26
+ """Abstract base class for Scheduler plugins."""
27
+
28
+ def __init__(
29
+ self,
30
+ appio_api_address: str,
31
+ flwr_dir: str,
32
+ get_run: Callable[[int], Run],
33
+ ) -> None:
34
+ self.appio_api_address = appio_api_address
35
+ self.flwr_dir = flwr_dir
36
+ self.get_run = get_run
37
+
38
+ @abstractmethod
39
+ def select_run_id(self, candidate_run_ids: Sequence[int]) -> Optional[int]:
40
+ """Select a run ID to execute from a sequence of candidates.
41
+
42
+ A candidate run ID is one that has at least one pending message and is
43
+ not currently in progress (i.e., not associated with a token).
44
+
45
+ Parameters
46
+ ----------
47
+ candidate_run_ids : Sequence[int]
48
+ A sequence of candidate run IDs to choose from.
49
+
50
+ Returns
51
+ -------
52
+ Optional[int]
53
+ The selected run ID, or None if no suitable candidate is found.
54
+ """
55
+
56
+ @abstractmethod
57
+ def launch_app(self, token: str, run_id: int) -> None:
58
+ """Launch the application associated with a given run ID and token.
59
+
60
+ This method starts the application process using the given `token`.
61
+ The `run_id` is used solely for bookkeeping purposes, allowing any
62
+ scheduler implementation to associate this launch with a specific run.
63
+
64
+ Parameters
65
+ ----------
66
+ token : str
67
+ The token required to run the application.
68
+ run_id : int
69
+ The ID of the run associated with the token, used for tracking or
70
+ logging purposes.
71
+ """
@@ -0,0 +1,22 @@
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 ClientApp Scheduler."""
16
+
17
+
18
+ from .simple_clientapp_scheduler_plugin import SimpleClientAppSchedulerPlugin
19
+
20
+ __all__ = [
21
+ "SimpleClientAppSchedulerPlugin",
22
+ ]
@@ -0,0 +1,49 @@
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
+ """Simple Flower ClientApp Scheduler plugin."""
16
+
17
+
18
+ import os
19
+ import subprocess
20
+ from collections.abc import Sequence
21
+ from typing import Optional
22
+
23
+ from flwr.supercore.scheduler import SchedulerPlugin
24
+
25
+
26
+ class SimpleClientAppSchedulerPlugin(SchedulerPlugin):
27
+ """Simple Flower ClientApp Scheduler plugin.
28
+
29
+ The plugin always selects the first candidate run ID.
30
+ """
31
+
32
+ def select_run_id(self, candidate_run_ids: Sequence[int]) -> Optional[int]:
33
+ """Select a run ID to execute from a sequence of candidates."""
34
+ if not candidate_run_ids:
35
+ return None
36
+ return candidate_run_ids[0]
37
+
38
+ def launch_app(self, token: str, run_id: int) -> None:
39
+ """Launch the application associated with a given run ID and token."""
40
+ cmds = ["flwr-clientapp", "--insecure"]
41
+ cmds += ["--clientappio-api-address", self.appio_api_address]
42
+ cmds += ["--token", token]
43
+ cmds += ["--parent-pid", str(os.getpid())]
44
+ cmds += ["--flwr-dir", self.flwr_dir]
45
+ # Launch the client app without waiting for it to complete.
46
+ # Since we don't need to manage the process, we intentionally avoid using
47
+ # a `with` statement. Suppress the pylint warning for it in this case.
48
+ # pylint: disable-next=consider-using-with
49
+ subprocess.Popen(cmds)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: flwr-nightly
3
- Version: 1.20.0.dev20250722
3
+ Version: 1.20.0.dev20250723
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
@@ -118,7 +118,7 @@ flwr/common/event_log_plugin/__init__.py,sha256=ts3VAL3Fk6Grp1EK_1Qg_V-BfOof9F86
118
118
  flwr/common/event_log_plugin/event_log_plugin.py,sha256=eK8OaDFagQRwqpb9eV0cJcm2ErtEBpMxFbhxJNx6n5w,2061
119
119
  flwr/common/exit/__init__.py,sha256=-ZOJYLaNnR729a7VzZiFsLiqngzKQh3xc27svYStZ_Q,826
120
120
  flwr/common/exit/exit.py,sha256=mJgbqMlVlwAgYtq-Vedj53wO4VxcDcy_P-GzqGK-1GQ,3452
121
- flwr/common/exit/exit_code.py,sha256=qpOQsh2-TNJosxrGpR-rKnLBiv5lnl_2sClNoDblAW4,3882
121
+ flwr/common/exit/exit_code.py,sha256=NbjJEywRb5YzDE7Xmo3Kd29inDEQbIUpskY9IEIGomE,4110
122
122
  flwr/common/exit_handlers.py,sha256=IaqJ60fXZuu7McaRYnoYKtlbH9t4Yl9goNExKqtmQbs,4304
123
123
  flwr/common/grpc.py,sha256=y70hUFvXkIf3l03xOhlb7qhS6W1UJZRSZqCdB0ir0v8,10381
124
124
  flwr/common/heartbeat.py,sha256=SyEpNDnmJ0lni0cWO67rcoJVKasCLmkNHm3dKLeNrLU,5749
@@ -242,7 +242,7 @@ flwr/server/criterion.py,sha256=G4e-6B48Pc7d5rmGVUpIzNKb6UF88O3VmTRuUltgjzM,1061
242
242
  flwr/server/fleet_event_log_interceptor.py,sha256=gtVPr2yQp3U2GnabIdFnuok18VerEcidKj1lKmDYGoY,3950
243
243
  flwr/server/grid/__init__.py,sha256=aWZHezoR2UGMJISB_gPMCm2N_2GSbm97A3lAp7ruhRQ,888
244
244
  flwr/server/grid/grid.py,sha256=naGCYt5J6dnmUvrcGkdNyKPe3MBd-0awGm1ALmgahqY,6625
245
- flwr/server/grid/grpc_grid.py,sha256=2AL1Niz77cOWGX0e7Y9eJFpOK962tDqyn8QQyjSN0qM,13735
245
+ flwr/server/grid/grpc_grid.py,sha256=WmtBvIKOlvH4sVj6HdkJKzAfWhBLgaQJKYNWxybYWmM,13763
246
246
  flwr/server/grid/inmemory_grid.py,sha256=RjejYT-d-hHuTs1KSs_5wvOdAWKLus8w5_UAcnGt4iw,6168
247
247
  flwr/server/history.py,sha256=cCkFhBN4GoHsYYNk5GG1Y089eKJh2DH_ZJbYPwLaGyk,5026
248
248
  flwr/server/run_serverapp.py,sha256=v0p6jXj2dFxlRUdoEeF1mnaFd9XRQi6dZCflPY6d3qI,2063
@@ -344,6 +344,8 @@ flwr/supercore/object_store/in_memory_object_store.py,sha256=CGY43syxDGrUPcdOzRH
344
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
+ flwr/supercore/scheduler/__init__.py,sha256=E4GviiNJoZKz1dOao8ZGRHExsiM23GtOrkpMrTHy3n8,787
348
+ flwr/supercore/scheduler/plugin.py,sha256=kIv0JUrHP-ghrcGT-pbporL9A2mUz8PxASw6KgxCRv8,2460
347
349
  flwr/supercore/utils.py,sha256=ebuHMbeA8eXisX0oMPqBK3hk7uVnIE_yiqWVz8YbkpQ,1324
348
350
  flwr/superexec/__init__.py,sha256=YFqER0IJc1XEWfsX6AxZ9LSRq0sawPYrNYki-brvTIc,715
349
351
  flwr/superexec/app.py,sha256=U2jjOHb2LGWoU7vrl9_czTzre9O2mPxu3CPGUZ86sK4,1465
@@ -366,11 +368,13 @@ flwr/supernode/nodestate/nodestate.py,sha256=kkGFxYnLIwT4-UmlPnf6HvAUpPey2urUNrw
366
368
  flwr/supernode/nodestate/nodestate_factory.py,sha256=UYTDCcwK_baHUmkzkJDxL0UEqvtTfOMlQRrROMCd0Xo,1430
367
369
  flwr/supernode/runtime/__init__.py,sha256=JQdqd2EMTn-ORMeTvewYYh52ls0YKP68jrps1qioxu4,718
368
370
  flwr/supernode/runtime/run_clientapp.py,sha256=woAO8rXclt5eZeNHokhBChgxMf-TAzqWnHCkoiSsLVs,10765
371
+ flwr/supernode/scheduler/__init__.py,sha256=nQLi5ROVCMz8ii_WsZn4MAqKHXI40Eb3tq5-9zZbmpg,850
372
+ flwr/supernode/scheduler/simple_clientapp_scheduler_plugin.py,sha256=nnNuKhelrAEGCnWZ3aAkqJrhPu7xlVQ-oO1Eih9shTU,2000
369
373
  flwr/supernode/servicer/__init__.py,sha256=lucTzre5WPK7G1YLCfaqg3rbFWdNSb7ZTt-ca8gxdEo,717
370
374
  flwr/supernode/servicer/clientappio/__init__.py,sha256=7Oy62Y_oijqF7Dxi6tpcUQyOpLc_QpIRZ83NvwmB0Yg,813
371
375
  flwr/supernode/servicer/clientappio/clientappio_servicer.py,sha256=SOx719uqdkIHryBri-XpuYpALQE__hxNtDjSAdeUtug,10059
372
376
  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,,
377
+ flwr_nightly-1.20.0.dev20250723.dist-info/METADATA,sha256=TZhBkek0rvMIVa0ae2M_u3fAdo3-phWakrtXgP320qg,15966
378
+ flwr_nightly-1.20.0.dev20250723.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
379
+ flwr_nightly-1.20.0.dev20250723.dist-info/entry_points.txt,sha256=jNpDXGBGgs21RqUxelF_jwGaxtqFwm-MQyfz-ZqSjrA,367
380
+ flwr_nightly-1.20.0.dev20250723.dist-info/RECORD,,