flwr 1.22.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.
- flwr/__init__.py +16 -5
- flwr/app/error.py +2 -2
- flwr/app/exception.py +3 -3
- flwr/cli/app.py +34 -1
- flwr/cli/app_cmd/__init__.py +23 -0
- flwr/cli/app_cmd/publish.py +285 -0
- flwr/cli/app_cmd/review.py +252 -0
- flwr/cli/auth_plugin/__init__.py +15 -6
- flwr/cli/auth_plugin/auth_plugin.py +94 -0
- flwr/cli/auth_plugin/noop_auth_plugin.py +101 -0
- flwr/cli/auth_plugin/oidc_cli_plugin.py +46 -32
- flwr/cli/build.py +166 -53
- flwr/cli/{cli_user_auth_interceptor.py → cli_account_auth_interceptor.py} +29 -11
- flwr/cli/config_utils.py +101 -13
- flwr/cli/federation/__init__.py +24 -0
- flwr/cli/federation/ls.py +140 -0
- flwr/cli/federation/show.py +317 -0
- flwr/cli/install.py +91 -13
- flwr/cli/log.py +54 -11
- flwr/cli/login/login.py +41 -27
- flwr/cli/ls.py +177 -133
- flwr/cli/new/new.py +175 -40
- flwr/cli/new/templates/app/code/task.pytorch.py.tpl +1 -0
- flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.jax.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +3 -3
- flwr/cli/new/templates/app/pyproject.pytorch_legacy_api.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +2 -2
- flwr/cli/new/templates/app/pyproject.xgboost.toml.tpl +1 -1
- flwr/cli/pull.py +12 -7
- flwr/cli/run/run.py +82 -31
- flwr/cli/run_utils.py +130 -0
- flwr/cli/stop.py +27 -9
- flwr/cli/supernode/__init__.py +25 -0
- flwr/cli/supernode/ls.py +268 -0
- flwr/cli/supernode/register.py +190 -0
- flwr/cli/supernode/unregister.py +140 -0
- flwr/cli/utils.py +464 -81
- flwr/client/__init__.py +2 -1
- flwr/client/dpfedavg_numpy_client.py +4 -1
- flwr/client/grpc_adapter_client/connection.py +12 -15
- flwr/client/grpc_rere_client/connection.py +68 -41
- flwr/client/grpc_rere_client/grpc_adapter.py +34 -14
- flwr/client/grpc_rere_client/{client_interceptor.py → node_auth_client_interceptor.py} +5 -7
- flwr/client/message_handler/message_handler.py +2 -2
- flwr/client/mod/secure_aggregation/secaggplus_mod.py +10 -8
- flwr/client/numpy_client.py +1 -1
- flwr/client/rest_client/connection.py +94 -51
- flwr/client/run_info_store.py +4 -5
- flwr/client/typing.py +1 -1
- flwr/clientapp/__init__.py +1 -2
- flwr/{client → clientapp}/client_app.py +9 -10
- flwr/clientapp/mod/centraldp_mods.py +16 -17
- flwr/clientapp/mod/localdp_mod.py +8 -9
- flwr/clientapp/typing.py +1 -1
- flwr/{client/clientapp → clientapp}/utils.py +4 -4
- flwr/common/address.py +1 -2
- flwr/common/args.py +3 -4
- flwr/common/config.py +13 -16
- flwr/common/constant.py +56 -13
- flwr/common/differential_privacy.py +3 -4
- flwr/common/event_log_plugin/event_log_plugin.py +3 -4
- flwr/common/exit/exit.py +15 -2
- flwr/common/exit/exit_code.py +39 -10
- flwr/common/exit/exit_handler.py +6 -2
- flwr/common/exit/signal_handler.py +5 -5
- flwr/common/grpc.py +6 -6
- flwr/common/inflatable_protobuf_utils.py +1 -1
- flwr/common/inflatable_utils.py +48 -31
- flwr/common/logger.py +19 -19
- flwr/common/message.py +4 -4
- flwr/common/object_ref.py +7 -7
- flwr/common/record/array.py +6 -6
- flwr/common/record/arrayrecord.py +18 -21
- flwr/common/record/configrecord.py +3 -3
- flwr/common/record/recorddict.py +5 -5
- flwr/common/record/typeddict.py +9 -2
- flwr/common/recorddict_compat.py +7 -10
- flwr/common/retry_invoker.py +20 -20
- flwr/common/secure_aggregation/crypto/symmetric_encryption.py +1 -89
- flwr/common/secure_aggregation/ndarrays_arithmetic.py +3 -3
- flwr/common/serde.py +9 -6
- flwr/common/serde_utils.py +2 -2
- flwr/common/telemetry.py +9 -5
- flwr/common/typing.py +59 -43
- flwr/compat/client/app.py +39 -38
- flwr/compat/client/grpc_client/connection.py +13 -13
- flwr/compat/server/app.py +5 -6
- flwr/proto/appio_pb2.py +13 -3
- flwr/proto/appio_pb2.pyi +134 -65
- flwr/proto/appio_pb2_grpc.py +20 -0
- flwr/proto/appio_pb2_grpc.pyi +27 -0
- flwr/proto/clientappio_pb2.py +17 -7
- flwr/proto/clientappio_pb2.pyi +15 -0
- flwr/proto/clientappio_pb2_grpc.py +206 -40
- flwr/proto/clientappio_pb2_grpc.pyi +168 -53
- flwr/proto/control_pb2.py +72 -40
- flwr/proto/control_pb2.pyi +319 -87
- flwr/proto/control_pb2_grpc.py +339 -28
- flwr/proto/control_pb2_grpc.pyi +209 -37
- flwr/proto/error_pb2.py +13 -3
- flwr/proto/error_pb2.pyi +24 -6
- flwr/proto/error_pb2_grpc.py +20 -0
- flwr/proto/error_pb2_grpc.pyi +27 -0
- flwr/proto/fab_pb2.py +24 -10
- flwr/proto/fab_pb2.pyi +68 -20
- flwr/proto/fab_pb2_grpc.py +20 -0
- flwr/proto/fab_pb2_grpc.pyi +27 -0
- flwr/proto/federation_pb2.py +38 -0
- flwr/proto/federation_pb2.pyi +56 -0
- flwr/proto/federation_pb2_grpc.py +24 -0
- flwr/proto/federation_pb2_grpc.pyi +31 -0
- flwr/proto/fleet_pb2.py +45 -27
- flwr/proto/fleet_pb2.pyi +186 -70
- flwr/proto/fleet_pb2_grpc.py +277 -66
- flwr/proto/fleet_pb2_grpc.pyi +201 -55
- flwr/proto/grpcadapter_pb2.py +14 -4
- flwr/proto/grpcadapter_pb2.pyi +38 -16
- flwr/proto/grpcadapter_pb2_grpc.py +35 -4
- flwr/proto/grpcadapter_pb2_grpc.pyi +38 -7
- flwr/proto/heartbeat_pb2.py +17 -7
- flwr/proto/heartbeat_pb2.pyi +51 -22
- flwr/proto/heartbeat_pb2_grpc.py +20 -0
- flwr/proto/heartbeat_pb2_grpc.pyi +27 -0
- flwr/proto/log_pb2.py +13 -3
- flwr/proto/log_pb2.pyi +34 -11
- flwr/proto/log_pb2_grpc.py +20 -0
- flwr/proto/log_pb2_grpc.pyi +27 -0
- flwr/proto/message_pb2.py +15 -5
- flwr/proto/message_pb2.pyi +154 -86
- flwr/proto/message_pb2_grpc.py +20 -0
- flwr/proto/message_pb2_grpc.pyi +27 -0
- flwr/proto/node_pb2.py +16 -4
- flwr/proto/node_pb2.pyi +77 -4
- flwr/proto/node_pb2_grpc.py +20 -0
- flwr/proto/node_pb2_grpc.pyi +27 -0
- flwr/proto/recorddict_pb2.py +13 -3
- flwr/proto/recorddict_pb2.pyi +184 -107
- flwr/proto/recorddict_pb2_grpc.py +20 -0
- flwr/proto/recorddict_pb2_grpc.pyi +27 -0
- flwr/proto/run_pb2.py +40 -31
- flwr/proto/run_pb2.pyi +149 -84
- flwr/proto/run_pb2_grpc.py +20 -0
- flwr/proto/run_pb2_grpc.pyi +27 -0
- flwr/proto/serverappio_pb2.py +13 -3
- flwr/proto/serverappio_pb2.pyi +32 -8
- flwr/proto/serverappio_pb2_grpc.py +246 -65
- flwr/proto/serverappio_pb2_grpc.pyi +221 -85
- flwr/proto/simulationio_pb2.py +16 -8
- flwr/proto/simulationio_pb2.pyi +15 -0
- flwr/proto/simulationio_pb2_grpc.py +162 -41
- flwr/proto/simulationio_pb2_grpc.pyi +149 -55
- flwr/proto/transport_pb2.py +20 -10
- flwr/proto/transport_pb2.pyi +249 -160
- flwr/proto/transport_pb2_grpc.py +35 -4
- flwr/proto/transport_pb2_grpc.pyi +38 -8
- flwr/server/app.py +173 -127
- flwr/server/client_manager.py +4 -5
- flwr/server/client_proxy.py +10 -11
- flwr/server/compat/app.py +4 -5
- flwr/server/compat/app_utils.py +2 -1
- flwr/server/compat/grid_client_proxy.py +10 -12
- flwr/server/compat/legacy_context.py +3 -4
- flwr/server/fleet_event_log_interceptor.py +2 -1
- flwr/server/grid/grid.py +2 -3
- flwr/server/grid/grpc_grid.py +10 -8
- flwr/server/grid/inmemory_grid.py +4 -4
- flwr/server/run_serverapp.py +2 -3
- flwr/server/server.py +34 -39
- flwr/server/server_app.py +7 -8
- flwr/server/server_config.py +1 -2
- flwr/server/serverapp/app.py +34 -28
- flwr/server/serverapp_components.py +4 -5
- flwr/server/strategy/aggregate.py +9 -8
- flwr/server/strategy/bulyan.py +13 -11
- flwr/server/strategy/dp_adaptive_clipping.py +16 -20
- flwr/server/strategy/dp_fixed_clipping.py +12 -17
- flwr/server/strategy/dpfedavg_adaptive.py +3 -4
- flwr/server/strategy/dpfedavg_fixed.py +6 -10
- flwr/server/strategy/fault_tolerant_fedavg.py +14 -13
- flwr/server/strategy/fedadagrad.py +18 -14
- flwr/server/strategy/fedadam.py +16 -14
- flwr/server/strategy/fedavg.py +16 -17
- flwr/server/strategy/fedavg_android.py +15 -15
- flwr/server/strategy/fedavgm.py +21 -18
- flwr/server/strategy/fedmedian.py +2 -3
- flwr/server/strategy/fedopt.py +11 -10
- flwr/server/strategy/fedprox.py +10 -9
- flwr/server/strategy/fedtrimmedavg.py +12 -11
- flwr/server/strategy/fedxgb_bagging.py +13 -11
- flwr/server/strategy/fedxgb_cyclic.py +6 -6
- flwr/server/strategy/fedxgb_nn_avg.py +4 -4
- flwr/server/strategy/fedyogi.py +16 -14
- flwr/server/strategy/krum.py +12 -11
- flwr/server/strategy/qfedavg.py +16 -15
- flwr/server/strategy/strategy.py +6 -9
- flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +19 -8
- flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +1 -2
- flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +3 -4
- flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +10 -12
- flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +1 -3
- flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +136 -42
- flwr/server/superlink/fleet/grpc_rere/{server_interceptor.py → node_auth_server_interceptor.py} +28 -51
- flwr/server/superlink/fleet/message_handler/message_handler.py +100 -49
- flwr/server/superlink/fleet/rest_rere/rest_api.py +54 -33
- flwr/server/superlink/fleet/vce/backend/backend.py +2 -2
- flwr/server/superlink/fleet/vce/backend/raybackend.py +6 -6
- flwr/server/superlink/fleet/vce/vce_api.py +32 -13
- flwr/server/superlink/linkstate/in_memory_linkstate.py +266 -207
- flwr/server/superlink/linkstate/linkstate.py +161 -62
- flwr/server/superlink/linkstate/linkstate_factory.py +24 -6
- flwr/server/superlink/linkstate/sqlite_linkstate.py +698 -638
- flwr/server/superlink/linkstate/utils.py +9 -60
- flwr/server/superlink/serverappio/serverappio_grpc.py +1 -2
- flwr/server/superlink/serverappio/serverappio_servicer.py +28 -23
- flwr/server/superlink/simulation/simulationio_grpc.py +1 -2
- flwr/server/superlink/simulation/simulationio_servicer.py +19 -14
- flwr/server/superlink/utils.py +4 -6
- flwr/server/typing.py +1 -1
- flwr/server/utils/tensorboard.py +15 -8
- flwr/server/utils/validator.py +2 -3
- flwr/server/workflow/default_workflows.py +5 -5
- flwr/server/workflow/secure_aggregation/secagg_workflow.py +2 -4
- flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +12 -10
- flwr/serverapp/strategy/bulyan.py +16 -15
- flwr/serverapp/strategy/dp_adaptive_clipping.py +12 -11
- flwr/serverapp/strategy/dp_fixed_clipping.py +11 -14
- flwr/serverapp/strategy/fedadagrad.py +10 -11
- flwr/serverapp/strategy/fedadam.py +10 -11
- flwr/serverapp/strategy/fedavg.py +9 -10
- flwr/serverapp/strategy/fedavgm.py +17 -16
- flwr/serverapp/strategy/fedmedian.py +2 -2
- flwr/serverapp/strategy/fedopt.py +10 -11
- flwr/serverapp/strategy/fedprox.py +7 -8
- flwr/serverapp/strategy/fedtrimmedavg.py +9 -9
- flwr/serverapp/strategy/fedxgb_bagging.py +3 -3
- flwr/serverapp/strategy/fedxgb_cyclic.py +9 -9
- flwr/serverapp/strategy/fedyogi.py +9 -11
- flwr/serverapp/strategy/krum.py +7 -7
- flwr/serverapp/strategy/multikrum.py +9 -9
- flwr/serverapp/strategy/qfedavg.py +17 -16
- flwr/serverapp/strategy/strategy.py +6 -9
- flwr/serverapp/strategy/strategy_utils.py +7 -8
- flwr/simulation/app.py +46 -42
- flwr/simulation/legacy_app.py +12 -12
- flwr/simulation/ray_transport/ray_actor.py +11 -12
- flwr/simulation/ray_transport/ray_client_proxy.py +12 -13
- flwr/simulation/run_simulation.py +44 -43
- flwr/simulation/simulationio_connection.py +4 -4
- flwr/supercore/cli/flower_superexec.py +3 -4
- flwr/supercore/constant.py +52 -0
- flwr/supercore/corestate/corestate.py +24 -3
- flwr/supercore/corestate/in_memory_corestate.py +138 -0
- flwr/supercore/corestate/sqlite_corestate.py +157 -0
- flwr/supercore/ffs/disk_ffs.py +1 -2
- flwr/supercore/ffs/ffs.py +1 -2
- flwr/supercore/ffs/ffs_factory.py +1 -2
- flwr/{common → supercore}/heartbeat.py +20 -25
- flwr/supercore/object_store/in_memory_object_store.py +1 -6
- flwr/supercore/object_store/object_store.py +1 -2
- flwr/supercore/object_store/object_store_factory.py +27 -8
- flwr/supercore/object_store/sqlite_object_store.py +253 -0
- flwr/{client/clientapp → supercore/primitives}/__init__.py +1 -1
- flwr/supercore/primitives/asymmetric.py +117 -0
- flwr/supercore/primitives/asymmetric_ed25519.py +175 -0
- flwr/supercore/sqlite_mixin.py +159 -0
- flwr/supercore/superexec/plugin/base_exec_plugin.py +1 -2
- flwr/supercore/superexec/plugin/exec_plugin.py +3 -3
- flwr/supercore/superexec/run_superexec.py +9 -13
- flwr/supercore/utils.py +20 -0
- flwr/superlink/artifact_provider/artifact_provider.py +1 -2
- flwr/{common → superlink}/auth_plugin/__init__.py +6 -6
- flwr/superlink/auth_plugin/auth_plugin.py +88 -0
- flwr/superlink/auth_plugin/noop_auth_plugin.py +84 -0
- flwr/superlink/federation/__init__.py +24 -0
- flwr/superlink/federation/federation_manager.py +64 -0
- flwr/superlink/federation/noop_federation_manager.py +71 -0
- flwr/superlink/servicer/control/{control_user_auth_interceptor.py → control_account_auth_interceptor.py} +41 -32
- flwr/superlink/servicer/control/control_event_log_interceptor.py +7 -7
- flwr/superlink/servicer/control/control_grpc.py +18 -17
- flwr/superlink/servicer/control/control_license_interceptor.py +3 -3
- flwr/superlink/servicer/control/control_servicer.py +239 -63
- flwr/supernode/cli/flower_supernode.py +74 -26
- flwr/supernode/nodestate/in_memory_nodestate.py +60 -49
- flwr/supernode/nodestate/nodestate.py +7 -8
- flwr/supernode/nodestate/nodestate_factory.py +7 -4
- flwr/supernode/runtime/run_clientapp.py +43 -24
- flwr/supernode/servicer/clientappio/clientappio_servicer.py +40 -10
- flwr/supernode/start_client_internal.py +175 -51
- {flwr-1.22.0.dist-info → flwr-1.24.0.dist-info}/METADATA +8 -8
- flwr-1.24.0.dist-info/RECORD +454 -0
- flwr/common/auth_plugin/auth_plugin.py +0 -149
- flwr/supercore/object_store/utils.py +0 -43
- flwr-1.22.0.dist-info/RECORD +0 -428
- {flwr-1.22.0.dist-info → flwr-1.24.0.dist-info}/WHEEL +0 -0
- {flwr-1.22.0.dist-info → flwr-1.24.0.dist-info}/entry_points.txt +0 -0
flwr/cli/log.py
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
import time
|
|
19
19
|
from logging import DEBUG, ERROR, INFO
|
|
20
20
|
from pathlib import Path
|
|
21
|
-
from typing import Annotated, Any,
|
|
21
|
+
from typing import Annotated, Any, cast
|
|
22
22
|
|
|
23
23
|
import grpc
|
|
24
24
|
import typer
|
|
@@ -35,17 +35,31 @@ from flwr.common.logger import log as logger
|
|
|
35
35
|
from flwr.proto.control_pb2 import StreamLogsRequest # pylint: disable=E0611
|
|
36
36
|
from flwr.proto.control_pb2_grpc import ControlStub
|
|
37
37
|
|
|
38
|
-
from .utils import flwr_cli_grpc_exc_handler, init_channel,
|
|
38
|
+
from .utils import flwr_cli_grpc_exc_handler, init_channel, load_cli_auth_plugin
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
class AllLogsRetrieved(BaseException):
|
|
42
|
-
"""
|
|
42
|
+
"""Exception raised when all available logs have been retrieved.
|
|
43
|
+
|
|
44
|
+
This exception is used internally to signal that the log stream has reached the end
|
|
45
|
+
and all logs have been successfully retrieved.
|
|
46
|
+
"""
|
|
43
47
|
|
|
44
48
|
|
|
45
49
|
def start_stream(
|
|
46
50
|
run_id: int, channel: grpc.Channel, refresh_period: int = CONN_REFRESH_PERIOD
|
|
47
51
|
) -> None:
|
|
48
|
-
"""Start log streaming for a given run ID.
|
|
52
|
+
"""Start log streaming for a given run ID.
|
|
53
|
+
|
|
54
|
+
Parameters
|
|
55
|
+
----------
|
|
56
|
+
run_id : int
|
|
57
|
+
The unique identifier of the run to stream logs from.
|
|
58
|
+
channel : grpc.Channel
|
|
59
|
+
The gRPC channel for communication.
|
|
60
|
+
refresh_period : int (default: CONN_REFRESH_PERIOD)
|
|
61
|
+
Connection refresh period in seconds.
|
|
62
|
+
"""
|
|
49
63
|
stub = ControlStub(channel)
|
|
50
64
|
after_timestamp = 0.0
|
|
51
65
|
try:
|
|
@@ -111,7 +125,17 @@ def stream_logs(
|
|
|
111
125
|
|
|
112
126
|
|
|
113
127
|
def print_logs(run_id: int, channel: grpc.Channel, timeout: int) -> None:
|
|
114
|
-
"""Print logs from the beginning of a run.
|
|
128
|
+
"""Print logs from the beginning of a run.
|
|
129
|
+
|
|
130
|
+
Parameters
|
|
131
|
+
----------
|
|
132
|
+
run_id : int
|
|
133
|
+
The unique identifier of the run to retrieve logs from.
|
|
134
|
+
channel : grpc.Channel
|
|
135
|
+
The gRPC channel for communication.
|
|
136
|
+
timeout : int
|
|
137
|
+
Timeout duration in seconds for the log retrieval request.
|
|
138
|
+
"""
|
|
115
139
|
stub = ControlStub(channel)
|
|
116
140
|
req = StreamLogsRequest(run_id=run_id, after_timestamp=0.0)
|
|
117
141
|
|
|
@@ -143,11 +167,11 @@ def log(
|
|
|
143
167
|
typer.Argument(help="Path of the Flower project to run"),
|
|
144
168
|
] = Path("."),
|
|
145
169
|
federation: Annotated[
|
|
146
|
-
|
|
170
|
+
str | None,
|
|
147
171
|
typer.Argument(help="Name of the federation to run the app on"),
|
|
148
172
|
] = None,
|
|
149
173
|
federation_config_overrides: Annotated[
|
|
150
|
-
|
|
174
|
+
list[str] | None,
|
|
151
175
|
typer.Option(
|
|
152
176
|
"--federation-config",
|
|
153
177
|
help=FEDERATION_CONFIG_HELP_MESSAGE,
|
|
@@ -161,11 +185,15 @@ def log(
|
|
|
161
185
|
),
|
|
162
186
|
] = True,
|
|
163
187
|
) -> None:
|
|
164
|
-
"""Get logs from a
|
|
188
|
+
"""Get logs from a run.
|
|
189
|
+
|
|
190
|
+
Retrieve and display logs from a Flower run. Logs can be streamed in real-time (with
|
|
191
|
+
--stream) or printed once (with --show).
|
|
192
|
+
"""
|
|
165
193
|
typer.secho("Loading project configuration... ", fg=typer.colors.BLUE)
|
|
166
194
|
|
|
167
195
|
pyproject_path = app / "pyproject.toml" if app else None
|
|
168
|
-
config, errors, warnings = load_and_validate(
|
|
196
|
+
config, errors, warnings = load_and_validate(pyproject_path, check_module=False)
|
|
169
197
|
config = process_loaded_project_config(config, errors, warnings)
|
|
170
198
|
federation, federation_config = validate_federation_in_project_config(
|
|
171
199
|
federation, config, federation_config_overrides
|
|
@@ -175,7 +203,7 @@ def log(
|
|
|
175
203
|
try:
|
|
176
204
|
_log_with_control_api(app, federation, federation_config, run_id, stream)
|
|
177
205
|
except Exception as err: # pylint: disable=broad-except
|
|
178
|
-
typer.secho(str(err), fg=typer.colors.RED, bold=True)
|
|
206
|
+
typer.secho(str(err), fg=typer.colors.RED, bold=True, err=True)
|
|
179
207
|
raise typer.Exit(code=1) from None
|
|
180
208
|
|
|
181
209
|
|
|
@@ -186,7 +214,22 @@ def _log_with_control_api(
|
|
|
186
214
|
run_id: int,
|
|
187
215
|
stream: bool,
|
|
188
216
|
) -> None:
|
|
189
|
-
|
|
217
|
+
"""Retrieve logs using the Control API.
|
|
218
|
+
|
|
219
|
+
Parameters
|
|
220
|
+
----------
|
|
221
|
+
app : Path
|
|
222
|
+
Path to the Flower app directory.
|
|
223
|
+
federation : str
|
|
224
|
+
Name of the federation.
|
|
225
|
+
federation_config : dict[str, Any]
|
|
226
|
+
Federation configuration dictionary.
|
|
227
|
+
run_id : int
|
|
228
|
+
The unique identifier of the run to retrieve logs from.
|
|
229
|
+
stream : bool
|
|
230
|
+
If True, stream logs continuously; if False, print once.
|
|
231
|
+
"""
|
|
232
|
+
auth_plugin = load_cli_auth_plugin(app, federation, federation_config)
|
|
190
233
|
channel = init_channel(app, federation_config, auth_plugin)
|
|
191
234
|
|
|
192
235
|
if stream:
|
flwr/cli/login/login.py
CHANGED
|
@@ -16,10 +16,11 @@
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
from pathlib import Path
|
|
19
|
-
from typing import Annotated
|
|
19
|
+
from typing import Annotated
|
|
20
20
|
|
|
21
21
|
import typer
|
|
22
22
|
|
|
23
|
+
from flwr.cli.auth_plugin import LoginError, NoOpCliAuthPlugin
|
|
23
24
|
from flwr.cli.config_utils import (
|
|
24
25
|
exit_if_no_address,
|
|
25
26
|
get_insecure_flag,
|
|
@@ -28,14 +29,19 @@ from flwr.cli.config_utils import (
|
|
|
28
29
|
validate_federation_in_project_config,
|
|
29
30
|
)
|
|
30
31
|
from flwr.cli.constant import FEDERATION_CONFIG_HELP_MESSAGE
|
|
31
|
-
from flwr.common.typing import
|
|
32
|
+
from flwr.common.typing import AccountAuthLoginDetails
|
|
32
33
|
from flwr.proto.control_pb2 import ( # pylint: disable=E0611
|
|
33
34
|
GetLoginDetailsRequest,
|
|
34
35
|
GetLoginDetailsResponse,
|
|
35
36
|
)
|
|
36
37
|
from flwr.proto.control_pb2_grpc import ControlStub
|
|
37
38
|
|
|
38
|
-
from ..utils import
|
|
39
|
+
from ..utils import (
|
|
40
|
+
account_auth_enabled,
|
|
41
|
+
flwr_cli_grpc_exc_handler,
|
|
42
|
+
init_channel,
|
|
43
|
+
load_cli_auth_plugin,
|
|
44
|
+
)
|
|
39
45
|
|
|
40
46
|
|
|
41
47
|
def login( # pylint: disable=R0914
|
|
@@ -44,11 +50,11 @@ def login( # pylint: disable=R0914
|
|
|
44
50
|
typer.Argument(help="Path of the Flower App to run."),
|
|
45
51
|
] = Path("."),
|
|
46
52
|
federation: Annotated[
|
|
47
|
-
|
|
53
|
+
str | None,
|
|
48
54
|
typer.Argument(help="Name of the federation to login into."),
|
|
49
55
|
] = None,
|
|
50
56
|
federation_config_overrides: Annotated[
|
|
51
|
-
|
|
57
|
+
list[str] | None,
|
|
52
58
|
typer.Option(
|
|
53
59
|
"--federation-config",
|
|
54
60
|
help=FEDERATION_CONFIG_HELP_MESSAGE,
|
|
@@ -59,7 +65,7 @@ def login( # pylint: disable=R0914
|
|
|
59
65
|
typer.secho("Loading project configuration... ", fg=typer.colors.BLUE)
|
|
60
66
|
|
|
61
67
|
pyproject_path = app / "pyproject.toml" if app else None
|
|
62
|
-
config, errors, warnings = load_and_validate(
|
|
68
|
+
config, errors, warnings = load_and_validate(pyproject_path, check_module=False)
|
|
63
69
|
|
|
64
70
|
config = process_loaded_project_config(config, errors, warnings)
|
|
65
71
|
federation, federation_config = validate_federation_in_project_config(
|
|
@@ -67,14 +73,16 @@ def login( # pylint: disable=R0914
|
|
|
67
73
|
)
|
|
68
74
|
exit_if_no_address(federation_config, "login")
|
|
69
75
|
|
|
70
|
-
# Check if `enable-
|
|
71
|
-
|
|
76
|
+
# Check if `enable-account-auth` is set to `true`
|
|
77
|
+
|
|
78
|
+
if not account_auth_enabled(federation_config):
|
|
72
79
|
typer.secho(
|
|
73
|
-
|
|
74
|
-
"To enable it, set `enable-
|
|
75
|
-
"configuration.",
|
|
80
|
+
"❌ Account authentication is not enabled for the federation "
|
|
81
|
+
f"'{federation}'. To enable it, set `enable-account-auth = true` "
|
|
82
|
+
"in the federation configuration.",
|
|
76
83
|
fg=typer.colors.RED,
|
|
77
84
|
bold=True,
|
|
85
|
+
err=True,
|
|
78
86
|
)
|
|
79
87
|
raise typer.Exit(code=1)
|
|
80
88
|
# Check if insecure flag is set to `True`
|
|
@@ -85,10 +93,11 @@ def login( # pylint: disable=R0914
|
|
|
85
93
|
"`true` in the federation configuration.",
|
|
86
94
|
fg=typer.colors.RED,
|
|
87
95
|
bold=True,
|
|
96
|
+
err=True,
|
|
88
97
|
)
|
|
89
98
|
raise typer.Exit(code=1)
|
|
90
99
|
|
|
91
|
-
channel = init_channel(app, federation_config,
|
|
100
|
+
channel = init_channel(app, federation_config, NoOpCliAuthPlugin(Path()))
|
|
92
101
|
stub = ControlStub(channel)
|
|
93
102
|
|
|
94
103
|
login_request = GetLoginDetailsRequest()
|
|
@@ -96,28 +105,33 @@ def login( # pylint: disable=R0914
|
|
|
96
105
|
login_response: GetLoginDetailsResponse = stub.GetLoginDetails(login_request)
|
|
97
106
|
|
|
98
107
|
# Get the auth plugin
|
|
99
|
-
|
|
100
|
-
auth_plugin =
|
|
101
|
-
app, federation, federation_config, auth_type
|
|
102
|
-
)
|
|
103
|
-
if auth_plugin is None:
|
|
104
|
-
typer.secho(
|
|
105
|
-
f'❌ Authentication type "{auth_type}" not found',
|
|
106
|
-
fg=typer.colors.RED,
|
|
107
|
-
bold=True,
|
|
108
|
-
)
|
|
109
|
-
raise typer.Exit(code=1)
|
|
108
|
+
authn_type = login_response.authn_type
|
|
109
|
+
auth_plugin = load_cli_auth_plugin(app, federation, federation_config, authn_type)
|
|
110
110
|
|
|
111
111
|
# Login
|
|
112
|
-
details =
|
|
113
|
-
|
|
112
|
+
details = AccountAuthLoginDetails(
|
|
113
|
+
authn_type=login_response.authn_type,
|
|
114
114
|
device_code=login_response.device_code,
|
|
115
115
|
verification_uri_complete=login_response.verification_uri_complete,
|
|
116
116
|
expires_in=login_response.expires_in,
|
|
117
117
|
interval=login_response.interval,
|
|
118
118
|
)
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
try:
|
|
120
|
+
with flwr_cli_grpc_exc_handler():
|
|
121
|
+
credentials = auth_plugin.login(details, stub)
|
|
122
|
+
typer.secho(
|
|
123
|
+
"✅ Login successful.",
|
|
124
|
+
fg=typer.colors.GREEN,
|
|
125
|
+
bold=False,
|
|
126
|
+
)
|
|
127
|
+
except LoginError as e:
|
|
128
|
+
typer.secho(
|
|
129
|
+
f"❌ Login failed: {e.message}",
|
|
130
|
+
fg=typer.colors.RED,
|
|
131
|
+
bold=True,
|
|
132
|
+
err=True,
|
|
133
|
+
)
|
|
134
|
+
raise typer.Exit(code=1) from None
|
|
121
135
|
|
|
122
136
|
# Store the tokens
|
|
123
137
|
auth_plugin.store_tokens(credentials)
|