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,9 +15,8 @@
15
15
  """RecordDict utilities."""
16
16
 
17
17
 
18
- from collections import OrderedDict
19
18
  from collections.abc import Mapping
20
- from typing import Union, cast, get_args
19
+ from typing import cast, get_args
21
20
 
22
21
  from . import Array, ArrayRecord, ConfigRecord, MetricRecord, RecordDict
23
22
  from .typing import (
@@ -104,25 +103,23 @@ def parameters_to_arrayrecord(parameters: Parameters, keep_input: bool) -> Array
104
103
  tensor_type = parameters.tensor_type
105
104
 
106
105
  num_arrays = len(parameters.tensors)
107
- ordered_dict = OrderedDict()
106
+ array_dict = {}
108
107
  for idx in range(num_arrays):
109
108
  if keep_input:
110
109
  tensor = parameters.tensors[idx]
111
110
  else:
112
111
  tensor = parameters.tensors.pop(0)
113
- ordered_dict[str(idx)] = Array(
114
- data=tensor, dtype="", stype=tensor_type, shape=()
115
- )
112
+ array_dict[str(idx)] = Array(data=tensor, dtype="", stype=tensor_type, shape=())
116
113
 
117
114
  if num_arrays == 0:
118
- ordered_dict[EMPTY_TENSOR_KEY] = Array(
115
+ array_dict[EMPTY_TENSOR_KEY] = Array(
119
116
  data=b"", dtype="", stype=tensor_type, shape=()
120
117
  )
121
- return ArrayRecord(ordered_dict, keep_input=keep_input)
118
+ return ArrayRecord(array_dict, keep_input=keep_input)
122
119
 
123
120
 
124
121
  def _check_mapping_from_recordscalartype_to_scalar(
125
- record_data: Mapping[str, Union[ConfigRecordValues, MetricRecordValues]]
122
+ record_data: Mapping[str, ConfigRecordValues | MetricRecordValues],
126
123
  ) -> dict[str, Scalar]:
127
124
  """Check mapping `common.*RecordValues` into `common.Scalar` is possible."""
128
125
  for value in record_data.values():
@@ -157,7 +154,7 @@ def _recorddict_to_fit_or_evaluate_ins_components(
157
154
 
158
155
 
159
156
  def _fit_or_evaluate_ins_to_recorddict(
160
- ins: Union[FitIns, EvaluateIns], keep_input: bool
157
+ ins: FitIns | EvaluateIns, keep_input: bool
161
158
  ) -> RecordDict:
162
159
  recorddict = RecordDict()
163
160
 
@@ -19,10 +19,10 @@ import itertools
19
19
  import random
20
20
  import threading
21
21
  import time
22
- from collections.abc import Generator, Iterable
22
+ from collections.abc import Callable, Generator, Iterable
23
23
  from dataclasses import dataclass
24
24
  from logging import INFO, WARN
25
- from typing import Any, Callable, Optional, Union, cast
25
+ from typing import Any, cast
26
26
 
27
27
  import grpc
28
28
 
@@ -39,7 +39,7 @@ from flwr.proto.simulationio_pb2_grpc import SimulationIoStub
39
39
  def exponential(
40
40
  base_delay: float = 1,
41
41
  multiplier: float = 2,
42
- max_delay: Optional[int] = None,
42
+ max_delay: int | None = None,
43
43
  ) -> Generator[float, None, None]:
44
44
  """Wait time generator for exponential backoff strategy.
45
45
 
@@ -66,7 +66,7 @@ def exponential(
66
66
 
67
67
 
68
68
  def constant(
69
- interval: Union[float, Iterable[float]] = 1,
69
+ interval: float | Iterable[float] = 1,
70
70
  ) -> Generator[float, None, None]:
71
71
  """Wait time generator for specified intervals.
72
72
 
@@ -114,8 +114,8 @@ class RetryState:
114
114
  kwargs: dict[str, Any]
115
115
  tries: int
116
116
  elapsed_time: float
117
- exception: Optional[Exception] = None
118
- actual_wait: Optional[float] = None
117
+ exception: Exception | None = None
118
+ actual_wait: float | None = None
119
119
 
120
120
 
121
121
  # pylint: disable-next=too-many-instance-attributes
@@ -184,16 +184,16 @@ class RetryInvoker:
184
184
  def __init__(
185
185
  self,
186
186
  wait_gen_factory: Callable[[], Generator[float, None, None]],
187
- recoverable_exceptions: Union[type[Exception], tuple[type[Exception], ...]],
188
- max_tries: Optional[int],
189
- max_time: Optional[float],
187
+ recoverable_exceptions: type[Exception] | tuple[type[Exception], ...],
188
+ max_tries: int | None,
189
+ max_time: float | None,
190
190
  *,
191
- on_success: Optional[Callable[[RetryState], None]] = None,
192
- on_backoff: Optional[Callable[[RetryState], None]] = None,
193
- on_giveup: Optional[Callable[[RetryState], None]] = None,
194
- jitter: Optional[Callable[[float], float]] = full_jitter,
195
- should_giveup: Optional[Callable[[Exception], bool]] = None,
196
- wait_function: Optional[Callable[[float], None]] = None,
191
+ on_success: Callable[[RetryState], None] | None = None,
192
+ on_backoff: Callable[[RetryState], None] | None = None,
193
+ on_giveup: Callable[[RetryState], None] | None = None,
194
+ jitter: Callable[[float], float] | None = full_jitter,
195
+ should_giveup: Callable[[Exception], bool] | None = None,
196
+ wait_function: Callable[[float], None] | None = None,
197
197
  ) -> None:
198
198
  self.wait_gen_factory = wait_gen_factory
199
199
  self.recoverable_exceptions = recoverable_exceptions
@@ -253,7 +253,7 @@ class RetryInvoker:
253
253
  """
254
254
 
255
255
  def try_call_event_handler(
256
- handler: Optional[Callable[[RetryState], None]]
256
+ handler: Callable[[RetryState], None] | None,
257
257
  ) -> None:
258
258
  if handler is not None:
259
259
  handler(cast(RetryState, ref_state[0]))
@@ -261,7 +261,7 @@ class RetryInvoker:
261
261
  try_cnt = 0
262
262
  wait_generator = self.wait_gen_factory()
263
263
  start = time.monotonic()
264
- ref_state: list[Optional[RetryState]] = [None]
264
+ ref_state: list[RetryState | None] = [None]
265
265
 
266
266
  while True:
267
267
  try_cnt += 1
@@ -387,9 +387,9 @@ def _make_simple_grpc_retry_invoker() -> RetryInvoker:
387
387
 
388
388
 
389
389
  def _wrap_stub(
390
- stub: Union[
391
- ServerAppIoStub, ClientAppIoStub, SimulationIoStub, FleetStub, GrpcAdapter
392
- ],
390
+ stub: (
391
+ ServerAppIoStub | ClientAppIoStub | SimulationIoStub | FleetStub | GrpcAdapter
392
+ ),
393
393
  retry_invoker: RetryInvoker,
394
394
  ) -> None:
395
395
  """Wrap a gRPC stub with a retry invoker."""
@@ -16,57 +16,14 @@
16
16
 
17
17
 
18
18
  import base64
19
- from typing import cast
20
19
 
21
20
  from cryptography.exceptions import InvalidSignature
22
21
  from cryptography.fernet import Fernet
23
- from cryptography.hazmat.primitives import hashes, hmac, serialization
22
+ from cryptography.hazmat.primitives import hashes, hmac
24
23
  from cryptography.hazmat.primitives.asymmetric import ec
25
24
  from cryptography.hazmat.primitives.kdf.hkdf import HKDF
26
25
 
27
26
 
28
- def generate_key_pairs() -> (
29
- tuple[ec.EllipticCurvePrivateKey, ec.EllipticCurvePublicKey]
30
- ):
31
- """Generate private and public key pairs with Cryptography."""
32
- private_key = ec.generate_private_key(ec.SECP384R1())
33
- public_key = private_key.public_key()
34
- return private_key, public_key
35
-
36
-
37
- def private_key_to_bytes(private_key: ec.EllipticCurvePrivateKey) -> bytes:
38
- """Serialize private key to bytes."""
39
- return private_key.private_bytes(
40
- encoding=serialization.Encoding.PEM,
41
- format=serialization.PrivateFormat.PKCS8,
42
- encryption_algorithm=serialization.NoEncryption(),
43
- )
44
-
45
-
46
- def bytes_to_private_key(private_key_bytes: bytes) -> ec.EllipticCurvePrivateKey:
47
- """Deserialize private key from bytes."""
48
- return cast(
49
- ec.EllipticCurvePrivateKey,
50
- serialization.load_pem_private_key(data=private_key_bytes, password=None),
51
- )
52
-
53
-
54
- def public_key_to_bytes(public_key: ec.EllipticCurvePublicKey) -> bytes:
55
- """Serialize public key to bytes."""
56
- return public_key.public_bytes(
57
- encoding=serialization.Encoding.PEM,
58
- format=serialization.PublicFormat.SubjectPublicKeyInfo,
59
- )
60
-
61
-
62
- def bytes_to_public_key(public_key_bytes: bytes) -> ec.EllipticCurvePublicKey:
63
- """Deserialize public key from bytes."""
64
- return cast(
65
- ec.EllipticCurvePublicKey,
66
- serialization.load_pem_public_key(data=public_key_bytes),
67
- )
68
-
69
-
70
27
  def generate_shared_key(
71
28
  private_key: ec.EllipticCurvePrivateKey, public_key: ec.EllipticCurvePublicKey
72
29
  ) -> bytes:
@@ -117,48 +74,3 @@ def verify_hmac(key: bytes, message: bytes, hmac_value: bytes) -> bool:
117
74
  return True
118
75
  except InvalidSignature:
119
76
  return False
120
-
121
-
122
- def sign_message(private_key: ec.EllipticCurvePrivateKey, message: bytes) -> bytes:
123
- """Sign a message using the provided EC private key.
124
-
125
- Parameters
126
- ----------
127
- private_key : ec.EllipticCurvePrivateKey
128
- The EC private key to sign the message with.
129
- message : bytes
130
- The message to be signed.
131
-
132
- Returns
133
- -------
134
- bytes
135
- The signature of the message.
136
- """
137
- signature = private_key.sign(message, ec.ECDSA(hashes.SHA256()))
138
- return signature
139
-
140
-
141
- def verify_signature(
142
- public_key: ec.EllipticCurvePublicKey, message: bytes, signature: bytes
143
- ) -> bool:
144
- """Verify a signature against a message using the provided EC public key.
145
-
146
- Parameters
147
- ----------
148
- public_key : ec.EllipticCurvePublicKey
149
- The EC public key to verify the signature.
150
- message : bytes
151
- The original message.
152
- signature : bytes
153
- The signature to verify.
154
-
155
- Returns
156
- -------
157
- bool
158
- True if the signature is valid, False otherwise.
159
- """
160
- try:
161
- public_key.verify(signature, message, ec.ECDSA(hashes.SHA256()))
162
- return True
163
- except InvalidSignature:
164
- return False
@@ -15,10 +15,10 @@
15
15
  """Utility functions for performing operations on Numpy NDArrays."""
16
16
 
17
17
 
18
- from typing import Any, Union
18
+ from typing import Any
19
19
 
20
20
  import numpy as np
21
- from numpy.typing import DTypeLike, NDArray
21
+ from numpy.typing import NDArray
22
22
 
23
23
 
24
24
  def factor_combine(factor: int, parameters: list[NDArray[Any]]) -> list[NDArray[Any]]:
@@ -38,8 +38,11 @@ def get_parameters_shape(parameters: list[NDArray[Any]]) -> list[tuple[int, ...]
38
38
  return [arr.shape for arr in parameters]
39
39
 
40
40
 
41
+ default_numpy_dtype = np.dtype(np.int64)
42
+
43
+
41
44
  def get_zero_parameters(
42
- dimensions_list: list[tuple[int, ...]], dtype: DTypeLike = np.int64
45
+ dimensions_list: list[tuple[int, ...]], dtype: np.dtype[Any] = default_numpy_dtype
43
46
  ) -> list[NDArray[Any]]:
44
47
  """Generate zero parameters based on the dimensions list."""
45
48
  return [np.zeros(dimensions, dtype=dtype) for dimensions in dimensions_list]
@@ -68,14 +71,14 @@ def parameters_mod(parameters: list[NDArray[Any]], divisor: int) -> list[NDArray
68
71
 
69
72
 
70
73
  def parameters_multiply(
71
- parameters: list[NDArray[Any]], multiplier: Union[int, float]
74
+ parameters: list[NDArray[Any]], multiplier: int | float
72
75
  ) -> list[NDArray[Any]]:
73
76
  """Multiply parameters by an integer/float multiplier."""
74
77
  return [parameters[idx] * multiplier for idx in range(len(parameters))]
75
78
 
76
79
 
77
80
  def parameters_divide(
78
- parameters: list[NDArray[Any]], divisor: Union[int, float]
81
+ parameters: list[NDArray[Any]], divisor: int | float
79
82
  ) -> list[NDArray[Any]]:
80
83
  """Divide weight by an integer/float divisor."""
81
84
  return [parameters[idx] / divisor for idx in range(len(parameters))]
flwr/common/serde.py CHANGED
@@ -15,9 +15,10 @@
15
15
  """ProtoBuf serialization and deserialization."""
16
16
 
17
17
 
18
- from collections import OrderedDict
19
18
  from typing import Any, cast
20
19
 
20
+ from flwr.app.user_config import UserConfig, UserConfigValue
21
+
21
22
  # pylint: disable=E0611
22
23
  from flwr.proto.fab_pb2 import Fab as ProtoFab
23
24
  from flwr.proto.message_pb2 import Context as ProtoContext
@@ -410,9 +411,9 @@ def array_record_from_proto(
410
411
  ) -> ArrayRecord:
411
412
  """Deserialize ArrayRecord from ProtoBuf."""
412
413
  return ArrayRecord(
413
- array_dict=OrderedDict(
414
- {item.key: array_from_proto(item.value) for item in record_proto.items}
415
- ),
414
+ array_dict={
415
+ item.key: array_from_proto(item.value) for item in record_proto.items
416
+ },
416
417
  keep_input=False,
417
418
  )
418
419
 
@@ -501,18 +502,20 @@ def recorddict_from_proto(recorddict_proto: ProtoRecordDict) -> RecordDict:
501
502
 
502
503
  def fab_to_proto(fab: typing.Fab) -> ProtoFab:
503
504
  """Create a proto Fab object from a Python Fab."""
504
- return ProtoFab(hash_str=fab.hash_str, content=fab.content)
505
+ return ProtoFab(
506
+ hash_str=fab.hash_str, content=fab.content, verifications=fab.verifications
507
+ )
505
508
 
506
509
 
507
510
  def fab_from_proto(fab: ProtoFab) -> typing.Fab:
508
511
  """Create a Python Fab object from a proto Fab."""
509
- return typing.Fab(fab.hash_str, fab.content)
512
+ return typing.Fab(fab.hash_str, fab.content, dict(fab.verifications))
510
513
 
511
514
 
512
515
  # === User configs ===
513
516
 
514
517
 
515
- def user_config_to_proto(user_config: typing.UserConfig) -> Any:
518
+ def user_config_to_proto(user_config: UserConfig) -> Any:
516
519
  """Serialize `UserConfig` to ProtoBuf."""
517
520
  proto = {}
518
521
  for key, value in user_config.items():
@@ -520,7 +523,7 @@ def user_config_to_proto(user_config: typing.UserConfig) -> Any:
520
523
  return proto
521
524
 
522
525
 
523
- def user_config_from_proto(proto: Any) -> typing.UserConfig:
526
+ def user_config_from_proto(proto: Any) -> UserConfig:
524
527
  """Deserialize `UserConfig` from ProtoBuf."""
525
528
  metrics = {}
526
529
  for key, value in proto.items():
@@ -528,7 +531,7 @@ def user_config_from_proto(proto: Any) -> typing.UserConfig:
528
531
  return metrics
529
532
 
530
533
 
531
- def user_config_value_to_proto(user_config_value: typing.UserConfigValue) -> Scalar:
534
+ def user_config_value_to_proto(user_config_value: UserConfigValue) -> Scalar:
532
535
  """Serialize `UserConfigValue` to ProtoBuf."""
533
536
  if isinstance(user_config_value, bool):
534
537
  return Scalar(bool=user_config_value)
@@ -547,11 +550,11 @@ def user_config_value_to_proto(user_config_value: typing.UserConfigValue) -> Sca
547
550
  )
548
551
 
549
552
 
550
- def user_config_value_from_proto(scalar_msg: Scalar) -> typing.UserConfigValue:
553
+ def user_config_value_from_proto(scalar_msg: Scalar) -> UserConfigValue:
551
554
  """Deserialize `UserConfigValue` from ProtoBuf."""
552
555
  scalar_field = scalar_msg.WhichOneof("scalar")
553
556
  scalar = getattr(scalar_msg, cast(str, scalar_field))
554
- return cast(typing.UserConfigValue, scalar)
557
+ return cast(UserConfigValue, scalar)
555
558
 
556
559
 
557
560
  # === Message messages ===
@@ -630,6 +633,10 @@ def run_to_proto(run: typing.Run) -> ProtoRun:
630
633
  finished_at=run.finished_at,
631
634
  status=run_status_to_proto(run.status),
632
635
  flwr_aid=run.flwr_aid,
636
+ federation=run.federation,
637
+ bytes_sent=run.bytes_sent,
638
+ bytes_recv=run.bytes_recv,
639
+ clientapp_runtime=run.clientapp_runtime,
633
640
  )
634
641
  return proto
635
642
 
@@ -648,6 +655,10 @@ def run_from_proto(run_proto: ProtoRun) -> typing.Run:
648
655
  finished_at=run_proto.finished_at,
649
656
  status=run_status_from_proto(run_proto.status),
650
657
  flwr_aid=run_proto.flwr_aid,
658
+ federation=run_proto.federation,
659
+ bytes_sent=run_proto.bytes_sent,
660
+ bytes_recv=run_proto.bytes_recv,
661
+ clientapp_runtime=run_proto.clientapp_runtime,
651
662
  )
652
663
  return run
653
664
 
@@ -114,7 +114,7 @@ def record_value_dict_to_proto(
114
114
  Note: `bool` MUST be put in the front of allowd_types if it exists.
115
115
  """
116
116
  # Move bool to the front
117
- if bool in allowed_types and allowed_types[0] != bool:
117
+ if bool in allowed_types and allowed_types[0] is not bool:
118
118
  allowed_types.remove(bool)
119
119
  allowed_types.insert(0, bool)
120
120
 
@@ -125,7 +125,7 @@ def record_value_dict_to_proto(
125
125
 
126
126
 
127
127
  def record_value_dict_from_proto(
128
- value_dict_proto: MutableMapping[str, Any]
128
+ value_dict_proto: MutableMapping[str, Any],
129
129
  ) -> dict[str, Any]:
130
130
  """Deserialize the record value dict from ProtoBuf."""
131
131
  return {k: _record_value_from_proto(v) for k, v in value_dict_proto.items()}
flwr/common/telemetry.py CHANGED
@@ -25,10 +25,10 @@ import uuid
25
25
  from concurrent.futures import Future, ThreadPoolExecutor
26
26
  from enum import Enum, auto
27
27
  from pathlib import Path
28
- from typing import Any, Optional, Union, cast
28
+ from typing import Any, cast
29
29
 
30
30
  from flwr.common.constant import FLWR_DIR
31
- from flwr.common.version import package_name, package_version
31
+ from flwr.supercore.version import package_name, package_version
32
32
 
33
33
  FLWR_TELEMETRY_ENABLED = os.getenv("FLWR_TELEMETRY_ENABLED", "1")
34
34
  FLWR_TELEMETRY_LOGGING = os.getenv("FLWR_TELEMETRY_LOGGING", "0")
@@ -56,7 +56,7 @@ def _configure_logger(log_level: int) -> None:
56
56
  _configure_logger(LOGGER_LEVEL)
57
57
 
58
58
 
59
- def log(msg: Union[str, Exception]) -> None:
59
+ def log(msg: str | Exception) -> None:
60
60
  """Log message using logger at DEBUG level."""
61
61
  logging.getLogger(LOGGER_NAME).log(LOGGER_LEVEL, msg)
62
62
 
@@ -161,6 +161,10 @@ class EventType(str, Enum):
161
161
  FLWR_SERVERAPP_RUN_ENTER = auto()
162
162
  FLWR_SERVERAPP_RUN_LEAVE = auto()
163
163
 
164
+ # CLI: flwr-clientapp
165
+ FLWR_CLIENTAPP_RUN_ENTER = auto()
166
+ FLWR_CLIENTAPP_RUN_LEAVE = auto()
167
+
164
168
  # --- Simulation Engine ------------------------------------------------------------
165
169
 
166
170
  # CLI: flower-simulation
@@ -188,7 +192,7 @@ class EventType(str, Enum):
188
192
 
189
193
  # Use the ThreadPoolExecutor with max_workers=1 to have a queue
190
194
  # and also ensure that telemetry calls are not blocking.
191
- state: dict[str, Union[Optional[str], Optional[ThreadPoolExecutor]]] = {
195
+ state: dict[str, str | None | ThreadPoolExecutor | None] = {
192
196
  # Will be assigned ThreadPoolExecutor(max_workers=1)
193
197
  # in event() the first time it's required
194
198
  "executor": None,
@@ -200,7 +204,7 @@ state: dict[str, Union[Optional[str], Optional[ThreadPoolExecutor]]] = {
200
204
 
201
205
  def event(
202
206
  event_type: EventType,
203
- event_details: Optional[dict[str, Any]] = None,
207
+ event_details: dict[str, Any] | None = None,
204
208
  ) -> Future: # type: ignore
205
209
  """Submit create_event to ThreadPoolExecutor to avoid blocking."""
206
210
  if state["executor"] is None:
@@ -212,7 +216,7 @@ def event(
212
216
  return result
213
217
 
214
218
 
215
- def create_event(event_type: EventType, event_details: Optional[dict[str, Any]]) -> str:
219
+ def create_event(event_type: EventType, event_details: dict[str, Any] | None) -> str:
216
220
  """Create telemetry event."""
217
221
  if state["source"] is None:
218
222
  state["source"] = _get_source_id()