flwr 1.24.0__py3-none-any.whl → 1.26.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 +1 -1
- flwr/app/__init__.py +4 -1
- flwr/app/message_type.py +29 -0
- flwr/app/metadata.py +5 -2
- flwr/app/user_config.py +19 -0
- flwr/cli/app.py +37 -19
- flwr/cli/app_cmd/publish.py +25 -75
- flwr/cli/app_cmd/review.py +25 -66
- flwr/cli/auth_plugin/auth_plugin.py +5 -10
- flwr/cli/auth_plugin/noop_auth_plugin.py +1 -2
- flwr/cli/auth_plugin/oidc_cli_plugin.py +38 -38
- flwr/cli/build.py +15 -28
- flwr/cli/config/__init__.py +21 -0
- flwr/cli/config/ls.py +71 -0
- flwr/cli/config_migration.py +297 -0
- flwr/cli/config_utils.py +63 -156
- flwr/cli/constant.py +71 -0
- flwr/cli/federation/__init__.py +0 -2
- flwr/cli/federation/ls.py +256 -64
- flwr/cli/flower_config.py +429 -0
- flwr/cli/install.py +23 -62
- flwr/cli/log.py +23 -37
- flwr/cli/login/login.py +29 -63
- flwr/cli/ls.py +72 -61
- flwr/cli/new/new.py +98 -309
- flwr/cli/pull.py +19 -37
- flwr/cli/run/run.py +87 -100
- flwr/cli/run_utils.py +23 -5
- flwr/cli/stop.py +33 -74
- flwr/cli/supernode/ls.py +35 -62
- flwr/cli/supernode/register.py +31 -80
- flwr/cli/supernode/unregister.py +24 -70
- flwr/cli/typing.py +200 -0
- flwr/cli/utils.py +160 -412
- flwr/client/grpc_adapter_client/connection.py +2 -2
- flwr/client/grpc_rere_client/connection.py +9 -6
- flwr/client/grpc_rere_client/grpc_adapter.py +1 -1
- flwr/client/message_handler/message_handler.py +2 -1
- flwr/client/mod/centraldp_mods.py +1 -1
- flwr/client/mod/localdp_mod.py +1 -1
- flwr/client/mod/secure_aggregation/secaggplus_mod.py +1 -1
- flwr/client/rest_client/connection.py +6 -4
- flwr/client/run_info_store.py +2 -1
- flwr/clientapp/client_app.py +2 -1
- flwr/common/__init__.py +3 -2
- flwr/common/args.py +5 -5
- flwr/common/config.py +12 -17
- flwr/common/constant.py +3 -16
- flwr/common/context.py +2 -1
- flwr/common/exit/exit.py +4 -4
- flwr/common/exit/exit_code.py +6 -0
- flwr/common/grpc.py +2 -1
- flwr/common/logger.py +1 -1
- flwr/common/message.py +1 -1
- flwr/common/retry_invoker.py +13 -5
- flwr/common/secure_aggregation/ndarrays_arithmetic.py +5 -2
- flwr/common/serde.py +13 -5
- flwr/common/telemetry.py +1 -1
- flwr/common/typing.py +10 -3
- flwr/compat/client/app.py +6 -9
- flwr/compat/client/grpc_client/connection.py +2 -1
- flwr/compat/common/constant.py +29 -0
- flwr/compat/server/app.py +1 -1
- flwr/proto/clientappio_pb2.py +2 -2
- flwr/proto/clientappio_pb2_grpc.py +104 -88
- flwr/proto/clientappio_pb2_grpc.pyi +140 -80
- flwr/proto/federation_pb2.py +5 -3
- flwr/proto/federation_pb2.pyi +32 -2
- flwr/proto/fleet_pb2.py +10 -10
- flwr/proto/fleet_pb2.pyi +5 -1
- flwr/proto/run_pb2.py +18 -26
- flwr/proto/run_pb2.pyi +10 -58
- flwr/proto/serverappio_pb2.py +2 -2
- flwr/proto/serverappio_pb2_grpc.py +138 -207
- flwr/proto/serverappio_pb2_grpc.pyi +189 -155
- flwr/proto/simulationio_pb2.py +2 -2
- flwr/proto/simulationio_pb2_grpc.py +62 -90
- flwr/proto/simulationio_pb2_grpc.pyi +95 -55
- flwr/server/app.py +7 -13
- flwr/server/compat/grid_client_proxy.py +2 -1
- flwr/server/grid/grpc_grid.py +5 -5
- flwr/server/serverapp/app.py +11 -4
- flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +1 -1
- flwr/server/superlink/fleet/grpc_rere/node_auth_server_interceptor.py +13 -12
- flwr/server/superlink/fleet/message_handler/message_handler.py +42 -2
- flwr/server/superlink/linkstate/__init__.py +2 -2
- flwr/server/superlink/linkstate/in_memory_linkstate.py +36 -10
- flwr/server/superlink/linkstate/linkstate.py +34 -21
- flwr/server/superlink/linkstate/linkstate_factory.py +16 -8
- flwr/server/superlink/linkstate/{sqlite_linkstate.py → sql_linkstate.py} +471 -516
- flwr/server/superlink/linkstate/utils.py +49 -2
- flwr/server/superlink/serverappio/serverappio_servicer.py +1 -33
- flwr/server/superlink/simulation/simulationio_servicer.py +0 -19
- flwr/server/utils/validator.py +1 -1
- flwr/server/workflow/default_workflows.py +2 -1
- flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +1 -1
- flwr/serverapp/strategy/bulyan.py +7 -1
- flwr/serverapp/strategy/dp_fixed_clipping.py +9 -1
- flwr/serverapp/strategy/fedavg.py +1 -1
- flwr/serverapp/strategy/fedxgb_cyclic.py +1 -1
- flwr/simulation/ray_transport/ray_client_proxy.py +2 -6
- flwr/simulation/run_simulation.py +3 -12
- flwr/simulation/simulationio_connection.py +3 -3
- flwr/{common → supercore}/address.py +7 -33
- flwr/supercore/app_utils.py +2 -1
- flwr/supercore/constant.py +27 -2
- flwr/supercore/corestate/{sqlite_corestate.py → sql_corestate.py} +19 -23
- flwr/supercore/credential_store/__init__.py +33 -0
- flwr/supercore/credential_store/credential_store.py +34 -0
- flwr/supercore/credential_store/file_credential_store.py +76 -0
- flwr/{common → supercore}/date.py +0 -11
- flwr/supercore/ffs/disk_ffs.py +1 -1
- flwr/supercore/object_store/object_store_factory.py +14 -6
- flwr/supercore/object_store/{sqlite_object_store.py → sql_object_store.py} +115 -117
- flwr/supercore/sql_mixin.py +315 -0
- flwr/{cli/new/templates → supercore/state}/__init__.py +2 -2
- flwr/{cli/new/templates/app/code/flwr_tune → supercore/state/alembic}/__init__.py +2 -2
- flwr/supercore/state/alembic/env.py +103 -0
- flwr/supercore/state/alembic/script.py.mako +43 -0
- flwr/supercore/state/alembic/utils.py +239 -0
- flwr/{cli/new/templates/app → supercore/state/alembic/versions}/__init__.py +2 -2
- flwr/supercore/state/alembic/versions/rev_2026_01_28_initialize_migration_of_state_tables.py +200 -0
- flwr/supercore/state/schema/README.md +121 -0
- flwr/{cli/new/templates/app/code → supercore/state/schema}/__init__.py +2 -2
- flwr/supercore/state/schema/corestate_tables.py +36 -0
- flwr/supercore/state/schema/linkstate_tables.py +152 -0
- flwr/supercore/state/schema/objectstore_tables.py +90 -0
- flwr/supercore/superexec/run_superexec.py +2 -2
- flwr/supercore/utils.py +225 -0
- flwr/superlink/federation/federation_manager.py +2 -2
- flwr/superlink/federation/noop_federation_manager.py +8 -6
- flwr/superlink/servicer/control/control_grpc.py +2 -0
- flwr/superlink/servicer/control/control_servicer.py +106 -21
- flwr/supernode/cli/flower_supernode.py +2 -1
- flwr/supernode/nodestate/in_memory_nodestate.py +62 -1
- flwr/supernode/nodestate/nodestate.py +45 -0
- flwr/supernode/runtime/run_clientapp.py +14 -14
- flwr/supernode/servicer/clientappio/clientappio_servicer.py +13 -5
- flwr/supernode/start_client_internal.py +17 -10
- {flwr-1.24.0.dist-info → flwr-1.26.0.dist-info}/METADATA +8 -8
- {flwr-1.24.0.dist-info → flwr-1.26.0.dist-info}/RECORD +144 -184
- flwr/cli/federation/show.py +0 -317
- flwr/cli/new/templates/app/.gitignore.tpl +0 -163
- flwr/cli/new/templates/app/LICENSE.tpl +0 -202
- flwr/cli/new/templates/app/README.baseline.md.tpl +0 -127
- flwr/cli/new/templates/app/README.flowertune.md.tpl +0 -68
- flwr/cli/new/templates/app/README.md.tpl +0 -37
- flwr/cli/new/templates/app/code/__init__.baseline.py.tpl +0 -1
- flwr/cli/new/templates/app/code/__init__.py.tpl +0 -1
- flwr/cli/new/templates/app/code/__init__.pytorch_legacy_api.py.tpl +0 -1
- flwr/cli/new/templates/app/code/client.baseline.py.tpl +0 -75
- flwr/cli/new/templates/app/code/client.huggingface.py.tpl +0 -93
- flwr/cli/new/templates/app/code/client.jax.py.tpl +0 -71
- flwr/cli/new/templates/app/code/client.mlx.py.tpl +0 -102
- flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -46
- flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -80
- flwr/cli/new/templates/app/code/client.pytorch_legacy_api.py.tpl +0 -55
- flwr/cli/new/templates/app/code/client.sklearn.py.tpl +0 -108
- flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -82
- flwr/cli/new/templates/app/code/client.xgboost.py.tpl +0 -110
- flwr/cli/new/templates/app/code/dataset.baseline.py.tpl +0 -36
- flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +0 -92
- flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +0 -87
- flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +0 -56
- flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +0 -73
- flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +0 -78
- flwr/cli/new/templates/app/code/model.baseline.py.tpl +0 -66
- flwr/cli/new/templates/app/code/server.baseline.py.tpl +0 -43
- flwr/cli/new/templates/app/code/server.huggingface.py.tpl +0 -42
- flwr/cli/new/templates/app/code/server.jax.py.tpl +0 -39
- flwr/cli/new/templates/app/code/server.mlx.py.tpl +0 -41
- flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -38
- flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -41
- flwr/cli/new/templates/app/code/server.pytorch_legacy_api.py.tpl +0 -31
- flwr/cli/new/templates/app/code/server.sklearn.py.tpl +0 -44
- flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -38
- flwr/cli/new/templates/app/code/server.xgboost.py.tpl +0 -56
- flwr/cli/new/templates/app/code/strategy.baseline.py.tpl +0 -1
- flwr/cli/new/templates/app/code/task.huggingface.py.tpl +0 -98
- flwr/cli/new/templates/app/code/task.jax.py.tpl +0 -57
- flwr/cli/new/templates/app/code/task.mlx.py.tpl +0 -102
- flwr/cli/new/templates/app/code/task.numpy.py.tpl +0 -7
- flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -99
- flwr/cli/new/templates/app/code/task.pytorch_legacy_api.py.tpl +0 -111
- flwr/cli/new/templates/app/code/task.sklearn.py.tpl +0 -67
- flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +0 -52
- flwr/cli/new/templates/app/code/task.xgboost.py.tpl +0 -67
- flwr/cli/new/templates/app/code/utils.baseline.py.tpl +0 -1
- flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +0 -146
- flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +0 -80
- flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +0 -65
- flwr/cli/new/templates/app/pyproject.jax.toml.tpl +0 -52
- flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +0 -56
- flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +0 -49
- flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +0 -53
- flwr/cli/new/templates/app/pyproject.pytorch_legacy_api.toml.tpl +0 -53
- flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +0 -52
- flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +0 -53
- flwr/cli/new/templates/app/pyproject.xgboost.toml.tpl +0 -61
- flwr/common/pyproject.py +0 -42
- flwr/supercore/sqlite_mixin.py +0 -159
- /flwr/{common → supercore}/version.py +0 -0
- {flwr-1.24.0.dist-info → flwr-1.26.0.dist-info}/WHEEL +0 -0
- {flwr-1.24.0.dist-info → flwr-1.26.0.dist-info}/entry_points.txt +0 -0
flwr/cli/login/login.py
CHANGED
|
@@ -15,20 +15,14 @@
|
|
|
15
15
|
"""Flower command line interface `login` command."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from
|
|
19
|
-
from typing import Annotated
|
|
18
|
+
from typing import Annotated, cast
|
|
20
19
|
|
|
20
|
+
import click
|
|
21
21
|
import typer
|
|
22
22
|
|
|
23
23
|
from flwr.cli.auth_plugin import LoginError, NoOpCliAuthPlugin
|
|
24
|
-
from flwr.cli.config_utils import (
|
|
25
|
-
exit_if_no_address,
|
|
26
|
-
get_insecure_flag,
|
|
27
|
-
load_and_validate,
|
|
28
|
-
process_loaded_project_config,
|
|
29
|
-
validate_federation_in_project_config,
|
|
30
|
-
)
|
|
31
24
|
from flwr.cli.constant import FEDERATION_CONFIG_HELP_MESSAGE
|
|
25
|
+
from flwr.cli.utils import init_channel_from_connection
|
|
32
26
|
from flwr.common.typing import AccountAuthLoginDetails
|
|
33
27
|
from flwr.proto.control_pb2 import ( # pylint: disable=E0611
|
|
34
28
|
GetLoginDetailsRequest,
|
|
@@ -36,68 +30,45 @@ from flwr.proto.control_pb2 import ( # pylint: disable=E0611
|
|
|
36
30
|
)
|
|
37
31
|
from flwr.proto.control_pb2_grpc import ControlStub
|
|
38
32
|
|
|
39
|
-
from ..
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
init_channel,
|
|
43
|
-
load_cli_auth_plugin,
|
|
44
|
-
)
|
|
33
|
+
from ..config_migration import migrate, warn_if_federation_config_overrides
|
|
34
|
+
from ..flower_config import read_superlink_connection
|
|
35
|
+
from ..utils import flwr_cli_grpc_exc_handler, load_cli_auth_plugin_from_connection
|
|
45
36
|
|
|
46
37
|
|
|
47
|
-
def login(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
typer.Argument(help="Path of the Flower App to run."),
|
|
51
|
-
] = Path("."),
|
|
52
|
-
federation: Annotated[
|
|
38
|
+
def login(
|
|
39
|
+
ctx: typer.Context,
|
|
40
|
+
superlink: Annotated[
|
|
53
41
|
str | None,
|
|
54
|
-
typer.Argument(help="Name of the
|
|
42
|
+
typer.Argument(help="Name of the SuperLink connection."),
|
|
55
43
|
] = None,
|
|
56
44
|
federation_config_overrides: Annotated[
|
|
57
45
|
list[str] | None,
|
|
58
46
|
typer.Option(
|
|
59
47
|
"--federation-config",
|
|
60
48
|
help=FEDERATION_CONFIG_HELP_MESSAGE,
|
|
49
|
+
hidden=True,
|
|
61
50
|
),
|
|
62
51
|
] = None,
|
|
63
52
|
) -> None:
|
|
64
53
|
"""Login to Flower SuperLink."""
|
|
65
|
-
|
|
54
|
+
# Warn `--federation-config` is ignored
|
|
55
|
+
warn_if_federation_config_overrides(federation_config_overrides)
|
|
66
56
|
|
|
67
|
-
|
|
68
|
-
|
|
57
|
+
# Migrate legacy usage if any
|
|
58
|
+
migrate(superlink, args=ctx.args)
|
|
69
59
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
)
|
|
74
|
-
exit_if_no_address(federation_config, "login")
|
|
60
|
+
# Read superlink connection configuration
|
|
61
|
+
superlink_connection = read_superlink_connection(superlink)
|
|
62
|
+
superlink = superlink_connection.name
|
|
75
63
|
|
|
76
|
-
# Check if `enable-account-auth` is set to `true`
|
|
77
|
-
|
|
78
|
-
if not account_auth_enabled(federation_config):
|
|
79
|
-
typer.secho(
|
|
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.",
|
|
83
|
-
fg=typer.colors.RED,
|
|
84
|
-
bold=True,
|
|
85
|
-
err=True,
|
|
86
|
-
)
|
|
87
|
-
raise typer.Exit(code=1)
|
|
88
64
|
# Check if insecure flag is set to `True`
|
|
89
|
-
insecure
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
"
|
|
93
|
-
"`true` in the federation configuration.",
|
|
94
|
-
fg=typer.colors.RED,
|
|
95
|
-
bold=True,
|
|
96
|
-
err=True,
|
|
65
|
+
if superlink_connection.insecure:
|
|
66
|
+
raise click.ClickException(
|
|
67
|
+
"`flwr login` requires TLS to be enabled. `insecure` must NOT be set to "
|
|
68
|
+
"`true` in the federation configuration."
|
|
97
69
|
)
|
|
98
|
-
raise typer.Exit(code=1)
|
|
99
70
|
|
|
100
|
-
channel =
|
|
71
|
+
channel = init_channel_from_connection(superlink_connection, NoOpCliAuthPlugin())
|
|
101
72
|
stub = ControlStub(channel)
|
|
102
73
|
|
|
103
74
|
login_request = GetLoginDetailsRequest()
|
|
@@ -105,8 +76,9 @@ def login( # pylint: disable=R0914
|
|
|
105
76
|
login_response: GetLoginDetailsResponse = stub.GetLoginDetails(login_request)
|
|
106
77
|
|
|
107
78
|
# Get the auth plugin
|
|
108
|
-
|
|
109
|
-
|
|
79
|
+
authn_plugin = load_cli_auth_plugin_from_connection(
|
|
80
|
+
cast(str, superlink_connection.address), login_response.authn_type
|
|
81
|
+
)
|
|
110
82
|
|
|
111
83
|
# Login
|
|
112
84
|
details = AccountAuthLoginDetails(
|
|
@@ -118,20 +90,14 @@ def login( # pylint: disable=R0914
|
|
|
118
90
|
)
|
|
119
91
|
try:
|
|
120
92
|
with flwr_cli_grpc_exc_handler():
|
|
121
|
-
credentials =
|
|
93
|
+
credentials = authn_plugin.login(details, stub)
|
|
122
94
|
typer.secho(
|
|
123
95
|
"✅ Login successful.",
|
|
124
96
|
fg=typer.colors.GREEN,
|
|
125
97
|
bold=False,
|
|
126
98
|
)
|
|
127
99
|
except LoginError as e:
|
|
128
|
-
|
|
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
|
|
100
|
+
raise click.ClickException(f"Login failed: {e.message}") from None
|
|
135
101
|
|
|
136
102
|
# Store the tokens
|
|
137
|
-
|
|
103
|
+
authn_plugin.store_tokens(credentials)
|
flwr/cli/ls.py
CHANGED
|
@@ -15,51 +15,47 @@
|
|
|
15
15
|
"""Flower command line interface `ls` command."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
import io
|
|
19
18
|
import json
|
|
20
|
-
from
|
|
21
|
-
from typing import Annotated, cast
|
|
19
|
+
from typing import Annotated
|
|
22
20
|
|
|
23
21
|
import typer
|
|
24
22
|
from rich.console import Console
|
|
25
23
|
from rich.table import Table
|
|
26
24
|
from rich.text import Text
|
|
27
25
|
|
|
28
|
-
from flwr.cli.
|
|
29
|
-
exit_if_no_address,
|
|
30
|
-
load_and_validate,
|
|
31
|
-
process_loaded_project_config,
|
|
32
|
-
validate_federation_in_project_config,
|
|
33
|
-
)
|
|
26
|
+
from flwr.cli.config_migration import migrate, warn_if_federation_config_overrides
|
|
34
27
|
from flwr.cli.constant import FEDERATION_CONFIG_HELP_MESSAGE
|
|
35
|
-
from flwr.
|
|
36
|
-
from flwr.common.
|
|
28
|
+
from flwr.cli.flower_config import read_superlink_connection
|
|
29
|
+
from flwr.common.constant import CliOutputFormat, Status, SubStatus
|
|
37
30
|
from flwr.common.serde import run_from_proto
|
|
38
31
|
from flwr.proto.control_pb2 import ( # pylint: disable=E0611
|
|
39
32
|
ListRunsRequest,
|
|
40
33
|
ListRunsResponse,
|
|
41
34
|
)
|
|
42
35
|
from flwr.proto.control_pb2_grpc import ControlStub
|
|
36
|
+
from flwr.supercore.utils import humanize_bytes, humanize_duration
|
|
43
37
|
|
|
44
38
|
from .run_utils import RunRow, format_runs
|
|
45
|
-
from .utils import
|
|
39
|
+
from .utils import (
|
|
40
|
+
cli_output_handler,
|
|
41
|
+
flwr_cli_grpc_exc_handler,
|
|
42
|
+
init_channel_from_connection,
|
|
43
|
+
print_json_to_stdout,
|
|
44
|
+
)
|
|
46
45
|
|
|
47
46
|
|
|
48
47
|
def ls( # pylint: disable=too-many-locals, too-many-branches, R0913, R0917
|
|
49
48
|
ctx: typer.Context,
|
|
50
|
-
|
|
51
|
-
Path,
|
|
52
|
-
typer.Argument(help="Path of the Flower project"),
|
|
53
|
-
] = Path("."),
|
|
54
|
-
federation: Annotated[
|
|
49
|
+
superlink: Annotated[
|
|
55
50
|
str | None,
|
|
56
|
-
typer.Argument(help="Name of the
|
|
51
|
+
typer.Argument(help="Name of the SuperLink connection."),
|
|
57
52
|
] = None,
|
|
58
53
|
federation_config_overrides: Annotated[
|
|
59
54
|
list[str] | None,
|
|
60
55
|
typer.Option(
|
|
61
56
|
"--federation-config",
|
|
62
57
|
help=FEDERATION_CONFIG_HELP_MESSAGE,
|
|
58
|
+
hidden=True,
|
|
63
59
|
),
|
|
64
60
|
] = None,
|
|
65
61
|
runs: Annotated[
|
|
@@ -85,7 +81,7 @@ def ls( # pylint: disable=too-many-locals, too-many-branches, R0913, R0917
|
|
|
85
81
|
),
|
|
86
82
|
] = CliOutputFormat.DEFAULT,
|
|
87
83
|
) -> None:
|
|
88
|
-
"""List the details of one provided run ID or all runs
|
|
84
|
+
"""List the details of one provided run ID or all runs (alias: ls).
|
|
89
85
|
|
|
90
86
|
The following details are displayed:
|
|
91
87
|
|
|
@@ -98,32 +94,23 @@ def ls( # pylint: disable=too-many-locals, too-many-branches, R0913, R0917
|
|
|
98
94
|
|
|
99
95
|
All timestamps follow ISO 8601, UTC and are formatted as ``YYYY-MM-DD HH:MM:SSZ``.
|
|
100
96
|
"""
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
typer.secho("Loading project configuration... ", fg=typer.colors.BLUE)
|
|
111
|
-
|
|
112
|
-
pyproject_path = app / FAB_CONFIG_FILE if app else None
|
|
113
|
-
config, errors, warnings = load_and_validate(pyproject_path, check_module=False)
|
|
114
|
-
config = process_loaded_project_config(config, errors, warnings)
|
|
115
|
-
federation, federation_config = validate_federation_in_project_config(
|
|
116
|
-
federation, config, federation_config_overrides
|
|
117
|
-
)
|
|
118
|
-
exit_if_no_address(federation_config, command_name)
|
|
97
|
+
with cli_output_handler(output_format=output_format) as is_json:
|
|
98
|
+
# Warn `--federation-config` is ignored
|
|
99
|
+
warn_if_federation_config_overrides(federation_config_overrides)
|
|
100
|
+
|
|
101
|
+
# Migrate legacy usage if any
|
|
102
|
+
migrate(superlink, args=ctx.args)
|
|
103
|
+
|
|
104
|
+
# Read superlink connection configuration
|
|
105
|
+
superlink_connection = read_superlink_connection(superlink)
|
|
119
106
|
channel = None
|
|
107
|
+
|
|
120
108
|
try:
|
|
121
109
|
if runs and run_id is not None:
|
|
122
110
|
raise ValueError(
|
|
123
111
|
"The options '--runs' and '--run-id' are mutually exclusive."
|
|
124
112
|
)
|
|
125
|
-
|
|
126
|
-
channel = init_channel(app, federation_config, auth_plugin)
|
|
113
|
+
channel = init_channel_from_connection(superlink_connection)
|
|
127
114
|
stub = ControlStub(channel)
|
|
128
115
|
|
|
129
116
|
# Display information about a specific run ID
|
|
@@ -134,9 +121,9 @@ def ls( # pylint: disable=too-many-locals, too-many-branches, R0913, R0917
|
|
|
134
121
|
else:
|
|
135
122
|
typer.echo("📄 Listing all runs...")
|
|
136
123
|
formatted_runs = _list_runs(stub)
|
|
137
|
-
|
|
138
|
-
if
|
|
139
|
-
|
|
124
|
+
|
|
125
|
+
if is_json:
|
|
126
|
+
print_json_to_stdout(_to_json(formatted_runs))
|
|
140
127
|
else:
|
|
141
128
|
if run_id is not None:
|
|
142
129
|
Console().print(_to_detail_table(formatted_runs[0]))
|
|
@@ -145,22 +132,6 @@ def ls( # pylint: disable=too-many-locals, too-many-branches, R0913, R0917
|
|
|
145
132
|
finally:
|
|
146
133
|
if channel:
|
|
147
134
|
channel.close()
|
|
148
|
-
except (typer.Exit, Exception) as err: # pylint: disable=broad-except
|
|
149
|
-
if suppress_output:
|
|
150
|
-
restore_output()
|
|
151
|
-
e_message = captured_output.getvalue()
|
|
152
|
-
print_json_error(e_message, err)
|
|
153
|
-
else:
|
|
154
|
-
typer.secho(
|
|
155
|
-
f"{err}",
|
|
156
|
-
fg=typer.colors.RED,
|
|
157
|
-
bold=True,
|
|
158
|
-
err=True,
|
|
159
|
-
)
|
|
160
|
-
finally:
|
|
161
|
-
if suppress_output:
|
|
162
|
-
restore_output()
|
|
163
|
-
captured_output.close()
|
|
164
135
|
|
|
165
136
|
|
|
166
137
|
def _get_status_style(status_text: str) -> str:
|
|
@@ -231,7 +202,7 @@ def _to_table(run_list: list[RunRow]) -> Table:
|
|
|
231
202
|
row.federation,
|
|
232
203
|
f"@{row.fab_id}=={row.fab_version}",
|
|
233
204
|
f"[{status_style}]{row.status_text}[/{status_style}]",
|
|
234
|
-
row.elapsed,
|
|
205
|
+
humanize_duration(row.elapsed),
|
|
235
206
|
status_changed_at,
|
|
236
207
|
)
|
|
237
208
|
table.add_row(*formatted_row)
|
|
@@ -265,11 +236,39 @@ def _to_detail_table(run: RunRow) -> Table:
|
|
|
265
236
|
table.add_row("App", f"@{run.fab_id}=={run.fab_version}")
|
|
266
237
|
table.add_row("FAB Hash", f"{run.fab_hash[:8]}...{run.fab_hash[-8:]}")
|
|
267
238
|
table.add_row("Status", f"[{status_style}]{run.status_text}[/{status_style}]")
|
|
268
|
-
table.add_row("Elapsed", f"[blue]{run.elapsed}[/blue]")
|
|
239
|
+
table.add_row("Elapsed", f"[blue]{humanize_duration(run.elapsed)}[/blue]")
|
|
269
240
|
table.add_row("Pending At", run.pending_at)
|
|
270
241
|
table.add_row("Starting At", run.starting_at)
|
|
271
242
|
table.add_row("Running At", run.running_at)
|
|
272
243
|
table.add_row("Finished At", run.finished_at)
|
|
244
|
+
table.add_row(
|
|
245
|
+
"Network traffic (inbound)",
|
|
246
|
+
f"[blue]{humanize_bytes(run.network_traffic_inbound)}[/blue]",
|
|
247
|
+
)
|
|
248
|
+
table.add_row(
|
|
249
|
+
"Network traffic (outbound)",
|
|
250
|
+
f"[blue]{humanize_bytes(run.network_traffic_outbound)}[/blue]",
|
|
251
|
+
)
|
|
252
|
+
table.add_row(
|
|
253
|
+
"Network Traffic (total)",
|
|
254
|
+
"[blue]"
|
|
255
|
+
f"{humanize_bytes(run.network_traffic_inbound + run.network_traffic_outbound)}"
|
|
256
|
+
"[/blue]",
|
|
257
|
+
)
|
|
258
|
+
table.add_row(
|
|
259
|
+
"Compute Time (ServerApp)",
|
|
260
|
+
f"[blue]{humanize_duration(run.compute_time_serverapp)}[/blue]",
|
|
261
|
+
)
|
|
262
|
+
table.add_row(
|
|
263
|
+
"Compute Time (ClientApp)",
|
|
264
|
+
f"[blue]{humanize_duration(run.compute_time_clientapp)}[/blue]",
|
|
265
|
+
)
|
|
266
|
+
table.add_row(
|
|
267
|
+
"Compute Time (total)",
|
|
268
|
+
"[blue]"
|
|
269
|
+
f"{humanize_duration(run.compute_time_serverapp + run.compute_time_clientapp)}"
|
|
270
|
+
"[/blue]",
|
|
271
|
+
)
|
|
273
272
|
|
|
274
273
|
return table
|
|
275
274
|
|
|
@@ -291,7 +290,7 @@ def _to_json(run_list: list[RunRow]) -> str:
|
|
|
291
290
|
for row in run_list:
|
|
292
291
|
runs_list.append(
|
|
293
292
|
{
|
|
294
|
-
"run-id": row.run_id,
|
|
293
|
+
"run-id": f"{row.run_id}",
|
|
295
294
|
"federation": row.federation,
|
|
296
295
|
"fab-id": row.fab_id,
|
|
297
296
|
"fab-name": row.fab_id.split("/")[-1],
|
|
@@ -303,6 +302,18 @@ def _to_json(run_list: list[RunRow]) -> str:
|
|
|
303
302
|
"starting-at": row.starting_at,
|
|
304
303
|
"running-at": row.running_at,
|
|
305
304
|
"finished-at": row.finished_at,
|
|
305
|
+
"network-traffic": {
|
|
306
|
+
"inbound-bytes": row.network_traffic_inbound,
|
|
307
|
+
"outbound-bytes": row.network_traffic_outbound,
|
|
308
|
+
"total-bytes": row.network_traffic_inbound
|
|
309
|
+
+ row.network_traffic_outbound,
|
|
310
|
+
},
|
|
311
|
+
"compute-time": {
|
|
312
|
+
"serverapp-seconds": row.compute_time_serverapp,
|
|
313
|
+
"clientapp-seconds": row.compute_time_clientapp,
|
|
314
|
+
"total-seconds": row.compute_time_serverapp
|
|
315
|
+
+ row.compute_time_clientapp,
|
|
316
|
+
},
|
|
306
317
|
}
|
|
307
318
|
)
|
|
308
319
|
|