Skip to content

Commit

Permalink
refactor(framework) Improve help message (#4672)
Browse files Browse the repository at this point in the history
  • Loading branch information
panh99 authored Dec 11, 2024
1 parent 85b5855 commit 1e5cf1e
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 51 deletions.
20 changes: 18 additions & 2 deletions src/py/flwr/cli/config_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,14 @@ def load_from_string(toml_content: str) -> Optional[dict[str, Any]]:
return None


def validate_project_config(
def process_loaded_project_config(
config: Union[dict[str, Any], None], errors: list[str], warnings: list[str]
) -> dict[str, Any]:
"""Validate and return the Flower project configuration."""
"""Process and return the loaded project configuration.
This function handles errors and warnings from the `load_and_validate` function,
exits on critical issues, and returns the validated configuration.
"""
if config is None:
typer.secho(
"Project configuration could not be loaded.\n"
Expand Down Expand Up @@ -324,3 +328,15 @@ def validate_certificate_in_federation_config(
raise typer.Exit(code=1)

return insecure, root_certificates_bytes


def exit_if_no_address(federation_config: dict[str, Any], cmd: str) -> None:
"""Exit if the provided federation_config has no "address" key."""
if "address" not in federation_config:
typer.secho(
f"❌ `flwr {cmd}` currently works with a SuperLink. Ensure that the correct"
"SuperLink (Exec API) address is provided in `pyproject.toml`.",
fg=typer.colors.RED,
bold=True,
)
raise typer.Exit(code=1)
4 changes: 2 additions & 2 deletions src/py/flwr/cli/config_utils_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@

from .config_utils import (
load,
process_loaded_project_config,
validate,
validate_certificate_in_federation_config,
validate_federation_in_project_config,
validate_fields,
validate_project_config,
)


Expand Down Expand Up @@ -349,7 +349,7 @@ def test_validate_project_config_fail() -> None:

# Execute
with pytest.raises(click.exceptions.Exit) as excinfo:
_ = validate_project_config(config, errors, warnings)
_ = process_loaded_project_config(config, errors, warnings)

# Assert
assert excinfo.value.exit_code == 1
Expand Down
15 changes: 4 additions & 11 deletions src/py/flwr/cli/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@
import typer

from flwr.cli.config_utils import (
exit_if_no_address,
load_and_validate,
process_loaded_project_config,
validate_federation_in_project_config,
validate_project_config,
)
from flwr.common.constant import CONN_RECONNECT_INTERVAL, CONN_REFRESH_PERIOD
from flwr.common.logger import log as logger
Expand Down Expand Up @@ -152,19 +153,11 @@ def log(

pyproject_path = app / "pyproject.toml" if app else None
config, errors, warnings = load_and_validate(path=pyproject_path)
config = validate_project_config(config, errors, warnings)
config = process_loaded_project_config(config, errors, warnings)
federation, federation_config = validate_federation_in_project_config(
federation, config
)

if "address" not in federation_config:
typer.secho(
"❌ `flwr log` currently works with Exec API. Ensure that the correct"
"Exec API address is provided in the `pyproject.toml`.",
fg=typer.colors.RED,
bold=True,
)
raise typer.Exit(code=1)
exit_if_no_address(federation_config, "log")

_log_with_exec_api(app, federation, federation_config, run_id, stream)

Expand Down
16 changes: 4 additions & 12 deletions src/py/flwr/cli/login/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
import typer

from flwr.cli.config_utils import (
exit_if_no_address,
load_and_validate,
process_loaded_project_config,
validate_federation_in_project_config,
validate_project_config,
)
from flwr.common.constant import AUTH_TYPE
from flwr.proto.exec_pb2 import ( # pylint: disable=E0611
Expand Down Expand Up @@ -50,20 +51,11 @@ def login( # pylint: disable=R0914
pyproject_path = app / "pyproject.toml" if app else None
config, errors, warnings = load_and_validate(path=pyproject_path)

config = validate_project_config(config, errors, warnings)
config = process_loaded_project_config(config, errors, warnings)
federation, federation_config = validate_federation_in_project_config(
federation, config
)

if "address" not in federation_config:
typer.secho(
"❌ `flwr login` currently works with a SuperLink. Ensure that the correct"
"SuperLink (Exec API) address is provided in `pyproject.toml`.",
fg=typer.colors.RED,
bold=True,
)
raise typer.Exit(code=1)

exit_if_no_address(federation_config, "login")
channel = init_channel(app, federation_config, None)
stub = ExecStub(channel)

Expand Down
15 changes: 4 additions & 11 deletions src/py/flwr/cli/ls.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@
from typer import Exit

from flwr.cli.config_utils import (
exit_if_no_address,
load_and_validate,
process_loaded_project_config,
validate_federation_in_project_config,
validate_project_config,
)
from flwr.common.constant import FAB_CONFIG_FILE, CliOutputFormat, SubStatus
from flwr.common.date import format_timedelta, isoformat8601_utc
Expand Down Expand Up @@ -92,19 +93,11 @@ def ls( # pylint: disable=too-many-locals, too-many-branches

pyproject_path = app / FAB_CONFIG_FILE if app else None
config, errors, warnings = load_and_validate(path=pyproject_path)
config = validate_project_config(config, errors, warnings)
config = process_loaded_project_config(config, errors, warnings)
federation, federation_config = validate_federation_in_project_config(
federation, config
)

if "address" not in federation_config:
typer.secho(
"❌ `flwr ls` currently works with Exec API. Ensure that the correct"
"Exec API address is provided in the `pyproject.toml`.",
fg=typer.colors.RED,
bold=True,
)
raise typer.Exit(code=1)
exit_if_no_address(federation_config, "ls")

try:
if runs and run_id is not None:
Expand Down
4 changes: 2 additions & 2 deletions src/py/flwr/cli/run/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
from flwr.cli.config_utils import (
get_fab_metadata,
load_and_validate,
process_loaded_project_config,
validate_federation_in_project_config,
validate_project_config,
)
from flwr.common.config import (
flatten_dict,
Expand Down Expand Up @@ -101,7 +101,7 @@ def run(

pyproject_path = app / "pyproject.toml" if app else None
config, errors, warnings = load_and_validate(path=pyproject_path)
config = validate_project_config(config, errors, warnings)
config = process_loaded_project_config(config, errors, warnings)
federation, federation_config = validate_federation_in_project_config(
federation, config
)
Expand Down
15 changes: 4 additions & 11 deletions src/py/flwr/cli/stop.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@
import typer

from flwr.cli.config_utils import (
exit_if_no_address,
load_and_validate,
process_loaded_project_config,
validate_federation_in_project_config,
validate_project_config,
)
from flwr.common.constant import FAB_CONFIG_FILE
from flwr.proto.exec_pb2 import StopRunRequest, StopRunResponse # pylint: disable=E0611
Expand Down Expand Up @@ -52,19 +53,11 @@ def stop(

pyproject_path = app / FAB_CONFIG_FILE if app else None
config, errors, warnings = load_and_validate(path=pyproject_path)
config = validate_project_config(config, errors, warnings)
config = process_loaded_project_config(config, errors, warnings)
federation, federation_config = validate_federation_in_project_config(
federation, config
)

if "address" not in federation_config:
typer.secho(
"❌ `flwr stop` currently works with Exec API. Ensure that the correct"
"Exec API address is provided in the `pyproject.toml`.",
fg=typer.colors.RED,
bold=True,
)
raise typer.Exit(code=1)
exit_if_no_address(federation_config, "stop")

try:
auth_plugin = try_obtain_cli_auth_plugin(app, federation, federation_config)
Expand Down

0 comments on commit 1e5cf1e

Please sign in to comment.