flwr 1.19.0__py3-none-any.whl → 1.21.0__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 (167) hide show
  1. flwr/__init__.py +4 -1
  2. flwr/app/__init__.py +28 -0
  3. flwr/app/exception.py +31 -0
  4. flwr/cli/auth_plugin/oidc_cli_plugin.py +4 -4
  5. flwr/cli/build.py +15 -5
  6. flwr/cli/cli_user_auth_interceptor.py +1 -1
  7. flwr/cli/config_utils.py +3 -3
  8. flwr/cli/constant.py +25 -8
  9. flwr/cli/log.py +9 -9
  10. flwr/cli/login/login.py +3 -3
  11. flwr/cli/ls.py +5 -5
  12. flwr/cli/new/new.py +23 -4
  13. flwr/cli/new/templates/app/README.flowertune.md.tpl +2 -0
  14. flwr/cli/new/templates/app/README.md.tpl +5 -0
  15. flwr/cli/new/templates/app/code/__init__.pytorch_msg_api.py.tpl +1 -0
  16. flwr/cli/new/templates/app/code/client.pytorch_msg_api.py.tpl +80 -0
  17. flwr/cli/new/templates/app/code/server.pytorch_msg_api.py.tpl +41 -0
  18. flwr/cli/new/templates/app/code/task.pytorch_msg_api.py.tpl +98 -0
  19. flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +14 -3
  20. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +13 -1
  21. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +21 -2
  22. flwr/cli/new/templates/app/pyproject.jax.toml.tpl +18 -1
  23. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +19 -2
  24. flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +18 -1
  25. flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +20 -3
  26. flwr/cli/new/templates/app/pyproject.pytorch_msg_api.toml.tpl +53 -0
  27. flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +18 -1
  28. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +18 -1
  29. flwr/cli/run/run.py +53 -50
  30. flwr/cli/stop.py +7 -4
  31. flwr/cli/utils.py +29 -11
  32. flwr/client/grpc_adapter_client/connection.py +11 -4
  33. flwr/client/grpc_rere_client/connection.py +93 -129
  34. flwr/client/rest_client/connection.py +134 -164
  35. flwr/clientapp/__init__.py +10 -0
  36. flwr/clientapp/mod/__init__.py +26 -0
  37. flwr/clientapp/mod/centraldp_mods.py +132 -0
  38. flwr/common/args.py +20 -6
  39. flwr/common/auth_plugin/__init__.py +4 -4
  40. flwr/common/auth_plugin/auth_plugin.py +7 -7
  41. flwr/common/constant.py +26 -5
  42. flwr/common/event_log_plugin/event_log_plugin.py +1 -1
  43. flwr/common/exit/__init__.py +4 -0
  44. flwr/common/exit/exit.py +8 -1
  45. flwr/common/exit/exit_code.py +42 -8
  46. flwr/common/exit/exit_handler.py +62 -0
  47. flwr/common/{exit_handlers.py → exit/signal_handler.py} +20 -37
  48. flwr/common/grpc.py +1 -1
  49. flwr/common/{inflatable_grpc_utils.py → inflatable_protobuf_utils.py} +52 -10
  50. flwr/common/inflatable_utils.py +191 -24
  51. flwr/common/logger.py +1 -1
  52. flwr/common/record/array.py +101 -22
  53. flwr/common/record/arraychunk.py +59 -0
  54. flwr/common/retry_invoker.py +30 -11
  55. flwr/common/serde.py +0 -28
  56. flwr/common/telemetry.py +4 -0
  57. flwr/compat/client/app.py +14 -31
  58. flwr/compat/server/app.py +2 -2
  59. flwr/proto/appio_pb2.py +51 -0
  60. flwr/proto/appio_pb2.pyi +195 -0
  61. flwr/proto/appio_pb2_grpc.py +4 -0
  62. flwr/proto/appio_pb2_grpc.pyi +4 -0
  63. flwr/proto/clientappio_pb2.py +4 -19
  64. flwr/proto/clientappio_pb2.pyi +0 -125
  65. flwr/proto/clientappio_pb2_grpc.py +269 -29
  66. flwr/proto/clientappio_pb2_grpc.pyi +114 -21
  67. flwr/proto/control_pb2.py +62 -0
  68. flwr/proto/{exec_pb2_grpc.py → control_pb2_grpc.py} +54 -54
  69. flwr/proto/{exec_pb2_grpc.pyi → control_pb2_grpc.pyi} +28 -28
  70. flwr/proto/fleet_pb2.py +12 -20
  71. flwr/proto/fleet_pb2.pyi +6 -36
  72. flwr/proto/serverappio_pb2.py +8 -31
  73. flwr/proto/serverappio_pb2.pyi +0 -152
  74. flwr/proto/serverappio_pb2_grpc.py +107 -38
  75. flwr/proto/serverappio_pb2_grpc.pyi +47 -20
  76. flwr/proto/simulationio_pb2.py +4 -11
  77. flwr/proto/simulationio_pb2.pyi +0 -58
  78. flwr/proto/simulationio_pb2_grpc.py +129 -27
  79. flwr/proto/simulationio_pb2_grpc.pyi +52 -13
  80. flwr/server/app.py +130 -153
  81. flwr/server/fleet_event_log_interceptor.py +4 -0
  82. flwr/server/grid/grpc_grid.py +94 -54
  83. flwr/server/grid/inmemory_grid.py +1 -0
  84. flwr/server/serverapp/app.py +165 -144
  85. flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +8 -0
  86. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +1 -1
  87. flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +2 -5
  88. flwr/server/superlink/fleet/message_handler/message_handler.py +10 -16
  89. flwr/server/superlink/fleet/rest_rere/rest_api.py +1 -2
  90. flwr/server/superlink/fleet/vce/backend/raybackend.py +3 -1
  91. flwr/server/superlink/fleet/vce/vce_api.py +6 -6
  92. flwr/server/superlink/linkstate/in_memory_linkstate.py +34 -0
  93. flwr/server/superlink/linkstate/linkstate.py +2 -1
  94. flwr/server/superlink/linkstate/sqlite_linkstate.py +45 -0
  95. flwr/server/superlink/serverappio/serverappio_grpc.py +2 -2
  96. flwr/server/superlink/serverappio/serverappio_servicer.py +95 -48
  97. flwr/server/superlink/simulation/simulationio_grpc.py +1 -1
  98. flwr/server/superlink/simulation/simulationio_servicer.py +98 -22
  99. flwr/server/superlink/utils.py +0 -35
  100. flwr/serverapp/__init__.py +12 -0
  101. flwr/serverapp/dp_fixed_clipping.py +352 -0
  102. flwr/serverapp/exception.py +38 -0
  103. flwr/serverapp/strategy/__init__.py +38 -0
  104. flwr/serverapp/strategy/dp_fixed_clipping.py +352 -0
  105. flwr/serverapp/strategy/fedadagrad.py +162 -0
  106. flwr/serverapp/strategy/fedadam.py +181 -0
  107. flwr/serverapp/strategy/fedavg.py +295 -0
  108. flwr/serverapp/strategy/fedopt.py +218 -0
  109. flwr/serverapp/strategy/fedyogi.py +173 -0
  110. flwr/serverapp/strategy/result.py +105 -0
  111. flwr/serverapp/strategy/strategy.py +285 -0
  112. flwr/serverapp/strategy/strategy_utils.py +251 -0
  113. flwr/serverapp/strategy/strategy_utils_tests.py +304 -0
  114. flwr/simulation/app.py +159 -154
  115. flwr/simulation/run_simulation.py +17 -0
  116. flwr/supercore/app_utils.py +58 -0
  117. flwr/supercore/cli/__init__.py +22 -0
  118. flwr/supercore/cli/flower_superexec.py +141 -0
  119. flwr/supercore/corestate/__init__.py +22 -0
  120. flwr/supercore/corestate/corestate.py +81 -0
  121. flwr/{server/superlink → supercore}/ffs/disk_ffs.py +1 -1
  122. flwr/supercore/grpc_health/__init__.py +25 -0
  123. flwr/supercore/grpc_health/health_server.py +53 -0
  124. flwr/supercore/grpc_health/simple_health_servicer.py +38 -0
  125. flwr/supercore/license_plugin/__init__.py +22 -0
  126. flwr/supercore/license_plugin/license_plugin.py +26 -0
  127. flwr/supercore/object_store/in_memory_object_store.py +31 -31
  128. flwr/supercore/object_store/object_store.py +20 -42
  129. flwr/supercore/object_store/utils.py +43 -0
  130. flwr/{superexec → supercore/superexec}/__init__.py +1 -1
  131. flwr/supercore/superexec/plugin/__init__.py +28 -0
  132. flwr/supercore/superexec/plugin/base_exec_plugin.py +53 -0
  133. flwr/supercore/superexec/plugin/clientapp_exec_plugin.py +28 -0
  134. flwr/supercore/superexec/plugin/exec_plugin.py +71 -0
  135. flwr/supercore/superexec/plugin/serverapp_exec_plugin.py +28 -0
  136. flwr/supercore/superexec/plugin/simulation_exec_plugin.py +28 -0
  137. flwr/supercore/superexec/run_superexec.py +185 -0
  138. flwr/supercore/utils.py +32 -0
  139. flwr/superlink/servicer/__init__.py +15 -0
  140. flwr/superlink/servicer/control/__init__.py +22 -0
  141. flwr/{superexec/exec_event_log_interceptor.py → superlink/servicer/control/control_event_log_interceptor.py} +9 -5
  142. flwr/{superexec/exec_grpc.py → superlink/servicer/control/control_grpc.py} +39 -28
  143. flwr/superlink/servicer/control/control_license_interceptor.py +82 -0
  144. flwr/{superexec/exec_servicer.py → superlink/servicer/control/control_servicer.py} +79 -31
  145. flwr/{superexec/exec_user_auth_interceptor.py → superlink/servicer/control/control_user_auth_interceptor.py} +18 -10
  146. flwr/supernode/cli/flower_supernode.py +3 -7
  147. flwr/supernode/cli/flwr_clientapp.py +20 -16
  148. flwr/supernode/nodestate/in_memory_nodestate.py +13 -4
  149. flwr/supernode/nodestate/nodestate.py +3 -44
  150. flwr/supernode/runtime/run_clientapp.py +129 -115
  151. flwr/supernode/servicer/clientappio/__init__.py +1 -3
  152. flwr/supernode/servicer/clientappio/clientappio_servicer.py +217 -165
  153. flwr/supernode/start_client_internal.py +205 -148
  154. {flwr-1.19.0.dist-info → flwr-1.21.0.dist-info}/METADATA +5 -3
  155. {flwr-1.19.0.dist-info → flwr-1.21.0.dist-info}/RECORD +161 -117
  156. {flwr-1.19.0.dist-info → flwr-1.21.0.dist-info}/entry_points.txt +1 -0
  157. flwr/common/inflatable_rest_utils.py +0 -99
  158. flwr/proto/exec_pb2.py +0 -62
  159. flwr/superexec/app.py +0 -45
  160. flwr/superexec/deployment.py +0 -192
  161. flwr/superexec/executor.py +0 -100
  162. flwr/superexec/simulation.py +0 -130
  163. /flwr/proto/{exec_pb2.pyi → control_pb2.pyi} +0 -0
  164. /flwr/{server/superlink → supercore}/ffs/__init__.py +0 -0
  165. /flwr/{server/superlink → supercore}/ffs/ffs.py +0 -0
  166. /flwr/{server/superlink → supercore}/ffs/ffs_factory.py +0 -0
  167. {flwr-1.19.0.dist-info → flwr-1.21.0.dist-info}/WHEEL +0 -0
flwr/proto/exec_pb2.py DELETED
@@ -1,62 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # Generated by the protocol buffer compiler. DO NOT EDIT!
3
- # source: flwr/proto/exec.proto
4
- # Protobuf Python Version: 4.25.1
5
- """Generated protocol buffer code."""
6
- from google.protobuf import descriptor as _descriptor
7
- from google.protobuf import descriptor_pool as _descriptor_pool
8
- from google.protobuf import symbol_database as _symbol_database
9
- from google.protobuf.internal import builder as _builder
10
- # @@protoc_insertion_point(imports)
11
-
12
- _sym_db = _symbol_database.Default()
13
-
14
-
15
- from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
16
- from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2
17
- from flwr.proto import recorddict_pb2 as flwr_dot_proto_dot_recorddict__pb2
18
- from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2
19
-
20
-
21
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/exec.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x1a\x66lwr/proto/transport.proto\x1a\x1b\x66lwr/proto/recorddict.proto\x1a\x14\x66lwr/proto/run.proto\"\xfa\x01\n\x0fStartRunRequest\x12\x1c\n\x03\x66\x61\x62\x18\x01 \x01(\x0b\x32\x0f.flwr.proto.Fab\x12H\n\x0foverride_config\x18\x02 \x03(\x0b\x32/.flwr.proto.StartRunRequest.OverrideConfigEntry\x12\x34\n\x12\x66\x65\x64\x65ration_options\x18\x03 \x01(\x0b\x32\x18.flwr.proto.ConfigRecord\x1aI\n\x13OverrideConfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\"2\n\x10StartRunResponse\x12\x13\n\x06run_id\x18\x01 \x01(\x04H\x00\x88\x01\x01\x42\t\n\x07_run_id\"<\n\x11StreamLogsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12\x17\n\x0f\x61\x66ter_timestamp\x18\x02 \x01(\x01\"B\n\x12StreamLogsResponse\x12\x12\n\nlog_output\x18\x01 \x01(\t\x12\x18\n\x10latest_timestamp\x18\x02 \x01(\x01\"1\n\x0fListRunsRequest\x12\x13\n\x06run_id\x18\x01 \x01(\x04H\x00\x88\x01\x01\x42\t\n\x07_run_id\"\x9d\x01\n\x10ListRunsResponse\x12;\n\x08run_dict\x18\x01 \x03(\x0b\x32).flwr.proto.ListRunsResponse.RunDictEntry\x12\x0b\n\x03now\x18\x02 \x01(\t\x1a?\n\x0cRunDictEntry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\x1e\n\x05value\x18\x02 \x01(\x0b\x32\x0f.flwr.proto.Run:\x02\x38\x01\"\x18\n\x16GetLoginDetailsRequest\"\x8a\x01\n\x17GetLoginDetailsResponse\x12\x11\n\tauth_type\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65vice_code\x18\x02 \x01(\t\x12!\n\x19verification_uri_complete\x18\x03 \x01(\t\x12\x12\n\nexpires_in\x18\x04 \x01(\x03\x12\x10\n\x08interval\x18\x05 \x01(\x03\"+\n\x14GetAuthTokensRequest\x12\x13\n\x0b\x64\x65vice_code\x18\x01 \x01(\t\"D\n\x15GetAuthTokensResponse\x12\x14\n\x0c\x61\x63\x63\x65ss_token\x18\x01 \x01(\t\x12\x15\n\rrefresh_token\x18\x02 \x01(\t\" \n\x0eStopRunRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\"\"\n\x0fStopRunResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x32\xe5\x03\n\x04\x45xec\x12G\n\x08StartRun\x12\x1b.flwr.proto.StartRunRequest\x1a\x1c.flwr.proto.StartRunResponse\"\x00\x12\x44\n\x07StopRun\x12\x1a.flwr.proto.StopRunRequest\x1a\x1b.flwr.proto.StopRunResponse\"\x00\x12O\n\nStreamLogs\x12\x1d.flwr.proto.StreamLogsRequest\x1a\x1e.flwr.proto.StreamLogsResponse\"\x00\x30\x01\x12G\n\x08ListRuns\x12\x1b.flwr.proto.ListRunsRequest\x1a\x1c.flwr.proto.ListRunsResponse\"\x00\x12\\\n\x0fGetLoginDetails\x12\".flwr.proto.GetLoginDetailsRequest\x1a#.flwr.proto.GetLoginDetailsResponse\"\x00\x12V\n\rGetAuthTokens\x12 .flwr.proto.GetAuthTokensRequest\x1a!.flwr.proto.GetAuthTokensResponse\"\x00\x62\x06proto3')
22
-
23
- _globals = globals()
24
- _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
25
- _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.exec_pb2', _globals)
26
- if _descriptor._USE_C_DESCRIPTORS == False:
27
- DESCRIPTOR._options = None
28
- _globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._options = None
29
- _globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_options = b'8\001'
30
- _globals['_LISTRUNSRESPONSE_RUNDICTENTRY']._options = None
31
- _globals['_LISTRUNSRESPONSE_RUNDICTENTRY']._serialized_options = b'8\001'
32
- _globals['_STARTRUNREQUEST']._serialized_start=139
33
- _globals['_STARTRUNREQUEST']._serialized_end=389
34
- _globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_start=316
35
- _globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_end=389
36
- _globals['_STARTRUNRESPONSE']._serialized_start=391
37
- _globals['_STARTRUNRESPONSE']._serialized_end=441
38
- _globals['_STREAMLOGSREQUEST']._serialized_start=443
39
- _globals['_STREAMLOGSREQUEST']._serialized_end=503
40
- _globals['_STREAMLOGSRESPONSE']._serialized_start=505
41
- _globals['_STREAMLOGSRESPONSE']._serialized_end=571
42
- _globals['_LISTRUNSREQUEST']._serialized_start=573
43
- _globals['_LISTRUNSREQUEST']._serialized_end=622
44
- _globals['_LISTRUNSRESPONSE']._serialized_start=625
45
- _globals['_LISTRUNSRESPONSE']._serialized_end=782
46
- _globals['_LISTRUNSRESPONSE_RUNDICTENTRY']._serialized_start=719
47
- _globals['_LISTRUNSRESPONSE_RUNDICTENTRY']._serialized_end=782
48
- _globals['_GETLOGINDETAILSREQUEST']._serialized_start=784
49
- _globals['_GETLOGINDETAILSREQUEST']._serialized_end=808
50
- _globals['_GETLOGINDETAILSRESPONSE']._serialized_start=811
51
- _globals['_GETLOGINDETAILSRESPONSE']._serialized_end=949
52
- _globals['_GETAUTHTOKENSREQUEST']._serialized_start=951
53
- _globals['_GETAUTHTOKENSREQUEST']._serialized_end=994
54
- _globals['_GETAUTHTOKENSRESPONSE']._serialized_start=996
55
- _globals['_GETAUTHTOKENSRESPONSE']._serialized_end=1064
56
- _globals['_STOPRUNREQUEST']._serialized_start=1066
57
- _globals['_STOPRUNREQUEST']._serialized_end=1098
58
- _globals['_STOPRUNRESPONSE']._serialized_start=1100
59
- _globals['_STOPRUNRESPONSE']._serialized_end=1134
60
- _globals['_EXEC']._serialized_start=1137
61
- _globals['_EXEC']._serialized_end=1622
62
- # @@protoc_insertion_point(module_scope)
flwr/superexec/app.py DELETED
@@ -1,45 +0,0 @@
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 SuperExec app."""
16
-
17
-
18
- import argparse
19
-
20
- from flwr.common.object_ref import load_app, validate
21
-
22
- from .executor import Executor
23
-
24
-
25
- def load_executor(
26
- args: argparse.Namespace,
27
- ) -> Executor:
28
- """Get the executor plugin."""
29
- executor_ref: str = args.executor
30
- valid, error_msg = validate(executor_ref, project_dir=args.executor_dir)
31
- if not valid and error_msg:
32
- raise LoadExecutorError(error_msg) from None
33
-
34
- executor = load_app(executor_ref, LoadExecutorError, args.executor_dir)
35
-
36
- if not isinstance(executor, Executor):
37
- raise LoadExecutorError(
38
- f"Attribute {executor_ref} is not of type {Executor}",
39
- ) from None
40
-
41
- return executor
42
-
43
-
44
- class LoadExecutorError(Exception):
45
- """Error when trying to load `Executor`."""
@@ -1,192 +0,0 @@
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
- """Deployment engine executor."""
16
-
17
-
18
- import hashlib
19
- from logging import ERROR, INFO
20
- from pathlib import Path
21
- from typing import Optional
22
-
23
- from typing_extensions import override
24
-
25
- from flwr.cli.config_utils import get_fab_metadata
26
- from flwr.common import ConfigRecord, Context, RecordDict
27
- from flwr.common.constant import (
28
- SERVERAPPIO_API_DEFAULT_CLIENT_ADDRESS,
29
- Status,
30
- SubStatus,
31
- )
32
- from flwr.common.logger import log
33
- from flwr.common.typing import Fab, RunStatus, UserConfig
34
- from flwr.server.superlink.ffs import Ffs
35
- from flwr.server.superlink.ffs.ffs_factory import FfsFactory
36
- from flwr.server.superlink.linkstate import LinkState, LinkStateFactory
37
-
38
- from .executor import Executor
39
-
40
-
41
- class DeploymentEngine(Executor):
42
- """Deployment engine executor.
43
-
44
- Parameters
45
- ----------
46
- serverappio_api_address: str (default: "127.0.0.1:9091")
47
- Address of the SuperLink to connect to.
48
- root_certificates: Optional[str] (default: None)
49
- Specifies the path to the PEM-encoded root certificate file for
50
- establishing secure HTTPS connections.
51
- flwr_dir: Optional[str] (default: None)
52
- The path containing installed Flower Apps.
53
- """
54
-
55
- def __init__(
56
- self,
57
- serverappio_api_address: str = SERVERAPPIO_API_DEFAULT_CLIENT_ADDRESS,
58
- root_certificates: Optional[str] = None,
59
- flwr_dir: Optional[str] = None,
60
- ) -> None:
61
- self.serverappio_api_address = serverappio_api_address
62
- if root_certificates is None:
63
- self.root_certificates = None
64
- self.root_certificates_bytes = None
65
- else:
66
- self.root_certificates = root_certificates
67
- self.root_certificates_bytes = Path(root_certificates).read_bytes()
68
- self.flwr_dir = flwr_dir
69
- self.linkstate_factory: Optional[LinkStateFactory] = None
70
- self.ffs_factory: Optional[FfsFactory] = None
71
-
72
- @override
73
- def initialize(
74
- self, linkstate_factory: LinkStateFactory, ffs_factory: FfsFactory
75
- ) -> None:
76
- """Initialize the executor with the necessary factories."""
77
- self.linkstate_factory = linkstate_factory
78
- self.ffs_factory = ffs_factory
79
-
80
- @property
81
- def linkstate(self) -> LinkState:
82
- """Return the LinkState."""
83
- if self.linkstate_factory is None:
84
- raise RuntimeError("Executor is not initialized.")
85
- return self.linkstate_factory.state()
86
-
87
- @property
88
- def ffs(self) -> Ffs:
89
- """Return the Flower File Storage (FFS)."""
90
- if self.ffs_factory is None:
91
- raise RuntimeError("Executor is not initialized.")
92
- return self.ffs_factory.ffs()
93
-
94
- @override
95
- def set_config(
96
- self,
97
- config: UserConfig,
98
- ) -> None:
99
- """Set executor config arguments.
100
-
101
- Parameters
102
- ----------
103
- config : UserConfig
104
- A dictionary for configuration values.
105
- Supported configuration key/value pairs:
106
- - "superlink": str
107
- The address of the SuperLink ServerAppIo API.
108
- - "root-certificates": str
109
- The path to the root certificates.
110
- - "flwr-dir": str
111
- The path to the Flower directory.
112
- """
113
- if not config:
114
- return
115
- if superlink_address := config.get("superlink"):
116
- if not isinstance(superlink_address, str):
117
- raise ValueError("The `superlink` value should be of type `str`.")
118
- self.serverappio_api_address = superlink_address
119
- if root_certificates := config.get("root-certificates"):
120
- if not isinstance(root_certificates, str):
121
- raise ValueError(
122
- "The `root-certificates` value should be of type `str`."
123
- )
124
- self.root_certificates = root_certificates
125
- self.root_certificates_bytes = Path(str(root_certificates)).read_bytes()
126
- if flwr_dir := config.get("flwr-dir"):
127
- if not isinstance(flwr_dir, str):
128
- raise ValueError("The `flwr-dir` value should be of type `str`.")
129
- self.flwr_dir = str(flwr_dir)
130
-
131
- def _create_run(
132
- self,
133
- fab: Fab,
134
- override_config: UserConfig,
135
- flwr_aid: Optional[str],
136
- ) -> int:
137
- fab_hash = self.ffs.put(fab.content, {})
138
- if fab_hash != fab.hash_str:
139
- raise RuntimeError(
140
- f"FAB ({fab.hash_str}) hash from request doesn't match contents"
141
- )
142
- fab_id, fab_version = get_fab_metadata(fab.content)
143
-
144
- run_id = self.linkstate.create_run(
145
- fab_id, fab_version, fab_hash, override_config, ConfigRecord(), flwr_aid
146
- )
147
- return run_id
148
-
149
- def _create_context(self, run_id: int) -> None:
150
- """Register a Context for a Run."""
151
- # Create an empty context for the Run
152
- context = Context(
153
- run_id=run_id, node_id=0, node_config={}, state=RecordDict(), run_config={}
154
- )
155
-
156
- # Register the context at the LinkState
157
- self.linkstate.set_serverapp_context(run_id=run_id, context=context)
158
-
159
- @override
160
- def start_run(
161
- self,
162
- fab_file: bytes,
163
- override_config: UserConfig,
164
- federation_options: ConfigRecord,
165
- flwr_aid: Optional[str],
166
- ) -> Optional[int]:
167
- """Start run using the Flower Deployment Engine."""
168
- run_id = None
169
- try:
170
-
171
- # Call SuperLink to create run
172
- run_id = self._create_run(
173
- Fab(hashlib.sha256(fab_file).hexdigest(), fab_file),
174
- override_config,
175
- flwr_aid,
176
- )
177
-
178
- # Register context for the Run
179
- self._create_context(run_id=run_id)
180
- log(INFO, "Created run %s", str(run_id))
181
-
182
- return run_id
183
- # pylint: disable-next=broad-except
184
- except Exception as e:
185
- log(ERROR, "Could not start run: %s", str(e))
186
- if run_id:
187
- run_status = RunStatus(Status.FINISHED, SubStatus.FAILED, str(e))
188
- self.linkstate.update_run_status(run_id, new_status=run_status)
189
- return None
190
-
191
-
192
- executor = DeploymentEngine()
@@ -1,100 +0,0 @@
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
- """Execute and monitor a Flower run."""
16
-
17
-
18
- from abc import ABC, abstractmethod
19
- from dataclasses import dataclass, field
20
- from subprocess import Popen
21
- from typing import Optional
22
-
23
- from flwr.common import ConfigRecord
24
- from flwr.common.typing import UserConfig
25
- from flwr.server.superlink.ffs.ffs_factory import FfsFactory
26
- from flwr.server.superlink.linkstate import LinkStateFactory
27
-
28
-
29
- @dataclass
30
- class RunTracker:
31
- """Track a Flower run (composed of a run_id and the associated process)."""
32
-
33
- run_id: int
34
- proc: Popen # type: ignore
35
- logs: list[str] = field(default_factory=list)
36
-
37
-
38
- class Executor(ABC):
39
- """Execute and monitor a Flower run."""
40
-
41
- @abstractmethod
42
- def initialize(
43
- self, linkstate_factory: LinkStateFactory, ffs_factory: FfsFactory
44
- ) -> None:
45
- """Initialize the executor with the necessary factories.
46
-
47
- This method sets up the executor by providing it with the factories required
48
- to access the LinkState and the Flower File Storage (FFS) in the SuperLink.
49
-
50
- Parameters
51
- ----------
52
- linkstate_factory : LinkStateFactory
53
- The factory to create access to the LinkState.
54
- ffs_factory : FfsFactory
55
- The factory to create access to the Flower File Storage (FFS).
56
- """
57
-
58
- @abstractmethod
59
- def set_config(
60
- self,
61
- config: UserConfig,
62
- ) -> None:
63
- """Register provided config as class attributes.
64
-
65
- Parameters
66
- ----------
67
- config : UserConfig
68
- A dictionary for configuration values.
69
- """
70
-
71
- @abstractmethod
72
- def start_run(
73
- self,
74
- fab_file: bytes,
75
- override_config: UserConfig,
76
- federation_options: ConfigRecord,
77
- flwr_aid: Optional[str],
78
- ) -> Optional[int]:
79
- """Start a run using the given Flower FAB ID and version.
80
-
81
- This method creates a new run on the SuperLink, returns its run_id
82
- and also starts the run execution.
83
-
84
- Parameters
85
- ----------
86
- fab_file : bytes
87
- The Flower App Bundle file bytes.
88
- override_config: UserConfig
89
- The config overrides dict sent by the user (using `flwr run`).
90
- federation_options: ConfigRecord
91
- The federation options sent by the user (using `flwr run`).
92
- flwr_aid : Optional[str]
93
- The Flower Account ID of the user starting the run, if authentication is
94
- enabled.
95
-
96
- Returns
97
- -------
98
- run_id : Optional[int]
99
- The run_id of the run created by the SuperLink, or `None` if it fails.
100
- """
@@ -1,130 +0,0 @@
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
- """Simulation engine executor."""
16
-
17
-
18
- import hashlib
19
- from logging import ERROR, INFO
20
- from typing import Optional
21
-
22
- from typing_extensions import override
23
-
24
- from flwr.cli.config_utils import get_fab_metadata
25
- from flwr.common import ConfigRecord, Context, RecordDict
26
- from flwr.common.logger import log
27
- from flwr.common.typing import Fab, UserConfig
28
- from flwr.server.superlink.ffs import Ffs
29
- from flwr.server.superlink.ffs.ffs_factory import FfsFactory
30
- from flwr.server.superlink.linkstate import LinkState, LinkStateFactory
31
-
32
- from .executor import Executor
33
-
34
-
35
- class SimulationEngine(Executor):
36
- """Simulation engine executor."""
37
-
38
- def __init__(
39
- self,
40
- ) -> None:
41
- self.linkstate_factory: Optional[LinkStateFactory] = None
42
- self.ffs_factory: Optional[FfsFactory] = None
43
-
44
- @override
45
- def initialize(
46
- self, linkstate_factory: LinkStateFactory, ffs_factory: FfsFactory
47
- ) -> None:
48
- """Initialize the executor with the necessary factories."""
49
- self.linkstate_factory = linkstate_factory
50
- self.ffs_factory = ffs_factory
51
-
52
- @property
53
- def linkstate(self) -> LinkState:
54
- """Return the LinkState."""
55
- if self.linkstate_factory is None:
56
- raise RuntimeError("Executor is not initialized.")
57
- return self.linkstate_factory.state()
58
-
59
- @property
60
- def ffs(self) -> Ffs:
61
- """Return the Flower File Storage (FFS)."""
62
- if self.ffs_factory is None:
63
- raise RuntimeError("Executor is not initialized.")
64
- return self.ffs_factory.ffs()
65
-
66
- @override
67
- def set_config(
68
- self,
69
- config: UserConfig,
70
- ) -> None:
71
- """Set executor config arguments."""
72
-
73
- # pylint: disable=too-many-locals
74
- @override
75
- def start_run(
76
- self,
77
- fab_file: bytes,
78
- override_config: UserConfig,
79
- federation_options: ConfigRecord,
80
- flwr_aid: Optional[str],
81
- ) -> Optional[int]:
82
- """Start run using the Flower Simulation Engine."""
83
- try:
84
- # Check that num-supernodes is set
85
- if "num-supernodes" not in federation_options:
86
- raise ValueError(
87
- "Federation options doesn't contain key `num-supernodes`."
88
- )
89
-
90
- # Create run
91
- fab = Fab(hashlib.sha256(fab_file).hexdigest(), fab_file)
92
- fab_hash = self.ffs.put(fab.content, {})
93
- if fab_hash != fab.hash_str:
94
- raise RuntimeError(
95
- f"FAB ({fab.hash_str}) hash from request doesn't match contents"
96
- )
97
- fab_id, fab_version = get_fab_metadata(fab.content)
98
-
99
- run_id = self.linkstate.create_run(
100
- fab_id,
101
- fab_version,
102
- fab_hash,
103
- override_config,
104
- federation_options,
105
- flwr_aid,
106
- )
107
-
108
- # Create an empty context for the Run
109
- context = Context(
110
- run_id=run_id,
111
- node_id=0,
112
- node_config={},
113
- state=RecordDict(),
114
- run_config={},
115
- )
116
-
117
- # Register the context at the LinkState
118
- self.linkstate.set_serverapp_context(run_id=run_id, context=context)
119
-
120
- log(INFO, "Created run %s", str(run_id))
121
-
122
- return run_id
123
-
124
- # pylint: disable-next=broad-except
125
- except Exception as e:
126
- log(ERROR, "Could not start run: %s", str(e))
127
- return None
128
-
129
-
130
- executor = SimulationEngine()
File without changes
File without changes
File without changes
File without changes
File without changes