flwr-nightly 1.23.0.dev20250930__py3-none-any.whl → 1.26.0.dev20260121__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 (375) hide show
  1. flwr/__init__.py +17 -6
  2. flwr/app/__init__.py +4 -1
  3. flwr/app/error.py +2 -2
  4. flwr/app/exception.py +3 -3
  5. flwr/app/message_type.py +29 -0
  6. flwr/app/metadata.py +5 -2
  7. flwr/app/user_config.py +19 -0
  8. flwr/cli/app.py +62 -9
  9. flwr/cli/{new/templates/app/code → app_cmd}/__init__.py +9 -1
  10. flwr/cli/app_cmd/publish.py +285 -0
  11. flwr/cli/app_cmd/review.py +262 -0
  12. flwr/cli/auth_plugin/__init__.py +13 -6
  13. flwr/cli/auth_plugin/auth_plugin.py +26 -15
  14. flwr/cli/auth_plugin/noop_auth_plugin.py +101 -0
  15. flwr/cli/auth_plugin/oidc_cli_plugin.py +52 -32
  16. flwr/cli/build.py +166 -53
  17. flwr/cli/{cli_user_auth_interceptor.py → cli_account_auth_interceptor.py} +27 -10
  18. flwr/cli/config/__init__.py +21 -0
  19. flwr/cli/config/ls.py +104 -0
  20. flwr/cli/config_migration.py +300 -0
  21. flwr/cli/config_utils.py +154 -13
  22. flwr/cli/constant.py +67 -0
  23. flwr/cli/{new/templates/app/code/flwr_tune → federation}/__init__.py +8 -1
  24. flwr/cli/federation/ls.py +361 -0
  25. flwr/cli/flower_config.py +447 -0
  26. flwr/cli/install.py +91 -13
  27. flwr/cli/log.py +65 -36
  28. flwr/cli/login/login.py +41 -27
  29. flwr/cli/ls.py +232 -158
  30. flwr/cli/new/new.py +188 -244
  31. flwr/cli/pull.py +25 -34
  32. flwr/cli/run/run.py +106 -74
  33. flwr/cli/run_utils.py +148 -0
  34. flwr/cli/stop.py +46 -37
  35. flwr/cli/supernode/__init__.py +25 -0
  36. flwr/cli/supernode/ls.py +273 -0
  37. flwr/cli/supernode/register.py +190 -0
  38. flwr/cli/supernode/unregister.py +140 -0
  39. flwr/cli/typing.py +211 -0
  40. flwr/cli/utils.py +428 -80
  41. flwr/client/__init__.py +2 -1
  42. flwr/client/dpfedavg_numpy_client.py +4 -1
  43. flwr/client/grpc_adapter_client/connection.py +14 -17
  44. flwr/client/grpc_rere_client/connection.py +73 -43
  45. flwr/client/grpc_rere_client/grpc_adapter.py +35 -15
  46. flwr/client/grpc_rere_client/{client_interceptor.py → node_auth_client_interceptor.py} +5 -7
  47. flwr/client/message_handler/message_handler.py +4 -3
  48. flwr/client/mod/centraldp_mods.py +1 -1
  49. flwr/client/mod/localdp_mod.py +1 -1
  50. flwr/client/mod/secure_aggregation/secaggplus_mod.py +11 -9
  51. flwr/client/numpy_client.py +1 -1
  52. flwr/client/rest_client/connection.py +99 -54
  53. flwr/client/run_info_store.py +6 -6
  54. flwr/client/typing.py +1 -1
  55. flwr/clientapp/__init__.py +1 -2
  56. flwr/{client → clientapp}/client_app.py +11 -11
  57. flwr/clientapp/mod/centraldp_mods.py +16 -17
  58. flwr/clientapp/mod/localdp_mod.py +8 -9
  59. flwr/clientapp/typing.py +1 -1
  60. flwr/{client/clientapp → clientapp}/utils.py +4 -4
  61. flwr/common/__init__.py +3 -2
  62. flwr/common/args.py +3 -4
  63. flwr/common/config.py +15 -17
  64. flwr/common/constant.py +56 -28
  65. flwr/common/context.py +2 -1
  66. flwr/common/differential_privacy.py +3 -4
  67. flwr/common/event_log_plugin/event_log_plugin.py +3 -4
  68. flwr/common/exit/exit.py +16 -3
  69. flwr/common/exit/exit_code.py +39 -10
  70. flwr/common/exit/exit_handler.py +6 -2
  71. flwr/common/exit/signal_handler.py +5 -5
  72. flwr/common/grpc.py +8 -7
  73. flwr/common/inflatable_protobuf_utils.py +1 -1
  74. flwr/common/inflatable_utils.py +48 -31
  75. flwr/common/logger.py +19 -19
  76. flwr/common/message.py +5 -5
  77. flwr/common/object_ref.py +7 -7
  78. flwr/common/record/array.py +6 -6
  79. flwr/common/record/arrayrecord.py +18 -21
  80. flwr/common/record/configrecord.py +3 -3
  81. flwr/common/record/recorddict.py +5 -5
  82. flwr/common/record/typeddict.py +9 -2
  83. flwr/common/recorddict_compat.py +7 -10
  84. flwr/common/retry_invoker.py +20 -20
  85. flwr/common/secure_aggregation/crypto/symmetric_encryption.py +1 -89
  86. flwr/common/secure_aggregation/ndarrays_arithmetic.py +8 -5
  87. flwr/common/serde.py +22 -11
  88. flwr/common/serde_utils.py +2 -2
  89. flwr/common/telemetry.py +10 -6
  90. flwr/common/typing.py +65 -44
  91. flwr/compat/client/app.py +45 -47
  92. flwr/compat/client/grpc_client/connection.py +15 -14
  93. flwr/compat/common/constant.py +29 -0
  94. flwr/compat/server/app.py +6 -7
  95. flwr/proto/appio_pb2.py +13 -3
  96. flwr/proto/appio_pb2.pyi +134 -65
  97. flwr/proto/appio_pb2_grpc.py +20 -0
  98. flwr/proto/appio_pb2_grpc.pyi +27 -0
  99. flwr/proto/clientappio_pb2.py +17 -7
  100. flwr/proto/clientappio_pb2.pyi +15 -0
  101. flwr/proto/clientappio_pb2_grpc.py +206 -40
  102. flwr/proto/clientappio_pb2_grpc.pyi +168 -53
  103. flwr/proto/control_pb2.py +72 -40
  104. flwr/proto/control_pb2.pyi +319 -87
  105. flwr/proto/control_pb2_grpc.py +339 -28
  106. flwr/proto/control_pb2_grpc.pyi +209 -37
  107. flwr/proto/error_pb2.py +13 -3
  108. flwr/proto/error_pb2.pyi +24 -6
  109. flwr/proto/error_pb2_grpc.py +20 -0
  110. flwr/proto/error_pb2_grpc.pyi +27 -0
  111. flwr/proto/fab_pb2.py +24 -10
  112. flwr/proto/fab_pb2.pyi +68 -20
  113. flwr/proto/fab_pb2_grpc.py +20 -0
  114. flwr/proto/fab_pb2_grpc.pyi +27 -0
  115. flwr/proto/federation_pb2.py +38 -0
  116. flwr/proto/federation_pb2.pyi +56 -0
  117. flwr/proto/federation_pb2_grpc.py +24 -0
  118. flwr/proto/federation_pb2_grpc.pyi +31 -0
  119. flwr/proto/fleet_pb2.py +45 -27
  120. flwr/proto/fleet_pb2.pyi +190 -70
  121. flwr/proto/fleet_pb2_grpc.py +277 -66
  122. flwr/proto/fleet_pb2_grpc.pyi +201 -55
  123. flwr/proto/grpcadapter_pb2.py +14 -4
  124. flwr/proto/grpcadapter_pb2.pyi +38 -16
  125. flwr/proto/grpcadapter_pb2_grpc.py +35 -4
  126. flwr/proto/grpcadapter_pb2_grpc.pyi +38 -7
  127. flwr/proto/heartbeat_pb2.py +17 -7
  128. flwr/proto/heartbeat_pb2.pyi +51 -22
  129. flwr/proto/heartbeat_pb2_grpc.py +20 -0
  130. flwr/proto/heartbeat_pb2_grpc.pyi +27 -0
  131. flwr/proto/log_pb2.py +13 -3
  132. flwr/proto/log_pb2.pyi +34 -11
  133. flwr/proto/log_pb2_grpc.py +20 -0
  134. flwr/proto/log_pb2_grpc.pyi +27 -0
  135. flwr/proto/message_pb2.py +15 -5
  136. flwr/proto/message_pb2.pyi +154 -86
  137. flwr/proto/message_pb2_grpc.py +20 -0
  138. flwr/proto/message_pb2_grpc.pyi +27 -0
  139. flwr/proto/node_pb2.py +16 -4
  140. flwr/proto/node_pb2.pyi +77 -4
  141. flwr/proto/node_pb2_grpc.py +20 -0
  142. flwr/proto/node_pb2_grpc.pyi +27 -0
  143. flwr/proto/recorddict_pb2.py +13 -3
  144. flwr/proto/recorddict_pb2.pyi +184 -107
  145. flwr/proto/recorddict_pb2_grpc.py +20 -0
  146. flwr/proto/recorddict_pb2_grpc.pyi +27 -0
  147. flwr/proto/run_pb2.py +40 -31
  148. flwr/proto/run_pb2.pyi +158 -84
  149. flwr/proto/run_pb2_grpc.py +20 -0
  150. flwr/proto/run_pb2_grpc.pyi +27 -0
  151. flwr/proto/serverappio_pb2.py +13 -3
  152. flwr/proto/serverappio_pb2.pyi +32 -8
  153. flwr/proto/serverappio_pb2_grpc.py +246 -65
  154. flwr/proto/serverappio_pb2_grpc.pyi +221 -85
  155. flwr/proto/simulationio_pb2.py +16 -8
  156. flwr/proto/simulationio_pb2.pyi +15 -0
  157. flwr/proto/simulationio_pb2_grpc.py +162 -41
  158. flwr/proto/simulationio_pb2_grpc.pyi +149 -55
  159. flwr/proto/transport_pb2.py +20 -10
  160. flwr/proto/transport_pb2.pyi +249 -160
  161. flwr/proto/transport_pb2_grpc.py +35 -4
  162. flwr/proto/transport_pb2_grpc.pyi +38 -8
  163. flwr/server/app.py +175 -128
  164. flwr/server/client_manager.py +4 -5
  165. flwr/server/client_proxy.py +10 -11
  166. flwr/server/compat/app.py +4 -5
  167. flwr/server/compat/app_utils.py +2 -1
  168. flwr/server/compat/grid_client_proxy.py +12 -13
  169. flwr/server/compat/legacy_context.py +3 -4
  170. flwr/server/fleet_event_log_interceptor.py +2 -1
  171. flwr/server/grid/grid.py +2 -3
  172. flwr/server/grid/grpc_grid.py +12 -10
  173. flwr/server/grid/inmemory_grid.py +4 -4
  174. flwr/server/run_serverapp.py +2 -3
  175. flwr/server/server.py +34 -39
  176. flwr/server/server_app.py +7 -8
  177. flwr/server/server_config.py +1 -2
  178. flwr/server/serverapp/app.py +34 -28
  179. flwr/server/serverapp_components.py +4 -5
  180. flwr/server/strategy/aggregate.py +9 -8
  181. flwr/server/strategy/bulyan.py +13 -11
  182. flwr/server/strategy/dp_adaptive_clipping.py +16 -20
  183. flwr/server/strategy/dp_fixed_clipping.py +12 -17
  184. flwr/server/strategy/dpfedavg_adaptive.py +3 -4
  185. flwr/server/strategy/dpfedavg_fixed.py +6 -10
  186. flwr/server/strategy/fault_tolerant_fedavg.py +14 -13
  187. flwr/server/strategy/fedadagrad.py +18 -14
  188. flwr/server/strategy/fedadam.py +16 -14
  189. flwr/server/strategy/fedavg.py +16 -17
  190. flwr/server/strategy/fedavg_android.py +15 -15
  191. flwr/server/strategy/fedavgm.py +21 -18
  192. flwr/server/strategy/fedmedian.py +2 -3
  193. flwr/server/strategy/fedopt.py +11 -10
  194. flwr/server/strategy/fedprox.py +10 -9
  195. flwr/server/strategy/fedtrimmedavg.py +12 -11
  196. flwr/server/strategy/fedxgb_bagging.py +13 -11
  197. flwr/server/strategy/fedxgb_cyclic.py +6 -6
  198. flwr/server/strategy/fedxgb_nn_avg.py +4 -4
  199. flwr/server/strategy/fedyogi.py +16 -14
  200. flwr/server/strategy/krum.py +12 -11
  201. flwr/server/strategy/qfedavg.py +16 -15
  202. flwr/server/strategy/strategy.py +6 -9
  203. flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +20 -9
  204. flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +1 -2
  205. flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +3 -4
  206. flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +10 -12
  207. flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +1 -3
  208. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +136 -42
  209. flwr/server/superlink/fleet/grpc_rere/{server_interceptor.py → node_auth_server_interceptor.py} +28 -50
  210. flwr/server/superlink/fleet/message_handler/message_handler.py +141 -51
  211. flwr/server/superlink/fleet/rest_rere/rest_api.py +54 -33
  212. flwr/server/superlink/fleet/vce/backend/backend.py +2 -2
  213. flwr/server/superlink/fleet/vce/backend/raybackend.py +6 -6
  214. flwr/server/superlink/fleet/vce/vce_api.py +32 -13
  215. flwr/server/superlink/linkstate/__init__.py +2 -0
  216. flwr/server/superlink/linkstate/in_memory_linkstate.py +293 -208
  217. flwr/server/superlink/linkstate/linkstate.py +176 -64
  218. flwr/server/superlink/linkstate/linkstate_factory.py +24 -6
  219. flwr/server/superlink/linkstate/sql_linkstate.py +221 -0
  220. flwr/server/superlink/linkstate/sqlite_linkstate.py +743 -648
  221. flwr/server/superlink/linkstate/utils.py +11 -62
  222. flwr/server/superlink/serverappio/serverappio_grpc.py +1 -2
  223. flwr/server/superlink/serverappio/serverappio_servicer.py +28 -23
  224. flwr/server/superlink/simulation/simulationio_grpc.py +1 -2
  225. flwr/server/superlink/simulation/simulationio_servicer.py +19 -14
  226. flwr/server/superlink/utils.py +4 -6
  227. flwr/server/typing.py +1 -1
  228. flwr/server/utils/tensorboard.py +15 -8
  229. flwr/server/utils/validator.py +2 -3
  230. flwr/server/workflow/default_workflows.py +7 -6
  231. flwr/server/workflow/secure_aggregation/secagg_workflow.py +2 -4
  232. flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +13 -11
  233. flwr/serverapp/strategy/bulyan.py +16 -15
  234. flwr/serverapp/strategy/dp_adaptive_clipping.py +12 -11
  235. flwr/serverapp/strategy/dp_fixed_clipping.py +11 -14
  236. flwr/serverapp/strategy/fedadagrad.py +10 -11
  237. flwr/serverapp/strategy/fedadam.py +10 -11
  238. flwr/serverapp/strategy/fedavg.py +10 -11
  239. flwr/serverapp/strategy/fedavgm.py +17 -16
  240. flwr/serverapp/strategy/fedmedian.py +2 -2
  241. flwr/serverapp/strategy/fedopt.py +10 -11
  242. flwr/serverapp/strategy/fedprox.py +7 -8
  243. flwr/serverapp/strategy/fedtrimmedavg.py +9 -9
  244. flwr/serverapp/strategy/fedxgb_bagging.py +3 -3
  245. flwr/serverapp/strategy/fedxgb_cyclic.py +10 -10
  246. flwr/serverapp/strategy/fedyogi.py +9 -11
  247. flwr/serverapp/strategy/krum.py +7 -7
  248. flwr/serverapp/strategy/multikrum.py +9 -9
  249. flwr/serverapp/strategy/qfedavg.py +17 -16
  250. flwr/serverapp/strategy/strategy.py +6 -9
  251. flwr/serverapp/strategy/strategy_utils.py +7 -8
  252. flwr/simulation/app.py +46 -42
  253. flwr/simulation/legacy_app.py +12 -12
  254. flwr/simulation/ray_transport/ray_actor.py +11 -12
  255. flwr/simulation/ray_transport/ray_client_proxy.py +14 -19
  256. flwr/simulation/run_simulation.py +46 -44
  257. flwr/simulation/simulationio_connection.py +4 -4
  258. flwr/{common → supercore}/address.py +1 -37
  259. flwr/supercore/cli/flower_superexec.py +3 -4
  260. flwr/supercore/constant.py +69 -0
  261. flwr/supercore/corestate/corestate.py +24 -3
  262. flwr/supercore/corestate/in_memory_corestate.py +138 -0
  263. flwr/supercore/corestate/sql_corestate.py +153 -0
  264. flwr/supercore/corestate/sqlite_corestate.py +157 -0
  265. flwr/supercore/credential_store/__init__.py +33 -0
  266. flwr/supercore/credential_store/credential_store.py +34 -0
  267. flwr/supercore/credential_store/file_credential_store.py +76 -0
  268. flwr/{common → supercore}/date.py +0 -11
  269. flwr/supercore/ffs/disk_ffs.py +1 -2
  270. flwr/supercore/ffs/ffs.py +1 -2
  271. flwr/supercore/ffs/ffs_factory.py +1 -2
  272. flwr/{common → supercore}/heartbeat.py +20 -25
  273. flwr/supercore/object_store/in_memory_object_store.py +1 -6
  274. flwr/supercore/object_store/object_store.py +1 -2
  275. flwr/supercore/object_store/object_store_factory.py +27 -8
  276. flwr/supercore/object_store/sqlite_object_store.py +253 -0
  277. flwr/{cli/new/templates/app → supercore/primitives}/__init__.py +1 -1
  278. flwr/supercore/primitives/asymmetric.py +117 -0
  279. flwr/supercore/primitives/asymmetric_ed25519.py +175 -0
  280. flwr/supercore/sql_mixin.py +292 -0
  281. flwr/supercore/sqlite_mixin.py +156 -0
  282. flwr/{client/clientapp → supercore/state}/__init__.py +2 -2
  283. flwr/supercore/state/schema/README.md +125 -0
  284. flwr/{cli/new/templates → supercore/state/schema}/__init__.py +2 -2
  285. flwr/supercore/state/schema/corestate_tables.py +36 -0
  286. flwr/supercore/state/schema/linkstate_tables.py +152 -0
  287. flwr/supercore/state/schema/objectstore_tables.py +90 -0
  288. flwr/supercore/superexec/plugin/base_exec_plugin.py +1 -2
  289. flwr/supercore/superexec/plugin/exec_plugin.py +3 -3
  290. flwr/supercore/superexec/run_superexec.py +9 -13
  291. flwr/supercore/utils.py +224 -0
  292. flwr/superlink/artifact_provider/artifact_provider.py +1 -2
  293. flwr/superlink/auth_plugin/__init__.py +5 -2
  294. flwr/superlink/auth_plugin/auth_plugin.py +20 -19
  295. flwr/superlink/auth_plugin/noop_auth_plugin.py +84 -0
  296. flwr/superlink/federation/__init__.py +24 -0
  297. flwr/superlink/federation/federation_manager.py +64 -0
  298. flwr/superlink/federation/noop_federation_manager.py +71 -0
  299. flwr/superlink/servicer/control/{control_user_auth_interceptor.py → control_account_auth_interceptor.py} +41 -32
  300. flwr/superlink/servicer/control/control_event_log_interceptor.py +7 -7
  301. flwr/superlink/servicer/control/control_grpc.py +20 -17
  302. flwr/superlink/servicer/control/control_license_interceptor.py +3 -3
  303. flwr/superlink/servicer/control/control_servicer.py +328 -68
  304. flwr/supernode/cli/flower_supernode.py +74 -26
  305. flwr/supernode/nodestate/in_memory_nodestate.py +121 -49
  306. flwr/supernode/nodestate/nodestate.py +52 -8
  307. flwr/supernode/nodestate/nodestate_factory.py +7 -4
  308. flwr/supernode/runtime/run_clientapp.py +43 -24
  309. flwr/supernode/servicer/clientappio/clientappio_servicer.py +48 -10
  310. flwr/supernode/start_client_internal.py +185 -57
  311. {flwr_nightly-1.23.0.dev20250930.dist-info → flwr_nightly-1.26.0.dev20260121.dist-info}/METADATA +10 -11
  312. flwr_nightly-1.26.0.dev20260121.dist-info/RECORD +411 -0
  313. flwr/cli/new/templates/app/.gitignore.tpl +0 -163
  314. flwr/cli/new/templates/app/LICENSE.tpl +0 -202
  315. flwr/cli/new/templates/app/README.baseline.md.tpl +0 -127
  316. flwr/cli/new/templates/app/README.flowertune.md.tpl +0 -68
  317. flwr/cli/new/templates/app/README.md.tpl +0 -37
  318. flwr/cli/new/templates/app/code/__init__.baseline.py.tpl +0 -1
  319. flwr/cli/new/templates/app/code/__init__.py.tpl +0 -1
  320. flwr/cli/new/templates/app/code/__init__.pytorch_legacy_api.py.tpl +0 -1
  321. flwr/cli/new/templates/app/code/client.baseline.py.tpl +0 -75
  322. flwr/cli/new/templates/app/code/client.huggingface.py.tpl +0 -93
  323. flwr/cli/new/templates/app/code/client.jax.py.tpl +0 -71
  324. flwr/cli/new/templates/app/code/client.mlx.py.tpl +0 -102
  325. flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -46
  326. flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -80
  327. flwr/cli/new/templates/app/code/client.pytorch_legacy_api.py.tpl +0 -55
  328. flwr/cli/new/templates/app/code/client.sklearn.py.tpl +0 -108
  329. flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -82
  330. flwr/cli/new/templates/app/code/client.xgboost.py.tpl +0 -110
  331. flwr/cli/new/templates/app/code/dataset.baseline.py.tpl +0 -36
  332. flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +0 -92
  333. flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +0 -87
  334. flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +0 -56
  335. flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +0 -73
  336. flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +0 -78
  337. flwr/cli/new/templates/app/code/model.baseline.py.tpl +0 -66
  338. flwr/cli/new/templates/app/code/server.baseline.py.tpl +0 -43
  339. flwr/cli/new/templates/app/code/server.huggingface.py.tpl +0 -42
  340. flwr/cli/new/templates/app/code/server.jax.py.tpl +0 -39
  341. flwr/cli/new/templates/app/code/server.mlx.py.tpl +0 -41
  342. flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -38
  343. flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -41
  344. flwr/cli/new/templates/app/code/server.pytorch_legacy_api.py.tpl +0 -31
  345. flwr/cli/new/templates/app/code/server.sklearn.py.tpl +0 -44
  346. flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -38
  347. flwr/cli/new/templates/app/code/server.xgboost.py.tpl +0 -56
  348. flwr/cli/new/templates/app/code/strategy.baseline.py.tpl +0 -1
  349. flwr/cli/new/templates/app/code/task.huggingface.py.tpl +0 -98
  350. flwr/cli/new/templates/app/code/task.jax.py.tpl +0 -57
  351. flwr/cli/new/templates/app/code/task.mlx.py.tpl +0 -102
  352. flwr/cli/new/templates/app/code/task.numpy.py.tpl +0 -7
  353. flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -98
  354. flwr/cli/new/templates/app/code/task.pytorch_legacy_api.py.tpl +0 -111
  355. flwr/cli/new/templates/app/code/task.sklearn.py.tpl +0 -67
  356. flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +0 -52
  357. flwr/cli/new/templates/app/code/task.xgboost.py.tpl +0 -67
  358. flwr/cli/new/templates/app/code/utils.baseline.py.tpl +0 -1
  359. flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +0 -146
  360. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +0 -80
  361. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +0 -65
  362. flwr/cli/new/templates/app/pyproject.jax.toml.tpl +0 -52
  363. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +0 -56
  364. flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +0 -49
  365. flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +0 -53
  366. flwr/cli/new/templates/app/pyproject.pytorch_legacy_api.toml.tpl +0 -53
  367. flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +0 -52
  368. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +0 -53
  369. flwr/cli/new/templates/app/pyproject.xgboost.toml.tpl +0 -61
  370. flwr/common/pyproject.py +0 -42
  371. flwr/supercore/object_store/utils.py +0 -43
  372. flwr_nightly-1.23.0.dev20250930.dist-info/RECORD +0 -429
  373. /flwr/{common → supercore}/version.py +0 -0
  374. {flwr_nightly-1.23.0.dev20250930.dist-info → flwr_nightly-1.26.0.dev20260121.dist-info}/WHEEL +0 -0
  375. {flwr_nightly-1.23.0.dev20250930.dist-info → flwr_nightly-1.26.0.dev20260121.dist-info}/entry_points.txt +0 -0
@@ -15,10 +15,10 @@
15
15
  """Contextmanager for a REST request-response channel to the Flower server."""
16
16
 
17
17
 
18
- from collections.abc import Iterator
18
+ from collections.abc import Callable, Iterator
19
19
  from contextlib import contextmanager
20
20
  from logging import ERROR, WARN
21
- from typing import Callable, Optional, TypeVar, Union
21
+ from typing import TypeVar
22
22
 
23
23
  from cryptography.hazmat.primitives.asymmetric import ec
24
24
  from google.protobuf.message import Message as GrpcMessage
@@ -27,7 +27,6 @@ from requests.exceptions import ConnectionError as RequestsConnectionError
27
27
  from flwr.common import GRPC_MAX_MESSAGE_LENGTH
28
28
  from flwr.common.constant import HEARTBEAT_DEFAULT_INTERVAL
29
29
  from flwr.common.exit import ExitCode, flwr_exit
30
- from flwr.common.heartbeat import HeartbeatSender
31
30
  from flwr.common.inflatable_protobuf_utils import (
32
31
  make_confirm_message_received_fn_protobuf,
33
32
  make_pull_object_fn_protobuf,
@@ -36,18 +35,27 @@ from flwr.common.inflatable_protobuf_utils import (
36
35
  from flwr.common.logger import log
37
36
  from flwr.common.message import Message, remove_content_from_message
38
37
  from flwr.common.retry_invoker import RetryInvoker
39
- from flwr.common.serde import message_from_proto, message_to_proto, run_from_proto
38
+ from flwr.common.serde import (
39
+ fab_from_proto,
40
+ message_from_proto,
41
+ message_to_proto,
42
+ run_from_proto,
43
+ )
40
44
  from flwr.common.typing import Fab, Run
41
45
  from flwr.proto.fab_pb2 import GetFabRequest, GetFabResponse # pylint: disable=E0611
42
46
  from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
43
- CreateNodeRequest,
44
- CreateNodeResponse,
45
- DeleteNodeRequest,
46
- DeleteNodeResponse,
47
+ ActivateNodeRequest,
48
+ ActivateNodeResponse,
49
+ DeactivateNodeRequest,
50
+ DeactivateNodeResponse,
47
51
  PullMessagesRequest,
48
52
  PullMessagesResponse,
49
53
  PushMessagesRequest,
50
54
  PushMessagesResponse,
55
+ RegisterNodeFleetRequest,
56
+ RegisterNodeFleetResponse,
57
+ UnregisterNodeFleetRequest,
58
+ UnregisterNodeFleetResponse,
51
59
  )
52
60
  from flwr.proto.heartbeat_pb2 import ( # pylint: disable=E0611
53
61
  SendNodeHeartbeatRequest,
@@ -64,6 +72,8 @@ from flwr.proto.message_pb2 import ( # pylint: disable=E0611
64
72
  )
65
73
  from flwr.proto.node_pb2 import Node # pylint: disable=E0611
66
74
  from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611
75
+ from flwr.supercore.heartbeat import HeartbeatSender
76
+ from flwr.supercore.primitives.asymmetric import generate_key_pairs, public_key_to_bytes
67
77
 
68
78
  try:
69
79
  import requests
@@ -71,8 +81,10 @@ except ModuleNotFoundError:
71
81
  flwr_exit(ExitCode.COMMON_MISSING_EXTRA_REST)
72
82
 
73
83
 
74
- PATH_CREATE_NODE: str = "api/v0/fleet/create-node"
75
- PATH_DELETE_NODE: str = "api/v0/fleet/delete-node"
84
+ PATH_REGISTER_NODE: str = "/api/v0/fleet/register-node"
85
+ PATH_ACTIVATE_NODE: str = "/api/v0/fleet/activate-node"
86
+ PATH_DEACTIVATE_NODE: str = "/api/v0/fleet/deactivate-node"
87
+ PATH_UNREGISTER_NODE: str = "/api/v0/fleet/unregister-node"
76
88
  PATH_PULL_MESSAGES: str = "/api/v0/fleet/pull-messages"
77
89
  PATH_PUSH_MESSAGES: str = "/api/v0/fleet/push-messages"
78
90
  PATH_PULL_OBJECT: str = "/api/v0/fleet/pull-object"
@@ -91,18 +103,15 @@ def http_request_response( # pylint: disable=R0913,R0914,R0915,R0917
91
103
  insecure: bool, # pylint: disable=unused-argument
92
104
  retry_invoker: RetryInvoker,
93
105
  max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, # pylint: disable=W0613
94
- root_certificates: Optional[
95
- Union[bytes, str]
96
- ] = None, # pylint: disable=unused-argument
97
- authentication_keys: Optional[ # pylint: disable=unused-argument
98
- tuple[ec.EllipticCurvePrivateKey, ec.EllipticCurvePublicKey]
99
- ] = None,
106
+ root_certificates: bytes | str | None = None, # pylint: disable=unused-argument
107
+ authentication_keys: (
108
+ tuple[ec.EllipticCurvePrivateKey, ec.EllipticCurvePublicKey] | None
109
+ ) = None,
100
110
  ) -> Iterator[
101
111
  tuple[
102
- Callable[[], Optional[tuple[Message, ObjectTree]]],
103
- Callable[[Message, ObjectTree], set[str]],
104
- Callable[[], Optional[int]],
105
- Callable[[], None],
112
+ int,
113
+ Callable[[], tuple[Message, ObjectTree] | None],
114
+ Callable[[Message, ObjectTree, float], set[str]],
106
115
  Callable[[int], Run],
107
116
  Callable[[str, int], Fab],
108
117
  Callable[[int, str], bytes],
@@ -134,15 +143,15 @@ def http_request_response( # pylint: disable=R0913,R0914,R0915,R0917
134
143
  connection using the certificates will be established to an SSL-enabled
135
144
  Flower server. Bytes won't work for the REST API.
136
145
  authentication_keys : Optional[Tuple[PrivateKey, PublicKey]] (default: None)
137
- Client authentication is not supported for this transport type.
146
+ SuperNode authentication is not supported for this transport type.
138
147
 
139
148
  Returns
140
149
  -------
141
- receive : Callable
142
- send : Callable
143
- create_node : Optional[Callable]
144
- delete_node : Optional[Callable]
145
- get_run : Optional[Callable]
150
+ node_id : int
151
+ receive : Callable[[], Optional[tuple[Message, ObjectTree]]]
152
+ send : Callable[[Message, ObjectTree, float], set[str]]
153
+ get_run : Callable[[int], Run]
154
+ get_fab : Callable[[str, int], Fab]
146
155
  pull_object : Callable[[str], bytes]
147
156
  push_object : Callable[[str, bytes], None]
148
157
  confirm_message_received : Callable[[str], None]
@@ -161,7 +170,7 @@ def http_request_response( # pylint: disable=R0913,R0914,R0915,R0917
161
170
  # Otherwise any server can fake its identity
162
171
  # Please refer to:
163
172
  # https://requests.readthedocs.io/en/latest/user/advanced/#ssl-cert-verification
164
- verify: Union[bool, str] = True
173
+ verify: bool | str = True
165
174
  if isinstance(root_certificates, str):
166
175
  verify = root_certificates
167
176
  elif isinstance(root_certificates, bytes):
@@ -171,21 +180,28 @@ def http_request_response( # pylint: disable=R0913,R0914,R0915,R0917
171
180
  "must be provided as a string path to the client.",
172
181
  )
173
182
  if authentication_keys is not None:
174
- log(ERROR, "Client authentication is not supported for this transport type.")
183
+ log(ERROR, "SuperNode authentication is not supported for this transport type.")
184
+
185
+ # REST does NOT support node authentication
186
+ self_registered = False
187
+ if authentication_keys is None:
188
+ self_registered = True
189
+ authentication_keys = generate_key_pairs()
190
+ node_pk = public_key_to_bytes(authentication_keys[1])
175
191
 
176
192
  # Shared variables for inner functions
177
- node: Optional[Node] = None
193
+ node: Node | None = None
178
194
 
179
195
  # Remove should_giveup from RetryInvoker as REST does not support gRPC status codes
180
196
  retry_invoker.should_giveup = None
181
197
 
182
198
  ###########################################################################
183
- # heartbeat/create_node/delete_node/receive/send/get_run functions
199
+ # SuperNode functions
184
200
  ###########################################################################
185
201
 
186
202
  def _request(
187
203
  req: GrpcMessage, res_type: type[T], api_path: str, retry: bool = True
188
- ) -> Optional[T]:
204
+ ) -> T | None:
189
205
  # Serialize the request
190
206
  req_bytes = req.SerializeToString()
191
207
 
@@ -290,23 +306,35 @@ def http_request_response( # pylint: disable=R0913,R0914,R0915,R0917
290
306
 
291
307
  heartbeat_sender = HeartbeatSender(send_node_heartbeat)
292
308
 
293
- def create_node() -> Optional[int]:
294
- """Set create_node."""
295
- req = CreateNodeRequest(heartbeat_interval=HEARTBEAT_DEFAULT_INTERVAL)
309
+ def register_node() -> None:
310
+ """Register node with SuperLink."""
311
+ req = RegisterNodeFleetRequest(public_key=node_pk)
296
312
 
297
313
  # Send the request
298
- res = _request(req, CreateNodeResponse, PATH_CREATE_NODE)
314
+ res = _request(req, RegisterNodeFleetResponse, PATH_REGISTER_NODE)
299
315
  if res is None:
300
- return None
316
+ raise RuntimeError("Failed to register node")
317
+
318
+ def activate_node() -> int:
319
+ """Activate node and start heartbeat."""
320
+ req = ActivateNodeRequest(
321
+ public_key=node_pk,
322
+ heartbeat_interval=HEARTBEAT_DEFAULT_INTERVAL,
323
+ )
324
+
325
+ # Send the request
326
+ res = _request(req, ActivateNodeResponse, PATH_ACTIVATE_NODE)
327
+ if res is None:
328
+ raise RuntimeError("Failed to activate node")
301
329
 
302
330
  # Remember the node and start the heartbeat sender
303
331
  nonlocal node
304
- node = res.node
332
+ node = Node(node_id=res.node_id)
305
333
  heartbeat_sender.start()
306
334
  return node.node_id
307
335
 
308
- def delete_node() -> None:
309
- """Set delete_node."""
336
+ def deactivate_node() -> None:
337
+ """Deactivate node and stop heartbeat."""
310
338
  nonlocal node
311
339
  if node is None:
312
340
  raise RuntimeError("Node instance missing")
@@ -314,18 +342,32 @@ def http_request_response( # pylint: disable=R0913,R0914,R0915,R0917
314
342
  # Stop the heartbeat sender
315
343
  heartbeat_sender.stop()
316
344
 
317
- # Send DeleteNode request
318
- req = DeleteNodeRequest(node=node)
345
+ # Send DeactivateNode request
346
+ req = DeactivateNodeRequest(node_id=node.node_id)
347
+
348
+ # Send the request
349
+ res = _request(req, DeactivateNodeResponse, PATH_DEACTIVATE_NODE)
350
+ if res is None:
351
+ raise RuntimeError("Failed to deactivate node")
352
+
353
+ def unregister_node() -> None:
354
+ """Unregister node from SuperLink."""
355
+ nonlocal node
356
+ if node is None:
357
+ raise RuntimeError("Node instance missing")
358
+
359
+ # Send UnregisterNode request
360
+ req = UnregisterNodeFleetRequest(node_id=node.node_id)
319
361
 
320
362
  # Send the request
321
- res = _request(req, DeleteNodeResponse, PATH_DELETE_NODE)
363
+ res = _request(req, UnregisterNodeFleetResponse, PATH_UNREGISTER_NODE)
322
364
  if res is None:
323
- return
365
+ raise RuntimeError("Failed to unregister node")
324
366
 
325
367
  # Cleanup
326
368
  node = None
327
369
 
328
- def receive() -> Optional[tuple[Message, ObjectTree]]:
370
+ def receive() -> tuple[Message, ObjectTree] | None:
329
371
  """Pull a message with its ObjectTree from SuperLink."""
330
372
  # Get Node
331
373
  if node is None:
@@ -351,12 +393,13 @@ def http_request_response( # pylint: disable=R0913,R0914,R0915,R0917
351
393
  # Return the Message and its object tree
352
394
  return in_message, object_tree
353
395
 
354
- def send(message: Message, object_tree: ObjectTree) -> set[str]:
396
+ def send(
397
+ message: Message, object_tree: ObjectTree, clientapp_runtime: float
398
+ ) -> set[str]:
355
399
  """Send the message with its ObjectTree to SuperLink."""
356
400
  # Get Node
357
401
  if node is None:
358
402
  raise RuntimeError("Node instance missing")
359
-
360
403
  # Remove the content from the message if it has
361
404
  if message.has_content():
362
405
  message = remove_content_from_message(message)
@@ -366,6 +409,7 @@ def http_request_response( # pylint: disable=R0913,R0914,R0915,R0917
366
409
  node=node,
367
410
  messages_list=[message_to_proto(message)],
368
411
  message_object_trees=[object_tree],
412
+ clientapp_runtime_list=[clientapp_runtime],
369
413
  )
370
414
  res = _request(req, PushMessagesResponse, PATH_PUSH_MESSAGES)
371
415
  if res is None:
@@ -392,12 +436,9 @@ def http_request_response( # pylint: disable=R0913,R0914,R0915,R0917
392
436
  # Send the request
393
437
  res = _request(req, GetFabResponse, PATH_GET_FAB)
394
438
  if res is None:
395
- return Fab("", b"")
439
+ return Fab("", b"", {})
396
440
 
397
- return Fab(
398
- res.fab.hash_str,
399
- res.fab.content,
400
- )
441
+ return fab_from_proto(res.fab)
401
442
 
402
443
  def pull_object(run_id: int, object_id: str) -> bytes:
403
444
  """Pull the object from the SuperLink."""
@@ -439,12 +480,14 @@ def http_request_response( # pylint: disable=R0913,R0914,R0915,R0917
439
480
  fn(object_id)
440
481
 
441
482
  try:
483
+ if self_registered:
484
+ register_node()
485
+ node_id = activate_node()
442
486
  # Yield methods
443
487
  yield (
488
+ node_id,
444
489
  receive,
445
490
  send,
446
- create_node,
447
- delete_node,
448
491
  get_run,
449
492
  get_fab,
450
493
  pull_object,
@@ -459,6 +502,8 @@ def http_request_response( # pylint: disable=R0913,R0914,R0915,R0917
459
502
  if node is not None:
460
503
  # Disable retrying
461
504
  retry_invoker.max_tries = 1
462
- delete_node()
505
+ deactivate_node()
506
+ if self_registered:
507
+ unregister_node()
463
508
  except RequestsConnectionError:
464
509
  pass
@@ -17,15 +17,15 @@
17
17
 
18
18
  from dataclasses import dataclass
19
19
  from pathlib import Path
20
- from typing import Optional
21
20
 
21
+ from flwr.app.user_config import UserConfig
22
22
  from flwr.common import Context, RecordDict
23
23
  from flwr.common.config import (
24
24
  get_fused_config,
25
25
  get_fused_config_from_dir,
26
26
  get_fused_config_from_fab,
27
27
  )
28
- from flwr.common.typing import Fab, Run, UserConfig
28
+ from flwr.common.typing import Fab, Run
29
29
 
30
30
 
31
31
  @dataclass()
@@ -52,10 +52,10 @@ class DeprecatedRunInfoStore:
52
52
  def register_context(
53
53
  self,
54
54
  run_id: int,
55
- run: Optional[Run] = None,
56
- flwr_path: Optional[Path] = None,
57
- app_dir: Optional[str] = None,
58
- fab: Optional[Fab] = None,
55
+ run: Run | None = None,
56
+ flwr_path: Path | None = None,
57
+ app_dir: str | None = None,
58
+ fab: Fab | None = None,
59
59
  ) -> None:
60
60
  """Register new run context for this node."""
61
61
  if run_id not in self.run_infos:
flwr/client/typing.py CHANGED
@@ -15,7 +15,7 @@
15
15
  """Custom types for Flower clients."""
16
16
 
17
17
 
18
- from typing import Callable
18
+ from collections.abc import Callable
19
19
 
20
20
  from flwr.common import Context, Message
21
21
 
@@ -15,9 +15,8 @@
15
15
  """Public Flower ClientApp APIs."""
16
16
 
17
17
 
18
- from flwr.client.client_app import ClientApp
19
-
20
18
  from . import mod
19
+ from .client_app import ClientApp as ClientApp
21
20
 
22
21
  __all__ = [
23
22
  "ClientApp",
@@ -16,10 +16,10 @@
16
16
 
17
17
 
18
18
  import inspect
19
- from collections.abc import Iterator
19
+ from collections.abc import Callable, Iterator
20
20
  from contextlib import contextmanager
21
- from typing import Callable, Optional
22
21
 
22
+ from flwr.app.message_type import MessageType
23
23
  from flwr.app.metadata import validate_message_type
24
24
  from flwr.client.client import Client
25
25
  from flwr.client.message_handler.message_handler import (
@@ -27,7 +27,7 @@ from flwr.client.message_handler.message_handler import (
27
27
  )
28
28
  from flwr.client.mod.utils import make_ffn
29
29
  from flwr.client.typing import ClientFnExt, Mod
30
- from flwr.common import Context, Message, MessageType
30
+ from flwr.common import Context, Message
31
31
  from flwr.common.logger import warn_deprecated_feature
32
32
 
33
33
  from .typing import ClientAppCallable
@@ -109,14 +109,14 @@ class ClientApp:
109
109
 
110
110
  def __init__(
111
111
  self,
112
- client_fn: Optional[ClientFnExt] = None, # Only for backward compatibility
113
- mods: Optional[list[Mod]] = None,
112
+ client_fn: ClientFnExt | None = None, # Only for backward compatibility
113
+ mods: list[Mod] | None = None,
114
114
  ) -> None:
115
115
  self._mods: list[Mod] = mods if mods is not None else []
116
116
  self._registered_funcs: dict[str, ClientAppCallable] = {}
117
117
 
118
118
  # Create wrapper function for `handle`
119
- self._call: Optional[ClientAppCallable] = None
119
+ self._call: ClientAppCallable | None = None
120
120
  if client_fn is not None:
121
121
 
122
122
  client_fn = _inspect_maybe_adapt_client_fn_signature(client_fn)
@@ -163,7 +163,7 @@ class ClientApp:
163
163
  raise ValueError(f"No {category} function registered with name '{action}'")
164
164
 
165
165
  def train(
166
- self, action: str = DEFAULT_ACTION, *, mods: Optional[list[Mod]] = None
166
+ self, action: str = DEFAULT_ACTION, *, mods: list[Mod] | None = None
167
167
  ) -> Callable[[ClientAppCallable], ClientAppCallable]:
168
168
  """Register a train function with the ``ClientApp``.
169
169
 
@@ -218,7 +218,7 @@ class ClientApp:
218
218
  return _get_decorator(self, MessageType.TRAIN, action, mods)
219
219
 
220
220
  def evaluate(
221
- self, action: str = DEFAULT_ACTION, *, mods: Optional[list[Mod]] = None
221
+ self, action: str = DEFAULT_ACTION, *, mods: list[Mod] | None = None
222
222
  ) -> Callable[[ClientAppCallable], ClientAppCallable]:
223
223
  """Register an evaluate function with the ``ClientApp``.
224
224
 
@@ -273,7 +273,7 @@ class ClientApp:
273
273
  return _get_decorator(self, MessageType.EVALUATE, action, mods)
274
274
 
275
275
  def query(
276
- self, action: str = DEFAULT_ACTION, *, mods: Optional[list[Mod]] = None
276
+ self, action: str = DEFAULT_ACTION, *, mods: list[Mod] | None = None
277
277
  ) -> Callable[[ClientAppCallable], ClientAppCallable]:
278
278
  """Register a query function with the ``ClientApp``.
279
279
 
@@ -355,7 +355,7 @@ class ClientApp:
355
355
  """
356
356
 
357
357
  def lifespan_decorator(
358
- lifespan_fn: Callable[[Context], Iterator[None]]
358
+ lifespan_fn: Callable[[Context], Iterator[None]],
359
359
  ) -> Callable[[Context], Iterator[None]]:
360
360
  """Register the lifespan fn with the ServerApp object."""
361
361
 
@@ -398,7 +398,7 @@ class LoadClientAppError(Exception):
398
398
 
399
399
 
400
400
  def _get_decorator(
401
- app: ClientApp, category: str, action: str, mods: Optional[list[Mod]]
401
+ app: ClientApp, category: str, action: str, mods: list[Mod] | None
402
402
  ) -> Callable[[ClientAppCallable], ClientAppCallable]:
403
403
  """Get the decorator for the given category and action."""
404
404
  # pylint: disable=protected-access
@@ -15,7 +15,6 @@
15
15
  """Clipping modifiers for central DP with client-side clipping."""
16
16
 
17
17
 
18
- from collections import OrderedDict
19
18
  from logging import ERROR, INFO
20
19
  from typing import cast
21
20
 
@@ -105,14 +104,14 @@ def fixedclipping_mod(
105
104
  )
106
105
  # Replace outgoing ArrayRecord's Array while preserving their keys
107
106
  out_msg.content.array_records[new_array_record_key] = ArrayRecord(
108
- OrderedDict(
109
- {
110
- k: Array(v)
111
- for k, v in zip(
112
- client_to_server_arrecord.keys(), client_to_server_ndarrays
113
- )
114
- }
115
- )
107
+ {
108
+ k: Array(v)
109
+ for k, v in zip(
110
+ client_to_server_arrecord.keys(),
111
+ client_to_server_ndarrays,
112
+ strict=True,
113
+ )
114
+ }
116
115
  )
117
116
  return out_msg
118
117
 
@@ -192,14 +191,14 @@ def adaptiveclipping_mod(
192
191
  )
193
192
  # Replace outgoing ArrayRecord's Array while preserving their keys
194
193
  out_msg.content.array_records[new_array_record_key] = ArrayRecord(
195
- OrderedDict(
196
- {
197
- k: Array(v)
198
- for k, v in zip(
199
- client_to_server_arrecord.keys(), client_to_server_ndarrays
200
- )
201
- }
202
- )
194
+ {
195
+ k: Array(v)
196
+ for k, v in zip(
197
+ client_to_server_arrecord.keys(),
198
+ client_to_server_ndarrays,
199
+ strict=True,
200
+ )
201
+ }
203
202
  )
204
203
  # Add to the MetricRecords the norm bit (recall reply messages only contain
205
204
  # one MetricRecord)
@@ -15,7 +15,6 @@
15
15
  """Local DP modifier."""
16
16
 
17
17
 
18
- from collections import OrderedDict
19
18
  from logging import INFO
20
19
 
21
20
  import numpy as np
@@ -157,13 +156,13 @@ class LocalDpMod:
157
156
 
158
157
  # Replace outgoing ArrayRecord's Array while preserving their keys
159
158
  out_msg.content[new_array_record_key] = ArrayRecord(
160
- OrderedDict(
161
- {
162
- k: Array(v)
163
- for k, v in zip(
164
- client_to_server_arrecord.keys(), client_to_server_ndarrays
165
- )
166
- }
167
- )
159
+ {
160
+ k: Array(v)
161
+ for k, v in zip(
162
+ client_to_server_arrecord.keys(),
163
+ client_to_server_ndarrays,
164
+ strict=True,
165
+ )
166
+ }
168
167
  )
169
168
  return out_msg
flwr/clientapp/typing.py CHANGED
@@ -15,7 +15,7 @@
15
15
  """Custom types for Flower clients."""
16
16
 
17
17
 
18
- from typing import Callable
18
+ from collections.abc import Callable
19
19
 
20
20
  from flwr.common import Context, Message
21
21
 
@@ -15,11 +15,11 @@
15
15
  """Flower ClientApp loading utils."""
16
16
 
17
17
 
18
+ from collections.abc import Callable
18
19
  from logging import DEBUG
19
20
  from pathlib import Path
20
- from typing import Callable, Optional
21
21
 
22
- from flwr.client.client_app import ClientApp, LoadClientAppError
22
+ from flwr.clientapp.client_app import ClientApp, LoadClientAppError
23
23
  from flwr.common.config import (
24
24
  get_flwr_dir,
25
25
  get_metadata_from_config,
@@ -32,9 +32,9 @@ from flwr.common.object_ref import load_app, validate
32
32
 
33
33
  def get_load_client_app_fn(
34
34
  default_app_ref: str,
35
- app_path: Optional[str],
35
+ app_path: str | None,
36
36
  multi_app: bool,
37
- flwr_dir: Optional[str] = None,
37
+ flwr_dir: str | None = None,
38
38
  ) -> Callable[[str, str, str], ClientApp]:
39
39
  """Get the load_client_app_fn function.
40
40
 
flwr/common/__init__.py CHANGED
@@ -15,12 +15,13 @@
15
15
  """Common components shared between server and client."""
16
16
 
17
17
 
18
+ from flwr.app.message_type import MessageType as MessageType
19
+
18
20
  from ..app.error import Error as Error
19
21
  from ..app.metadata import Metadata as Metadata
20
- from .constant import MessageType as MessageType
22
+ from ..supercore.date import now as now
21
23
  from .constant import MessageTypeLegacy as MessageTypeLegacy
22
24
  from .context import Context as Context
23
- from .date import now as now
24
25
  from .grpc import GRPC_MAX_MESSAGE_LENGTH
25
26
  from .logger import configure as configure
26
27
  from .logger import log as log
flwr/common/args.py CHANGED
@@ -20,7 +20,6 @@ import sys
20
20
  from logging import DEBUG, ERROR, INFO, WARN
21
21
  from os.path import isfile
22
22
  from pathlib import Path
23
- from typing import Optional, Union
24
23
 
25
24
  from flwr.common.constant import TRANSPORT_TYPE_REST
26
25
  from flwr.common.logger import log
@@ -70,9 +69,9 @@ def add_args_flwr_app_common(parser: argparse.ArgumentParser) -> None:
70
69
  def try_obtain_root_certificates(
71
70
  args: argparse.Namespace,
72
71
  grpc_server_address: str,
73
- ) -> Optional[Union[bytes, str]]:
72
+ ) -> bytes | str | None:
74
73
  """Validate and return the root certificates."""
75
- root_cert_path: Optional[str] = args.root_certificates
74
+ root_cert_path: str | None = args.root_certificates
76
75
  if args.insecure:
77
76
  if root_cert_path is not None:
78
77
  sys.exit(
@@ -111,7 +110,7 @@ def try_obtain_root_certificates(
111
110
 
112
111
  def try_obtain_server_certificates(
113
112
  args: argparse.Namespace,
114
- ) -> Optional[tuple[bytes, bytes, bytes]]:
113
+ ) -> tuple[bytes, bytes, bytes] | None:
115
114
  """Validate and return the CA cert, server cert, and server private key."""
116
115
  if args.insecure:
117
116
  log(