flwr 1.23.0__py3-none-any.whl → 1.24.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 (292) hide show
  1. flwr/__init__.py +16 -5
  2. flwr/app/error.py +2 -2
  3. flwr/app/exception.py +3 -3
  4. flwr/cli/app.py +19 -0
  5. flwr/cli/app_cmd/__init__.py +23 -0
  6. flwr/cli/app_cmd/publish.py +285 -0
  7. flwr/cli/app_cmd/review.py +252 -0
  8. flwr/cli/auth_plugin/auth_plugin.py +4 -5
  9. flwr/cli/auth_plugin/noop_auth_plugin.py +54 -11
  10. flwr/cli/auth_plugin/oidc_cli_plugin.py +32 -9
  11. flwr/cli/build.py +60 -18
  12. flwr/cli/cli_account_auth_interceptor.py +24 -7
  13. flwr/cli/config_utils.py +101 -13
  14. flwr/cli/federation/__init__.py +24 -0
  15. flwr/cli/federation/ls.py +140 -0
  16. flwr/cli/federation/show.py +317 -0
  17. flwr/cli/install.py +91 -13
  18. flwr/cli/log.py +52 -9
  19. flwr/cli/login/login.py +7 -4
  20. flwr/cli/ls.py +170 -130
  21. flwr/cli/new/new.py +33 -50
  22. flwr/cli/new/templates/app/code/task.pytorch.py.tpl +1 -0
  23. flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +1 -1
  24. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +1 -1
  25. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +1 -1
  26. flwr/cli/new/templates/app/pyproject.jax.toml.tpl +1 -1
  27. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +1 -1
  28. flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +1 -1
  29. flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +3 -3
  30. flwr/cli/new/templates/app/pyproject.pytorch_legacy_api.toml.tpl +1 -1
  31. flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +1 -1
  32. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +2 -2
  33. flwr/cli/new/templates/app/pyproject.xgboost.toml.tpl +1 -1
  34. flwr/cli/pull.py +10 -5
  35. flwr/cli/run/run.py +77 -30
  36. flwr/cli/run_utils.py +130 -0
  37. flwr/cli/stop.py +25 -7
  38. flwr/cli/supernode/ls.py +16 -8
  39. flwr/cli/supernode/register.py +9 -4
  40. flwr/cli/supernode/unregister.py +5 -3
  41. flwr/cli/utils.py +376 -16
  42. flwr/client/__init__.py +1 -1
  43. flwr/client/dpfedavg_numpy_client.py +4 -1
  44. flwr/client/grpc_adapter_client/connection.py +6 -7
  45. flwr/client/grpc_rere_client/connection.py +10 -11
  46. flwr/client/grpc_rere_client/grpc_adapter.py +6 -2
  47. flwr/client/grpc_rere_client/node_auth_client_interceptor.py +2 -1
  48. flwr/client/message_handler/message_handler.py +2 -2
  49. flwr/client/mod/secure_aggregation/secaggplus_mod.py +3 -3
  50. flwr/client/numpy_client.py +1 -1
  51. flwr/client/rest_client/connection.py +12 -14
  52. flwr/client/run_info_store.py +4 -5
  53. flwr/client/typing.py +1 -1
  54. flwr/clientapp/client_app.py +9 -10
  55. flwr/clientapp/mod/centraldp_mods.py +16 -17
  56. flwr/clientapp/mod/localdp_mod.py +8 -9
  57. flwr/clientapp/typing.py +1 -1
  58. flwr/clientapp/utils.py +3 -3
  59. flwr/common/address.py +1 -2
  60. flwr/common/args.py +3 -4
  61. flwr/common/config.py +13 -16
  62. flwr/common/constant.py +5 -2
  63. flwr/common/differential_privacy.py +3 -4
  64. flwr/common/event_log_plugin/event_log_plugin.py +3 -4
  65. flwr/common/exit/exit.py +15 -2
  66. flwr/common/exit/exit_code.py +19 -0
  67. flwr/common/exit/exit_handler.py +6 -2
  68. flwr/common/exit/signal_handler.py +5 -5
  69. flwr/common/grpc.py +6 -6
  70. flwr/common/inflatable_protobuf_utils.py +1 -1
  71. flwr/common/inflatable_utils.py +38 -21
  72. flwr/common/logger.py +19 -19
  73. flwr/common/message.py +4 -4
  74. flwr/common/object_ref.py +7 -7
  75. flwr/common/record/array.py +3 -3
  76. flwr/common/record/arrayrecord.py +18 -30
  77. flwr/common/record/configrecord.py +3 -3
  78. flwr/common/record/recorddict.py +5 -5
  79. flwr/common/record/typeddict.py +9 -2
  80. flwr/common/recorddict_compat.py +7 -10
  81. flwr/common/retry_invoker.py +20 -20
  82. flwr/common/secure_aggregation/ndarrays_arithmetic.py +3 -3
  83. flwr/common/serde.py +5 -4
  84. flwr/common/serde_utils.py +2 -2
  85. flwr/common/telemetry.py +9 -5
  86. flwr/common/typing.py +52 -37
  87. flwr/compat/client/app.py +38 -37
  88. flwr/compat/client/grpc_client/connection.py +11 -11
  89. flwr/compat/server/app.py +5 -6
  90. flwr/proto/appio_pb2.py +13 -3
  91. flwr/proto/appio_pb2.pyi +134 -65
  92. flwr/proto/appio_pb2_grpc.py +20 -0
  93. flwr/proto/appio_pb2_grpc.pyi +27 -0
  94. flwr/proto/clientappio_pb2.py +17 -7
  95. flwr/proto/clientappio_pb2.pyi +15 -0
  96. flwr/proto/clientappio_pb2_grpc.py +206 -40
  97. flwr/proto/clientappio_pb2_grpc.pyi +168 -53
  98. flwr/proto/control_pb2.py +71 -52
  99. flwr/proto/control_pb2.pyi +277 -111
  100. flwr/proto/control_pb2_grpc.py +249 -40
  101. flwr/proto/control_pb2_grpc.pyi +185 -52
  102. flwr/proto/error_pb2.py +13 -3
  103. flwr/proto/error_pb2.pyi +24 -6
  104. flwr/proto/error_pb2_grpc.py +20 -0
  105. flwr/proto/error_pb2_grpc.pyi +27 -0
  106. flwr/proto/fab_pb2.py +14 -4
  107. flwr/proto/fab_pb2.pyi +59 -31
  108. flwr/proto/fab_pb2_grpc.py +20 -0
  109. flwr/proto/fab_pb2_grpc.pyi +27 -0
  110. flwr/proto/federation_pb2.py +38 -0
  111. flwr/proto/federation_pb2.pyi +56 -0
  112. flwr/proto/federation_pb2_grpc.py +24 -0
  113. flwr/proto/federation_pb2_grpc.pyi +31 -0
  114. flwr/proto/fleet_pb2.py +14 -4
  115. flwr/proto/fleet_pb2.pyi +137 -61
  116. flwr/proto/fleet_pb2_grpc.py +189 -48
  117. flwr/proto/fleet_pb2_grpc.pyi +175 -61
  118. flwr/proto/grpcadapter_pb2.py +14 -4
  119. flwr/proto/grpcadapter_pb2.pyi +38 -16
  120. flwr/proto/grpcadapter_pb2_grpc.py +35 -4
  121. flwr/proto/grpcadapter_pb2_grpc.pyi +38 -7
  122. flwr/proto/heartbeat_pb2.py +17 -7
  123. flwr/proto/heartbeat_pb2.pyi +51 -22
  124. flwr/proto/heartbeat_pb2_grpc.py +20 -0
  125. flwr/proto/heartbeat_pb2_grpc.pyi +27 -0
  126. flwr/proto/log_pb2.py +13 -3
  127. flwr/proto/log_pb2.pyi +34 -11
  128. flwr/proto/log_pb2_grpc.py +20 -0
  129. flwr/proto/log_pb2_grpc.pyi +27 -0
  130. flwr/proto/message_pb2.py +15 -5
  131. flwr/proto/message_pb2.pyi +154 -86
  132. flwr/proto/message_pb2_grpc.py +20 -0
  133. flwr/proto/message_pb2_grpc.pyi +27 -0
  134. flwr/proto/node_pb2.py +15 -5
  135. flwr/proto/node_pb2.pyi +50 -25
  136. flwr/proto/node_pb2_grpc.py +20 -0
  137. flwr/proto/node_pb2_grpc.pyi +27 -0
  138. flwr/proto/recorddict_pb2.py +13 -3
  139. flwr/proto/recorddict_pb2.pyi +184 -107
  140. flwr/proto/recorddict_pb2_grpc.py +20 -0
  141. flwr/proto/recorddict_pb2_grpc.pyi +27 -0
  142. flwr/proto/run_pb2.py +40 -31
  143. flwr/proto/run_pb2.pyi +149 -84
  144. flwr/proto/run_pb2_grpc.py +20 -0
  145. flwr/proto/run_pb2_grpc.pyi +27 -0
  146. flwr/proto/serverappio_pb2.py +13 -3
  147. flwr/proto/serverappio_pb2.pyi +32 -8
  148. flwr/proto/serverappio_pb2_grpc.py +246 -65
  149. flwr/proto/serverappio_pb2_grpc.pyi +221 -85
  150. flwr/proto/simulationio_pb2.py +16 -8
  151. flwr/proto/simulationio_pb2.pyi +15 -0
  152. flwr/proto/simulationio_pb2_grpc.py +162 -41
  153. flwr/proto/simulationio_pb2_grpc.pyi +149 -55
  154. flwr/proto/transport_pb2.py +20 -10
  155. flwr/proto/transport_pb2.pyi +249 -160
  156. flwr/proto/transport_pb2_grpc.py +35 -4
  157. flwr/proto/transport_pb2_grpc.pyi +38 -8
  158. flwr/server/app.py +38 -17
  159. flwr/server/client_manager.py +4 -5
  160. flwr/server/client_proxy.py +10 -11
  161. flwr/server/compat/app.py +4 -5
  162. flwr/server/compat/app_utils.py +2 -1
  163. flwr/server/compat/grid_client_proxy.py +10 -12
  164. flwr/server/compat/legacy_context.py +3 -4
  165. flwr/server/fleet_event_log_interceptor.py +2 -1
  166. flwr/server/grid/grid.py +2 -3
  167. flwr/server/grid/grpc_grid.py +10 -8
  168. flwr/server/grid/inmemory_grid.py +4 -4
  169. flwr/server/run_serverapp.py +2 -3
  170. flwr/server/server.py +34 -39
  171. flwr/server/server_app.py +7 -8
  172. flwr/server/server_config.py +1 -2
  173. flwr/server/serverapp/app.py +34 -28
  174. flwr/server/serverapp_components.py +4 -5
  175. flwr/server/strategy/aggregate.py +9 -8
  176. flwr/server/strategy/bulyan.py +13 -11
  177. flwr/server/strategy/dp_adaptive_clipping.py +16 -20
  178. flwr/server/strategy/dp_fixed_clipping.py +12 -17
  179. flwr/server/strategy/dpfedavg_adaptive.py +3 -4
  180. flwr/server/strategy/dpfedavg_fixed.py +6 -10
  181. flwr/server/strategy/fault_tolerant_fedavg.py +14 -13
  182. flwr/server/strategy/fedadagrad.py +18 -14
  183. flwr/server/strategy/fedadam.py +16 -14
  184. flwr/server/strategy/fedavg.py +16 -17
  185. flwr/server/strategy/fedavg_android.py +15 -15
  186. flwr/server/strategy/fedavgm.py +21 -18
  187. flwr/server/strategy/fedmedian.py +2 -3
  188. flwr/server/strategy/fedopt.py +11 -10
  189. flwr/server/strategy/fedprox.py +10 -9
  190. flwr/server/strategy/fedtrimmedavg.py +12 -11
  191. flwr/server/strategy/fedxgb_bagging.py +13 -11
  192. flwr/server/strategy/fedxgb_cyclic.py +6 -6
  193. flwr/server/strategy/fedxgb_nn_avg.py +4 -4
  194. flwr/server/strategy/fedyogi.py +16 -14
  195. flwr/server/strategy/krum.py +12 -11
  196. flwr/server/strategy/qfedavg.py +16 -15
  197. flwr/server/strategy/strategy.py +6 -9
  198. flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +2 -1
  199. flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +1 -2
  200. flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +3 -4
  201. flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +10 -12
  202. flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +1 -3
  203. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +4 -4
  204. flwr/server/superlink/fleet/grpc_rere/node_auth_server_interceptor.py +3 -2
  205. flwr/server/superlink/fleet/message_handler/message_handler.py +34 -28
  206. flwr/server/superlink/fleet/rest_rere/rest_api.py +2 -2
  207. flwr/server/superlink/fleet/vce/backend/backend.py +1 -1
  208. flwr/server/superlink/fleet/vce/backend/raybackend.py +5 -5
  209. flwr/server/superlink/fleet/vce/vce_api.py +15 -9
  210. flwr/server/superlink/linkstate/in_memory_linkstate.py +115 -150
  211. flwr/server/superlink/linkstate/linkstate.py +59 -43
  212. flwr/server/superlink/linkstate/linkstate_factory.py +22 -5
  213. flwr/server/superlink/linkstate/sqlite_linkstate.py +447 -438
  214. flwr/server/superlink/linkstate/utils.py +6 -6
  215. flwr/server/superlink/serverappio/serverappio_grpc.py +1 -2
  216. flwr/server/superlink/serverappio/serverappio_servicer.py +26 -21
  217. flwr/server/superlink/simulation/simulationio_grpc.py +1 -2
  218. flwr/server/superlink/simulation/simulationio_servicer.py +18 -13
  219. flwr/server/superlink/utils.py +4 -6
  220. flwr/server/typing.py +1 -1
  221. flwr/server/utils/tensorboard.py +15 -8
  222. flwr/server/workflow/default_workflows.py +5 -5
  223. flwr/server/workflow/secure_aggregation/secagg_workflow.py +2 -4
  224. flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +8 -8
  225. flwr/serverapp/strategy/bulyan.py +16 -15
  226. flwr/serverapp/strategy/dp_adaptive_clipping.py +12 -11
  227. flwr/serverapp/strategy/dp_fixed_clipping.py +11 -14
  228. flwr/serverapp/strategy/fedadagrad.py +10 -11
  229. flwr/serverapp/strategy/fedadam.py +10 -11
  230. flwr/serverapp/strategy/fedavg.py +9 -10
  231. flwr/serverapp/strategy/fedavgm.py +17 -16
  232. flwr/serverapp/strategy/fedmedian.py +2 -2
  233. flwr/serverapp/strategy/fedopt.py +10 -11
  234. flwr/serverapp/strategy/fedprox.py +7 -8
  235. flwr/serverapp/strategy/fedtrimmedavg.py +9 -9
  236. flwr/serverapp/strategy/fedxgb_bagging.py +3 -3
  237. flwr/serverapp/strategy/fedxgb_cyclic.py +9 -9
  238. flwr/serverapp/strategy/fedyogi.py +9 -11
  239. flwr/serverapp/strategy/krum.py +7 -7
  240. flwr/serverapp/strategy/multikrum.py +9 -9
  241. flwr/serverapp/strategy/qfedavg.py +17 -16
  242. flwr/serverapp/strategy/strategy.py +6 -9
  243. flwr/serverapp/strategy/strategy_utils.py +7 -8
  244. flwr/simulation/app.py +46 -42
  245. flwr/simulation/legacy_app.py +12 -12
  246. flwr/simulation/ray_transport/ray_actor.py +10 -11
  247. flwr/simulation/ray_transport/ray_client_proxy.py +11 -12
  248. flwr/simulation/run_simulation.py +43 -43
  249. flwr/simulation/simulationio_connection.py +4 -4
  250. flwr/supercore/cli/flower_superexec.py +3 -4
  251. flwr/supercore/constant.py +31 -1
  252. flwr/supercore/corestate/corestate.py +24 -3
  253. flwr/supercore/corestate/in_memory_corestate.py +138 -0
  254. flwr/supercore/corestate/sqlite_corestate.py +157 -0
  255. flwr/supercore/ffs/disk_ffs.py +1 -2
  256. flwr/supercore/ffs/ffs.py +1 -2
  257. flwr/supercore/ffs/ffs_factory.py +1 -2
  258. flwr/{common → supercore}/heartbeat.py +20 -25
  259. flwr/supercore/object_store/in_memory_object_store.py +1 -2
  260. flwr/supercore/object_store/object_store.py +1 -2
  261. flwr/supercore/object_store/object_store_factory.py +1 -2
  262. flwr/supercore/object_store/sqlite_object_store.py +8 -7
  263. flwr/supercore/primitives/asymmetric.py +1 -1
  264. flwr/supercore/primitives/asymmetric_ed25519.py +11 -1
  265. flwr/supercore/sqlite_mixin.py +37 -34
  266. flwr/supercore/superexec/plugin/base_exec_plugin.py +1 -2
  267. flwr/supercore/superexec/plugin/exec_plugin.py +3 -3
  268. flwr/supercore/superexec/run_superexec.py +9 -13
  269. flwr/superlink/artifact_provider/artifact_provider.py +1 -2
  270. flwr/superlink/auth_plugin/auth_plugin.py +6 -9
  271. flwr/superlink/auth_plugin/noop_auth_plugin.py +6 -9
  272. flwr/superlink/federation/__init__.py +24 -0
  273. flwr/superlink/federation/federation_manager.py +64 -0
  274. flwr/superlink/federation/noop_federation_manager.py +71 -0
  275. flwr/superlink/servicer/control/control_account_auth_interceptor.py +22 -13
  276. flwr/superlink/servicer/control/control_event_log_interceptor.py +7 -7
  277. flwr/superlink/servicer/control/control_grpc.py +5 -6
  278. flwr/superlink/servicer/control/control_license_interceptor.py +3 -3
  279. flwr/superlink/servicer/control/control_servicer.py +102 -18
  280. flwr/supernode/cli/flower_supernode.py +58 -3
  281. flwr/supernode/nodestate/in_memory_nodestate.py +60 -49
  282. flwr/supernode/nodestate/nodestate.py +7 -8
  283. flwr/supernode/nodestate/nodestate_factory.py +7 -4
  284. flwr/supernode/runtime/run_clientapp.py +41 -22
  285. flwr/supernode/servicer/clientappio/clientappio_servicer.py +40 -10
  286. flwr/supernode/start_client_internal.py +158 -42
  287. {flwr-1.23.0.dist-info → flwr-1.24.0.dist-info}/METADATA +8 -8
  288. flwr-1.24.0.dist-info/RECORD +454 -0
  289. flwr/supercore/object_store/utils.py +0 -43
  290. flwr-1.23.0.dist-info/RECORD +0 -439
  291. {flwr-1.23.0.dist-info → flwr-1.24.0.dist-info}/WHEEL +0 -0
  292. {flwr-1.23.0.dist-info → flwr-1.24.0.dist-info}/entry_points.txt +0 -0
@@ -20,8 +20,7 @@ Relevant knowledge for reading this modules code:
20
20
 
21
21
 
22
22
  import uuid
23
- from collections.abc import Iterator
24
- from typing import Callable
23
+ from collections.abc import Callable, Iterator
25
24
 
26
25
  import grpc
27
26
  from iterators import TimeoutIterator
@@ -19,7 +19,6 @@ from collections.abc import Iterator
19
19
  from dataclasses import dataclass
20
20
  from enum import Enum
21
21
  from threading import Condition
22
- from typing import Optional
23
22
 
24
23
  from flwr.proto.transport_pb2 import ( # pylint: disable=E0611
25
24
  ClientMessage,
@@ -32,7 +31,7 @@ class InsWrapper:
32
31
  """Instruction wrapper class for a single server message."""
33
32
 
34
33
  server_message: ServerMessage
35
- timeout: Optional[float]
34
+ timeout: float | None
36
35
 
37
36
 
38
37
  @dataclass
@@ -70,8 +69,8 @@ class GrpcBridge:
70
69
  # pylint: disable=unsubscriptable-object
71
70
  self._cv = Condition() # cv stands for condition variable
72
71
  self._status = Status.AWAITING_INS_WRAPPER
73
- self._ins_wrapper: Optional[InsWrapper] = None
74
- self._res_wrapper: Optional[ResWrapper] = None
72
+ self._ins_wrapper: InsWrapper | None = None
73
+ self._res_wrapper: ResWrapper | None = None
75
74
 
76
75
  def _is_closed(self) -> bool:
77
76
  """Return True if closed and False otherwise."""
@@ -15,8 +15,6 @@
15
15
  """Flower ClientProxy implementation using gRPC bidirectional streaming."""
16
16
 
17
17
 
18
- from typing import Optional
19
-
20
18
  from flwr import common
21
19
  from flwr.common import serde
22
20
  from flwr.proto.transport_pb2 import ( # pylint: disable=E0611
@@ -45,8 +43,8 @@ class GrpcClientProxy(ClientProxy):
45
43
  def get_properties(
46
44
  self,
47
45
  ins: common.GetPropertiesIns,
48
- timeout: Optional[float],
49
- group_id: Optional[int],
46
+ timeout: float | None,
47
+ group_id: int | None,
50
48
  ) -> common.GetPropertiesRes:
51
49
  """Request client's set of internal properties."""
52
50
  get_properties_msg = serde.get_properties_ins_to_proto(ins)
@@ -65,8 +63,8 @@ class GrpcClientProxy(ClientProxy):
65
63
  def get_parameters(
66
64
  self,
67
65
  ins: common.GetParametersIns,
68
- timeout: Optional[float],
69
- group_id: Optional[int],
66
+ timeout: float | None,
67
+ group_id: int | None,
70
68
  ) -> common.GetParametersRes:
71
69
  """Return the current local model parameters."""
72
70
  get_parameters_msg = serde.get_parameters_ins_to_proto(ins)
@@ -85,8 +83,8 @@ class GrpcClientProxy(ClientProxy):
85
83
  def fit(
86
84
  self,
87
85
  ins: common.FitIns,
88
- timeout: Optional[float],
89
- group_id: Optional[int],
86
+ timeout: float | None,
87
+ group_id: int | None,
90
88
  ) -> common.FitRes:
91
89
  """Refine the provided parameters using the locally held dataset."""
92
90
  fit_ins_msg = serde.fit_ins_to_proto(ins)
@@ -104,8 +102,8 @@ class GrpcClientProxy(ClientProxy):
104
102
  def evaluate(
105
103
  self,
106
104
  ins: common.EvaluateIns,
107
- timeout: Optional[float],
108
- group_id: Optional[int],
105
+ timeout: float | None,
106
+ group_id: int | None,
109
107
  ) -> common.EvaluateRes:
110
108
  """Evaluate the provided parameters using the locally held dataset."""
111
109
  evaluate_msg = serde.evaluate_ins_to_proto(ins)
@@ -122,8 +120,8 @@ class GrpcClientProxy(ClientProxy):
122
120
  def reconnect(
123
121
  self,
124
122
  ins: common.ReconnectIns,
125
- timeout: Optional[float],
126
- group_id: Optional[int],
123
+ timeout: float | None,
124
+ group_id: int | None,
127
125
  ) -> common.DisconnectRes:
128
126
  """Disconnect and (optionally) reconnect later."""
129
127
  reconnect_ins_msg = serde.reconnect_ins_to_proto(ins)
@@ -15,8 +15,6 @@
15
15
  """Implements utility function to create a gRPC server."""
16
16
 
17
17
 
18
- from typing import Optional
19
-
20
18
  import grpc
21
19
 
22
20
  from flwr.common import GRPC_MAX_MESSAGE_LENGTH
@@ -36,7 +34,7 @@ def start_grpc_server( # pylint: disable=too-many-arguments,R0917
36
34
  max_concurrent_workers: int = 1000,
37
35
  max_message_length: int = GRPC_MAX_MESSAGE_LENGTH,
38
36
  keepalive_time_ms: int = 210000,
39
- certificates: Optional[tuple[bytes, bytes, bytes]] = None,
37
+ certificates: tuple[bytes, bytes, bytes] | None = None,
40
38
  ) -> grpc.Server:
41
39
  """Create and start a gRPC server running FlowerServiceServicer.
42
40
 
@@ -249,8 +249,8 @@ class FleetServicer(fleet_pb2_grpc.FleetServicer):
249
249
  state=self.state_factory.state(),
250
250
  store=self.objectstore_factory.store(),
251
251
  )
252
- except InvalidRunStatusException as e:
253
- abort_grpc_context(e.message, context)
252
+ except (InvalidRunStatusException, ValueError) as e:
253
+ abort_grpc_context(str(e), context)
254
254
 
255
255
  return res
256
256
 
@@ -266,8 +266,8 @@ class FleetServicer(fleet_pb2_grpc.FleetServicer):
266
266
  state=self.state_factory.state(),
267
267
  store=self.objectstore_factory.store(),
268
268
  )
269
- except InvalidRunStatusException as e:
270
- abort_grpc_context(e.message, context)
269
+ except (InvalidRunStatusException, ValueError) as e:
270
+ abort_grpc_context(str(e), context)
271
271
 
272
272
  return res
273
273
 
@@ -16,7 +16,8 @@
16
16
 
17
17
 
18
18
  import datetime
19
- from typing import Any, Callable, cast
19
+ from collections.abc import Callable
20
+ from typing import Any, cast
20
21
 
21
22
  import grpc
22
23
  from google.protobuf.message import Message as GrpcMessage
@@ -117,7 +118,7 @@ class NodeAuthServerInterceptor(grpc.ServerInterceptor): # type: ignore
117
118
  # than the `intercept_service` function.
118
119
 
119
120
  # Retrieve the public key
120
- if isinstance(request, (RegisterNodeFleetRequest, ActivateNodeRequest)):
121
+ if isinstance(request, (RegisterNodeFleetRequest | ActivateNodeRequest)):
121
122
  actual_public_key = request.public_key
122
123
  else:
123
124
  if hasattr(request, "node"):
@@ -15,12 +15,12 @@
15
15
  """Fleet API message handlers."""
16
16
 
17
17
  from logging import ERROR
18
- from typing import Optional
19
18
 
20
19
  from flwr.common import Message, log
21
20
  from flwr.common.constant import (
22
21
  HEARTBEAT_MAX_INTERVAL,
23
22
  HEARTBEAT_MIN_INTERVAL,
23
+ NOOP_ACCOUNT_NAME,
24
24
  NOOP_FLWR_AID,
25
25
  Status,
26
26
  )
@@ -29,9 +29,9 @@ from flwr.common.serde import (
29
29
  fab_to_proto,
30
30
  message_from_proto,
31
31
  message_to_proto,
32
- user_config_to_proto,
32
+ run_to_proto,
33
33
  )
34
- from flwr.common.typing import Fab, InvalidRunStatusException
34
+ from flwr.common.typing import Fab, InvalidRunStatusException, Run
35
35
  from flwr.proto.fab_pb2 import GetFabRequest, GetFabResponse # pylint: disable=E0611
36
36
  from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
37
37
  ActivateNodeRequest,
@@ -60,16 +60,11 @@ from flwr.proto.message_pb2 import ( # pylint: disable=E0611
60
60
  PushObjectRequest,
61
61
  PushObjectResponse,
62
62
  )
63
- from flwr.proto.run_pb2 import ( # pylint: disable=E0611
64
- GetRunRequest,
65
- GetRunResponse,
66
- Run,
67
- )
63
+ from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611
68
64
  from flwr.server.superlink.linkstate import LinkState
69
65
  from flwr.server.superlink.utils import check_abort
70
66
  from flwr.supercore.ffs import Ffs
71
67
  from flwr.supercore.object_store import NoObjectInStoreError, ObjectStore
72
- from flwr.supercore.object_store.utils import store_mapping_and_register_objects
73
68
 
74
69
 
75
70
  class InvalidHeartbeatIntervalError(Exception):
@@ -81,7 +76,7 @@ def register_node(
81
76
  state: LinkState,
82
77
  ) -> RegisterNodeFleetResponse:
83
78
  """Register a node (Fleet API only)."""
84
- node_id = state.create_node(NOOP_FLWR_AID, request.public_key, 0)
79
+ node_id = state.create_node(NOOP_FLWR_AID, NOOP_ACCOUNT_NAME, request.public_key, 0)
85
80
  return RegisterNodeFleetResponse(node_id=node_id)
86
81
 
87
82
 
@@ -173,10 +168,11 @@ def push_messages(
173
168
  """Push Messages handler."""
174
169
  # Convert Message from proto
175
170
  msg = message_from_proto(message_proto=request.messages_list[0])
171
+ run_id = msg.metadata.run_id
176
172
 
177
173
  # Abort if the run is not running
178
174
  abort_msg = check_abort(
179
- msg.metadata.run_id,
175
+ run_id,
180
176
  [Status.PENDING, Status.STARTING, Status.FINISHED],
181
177
  state,
182
178
  store,
@@ -184,11 +180,12 @@ def push_messages(
184
180
  if abort_msg:
185
181
  raise InvalidRunStatusException(abort_msg)
186
182
 
187
- # Store Message in State
188
- message_id: Optional[str] = state.store_message_res(message=msg)
189
-
190
183
  # Store Message object to descendants mapping and preregister objects
191
- objects_to_push = store_mapping_and_register_objects(store, request=request)
184
+ objects_to_push: set[str] = set()
185
+ for object_tree in request.message_object_trees:
186
+ objects_to_push |= set(store.preregister(run_id, object_tree))
187
+ # Store Message in State
188
+ message_id: str | None = state.store_message_res(message=msg)
192
189
 
193
190
  # Build response
194
191
  response = PushMessagesResponse(
@@ -203,10 +200,8 @@ def get_run(
203
200
  request: GetRunRequest, state: LinkState, store: ObjectStore
204
201
  ) -> GetRunResponse:
205
202
  """Get run information."""
206
- run = state.get_run(request.run_id)
207
-
208
- if run is None:
209
- return GetRunResponse()
203
+ # Validate that the requesting SuperNode is part of the federation
204
+ run = _validate_node_in_federation(state, request.node.node_id, request.run_id)
210
205
 
211
206
  # Abort if the run is not running
212
207
  abort_msg = check_abort(
@@ -218,21 +213,16 @@ def get_run(
218
213
  if abort_msg:
219
214
  raise InvalidRunStatusException(abort_msg)
220
215
 
221
- return GetRunResponse(
222
- run=Run(
223
- run_id=run.run_id,
224
- fab_id=run.fab_id,
225
- fab_version=run.fab_version,
226
- override_config=user_config_to_proto(run.override_config),
227
- fab_hash=run.fab_hash,
228
- )
229
- )
216
+ return GetRunResponse(run=run_to_proto(run))
230
217
 
231
218
 
232
219
  def get_fab(
233
220
  request: GetFabRequest, ffs: Ffs, state: LinkState, store: ObjectStore
234
221
  ) -> GetFabResponse:
235
222
  """Get FAB."""
223
+ # Validate that the requesting SuperNode is part of the federation
224
+ _validate_node_in_federation(state, request.node.node_id, request.run_id)
225
+
236
226
  # Abort if the run is not running
237
227
  abort_msg = check_abort(
238
228
  request.run_id,
@@ -329,3 +319,19 @@ def _validate_heartbeat_interval(interval: float) -> None:
329
319
  f"Heartbeat interval {interval} is out of bounds "
330
320
  f"[{HEARTBEAT_MIN_INTERVAL}, {HEARTBEAT_MAX_INTERVAL}]."
331
321
  )
322
+
323
+
324
+ def _validate_node_in_federation(
325
+ state: LinkState,
326
+ node_id: int,
327
+ run_id: int,
328
+ ) -> Run:
329
+ """Raise if the requesting SuperNode is not part of the federation the run belongs
330
+ to."""
331
+ run = state.get_run(run_id)
332
+ if not run:
333
+ raise ValueError(f"Run ID not found: {run_id}")
334
+
335
+ if not state.federation_manager.has_node(node_id, run.federation):
336
+ raise ValueError(f"SuperNode is not part of the federation '{run.federation}'.")
337
+ return run
@@ -17,8 +17,8 @@
17
17
 
18
18
  from __future__ import annotations
19
19
 
20
- from collections.abc import Awaitable
21
- from typing import Callable, TypeVar, cast
20
+ from collections.abc import Awaitable, Callable
21
+ from typing import TypeVar, cast
22
22
 
23
23
  from google.protobuf.message import Message as GrpcMessage
24
24
 
@@ -16,7 +16,7 @@
16
16
 
17
17
 
18
18
  from abc import ABC, abstractmethod
19
- from typing import Callable
19
+ from collections.abc import Callable
20
20
 
21
21
  from flwr.clientapp.client_app import ClientApp
22
22
  from flwr.common.context import Context
@@ -16,8 +16,8 @@
16
16
 
17
17
 
18
18
  import sys
19
+ from collections.abc import Callable
19
20
  from logging import DEBUG, ERROR
20
- from typing import Callable, Optional, Union
21
21
 
22
22
  import ray
23
23
 
@@ -32,8 +32,8 @@ from flwr.simulation.ray_transport.utils import enable_tf_gpu_growth
32
32
 
33
33
  from .backend import Backend, BackendConfig
34
34
 
35
- ClientResourcesDict = dict[str, Union[int, float]]
36
- ActorArgsDict = dict[str, Union[int, float, Callable[[], None]]]
35
+ ClientResourcesDict = dict[str, int | float]
36
+ ActorArgsDict = dict[str, int | float | Callable[[], None]]
37
37
 
38
38
 
39
39
  class RayBackend(Backend):
@@ -57,9 +57,9 @@ class RayBackend(Backend):
57
57
 
58
58
  # Valide actor resources
59
59
  self.actor_kwargs = self._validate_actor_arguments(config=backend_config)
60
- self.pool: Optional[BasicActorPool] = None
60
+ self.pool: BasicActorPool | None = None
61
61
 
62
- self.app_fn: Optional[Callable[[], ClientApp]] = None
62
+ self.app_fn: Callable[[], ClientApp] | None = None
63
63
 
64
64
  def _validate_client_resources(self, config: BackendConfig) -> ClientResourcesDict:
65
65
  client_resources_config = config.get(self.client_resources_key)
@@ -20,11 +20,11 @@ import secrets
20
20
  import threading
21
21
  import time
22
22
  import traceback
23
+ from collections.abc import Callable
23
24
  from concurrent.futures import ThreadPoolExecutor
24
25
  from logging import DEBUG, ERROR, INFO, WARN
25
26
  from pathlib import Path
26
27
  from queue import Empty, Queue
27
- from typing import Callable, Optional
28
28
  from uuid import uuid4
29
29
 
30
30
  from flwr.app.error import Error
@@ -34,6 +34,7 @@ from flwr.clientapp.utils import get_load_client_app_fn
34
34
  from flwr.common import Message
35
35
  from flwr.common.constant import (
36
36
  HEARTBEAT_INTERVAL_INF,
37
+ NOOP_ACCOUNT_NAME,
37
38
  NOOP_FLWR_AID,
38
39
  NUM_PARTITIONS_KEY,
39
40
  PARTITION_ID_KEY,
@@ -43,6 +44,8 @@ from flwr.common.logger import log
43
44
  from flwr.common.typing import Run
44
45
  from flwr.server.superlink.linkstate import LinkState, LinkStateFactory
45
46
  from flwr.supercore.constant import FLWR_IN_MEMORY_DB_NAME
47
+ from flwr.supercore.object_store import ObjectStoreFactory
48
+ from flwr.superlink.federation import NoOpFederationManager
46
49
 
47
50
  from .backend import Backend, error_messages_backends, supported_backends
48
51
 
@@ -61,6 +64,7 @@ def _register_nodes(
61
64
  # use NOOP_FLWR_AID as owner_aid and
62
65
  # use random bytes as public key
63
66
  NOOP_FLWR_AID,
67
+ NOOP_ACCOUNT_NAME,
64
68
  secrets.token_bytes(32),
65
69
  heartbeat_interval=HEARTBEAT_INTERVAL_INF,
66
70
  )
@@ -75,7 +79,7 @@ def _register_nodes(
75
79
  def _register_node_info_stores(
76
80
  nodes_mapping: NodeToPartitionMapping,
77
81
  run: Run,
78
- app_dir: Optional[str] = None,
82
+ app_dir: str | None = None,
79
83
  ) -> dict[int, DeprecatedRunInfoStore]:
80
84
  """Create DeprecatedRunInfoStore objects and register the context for the run."""
81
85
  node_info_store: dict[int, DeprecatedRunInfoStore] = {}
@@ -270,12 +274,12 @@ def start_vce(
270
274
  is_app: bool,
271
275
  f_stop: threading.Event,
272
276
  run: Run,
273
- flwr_dir: Optional[str] = None,
274
- client_app: Optional[ClientApp] = None,
275
- client_app_attr: Optional[str] = None,
276
- num_supernodes: Optional[int] = None,
277
- state_factory: Optional[LinkStateFactory] = None,
278
- existing_nodes_mapping: Optional[NodeToPartitionMapping] = None,
277
+ flwr_dir: str | None = None,
278
+ client_app: ClientApp | None = None,
279
+ client_app_attr: str | None = None,
280
+ num_supernodes: int | None = None,
281
+ state_factory: LinkStateFactory | None = None,
282
+ existing_nodes_mapping: NodeToPartitionMapping | None = None,
279
283
  ) -> None:
280
284
  """Start Fleet API with the Simulation Engine."""
281
285
  nodes_mapping = {}
@@ -313,7 +317,9 @@ def start_vce(
313
317
  if not state_factory:
314
318
  log(INFO, "A StateFactory was not supplied to the SimulationEngine.")
315
319
  # Create an empty in-memory state factory
316
- state_factory = LinkStateFactory(FLWR_IN_MEMORY_DB_NAME)
320
+ state_factory = LinkStateFactory(
321
+ FLWR_IN_MEMORY_DB_NAME, NoOpFederationManager(), ObjectStoreFactory()
322
+ )
317
323
  log(INFO, "Created new %s.", state_factory.__class__.__name__)
318
324
 
319
325
  if num_supernodes: