flwr 1.23.0__py3-none-any.whl → 1.25.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 (339) 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/{new/templates → app_cmd}/__init__.py +9 -1
  6. flwr/cli/app_cmd/publish.py +285 -0
  7. flwr/cli/app_cmd/review.py +262 -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/{new/templates/app/code/flwr_tune → federation}/__init__.py +10 -1
  15. flwr/cli/federation/ls.py +140 -0
  16. flwr/cli/federation/show.py +318 -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 +211 -130
  21. flwr/cli/new/new.py +123 -331
  22. flwr/cli/pull.py +10 -5
  23. flwr/cli/run/run.py +71 -29
  24. flwr/cli/run_utils.py +148 -0
  25. flwr/cli/stop.py +26 -8
  26. flwr/cli/supernode/ls.py +25 -12
  27. flwr/cli/supernode/register.py +9 -4
  28. flwr/cli/supernode/unregister.py +5 -3
  29. flwr/cli/utils.py +239 -16
  30. flwr/client/__init__.py +1 -1
  31. flwr/client/dpfedavg_numpy_client.py +4 -1
  32. flwr/client/grpc_adapter_client/connection.py +8 -9
  33. flwr/client/grpc_rere_client/connection.py +16 -14
  34. flwr/client/grpc_rere_client/grpc_adapter.py +6 -2
  35. flwr/client/grpc_rere_client/node_auth_client_interceptor.py +2 -1
  36. flwr/client/message_handler/message_handler.py +2 -2
  37. flwr/client/mod/secure_aggregation/secaggplus_mod.py +3 -3
  38. flwr/client/numpy_client.py +1 -1
  39. flwr/client/rest_client/connection.py +18 -18
  40. flwr/client/run_info_store.py +4 -5
  41. flwr/client/typing.py +1 -1
  42. flwr/clientapp/client_app.py +9 -10
  43. flwr/clientapp/mod/centraldp_mods.py +16 -17
  44. flwr/clientapp/mod/localdp_mod.py +8 -9
  45. flwr/clientapp/typing.py +1 -1
  46. flwr/clientapp/utils.py +3 -3
  47. flwr/common/address.py +1 -2
  48. flwr/common/args.py +3 -4
  49. flwr/common/config.py +13 -16
  50. flwr/common/constant.py +5 -2
  51. flwr/common/differential_privacy.py +3 -4
  52. flwr/common/event_log_plugin/event_log_plugin.py +3 -4
  53. flwr/common/exit/exit.py +15 -2
  54. flwr/common/exit/exit_code.py +19 -0
  55. flwr/common/exit/exit_handler.py +6 -2
  56. flwr/common/exit/signal_handler.py +5 -5
  57. flwr/common/grpc.py +6 -6
  58. flwr/common/inflatable_protobuf_utils.py +1 -1
  59. flwr/common/inflatable_utils.py +38 -21
  60. flwr/common/logger.py +19 -19
  61. flwr/common/message.py +4 -4
  62. flwr/common/object_ref.py +7 -7
  63. flwr/common/record/array.py +3 -3
  64. flwr/common/record/arrayrecord.py +18 -30
  65. flwr/common/record/configrecord.py +3 -3
  66. flwr/common/record/recorddict.py +5 -5
  67. flwr/common/record/typeddict.py +9 -2
  68. flwr/common/recorddict_compat.py +7 -10
  69. flwr/common/retry_invoker.py +20 -20
  70. flwr/common/secure_aggregation/ndarrays_arithmetic.py +3 -3
  71. flwr/common/serde.py +11 -4
  72. flwr/common/serde_utils.py +2 -2
  73. flwr/common/telemetry.py +9 -5
  74. flwr/common/typing.py +58 -37
  75. flwr/compat/client/app.py +38 -37
  76. flwr/compat/client/grpc_client/connection.py +11 -11
  77. flwr/compat/server/app.py +5 -6
  78. flwr/proto/appio_pb2.py +13 -3
  79. flwr/proto/appio_pb2.pyi +134 -65
  80. flwr/proto/appio_pb2_grpc.py +20 -0
  81. flwr/proto/appio_pb2_grpc.pyi +27 -0
  82. flwr/proto/clientappio_pb2.py +17 -7
  83. flwr/proto/clientappio_pb2.pyi +15 -0
  84. flwr/proto/clientappio_pb2_grpc.py +206 -40
  85. flwr/proto/clientappio_pb2_grpc.pyi +168 -53
  86. flwr/proto/control_pb2.py +71 -52
  87. flwr/proto/control_pb2.pyi +277 -111
  88. flwr/proto/control_pb2_grpc.py +249 -40
  89. flwr/proto/control_pb2_grpc.pyi +185 -52
  90. flwr/proto/error_pb2.py +13 -3
  91. flwr/proto/error_pb2.pyi +24 -6
  92. flwr/proto/error_pb2_grpc.py +20 -0
  93. flwr/proto/error_pb2_grpc.pyi +27 -0
  94. flwr/proto/fab_pb2.py +14 -4
  95. flwr/proto/fab_pb2.pyi +59 -31
  96. flwr/proto/fab_pb2_grpc.py +20 -0
  97. flwr/proto/fab_pb2_grpc.pyi +27 -0
  98. flwr/proto/federation_pb2.py +38 -0
  99. flwr/proto/federation_pb2.pyi +56 -0
  100. flwr/proto/federation_pb2_grpc.py +24 -0
  101. flwr/proto/federation_pb2_grpc.pyi +31 -0
  102. flwr/proto/fleet_pb2.py +24 -14
  103. flwr/proto/fleet_pb2.pyi +141 -61
  104. flwr/proto/fleet_pb2_grpc.py +189 -48
  105. flwr/proto/fleet_pb2_grpc.pyi +175 -61
  106. flwr/proto/grpcadapter_pb2.py +14 -4
  107. flwr/proto/grpcadapter_pb2.pyi +38 -16
  108. flwr/proto/grpcadapter_pb2_grpc.py +35 -4
  109. flwr/proto/grpcadapter_pb2_grpc.pyi +38 -7
  110. flwr/proto/heartbeat_pb2.py +17 -7
  111. flwr/proto/heartbeat_pb2.pyi +51 -22
  112. flwr/proto/heartbeat_pb2_grpc.py +20 -0
  113. flwr/proto/heartbeat_pb2_grpc.pyi +27 -0
  114. flwr/proto/log_pb2.py +13 -3
  115. flwr/proto/log_pb2.pyi +34 -11
  116. flwr/proto/log_pb2_grpc.py +20 -0
  117. flwr/proto/log_pb2_grpc.pyi +27 -0
  118. flwr/proto/message_pb2.py +15 -5
  119. flwr/proto/message_pb2.pyi +154 -86
  120. flwr/proto/message_pb2_grpc.py +20 -0
  121. flwr/proto/message_pb2_grpc.pyi +27 -0
  122. flwr/proto/node_pb2.py +15 -5
  123. flwr/proto/node_pb2.pyi +50 -25
  124. flwr/proto/node_pb2_grpc.py +20 -0
  125. flwr/proto/node_pb2_grpc.pyi +27 -0
  126. flwr/proto/recorddict_pb2.py +13 -3
  127. flwr/proto/recorddict_pb2.pyi +184 -107
  128. flwr/proto/recorddict_pb2_grpc.py +20 -0
  129. flwr/proto/recorddict_pb2_grpc.pyi +27 -0
  130. flwr/proto/run_pb2.py +40 -31
  131. flwr/proto/run_pb2.pyi +158 -84
  132. flwr/proto/run_pb2_grpc.py +20 -0
  133. flwr/proto/run_pb2_grpc.pyi +27 -0
  134. flwr/proto/serverappio_pb2.py +13 -3
  135. flwr/proto/serverappio_pb2.pyi +32 -8
  136. flwr/proto/serverappio_pb2_grpc.py +246 -65
  137. flwr/proto/serverappio_pb2_grpc.pyi +221 -85
  138. flwr/proto/simulationio_pb2.py +16 -8
  139. flwr/proto/simulationio_pb2.pyi +15 -0
  140. flwr/proto/simulationio_pb2_grpc.py +162 -41
  141. flwr/proto/simulationio_pb2_grpc.pyi +149 -55
  142. flwr/proto/transport_pb2.py +20 -10
  143. flwr/proto/transport_pb2.pyi +249 -160
  144. flwr/proto/transport_pb2_grpc.py +35 -4
  145. flwr/proto/transport_pb2_grpc.pyi +38 -8
  146. flwr/server/app.py +39 -17
  147. flwr/server/client_manager.py +4 -5
  148. flwr/server/client_proxy.py +10 -11
  149. flwr/server/compat/app.py +4 -5
  150. flwr/server/compat/app_utils.py +2 -1
  151. flwr/server/compat/grid_client_proxy.py +10 -12
  152. flwr/server/compat/legacy_context.py +3 -4
  153. flwr/server/fleet_event_log_interceptor.py +2 -1
  154. flwr/server/grid/grid.py +2 -3
  155. flwr/server/grid/grpc_grid.py +10 -8
  156. flwr/server/grid/inmemory_grid.py +4 -4
  157. flwr/server/run_serverapp.py +2 -3
  158. flwr/server/server.py +34 -39
  159. flwr/server/server_app.py +7 -8
  160. flwr/server/server_config.py +1 -2
  161. flwr/server/serverapp/app.py +34 -28
  162. flwr/server/serverapp_components.py +4 -5
  163. flwr/server/strategy/aggregate.py +9 -8
  164. flwr/server/strategy/bulyan.py +13 -11
  165. flwr/server/strategy/dp_adaptive_clipping.py +16 -20
  166. flwr/server/strategy/dp_fixed_clipping.py +12 -17
  167. flwr/server/strategy/dpfedavg_adaptive.py +3 -4
  168. flwr/server/strategy/dpfedavg_fixed.py +6 -10
  169. flwr/server/strategy/fault_tolerant_fedavg.py +14 -13
  170. flwr/server/strategy/fedadagrad.py +18 -14
  171. flwr/server/strategy/fedadam.py +16 -14
  172. flwr/server/strategy/fedavg.py +16 -17
  173. flwr/server/strategy/fedavg_android.py +15 -15
  174. flwr/server/strategy/fedavgm.py +21 -18
  175. flwr/server/strategy/fedmedian.py +2 -3
  176. flwr/server/strategy/fedopt.py +11 -10
  177. flwr/server/strategy/fedprox.py +10 -9
  178. flwr/server/strategy/fedtrimmedavg.py +12 -11
  179. flwr/server/strategy/fedxgb_bagging.py +13 -11
  180. flwr/server/strategy/fedxgb_cyclic.py +6 -6
  181. flwr/server/strategy/fedxgb_nn_avg.py +4 -4
  182. flwr/server/strategy/fedyogi.py +16 -14
  183. flwr/server/strategy/krum.py +12 -11
  184. flwr/server/strategy/qfedavg.py +16 -15
  185. flwr/server/strategy/strategy.py +6 -9
  186. flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +2 -1
  187. flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +1 -2
  188. flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +3 -4
  189. flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +10 -12
  190. flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +1 -3
  191. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +4 -4
  192. flwr/server/superlink/fleet/grpc_rere/node_auth_server_interceptor.py +3 -2
  193. flwr/server/superlink/fleet/message_handler/message_handler.py +75 -30
  194. flwr/server/superlink/fleet/rest_rere/rest_api.py +2 -2
  195. flwr/server/superlink/fleet/vce/backend/backend.py +1 -1
  196. flwr/server/superlink/fleet/vce/backend/raybackend.py +5 -5
  197. flwr/server/superlink/fleet/vce/vce_api.py +15 -9
  198. flwr/server/superlink/linkstate/in_memory_linkstate.py +148 -149
  199. flwr/server/superlink/linkstate/linkstate.py +91 -43
  200. flwr/server/superlink/linkstate/linkstate_factory.py +22 -5
  201. flwr/server/superlink/linkstate/sqlite_linkstate.py +502 -436
  202. flwr/server/superlink/linkstate/utils.py +6 -6
  203. flwr/server/superlink/serverappio/serverappio_grpc.py +1 -2
  204. flwr/server/superlink/serverappio/serverappio_servicer.py +26 -21
  205. flwr/server/superlink/simulation/simulationio_grpc.py +1 -2
  206. flwr/server/superlink/simulation/simulationio_servicer.py +18 -13
  207. flwr/server/superlink/utils.py +4 -6
  208. flwr/server/typing.py +1 -1
  209. flwr/server/utils/tensorboard.py +15 -8
  210. flwr/server/workflow/default_workflows.py +5 -5
  211. flwr/server/workflow/secure_aggregation/secagg_workflow.py +2 -4
  212. flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +8 -8
  213. flwr/serverapp/strategy/bulyan.py +16 -15
  214. flwr/serverapp/strategy/dp_adaptive_clipping.py +12 -11
  215. flwr/serverapp/strategy/dp_fixed_clipping.py +11 -14
  216. flwr/serverapp/strategy/fedadagrad.py +10 -11
  217. flwr/serverapp/strategy/fedadam.py +10 -11
  218. flwr/serverapp/strategy/fedavg.py +9 -10
  219. flwr/serverapp/strategy/fedavgm.py +17 -16
  220. flwr/serverapp/strategy/fedmedian.py +2 -2
  221. flwr/serverapp/strategy/fedopt.py +10 -11
  222. flwr/serverapp/strategy/fedprox.py +7 -8
  223. flwr/serverapp/strategy/fedtrimmedavg.py +9 -9
  224. flwr/serverapp/strategy/fedxgb_bagging.py +3 -3
  225. flwr/serverapp/strategy/fedxgb_cyclic.py +9 -9
  226. flwr/serverapp/strategy/fedyogi.py +9 -11
  227. flwr/serverapp/strategy/krum.py +7 -7
  228. flwr/serverapp/strategy/multikrum.py +9 -9
  229. flwr/serverapp/strategy/qfedavg.py +17 -16
  230. flwr/serverapp/strategy/strategy.py +6 -9
  231. flwr/serverapp/strategy/strategy_utils.py +7 -8
  232. flwr/simulation/app.py +46 -42
  233. flwr/simulation/legacy_app.py +12 -12
  234. flwr/simulation/ray_transport/ray_actor.py +10 -11
  235. flwr/simulation/ray_transport/ray_client_proxy.py +11 -12
  236. flwr/simulation/run_simulation.py +43 -43
  237. flwr/simulation/simulationio_connection.py +4 -4
  238. flwr/supercore/cli/flower_superexec.py +3 -4
  239. flwr/supercore/constant.py +34 -1
  240. flwr/supercore/corestate/corestate.py +24 -3
  241. flwr/supercore/corestate/in_memory_corestate.py +138 -0
  242. flwr/supercore/corestate/sqlite_corestate.py +157 -0
  243. flwr/supercore/ffs/disk_ffs.py +1 -2
  244. flwr/supercore/ffs/ffs.py +1 -2
  245. flwr/supercore/ffs/ffs_factory.py +1 -2
  246. flwr/{common → supercore}/heartbeat.py +20 -25
  247. flwr/supercore/object_store/in_memory_object_store.py +1 -2
  248. flwr/supercore/object_store/object_store.py +1 -2
  249. flwr/supercore/object_store/object_store_factory.py +1 -2
  250. flwr/supercore/object_store/sqlite_object_store.py +8 -7
  251. flwr/supercore/primitives/asymmetric.py +1 -1
  252. flwr/supercore/primitives/asymmetric_ed25519.py +11 -1
  253. flwr/supercore/sqlite_mixin.py +37 -34
  254. flwr/supercore/superexec/plugin/base_exec_plugin.py +1 -2
  255. flwr/supercore/superexec/plugin/exec_plugin.py +3 -3
  256. flwr/supercore/superexec/run_superexec.py +9 -13
  257. flwr/supercore/utils.py +190 -0
  258. flwr/superlink/artifact_provider/artifact_provider.py +1 -2
  259. flwr/superlink/auth_plugin/auth_plugin.py +6 -9
  260. flwr/superlink/auth_plugin/noop_auth_plugin.py +6 -9
  261. flwr/{cli/new/templates/app → superlink/federation}/__init__.py +10 -1
  262. flwr/superlink/federation/federation_manager.py +64 -0
  263. flwr/superlink/federation/noop_federation_manager.py +71 -0
  264. flwr/superlink/servicer/control/control_account_auth_interceptor.py +22 -13
  265. flwr/superlink/servicer/control/control_event_log_interceptor.py +7 -7
  266. flwr/superlink/servicer/control/control_grpc.py +7 -6
  267. flwr/superlink/servicer/control/control_license_interceptor.py +3 -3
  268. flwr/superlink/servicer/control/control_servicer.py +190 -23
  269. flwr/supernode/cli/flower_supernode.py +58 -3
  270. flwr/supernode/nodestate/in_memory_nodestate.py +121 -49
  271. flwr/supernode/nodestate/nodestate.py +52 -8
  272. flwr/supernode/nodestate/nodestate_factory.py +7 -4
  273. flwr/supernode/runtime/run_clientapp.py +41 -22
  274. flwr/supernode/servicer/clientappio/clientappio_servicer.py +46 -10
  275. flwr/supernode/start_client_internal.py +165 -46
  276. {flwr-1.23.0.dist-info → flwr-1.25.0.dist-info}/METADATA +9 -11
  277. flwr-1.25.0.dist-info/RECORD +393 -0
  278. flwr/cli/new/templates/app/.gitignore.tpl +0 -163
  279. flwr/cli/new/templates/app/LICENSE.tpl +0 -202
  280. flwr/cli/new/templates/app/README.baseline.md.tpl +0 -127
  281. flwr/cli/new/templates/app/README.flowertune.md.tpl +0 -68
  282. flwr/cli/new/templates/app/README.md.tpl +0 -37
  283. flwr/cli/new/templates/app/code/__init__.baseline.py.tpl +0 -1
  284. flwr/cli/new/templates/app/code/__init__.py +0 -15
  285. flwr/cli/new/templates/app/code/__init__.py.tpl +0 -1
  286. flwr/cli/new/templates/app/code/__init__.pytorch_legacy_api.py.tpl +0 -1
  287. flwr/cli/new/templates/app/code/client.baseline.py.tpl +0 -75
  288. flwr/cli/new/templates/app/code/client.huggingface.py.tpl +0 -93
  289. flwr/cli/new/templates/app/code/client.jax.py.tpl +0 -71
  290. flwr/cli/new/templates/app/code/client.mlx.py.tpl +0 -102
  291. flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -46
  292. flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -80
  293. flwr/cli/new/templates/app/code/client.pytorch_legacy_api.py.tpl +0 -55
  294. flwr/cli/new/templates/app/code/client.sklearn.py.tpl +0 -108
  295. flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -82
  296. flwr/cli/new/templates/app/code/client.xgboost.py.tpl +0 -110
  297. flwr/cli/new/templates/app/code/dataset.baseline.py.tpl +0 -36
  298. flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +0 -92
  299. flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +0 -87
  300. flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +0 -56
  301. flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +0 -73
  302. flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +0 -78
  303. flwr/cli/new/templates/app/code/model.baseline.py.tpl +0 -66
  304. flwr/cli/new/templates/app/code/server.baseline.py.tpl +0 -43
  305. flwr/cli/new/templates/app/code/server.huggingface.py.tpl +0 -42
  306. flwr/cli/new/templates/app/code/server.jax.py.tpl +0 -39
  307. flwr/cli/new/templates/app/code/server.mlx.py.tpl +0 -41
  308. flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -38
  309. flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -41
  310. flwr/cli/new/templates/app/code/server.pytorch_legacy_api.py.tpl +0 -31
  311. flwr/cli/new/templates/app/code/server.sklearn.py.tpl +0 -44
  312. flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -38
  313. flwr/cli/new/templates/app/code/server.xgboost.py.tpl +0 -56
  314. flwr/cli/new/templates/app/code/strategy.baseline.py.tpl +0 -1
  315. flwr/cli/new/templates/app/code/task.huggingface.py.tpl +0 -98
  316. flwr/cli/new/templates/app/code/task.jax.py.tpl +0 -57
  317. flwr/cli/new/templates/app/code/task.mlx.py.tpl +0 -102
  318. flwr/cli/new/templates/app/code/task.numpy.py.tpl +0 -7
  319. flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -98
  320. flwr/cli/new/templates/app/code/task.pytorch_legacy_api.py.tpl +0 -111
  321. flwr/cli/new/templates/app/code/task.sklearn.py.tpl +0 -67
  322. flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +0 -52
  323. flwr/cli/new/templates/app/code/task.xgboost.py.tpl +0 -67
  324. flwr/cli/new/templates/app/code/utils.baseline.py.tpl +0 -1
  325. flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +0 -146
  326. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +0 -80
  327. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +0 -65
  328. flwr/cli/new/templates/app/pyproject.jax.toml.tpl +0 -52
  329. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +0 -56
  330. flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +0 -49
  331. flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +0 -53
  332. flwr/cli/new/templates/app/pyproject.pytorch_legacy_api.toml.tpl +0 -53
  333. flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +0 -52
  334. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +0 -53
  335. flwr/cli/new/templates/app/pyproject.xgboost.toml.tpl +0 -61
  336. flwr/supercore/object_store/utils.py +0 -43
  337. flwr-1.23.0.dist-info/RECORD +0 -439
  338. {flwr-1.23.0.dist-info → flwr-1.25.0.dist-info}/WHEEL +0 -0
  339. {flwr-1.23.0.dist-info → flwr-1.25.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
 
@@ -132,7 +127,7 @@ def send_node_heartbeat(
132
127
  return SendNodeHeartbeatResponse(success=res)
133
128
 
134
129
 
135
- def pull_messages(
130
+ def pull_messages( # pylint: disable=too-many-locals
136
131
  request: PullMessagesRequest,
137
132
  state: LinkState,
138
133
  store: ObjectStore,
@@ -148,6 +143,8 @@ def pull_messages(
148
143
  # Convert to Messages
149
144
  msg_proto = []
150
145
  trees = []
146
+ run_id_to_record: int | None = None
147
+
151
148
  for msg in message_list:
152
149
  try:
153
150
  # Retrieve Message object tree from ObjectStore
@@ -157,12 +154,30 @@ def pull_messages(
157
154
  # Add Message and its object tree to the response
158
155
  msg_proto.append(message_to_proto(msg))
159
156
  trees.append(obj_tree)
157
+
158
+ # Track run_id for traffic recording
159
+ run_id_to_record = msg.metadata.run_id
160
+
160
161
  except NoObjectInStoreError as e:
161
162
  log(ERROR, e.message)
162
163
  # Delete message ins from state
163
164
  state.delete_messages(message_ins_ids={msg_object_id})
164
165
 
165
- return PullMessagesResponse(messages_list=msg_proto, message_object_trees=trees)
166
+ response = PullMessagesResponse(messages_list=msg_proto, message_object_trees=trees)
167
+
168
+ # Record incoming traffic size
169
+ bytes_recv = len(request.SerializeToString())
170
+
171
+ # Record traffic only if message was successfully processed
172
+ # All messages in this request are assumed to belong to the same run
173
+ if run_id_to_record is not None:
174
+ # Record outgoing traffic size
175
+ bytes_sent = len(response.SerializeToString())
176
+ state.store_traffic(
177
+ run_id_to_record, bytes_sent=bytes_sent, bytes_recv=bytes_recv
178
+ )
179
+
180
+ return response
166
181
 
167
182
 
168
183
  def push_messages(
@@ -173,10 +188,14 @@ def push_messages(
173
188
  """Push Messages handler."""
174
189
  # Convert Message from proto
175
190
  msg = message_from_proto(message_proto=request.messages_list[0])
191
+ run_id = msg.metadata.run_id
192
+
193
+ # Record incoming traffic size
194
+ bytes_recv = len(request.SerializeToString())
176
195
 
177
196
  # Abort if the run is not running
178
197
  abort_msg = check_abort(
179
- msg.metadata.run_id,
198
+ run_id,
180
199
  [Status.PENDING, Status.STARTING, Status.FINISHED],
181
200
  state,
182
201
  store,
@@ -184,11 +203,12 @@ def push_messages(
184
203
  if abort_msg:
185
204
  raise InvalidRunStatusException(abort_msg)
186
205
 
187
- # Store Message in State
188
- message_id: Optional[str] = state.store_message_res(message=msg)
189
-
190
206
  # Store Message object to descendants mapping and preregister objects
191
- objects_to_push = store_mapping_and_register_objects(store, request=request)
207
+ objects_to_push: set[str] = set()
208
+ for object_tree in request.message_object_trees:
209
+ objects_to_push |= set(store.preregister(run_id, object_tree))
210
+ # Store Message in State
211
+ message_id: str | None = state.store_message_res(message=msg)
192
212
 
193
213
  # Build response
194
214
  response = PushMessagesResponse(
@@ -196,6 +216,16 @@ def push_messages(
196
216
  results={str(message_id): 0},
197
217
  objects_to_push=objects_to_push,
198
218
  )
219
+
220
+ # Record outgoing traffic size
221
+ bytes_sent = len(response.SerializeToString())
222
+
223
+ # Record traffic only if message was successfully processed
224
+ # Only one message is processed per request
225
+ state.store_traffic(run_id, bytes_sent=bytes_sent, bytes_recv=bytes_recv)
226
+ if request.clientapp_runtime_list:
227
+ state.add_clientapp_runtime(run_id, request.clientapp_runtime_list[0])
228
+
199
229
  return response
200
230
 
201
231
 
@@ -203,10 +233,8 @@ def get_run(
203
233
  request: GetRunRequest, state: LinkState, store: ObjectStore
204
234
  ) -> GetRunResponse:
205
235
  """Get run information."""
206
- run = state.get_run(request.run_id)
207
-
208
- if run is None:
209
- return GetRunResponse()
236
+ # Validate that the requesting SuperNode is part of the federation
237
+ run = _validate_node_in_federation(state, request.node.node_id, request.run_id)
210
238
 
211
239
  # Abort if the run is not running
212
240
  abort_msg = check_abort(
@@ -218,21 +246,16 @@ def get_run(
218
246
  if abort_msg:
219
247
  raise InvalidRunStatusException(abort_msg)
220
248
 
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
- )
249
+ return GetRunResponse(run=run_to_proto(run))
230
250
 
231
251
 
232
252
  def get_fab(
233
253
  request: GetFabRequest, ffs: Ffs, state: LinkState, store: ObjectStore
234
254
  ) -> GetFabResponse:
235
255
  """Get FAB."""
256
+ # Validate that the requesting SuperNode is part of the federation
257
+ _validate_node_in_federation(state, request.node.node_id, request.run_id)
258
+
236
259
  # Abort if the run is not running
237
260
  abort_msg = check_abort(
238
261
  request.run_id,
@@ -267,6 +290,10 @@ def push_object(
267
290
  try:
268
291
  store.put(request.object_id, request.object_content)
269
292
  stored = True
293
+ # Record bytes traffic pushed from SuperNode
294
+ state.store_traffic(
295
+ request.run_id, bytes_sent=0, bytes_recv=len(request.object_content)
296
+ )
270
297
  except (NoObjectInStoreError, ValueError) as e:
271
298
  log(ERROR, str(e))
272
299
  except UnexpectedObjectContentError as e:
@@ -293,6 +320,8 @@ def pull_object(
293
320
  content = store.get(request.object_id)
294
321
  if content is not None:
295
322
  object_available = content != b""
323
+ # Record bytes traffic pulled by SuperNode
324
+ state.store_traffic(request.run_id, bytes_sent=len(content), bytes_recv=0)
296
325
  return PullObjectResponse(
297
326
  object_found=True,
298
327
  object_available=object_available,
@@ -329,3 +358,19 @@ def _validate_heartbeat_interval(interval: float) -> None:
329
358
  f"Heartbeat interval {interval} is out of bounds "
330
359
  f"[{HEARTBEAT_MIN_INTERVAL}, {HEARTBEAT_MAX_INTERVAL}]."
331
360
  )
361
+
362
+
363
+ def _validate_node_in_federation(
364
+ state: LinkState,
365
+ node_id: int,
366
+ run_id: int,
367
+ ) -> Run:
368
+ """Raise if the requesting SuperNode is not part of the federation the run belongs
369
+ to."""
370
+ run = state.get_run(run_id)
371
+ if not run:
372
+ raise ValueError(f"Run ID not found: {run_id}")
373
+
374
+ if not state.federation_manager.has_node(node_id, run.federation):
375
+ raise ValueError(f"SuperNode is not part of the federation '{run.federation}'.")
376
+ 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: