flwr 1.23.0__py3-none-any.whl → 1.24.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (292) hide show
  1. flwr/__init__.py +16 -5
  2. flwr/app/error.py +2 -2
  3. flwr/app/exception.py +3 -3
  4. flwr/cli/app.py +19 -0
  5. flwr/cli/app_cmd/__init__.py +23 -0
  6. flwr/cli/app_cmd/publish.py +285 -0
  7. flwr/cli/app_cmd/review.py +252 -0
  8. flwr/cli/auth_plugin/auth_plugin.py +4 -5
  9. flwr/cli/auth_plugin/noop_auth_plugin.py +54 -11
  10. flwr/cli/auth_plugin/oidc_cli_plugin.py +32 -9
  11. flwr/cli/build.py +60 -18
  12. flwr/cli/cli_account_auth_interceptor.py +24 -7
  13. flwr/cli/config_utils.py +101 -13
  14. flwr/cli/federation/__init__.py +24 -0
  15. flwr/cli/federation/ls.py +140 -0
  16. flwr/cli/federation/show.py +317 -0
  17. flwr/cli/install.py +91 -13
  18. flwr/cli/log.py +52 -9
  19. flwr/cli/login/login.py +7 -4
  20. flwr/cli/ls.py +170 -130
  21. flwr/cli/new/new.py +33 -50
  22. flwr/cli/new/templates/app/code/task.pytorch.py.tpl +1 -0
  23. flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +1 -1
  24. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +1 -1
  25. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +1 -1
  26. flwr/cli/new/templates/app/pyproject.jax.toml.tpl +1 -1
  27. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +1 -1
  28. flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +1 -1
  29. flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +3 -3
  30. flwr/cli/new/templates/app/pyproject.pytorch_legacy_api.toml.tpl +1 -1
  31. flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +1 -1
  32. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +2 -2
  33. flwr/cli/new/templates/app/pyproject.xgboost.toml.tpl +1 -1
  34. flwr/cli/pull.py +10 -5
  35. flwr/cli/run/run.py +77 -30
  36. flwr/cli/run_utils.py +130 -0
  37. flwr/cli/stop.py +25 -7
  38. flwr/cli/supernode/ls.py +16 -8
  39. flwr/cli/supernode/register.py +9 -4
  40. flwr/cli/supernode/unregister.py +5 -3
  41. flwr/cli/utils.py +376 -16
  42. flwr/client/__init__.py +1 -1
  43. flwr/client/dpfedavg_numpy_client.py +4 -1
  44. flwr/client/grpc_adapter_client/connection.py +6 -7
  45. flwr/client/grpc_rere_client/connection.py +10 -11
  46. flwr/client/grpc_rere_client/grpc_adapter.py +6 -2
  47. flwr/client/grpc_rere_client/node_auth_client_interceptor.py +2 -1
  48. flwr/client/message_handler/message_handler.py +2 -2
  49. flwr/client/mod/secure_aggregation/secaggplus_mod.py +3 -3
  50. flwr/client/numpy_client.py +1 -1
  51. flwr/client/rest_client/connection.py +12 -14
  52. flwr/client/run_info_store.py +4 -5
  53. flwr/client/typing.py +1 -1
  54. flwr/clientapp/client_app.py +9 -10
  55. flwr/clientapp/mod/centraldp_mods.py +16 -17
  56. flwr/clientapp/mod/localdp_mod.py +8 -9
  57. flwr/clientapp/typing.py +1 -1
  58. flwr/clientapp/utils.py +3 -3
  59. flwr/common/address.py +1 -2
  60. flwr/common/args.py +3 -4
  61. flwr/common/config.py +13 -16
  62. flwr/common/constant.py +5 -2
  63. flwr/common/differential_privacy.py +3 -4
  64. flwr/common/event_log_plugin/event_log_plugin.py +3 -4
  65. flwr/common/exit/exit.py +15 -2
  66. flwr/common/exit/exit_code.py +19 -0
  67. flwr/common/exit/exit_handler.py +6 -2
  68. flwr/common/exit/signal_handler.py +5 -5
  69. flwr/common/grpc.py +6 -6
  70. flwr/common/inflatable_protobuf_utils.py +1 -1
  71. flwr/common/inflatable_utils.py +38 -21
  72. flwr/common/logger.py +19 -19
  73. flwr/common/message.py +4 -4
  74. flwr/common/object_ref.py +7 -7
  75. flwr/common/record/array.py +3 -3
  76. flwr/common/record/arrayrecord.py +18 -30
  77. flwr/common/record/configrecord.py +3 -3
  78. flwr/common/record/recorddict.py +5 -5
  79. flwr/common/record/typeddict.py +9 -2
  80. flwr/common/recorddict_compat.py +7 -10
  81. flwr/common/retry_invoker.py +20 -20
  82. flwr/common/secure_aggregation/ndarrays_arithmetic.py +3 -3
  83. flwr/common/serde.py +5 -4
  84. flwr/common/serde_utils.py +2 -2
  85. flwr/common/telemetry.py +9 -5
  86. flwr/common/typing.py +52 -37
  87. flwr/compat/client/app.py +38 -37
  88. flwr/compat/client/grpc_client/connection.py +11 -11
  89. flwr/compat/server/app.py +5 -6
  90. flwr/proto/appio_pb2.py +13 -3
  91. flwr/proto/appio_pb2.pyi +134 -65
  92. flwr/proto/appio_pb2_grpc.py +20 -0
  93. flwr/proto/appio_pb2_grpc.pyi +27 -0
  94. flwr/proto/clientappio_pb2.py +17 -7
  95. flwr/proto/clientappio_pb2.pyi +15 -0
  96. flwr/proto/clientappio_pb2_grpc.py +206 -40
  97. flwr/proto/clientappio_pb2_grpc.pyi +168 -53
  98. flwr/proto/control_pb2.py +71 -52
  99. flwr/proto/control_pb2.pyi +277 -111
  100. flwr/proto/control_pb2_grpc.py +249 -40
  101. flwr/proto/control_pb2_grpc.pyi +185 -52
  102. flwr/proto/error_pb2.py +13 -3
  103. flwr/proto/error_pb2.pyi +24 -6
  104. flwr/proto/error_pb2_grpc.py +20 -0
  105. flwr/proto/error_pb2_grpc.pyi +27 -0
  106. flwr/proto/fab_pb2.py +14 -4
  107. flwr/proto/fab_pb2.pyi +59 -31
  108. flwr/proto/fab_pb2_grpc.py +20 -0
  109. flwr/proto/fab_pb2_grpc.pyi +27 -0
  110. flwr/proto/federation_pb2.py +38 -0
  111. flwr/proto/federation_pb2.pyi +56 -0
  112. flwr/proto/federation_pb2_grpc.py +24 -0
  113. flwr/proto/federation_pb2_grpc.pyi +31 -0
  114. flwr/proto/fleet_pb2.py +14 -4
  115. flwr/proto/fleet_pb2.pyi +137 -61
  116. flwr/proto/fleet_pb2_grpc.py +189 -48
  117. flwr/proto/fleet_pb2_grpc.pyi +175 -61
  118. flwr/proto/grpcadapter_pb2.py +14 -4
  119. flwr/proto/grpcadapter_pb2.pyi +38 -16
  120. flwr/proto/grpcadapter_pb2_grpc.py +35 -4
  121. flwr/proto/grpcadapter_pb2_grpc.pyi +38 -7
  122. flwr/proto/heartbeat_pb2.py +17 -7
  123. flwr/proto/heartbeat_pb2.pyi +51 -22
  124. flwr/proto/heartbeat_pb2_grpc.py +20 -0
  125. flwr/proto/heartbeat_pb2_grpc.pyi +27 -0
  126. flwr/proto/log_pb2.py +13 -3
  127. flwr/proto/log_pb2.pyi +34 -11
  128. flwr/proto/log_pb2_grpc.py +20 -0
  129. flwr/proto/log_pb2_grpc.pyi +27 -0
  130. flwr/proto/message_pb2.py +15 -5
  131. flwr/proto/message_pb2.pyi +154 -86
  132. flwr/proto/message_pb2_grpc.py +20 -0
  133. flwr/proto/message_pb2_grpc.pyi +27 -0
  134. flwr/proto/node_pb2.py +15 -5
  135. flwr/proto/node_pb2.pyi +50 -25
  136. flwr/proto/node_pb2_grpc.py +20 -0
  137. flwr/proto/node_pb2_grpc.pyi +27 -0
  138. flwr/proto/recorddict_pb2.py +13 -3
  139. flwr/proto/recorddict_pb2.pyi +184 -107
  140. flwr/proto/recorddict_pb2_grpc.py +20 -0
  141. flwr/proto/recorddict_pb2_grpc.pyi +27 -0
  142. flwr/proto/run_pb2.py +40 -31
  143. flwr/proto/run_pb2.pyi +149 -84
  144. flwr/proto/run_pb2_grpc.py +20 -0
  145. flwr/proto/run_pb2_grpc.pyi +27 -0
  146. flwr/proto/serverappio_pb2.py +13 -3
  147. flwr/proto/serverappio_pb2.pyi +32 -8
  148. flwr/proto/serverappio_pb2_grpc.py +246 -65
  149. flwr/proto/serverappio_pb2_grpc.pyi +221 -85
  150. flwr/proto/simulationio_pb2.py +16 -8
  151. flwr/proto/simulationio_pb2.pyi +15 -0
  152. flwr/proto/simulationio_pb2_grpc.py +162 -41
  153. flwr/proto/simulationio_pb2_grpc.pyi +149 -55
  154. flwr/proto/transport_pb2.py +20 -10
  155. flwr/proto/transport_pb2.pyi +249 -160
  156. flwr/proto/transport_pb2_grpc.py +35 -4
  157. flwr/proto/transport_pb2_grpc.pyi +38 -8
  158. flwr/server/app.py +38 -17
  159. flwr/server/client_manager.py +4 -5
  160. flwr/server/client_proxy.py +10 -11
  161. flwr/server/compat/app.py +4 -5
  162. flwr/server/compat/app_utils.py +2 -1
  163. flwr/server/compat/grid_client_proxy.py +10 -12
  164. flwr/server/compat/legacy_context.py +3 -4
  165. flwr/server/fleet_event_log_interceptor.py +2 -1
  166. flwr/server/grid/grid.py +2 -3
  167. flwr/server/grid/grpc_grid.py +10 -8
  168. flwr/server/grid/inmemory_grid.py +4 -4
  169. flwr/server/run_serverapp.py +2 -3
  170. flwr/server/server.py +34 -39
  171. flwr/server/server_app.py +7 -8
  172. flwr/server/server_config.py +1 -2
  173. flwr/server/serverapp/app.py +34 -28
  174. flwr/server/serverapp_components.py +4 -5
  175. flwr/server/strategy/aggregate.py +9 -8
  176. flwr/server/strategy/bulyan.py +13 -11
  177. flwr/server/strategy/dp_adaptive_clipping.py +16 -20
  178. flwr/server/strategy/dp_fixed_clipping.py +12 -17
  179. flwr/server/strategy/dpfedavg_adaptive.py +3 -4
  180. flwr/server/strategy/dpfedavg_fixed.py +6 -10
  181. flwr/server/strategy/fault_tolerant_fedavg.py +14 -13
  182. flwr/server/strategy/fedadagrad.py +18 -14
  183. flwr/server/strategy/fedadam.py +16 -14
  184. flwr/server/strategy/fedavg.py +16 -17
  185. flwr/server/strategy/fedavg_android.py +15 -15
  186. flwr/server/strategy/fedavgm.py +21 -18
  187. flwr/server/strategy/fedmedian.py +2 -3
  188. flwr/server/strategy/fedopt.py +11 -10
  189. flwr/server/strategy/fedprox.py +10 -9
  190. flwr/server/strategy/fedtrimmedavg.py +12 -11
  191. flwr/server/strategy/fedxgb_bagging.py +13 -11
  192. flwr/server/strategy/fedxgb_cyclic.py +6 -6
  193. flwr/server/strategy/fedxgb_nn_avg.py +4 -4
  194. flwr/server/strategy/fedyogi.py +16 -14
  195. flwr/server/strategy/krum.py +12 -11
  196. flwr/server/strategy/qfedavg.py +16 -15
  197. flwr/server/strategy/strategy.py +6 -9
  198. flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +2 -1
  199. flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +1 -2
  200. flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +3 -4
  201. flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +10 -12
  202. flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +1 -3
  203. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +4 -4
  204. flwr/server/superlink/fleet/grpc_rere/node_auth_server_interceptor.py +3 -2
  205. flwr/server/superlink/fleet/message_handler/message_handler.py +34 -28
  206. flwr/server/superlink/fleet/rest_rere/rest_api.py +2 -2
  207. flwr/server/superlink/fleet/vce/backend/backend.py +1 -1
  208. flwr/server/superlink/fleet/vce/backend/raybackend.py +5 -5
  209. flwr/server/superlink/fleet/vce/vce_api.py +15 -9
  210. flwr/server/superlink/linkstate/in_memory_linkstate.py +115 -150
  211. flwr/server/superlink/linkstate/linkstate.py +59 -43
  212. flwr/server/superlink/linkstate/linkstate_factory.py +22 -5
  213. flwr/server/superlink/linkstate/sqlite_linkstate.py +447 -438
  214. flwr/server/superlink/linkstate/utils.py +6 -6
  215. flwr/server/superlink/serverappio/serverappio_grpc.py +1 -2
  216. flwr/server/superlink/serverappio/serverappio_servicer.py +26 -21
  217. flwr/server/superlink/simulation/simulationio_grpc.py +1 -2
  218. flwr/server/superlink/simulation/simulationio_servicer.py +18 -13
  219. flwr/server/superlink/utils.py +4 -6
  220. flwr/server/typing.py +1 -1
  221. flwr/server/utils/tensorboard.py +15 -8
  222. flwr/server/workflow/default_workflows.py +5 -5
  223. flwr/server/workflow/secure_aggregation/secagg_workflow.py +2 -4
  224. flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +8 -8
  225. flwr/serverapp/strategy/bulyan.py +16 -15
  226. flwr/serverapp/strategy/dp_adaptive_clipping.py +12 -11
  227. flwr/serverapp/strategy/dp_fixed_clipping.py +11 -14
  228. flwr/serverapp/strategy/fedadagrad.py +10 -11
  229. flwr/serverapp/strategy/fedadam.py +10 -11
  230. flwr/serverapp/strategy/fedavg.py +9 -10
  231. flwr/serverapp/strategy/fedavgm.py +17 -16
  232. flwr/serverapp/strategy/fedmedian.py +2 -2
  233. flwr/serverapp/strategy/fedopt.py +10 -11
  234. flwr/serverapp/strategy/fedprox.py +7 -8
  235. flwr/serverapp/strategy/fedtrimmedavg.py +9 -9
  236. flwr/serverapp/strategy/fedxgb_bagging.py +3 -3
  237. flwr/serverapp/strategy/fedxgb_cyclic.py +9 -9
  238. flwr/serverapp/strategy/fedyogi.py +9 -11
  239. flwr/serverapp/strategy/krum.py +7 -7
  240. flwr/serverapp/strategy/multikrum.py +9 -9
  241. flwr/serverapp/strategy/qfedavg.py +17 -16
  242. flwr/serverapp/strategy/strategy.py +6 -9
  243. flwr/serverapp/strategy/strategy_utils.py +7 -8
  244. flwr/simulation/app.py +46 -42
  245. flwr/simulation/legacy_app.py +12 -12
  246. flwr/simulation/ray_transport/ray_actor.py +10 -11
  247. flwr/simulation/ray_transport/ray_client_proxy.py +11 -12
  248. flwr/simulation/run_simulation.py +43 -43
  249. flwr/simulation/simulationio_connection.py +4 -4
  250. flwr/supercore/cli/flower_superexec.py +3 -4
  251. flwr/supercore/constant.py +31 -1
  252. flwr/supercore/corestate/corestate.py +24 -3
  253. flwr/supercore/corestate/in_memory_corestate.py +138 -0
  254. flwr/supercore/corestate/sqlite_corestate.py +157 -0
  255. flwr/supercore/ffs/disk_ffs.py +1 -2
  256. flwr/supercore/ffs/ffs.py +1 -2
  257. flwr/supercore/ffs/ffs_factory.py +1 -2
  258. flwr/{common → supercore}/heartbeat.py +20 -25
  259. flwr/supercore/object_store/in_memory_object_store.py +1 -2
  260. flwr/supercore/object_store/object_store.py +1 -2
  261. flwr/supercore/object_store/object_store_factory.py +1 -2
  262. flwr/supercore/object_store/sqlite_object_store.py +8 -7
  263. flwr/supercore/primitives/asymmetric.py +1 -1
  264. flwr/supercore/primitives/asymmetric_ed25519.py +11 -1
  265. flwr/supercore/sqlite_mixin.py +37 -34
  266. flwr/supercore/superexec/plugin/base_exec_plugin.py +1 -2
  267. flwr/supercore/superexec/plugin/exec_plugin.py +3 -3
  268. flwr/supercore/superexec/run_superexec.py +9 -13
  269. flwr/superlink/artifact_provider/artifact_provider.py +1 -2
  270. flwr/superlink/auth_plugin/auth_plugin.py +6 -9
  271. flwr/superlink/auth_plugin/noop_auth_plugin.py +6 -9
  272. flwr/superlink/federation/__init__.py +24 -0
  273. flwr/superlink/federation/federation_manager.py +64 -0
  274. flwr/superlink/federation/noop_federation_manager.py +71 -0
  275. flwr/superlink/servicer/control/control_account_auth_interceptor.py +22 -13
  276. flwr/superlink/servicer/control/control_event_log_interceptor.py +7 -7
  277. flwr/superlink/servicer/control/control_grpc.py +5 -6
  278. flwr/superlink/servicer/control/control_license_interceptor.py +3 -3
  279. flwr/superlink/servicer/control/control_servicer.py +102 -18
  280. flwr/supernode/cli/flower_supernode.py +58 -3
  281. flwr/supernode/nodestate/in_memory_nodestate.py +60 -49
  282. flwr/supernode/nodestate/nodestate.py +7 -8
  283. flwr/supernode/nodestate/nodestate_factory.py +7 -4
  284. flwr/supernode/runtime/run_clientapp.py +41 -22
  285. flwr/supernode/servicer/clientappio/clientappio_servicer.py +40 -10
  286. flwr/supernode/start_client_internal.py +158 -42
  287. {flwr-1.23.0.dist-info → flwr-1.24.0.dist-info}/METADATA +8 -8
  288. flwr-1.24.0.dist-info/RECORD +454 -0
  289. flwr/supercore/object_store/utils.py +0 -43
  290. flwr-1.23.0.dist-info/RECORD +0 -439
  291. {flwr-1.23.0.dist-info → flwr-1.24.0.dist-info}/WHEEL +0 -0
  292. {flwr-1.23.0.dist-info → flwr-1.24.0.dist-info}/entry_points.txt +0 -0
flwr/cli/stop.py CHANGED
@@ -18,7 +18,7 @@
18
18
  import io
19
19
  import json
20
20
  from pathlib import Path
21
- from typing import Annotated, Optional
21
+ from typing import Annotated
22
22
 
23
23
  import typer
24
24
  from rich.console import Console
@@ -51,11 +51,11 @@ def stop( # pylint: disable=R0914
51
51
  typer.Argument(help="Path of the Flower project"),
52
52
  ] = Path("."),
53
53
  federation: Annotated[
54
- Optional[str],
54
+ str | None,
55
55
  typer.Argument(help="Name of the federation"),
56
56
  ] = None,
57
57
  federation_config_overrides: Annotated[
58
- Optional[list[str]],
58
+ list[str] | None,
59
59
  typer.Option(
60
60
  "--federation-config",
61
61
  help=FEDERATION_CONFIG_HELP_MESSAGE,
@@ -70,7 +70,11 @@ def stop( # pylint: disable=R0914
70
70
  ),
71
71
  ] = CliOutputFormat.DEFAULT,
72
72
  ) -> None:
73
- """Stop a run."""
73
+ """Stop a Flower run.
74
+
75
+ This command stops a running Flower App execution by sending a stop request to the
76
+ SuperLink via the Control API.
77
+ """
74
78
  suppress_output = output_format == CliOutputFormat.JSON
75
79
  captured_output = io.StringIO()
76
80
  try:
@@ -81,7 +85,7 @@ def stop( # pylint: disable=R0914
81
85
  typer.secho("Loading project configuration... ", fg=typer.colors.BLUE)
82
86
 
83
87
  pyproject_path = app / FAB_CONFIG_FILE if app else None
84
- config, errors, warnings = load_and_validate(path=pyproject_path)
88
+ config, errors, warnings = load_and_validate(pyproject_path, check_module=False)
85
89
  config = process_loaded_project_config(config, errors, warnings)
86
90
  federation, federation_config = validate_federation_in_project_config(
87
91
  federation, config, federation_config_overrides
@@ -101,6 +105,7 @@ def stop( # pylint: disable=R0914
101
105
  f"❌ {err}",
102
106
  fg=typer.colors.RED,
103
107
  bold=True,
108
+ err=True,
104
109
  )
105
110
  raise typer.Exit(code=1) from err
106
111
  finally:
@@ -116,6 +121,7 @@ def stop( # pylint: disable=R0914
116
121
  f"{err}",
117
122
  fg=typer.colors.RED,
118
123
  bold=True,
124
+ err=True,
119
125
  )
120
126
  finally:
121
127
  if suppress_output:
@@ -124,7 +130,17 @@ def stop( # pylint: disable=R0914
124
130
 
125
131
 
126
132
  def _stop_run(stub: ControlStub, run_id: int, output_format: str) -> None:
127
- """Stop a run."""
133
+ """Stop a run and display the result.
134
+
135
+ Parameters
136
+ ----------
137
+ stub : ControlStub
138
+ The gRPC stub for Control API communication.
139
+ run_id : int
140
+ The unique identifier of the run to stop.
141
+ output_format : str
142
+ Output format ('default' or 'json').
143
+ """
128
144
  with flwr_cli_grpc_exc_handler():
129
145
  response: StopRunResponse = stub.StopRun(request=StopRunRequest(run_id=run_id))
130
146
  if response.success:
@@ -139,4 +155,6 @@ def _stop_run(stub: ControlStub, run_id: int, output_format: str) -> None:
139
155
  restore_output()
140
156
  Console().print_json(run_output)
141
157
  else:
142
- typer.secho(f"❌ Run {run_id} couldn't be stopped.", fg=typer.colors.RED)
158
+ typer.secho(
159
+ f"❌ Run {run_id} couldn't be stopped.", fg=typer.colors.RED, err=True
160
+ )
flwr/cli/supernode/ls.py CHANGED
@@ -19,7 +19,7 @@ import io
19
19
  import json
20
20
  from datetime import datetime, timedelta
21
21
  from pathlib import Path
22
- from typing import Annotated, Optional, cast
22
+ from typing import Annotated, cast
23
23
 
24
24
  import typer
25
25
  from rich.console import Console
@@ -32,7 +32,7 @@ from flwr.cli.config_utils import (
32
32
  process_loaded_project_config,
33
33
  validate_federation_in_project_config,
34
34
  )
35
- from flwr.common.constant import FAB_CONFIG_FILE, NOOP_FLWR_AID, CliOutputFormat
35
+ from flwr.common.constant import FAB_CONFIG_FILE, NOOP_ACCOUNT_NAME, CliOutputFormat
36
36
  from flwr.common.date import format_timedelta, isoformat8601_utc
37
37
  from flwr.common.logger import print_json_error, redirect_output, restore_output
38
38
  from flwr.proto.control_pb2 import ( # pylint: disable=E0611
@@ -44,7 +44,7 @@ from flwr.proto.node_pb2 import NodeInfo # pylint: disable=E0611
44
44
 
45
45
  from ..utils import flwr_cli_grpc_exc_handler, init_channel, load_cli_auth_plugin
46
46
 
47
- _NodeListType = tuple[int, str, str, str, str, str, str, str]
47
+ _NodeListType = tuple[int, str, str, str, str, str, str, str, str]
48
48
 
49
49
 
50
50
  def ls( # pylint: disable=R0914, R0913, R0917
@@ -54,7 +54,7 @@ def ls( # pylint: disable=R0914, R0913, R0917
54
54
  typer.Argument(help="Path of the Flower project"),
55
55
  ] = Path("."),
56
56
  federation: Annotated[
57
- Optional[str],
57
+ str | None,
58
58
  typer.Argument(help="Name of the federation"),
59
59
  ] = None,
60
60
  output_format: Annotated[
@@ -86,7 +86,7 @@ def ls( # pylint: disable=R0914, R0913, R0917
86
86
  typer.secho("Loading project configuration... ", fg=typer.colors.BLUE)
87
87
 
88
88
  pyproject_path = app / FAB_CONFIG_FILE if app else None
89
- config, errors, warnings = load_and_validate(path=pyproject_path)
89
+ config, errors, warnings = load_and_validate(pyproject_path, check_module=False)
90
90
  config = process_loaded_project_config(config, errors, warnings)
91
91
  federation, federation_config = validate_federation_in_project_config(
92
92
  federation, config
@@ -138,7 +138,7 @@ def _format_nodes(
138
138
  ) -> list[_NodeListType]:
139
139
  """Format node information for display."""
140
140
 
141
- def _format_datetime(dt_str: Optional[str]) -> str:
141
+ def _format_datetime(dt_str: str | None) -> str:
142
142
  dt = datetime.fromisoformat(dt_str) if dt_str else None
143
143
  return isoformat8601_utc(dt).replace("T", " ") if dt else "N/A"
144
144
 
@@ -160,6 +160,7 @@ def _format_nodes(
160
160
  (
161
161
  node.node_id,
162
162
  node.owner_aid,
163
+ node.owner_name,
163
164
  node.status,
164
165
  _format_datetime(node.registered_at),
165
166
  _format_datetime(node.last_activated_at),
@@ -188,7 +189,8 @@ def _to_table(nodes_info: list[_NodeListType], verbose: bool) -> Table:
188
189
  for row in nodes_info:
189
190
  (
190
191
  node_id,
191
- owner_aid,
192
+ _,
193
+ owner_name,
192
194
  status,
193
195
  _,
194
196
  last_activated_at,
@@ -216,7 +218,11 @@ def _to_table(nodes_info: list[_NodeListType], verbose: bool) -> Table:
216
218
 
217
219
  formatted_row = (
218
220
  f"[bold]{node_id}[/bold]",
219
- f"{owner_aid}" if owner_aid != NOOP_FLWR_AID else f"[dim]{owner_aid}[/dim]",
221
+ (
222
+ f"{owner_name}"
223
+ if owner_name != NOOP_ACCOUNT_NAME
224
+ else f"[dim]{owner_name}[/dim]"
225
+ ),
220
226
  f"[{status_style}]{status}",
221
227
  f"[cyan]{elapse_activated}[/cyan]" if status == "online" else "",
222
228
  time_at,
@@ -233,6 +239,7 @@ def _to_json(nodes_info: list[_NodeListType], verbose: bool) -> str:
233
239
  (
234
240
  node_id,
235
241
  owner_aid,
242
+ owner_name,
236
243
  status,
237
244
  created_at,
238
245
  activated_at,
@@ -248,6 +255,7 @@ def _to_json(nodes_info: list[_NodeListType], verbose: bool) -> str:
248
255
  {
249
256
  "node-id": node_id,
250
257
  "owner-aid": owner_aid,
258
+ "owner-name": owner_name,
251
259
  "status": status,
252
260
  "created-at": created_at,
253
261
  "online-at": activated_at,
@@ -18,7 +18,7 @@
18
18
  import io
19
19
  import json
20
20
  from pathlib import Path
21
- from typing import Annotated, Optional
21
+ from typing import Annotated
22
22
 
23
23
  import typer
24
24
  from cryptography.exceptions import UnsupportedAlgorithm
@@ -57,7 +57,7 @@ def register( # pylint: disable=R0914
57
57
  typer.Argument(help="Path of the Flower project"),
58
58
  ] = Path("."),
59
59
  federation: Annotated[
60
- Optional[str],
60
+ str | None,
61
61
  typer.Argument(help="Name of the federation"),
62
62
  ] = None,
63
63
  output_format: Annotated[
@@ -85,7 +85,7 @@ def register( # pylint: disable=R0914
85
85
  typer.secho("Loading project configuration... ", fg=typer.colors.BLUE)
86
86
 
87
87
  pyproject_path = app / FAB_CONFIG_FILE if app else None
88
- config, errors, warnings = load_and_validate(path=pyproject_path)
88
+ config, errors, warnings = load_and_validate(pyproject_path, check_module=False)
89
89
  config = process_loaded_project_config(config, errors, warnings)
90
90
  federation, federation_config = validate_federation_in_project_config(
91
91
  federation, config
@@ -107,6 +107,7 @@ def register( # pylint: disable=R0914
107
107
  f"❌ {err}",
108
108
  fg=typer.colors.RED,
109
109
  bold=True,
110
+ err=True,
110
111
  )
111
112
  raise typer.Exit(code=1) from err
112
113
  finally:
@@ -123,6 +124,7 @@ def register( # pylint: disable=R0914
123
124
  f"{err}",
124
125
  fg=typer.colors.RED,
125
126
  bold=True,
127
+ err=True,
126
128
  )
127
129
  finally:
128
130
  if suppress_output:
@@ -151,7 +153,9 @@ def _register_node(stub: ControlStub, public_key: bytes, output_format: str) ->
151
153
  restore_output()
152
154
  Console().print_json(run_output)
153
155
  else:
154
- typer.secho("❌ SuperNode couldn't be registered.", fg=typer.colors.RED)
156
+ typer.secho(
157
+ "❌ SuperNode couldn't be registered.", fg=typer.colors.RED, err=True
158
+ )
155
159
 
156
160
 
157
161
  def try_load_public_key(public_key_path: Path) -> bytes:
@@ -161,6 +165,7 @@ def try_load_public_key(public_key_path: Path) -> bytes:
161
165
  f"❌ Public key file '{public_key_path}' does not exist.",
162
166
  fg=typer.colors.RED,
163
167
  bold=True,
168
+ err=True,
164
169
  )
165
170
  raise typer.Exit(code=1)
166
171
 
@@ -18,7 +18,7 @@
18
18
  import io
19
19
  import json
20
20
  from pathlib import Path
21
- from typing import Annotated, Optional
21
+ from typing import Annotated
22
22
 
23
23
  import typer
24
24
  from rich.console import Console
@@ -49,7 +49,7 @@ def unregister( # pylint: disable=R0914
49
49
  typer.Argument(help="Path of the Flower project"),
50
50
  ] = Path("."),
51
51
  federation: Annotated[
52
- Optional[str],
52
+ str | None,
53
53
  typer.Argument(help="Name of the federation"),
54
54
  ] = None,
55
55
  output_format: Annotated[
@@ -73,7 +73,7 @@ def unregister( # pylint: disable=R0914
73
73
  typer.secho("Loading project configuration... ", fg=typer.colors.BLUE)
74
74
 
75
75
  pyproject_path = app / FAB_CONFIG_FILE if app else None
76
- config, errors, warnings = load_and_validate(path=pyproject_path)
76
+ config, errors, warnings = load_and_validate(pyproject_path, check_module=False)
77
77
  config = process_loaded_project_config(config, errors, warnings)
78
78
  federation, federation_config = validate_federation_in_project_config(
79
79
  federation, config
@@ -93,6 +93,7 @@ def unregister( # pylint: disable=R0914
93
93
  f"❌ {err}",
94
94
  fg=typer.colors.RED,
95
95
  bold=True,
96
+ err=True,
96
97
  )
97
98
  raise typer.Exit(code=1) from err
98
99
  finally:
@@ -109,6 +110,7 @@ def unregister( # pylint: disable=R0914
109
110
  f"{err}",
110
111
  fg=typer.colors.RED,
111
112
  bold=True,
113
+ err=True,
112
114
  )
113
115
  finally:
114
116
  if suppress_output: