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
@@ -17,20 +17,25 @@
17
17
 
18
18
  import abc
19
19
  from collections.abc import Sequence
20
- from typing import Optional
21
20
 
22
21
  from flwr.common import Context, Message
23
22
  from flwr.common.record import ConfigRecord
24
23
  from flwr.common.typing import Run, RunStatus, UserConfig
25
24
  from flwr.proto.node_pb2 import NodeInfo # pylint: disable=E0611
26
25
  from flwr.supercore.corestate import CoreState
26
+ from flwr.superlink.federation import FederationManager
27
27
 
28
28
 
29
29
  class LinkState(CoreState): # pylint: disable=R0904
30
30
  """Abstract LinkState."""
31
31
 
32
+ @property
32
33
  @abc.abstractmethod
33
- def store_message_ins(self, message: Message) -> Optional[str]:
34
+ def federation_manager(self) -> FederationManager:
35
+ """Return the FederationManager instance."""
36
+
37
+ @abc.abstractmethod
38
+ def store_message_ins(self, message: Message) -> str | None:
34
39
  """Store one Message.
35
40
 
36
41
  Usually, the ServerAppIo API calls this to schedule instructions.
@@ -48,7 +53,7 @@ class LinkState(CoreState): # pylint: disable=R0904
48
53
  """
49
54
 
50
55
  @abc.abstractmethod
51
- def get_message_ins(self, node_id: int, limit: Optional[int]) -> list[Message]:
56
+ def get_message_ins(self, node_id: int, limit: int | None) -> list[Message]:
52
57
  """Get zero or more `Message` objects for the provided `node_id`.
53
58
 
54
59
  Usually, the Fleet API calls this for Nodes planning to work on one or more
@@ -63,7 +68,7 @@ class LinkState(CoreState): # pylint: disable=R0904
63
68
  """
64
69
 
65
70
  @abc.abstractmethod
66
- def store_message_res(self, message: Message) -> Optional[str]:
71
+ def store_message_res(self, message: Message) -> str | None:
67
72
  """Store one Message.
68
73
 
69
74
  Usually, the Fleet API calls this for Nodes returning results.
@@ -131,7 +136,11 @@ class LinkState(CoreState): # pylint: disable=R0904
131
136
 
132
137
  @abc.abstractmethod
133
138
  def create_node(
134
- self, owner_aid: str, public_key: bytes, heartbeat_interval: float
139
+ self,
140
+ owner_aid: str,
141
+ owner_name: str,
142
+ public_key: bytes,
143
+ heartbeat_interval: float,
135
144
  ) -> int:
136
145
  """Create, store in the link state, and return `node_id`."""
137
146
 
@@ -189,7 +198,7 @@ class LinkState(CoreState): # pylint: disable=R0904
189
198
  """
190
199
 
191
200
  @abc.abstractmethod
192
- def get_node_id_by_public_key(self, public_key: bytes) -> Optional[int]:
201
+ def get_node_id_by_public_key(self, public_key: bytes) -> int | None:
193
202
  """Get `node_id` for the specified `public_key` if it exists and is not deleted.
194
203
 
195
204
  Parameters
@@ -208,9 +217,9 @@ class LinkState(CoreState): # pylint: disable=R0904
208
217
  def get_node_info(
209
218
  self,
210
219
  *,
211
- node_ids: Optional[Sequence[int]] = None,
212
- owner_aids: Optional[Sequence[str]] = None,
213
- statuses: Optional[Sequence[str]] = None,
220
+ node_ids: Sequence[int] | None = None,
221
+ owner_aids: Sequence[str] | None = None,
222
+ statuses: Sequence[str] | None = None,
214
223
  ) -> Sequence[NodeInfo]:
215
224
  """Retrieve information about nodes based on the specified filters.
216
225
 
@@ -259,24 +268,54 @@ class LinkState(CoreState): # pylint: disable=R0904
259
268
  @abc.abstractmethod
260
269
  def create_run( # pylint: disable=too-many-arguments,too-many-positional-arguments
261
270
  self,
262
- fab_id: Optional[str],
263
- fab_version: Optional[str],
264
- fab_hash: Optional[str],
271
+ fab_id: str | None,
272
+ fab_version: str | None,
273
+ fab_hash: str | None,
265
274
  override_config: UserConfig,
275
+ federation: str,
266
276
  federation_options: ConfigRecord,
267
- flwr_aid: Optional[str],
277
+ flwr_aid: str | None,
268
278
  ) -> int:
269
- """Create a new run for the specified `fab_hash`."""
279
+ """Create a new run.
280
+
281
+ Parameters
282
+ ----------
283
+ fab_id : Optional[str]
284
+ The ID of the FAB, of format `<publisher>/<app-name>`.
285
+ fab_version : Optional[str]
286
+ The version of the FAB.
287
+ fab_hash : Optional[str]
288
+ The SHA256 hex hash of the FAB.
289
+ override_config : UserConfig
290
+ Configuration overrides for the run config.
291
+ federation : str
292
+ The federation this run belongs to.
293
+ federation_options : ConfigRecord
294
+ Federation configurations. For now, only `num-supernodes` for
295
+ the simulation runtime.
296
+ flwr_aid : Optional[str]
297
+ Flower Account ID of the creator.
298
+
299
+ Returns
300
+ -------
301
+ int
302
+ The run ID of the newly created run.
303
+
304
+ Notes
305
+ -----
306
+ This method will not verify if the account has permission to create
307
+ a run in the federation.
308
+ """
270
309
 
271
310
  @abc.abstractmethod
272
- def get_run_ids(self, flwr_aid: Optional[str]) -> set[int]:
311
+ def get_run_ids(self, flwr_aid: str | None) -> set[int]:
273
312
  """Retrieve all run IDs if `flwr_aid` is not specified.
274
313
 
275
314
  Otherwise, retrieve all run IDs for the specified `flwr_aid`.
276
315
  """
277
316
 
278
317
  @abc.abstractmethod
279
- def get_run(self, run_id: int) -> Optional[Run]:
318
+ def get_run(self, run_id: int) -> Run | None:
280
319
  """Retrieve information about the run with the specified `run_id`.
281
320
 
282
321
  Parameters
@@ -328,7 +367,7 @@ class LinkState(CoreState): # pylint: disable=R0904
328
367
  """
329
368
 
330
369
  @abc.abstractmethod
331
- def get_pending_run_id(self) -> Optional[int]:
370
+ def get_pending_run_id(self) -> int | None:
332
371
  """Get the `run_id` of a run with `Status.PENDING` status.
333
372
 
334
373
  Returns
@@ -339,7 +378,7 @@ class LinkState(CoreState): # pylint: disable=R0904
339
378
  """
340
379
 
341
380
  @abc.abstractmethod
342
- def get_federation_options(self, run_id: int) -> Optional[ConfigRecord]:
381
+ def get_federation_options(self, run_id: int) -> ConfigRecord | None:
343
382
  """Retrieve the federation options for the specified `run_id`.
344
383
 
345
384
  Parameters
@@ -380,30 +419,7 @@ class LinkState(CoreState): # pylint: disable=R0904
380
419
  """
381
420
 
382
421
  @abc.abstractmethod
383
- def acknowledge_app_heartbeat(self, run_id: int, heartbeat_interval: float) -> bool:
384
- """Acknowledge a heartbeat received from a ServerApp for a given run.
385
-
386
- A run with status `"running"` is considered alive as long as it sends heartbeats
387
- within the tolerated interval: HEARTBEAT_PATIENCE × heartbeat_interval.
388
- HEARTBEAT_PATIENCE = N allows for N-1 missed heartbeat before the run is
389
- marked as `"completed:failed"`.
390
-
391
- Parameters
392
- ----------
393
- run_id : int
394
- The `run_id` from which the heartbeat was received.
395
- heartbeat_interval : float
396
- The interval (in seconds) from the current timestamp within which the next
397
- heartbeat from the ServerApp for this run must be received.
398
-
399
- Returns
400
- -------
401
- is_acknowledged : bool
402
- True if the heartbeat is successfully acknowledged; otherwise, False.
403
- """
404
-
405
- @abc.abstractmethod
406
- def get_serverapp_context(self, run_id: int) -> Optional[Context]:
422
+ def get_serverapp_context(self, run_id: int) -> Context | None:
407
423
  """Get the context for the specified `run_id`.
408
424
 
409
425
  Parameters
@@ -444,7 +460,7 @@ class LinkState(CoreState): # pylint: disable=R0904
444
460
 
445
461
  @abc.abstractmethod
446
462
  def get_serverapp_log(
447
- self, run_id: int, after_timestamp: Optional[float]
463
+ self, run_id: int, after_timestamp: float | None
448
464
  ) -> tuple[str, float]:
449
465
  """Get the ServerApp logs for the specified `run_id`.
450
466
 
@@ -464,3 +480,35 @@ class LinkState(CoreState): # pylint: disable=R0904
464
480
  - The timestamp of the latest log entry in the returned logs.
465
481
  Returns `0` if no logs are returned.
466
482
  """
483
+
484
+ @abc.abstractmethod
485
+ def store_traffic(self, run_id: int, *, bytes_sent: int, bytes_recv: int) -> None:
486
+ """Store traffic data for the specified `run_id`.
487
+
488
+ Parameters
489
+ ----------
490
+ run_id : int
491
+ The identifier of the run for which to store traffic data.
492
+ bytes_sent : int
493
+ The number of bytes pulled by SuperNodes from the SuperLink to add to the
494
+ run's total.
495
+ bytes_recv : int
496
+ The number of bytes received by SuperLink from SuperNodes to add to the
497
+ run's total.
498
+ """
499
+
500
+ @abc.abstractmethod
501
+ def add_clientapp_runtime(self, run_id: int, runtime: float) -> None:
502
+ """Add ClientApp runtime to the cumulative total for the specified `run_id`.
503
+
504
+ This method accumulates the runtime by adding the provided value to the
505
+ existing total runtime for the run. Multiple ClientApps can contribute
506
+ to the same run's total runtime.
507
+
508
+ Parameters
509
+ ----------
510
+ run_id : int
511
+ The identifier of the run for which to store each ClientApp's runtime.
512
+ runtime : float
513
+ The runtime in seconds to add to the `run_id`'s cumulative total.
514
+ """
@@ -16,10 +16,11 @@
16
16
 
17
17
 
18
18
  from logging import DEBUG
19
- from typing import Optional
20
19
 
21
20
  from flwr.common.logger import log
22
21
  from flwr.supercore.constant import FLWR_IN_MEMORY_DB_NAME
22
+ from flwr.supercore.object_store import ObjectStoreFactory
23
+ from flwr.superlink.federation import FederationManager
23
24
 
24
25
  from .in_memory_linkstate import InMemoryLinkState
25
26
  from .linkstate import LinkState
@@ -36,23 +37,39 @@ class LinkStateFactory:
36
37
  Note that passing ':memory:' will open a connection to a database that is
37
38
  in RAM, instead of on disk. For more information on special in-memory
38
39
  databases, please refer to https://sqlite.org/inmemorydb.html.
40
+ federation_manager : FederationManager
41
+ An instance of FederationManager to manage federations.
42
+ objectstore_factory : ObjectStoreFactory
43
+ An instance of ObjectStoreFactory to create object stores.
39
44
  """
40
45
 
41
- def __init__(self, database: str) -> None:
46
+ def __init__(
47
+ self,
48
+ database: str,
49
+ federation_manager: FederationManager,
50
+ objectstore_factory: ObjectStoreFactory,
51
+ ) -> None:
42
52
  self.database = database
43
- self.state_instance: Optional[LinkState] = None
53
+ self.state_instance: LinkState | None = None
54
+ self.federation_manager = federation_manager
55
+ self.objectstore_factory = objectstore_factory
44
56
 
45
57
  def state(self) -> LinkState:
46
58
  """Return a State instance and create it, if necessary."""
59
+ # Get the ObjectStore instance
60
+ object_store = self.objectstore_factory.store()
61
+
47
62
  # InMemoryState
48
63
  if self.database == FLWR_IN_MEMORY_DB_NAME:
49
64
  if self.state_instance is None:
50
- self.state_instance = InMemoryLinkState()
65
+ self.state_instance = InMemoryLinkState(
66
+ self.federation_manager, object_store
67
+ )
51
68
  log(DEBUG, "Using InMemoryState")
52
69
  return self.state_instance
53
70
 
54
71
  # SqliteState
55
- state = SqliteLinkState(self.database)
72
+ state = SqliteLinkState(self.database, self.federation_manager, object_store)
56
73
  state.initialize()
57
74
  log(DEBUG, "Using SqliteState")
58
75
  return state