From dc1f710001a5f0c0ebfe1cefe8c9772b24c463fc Mon Sep 17 00:00:00 2001 From: Chong Shen Ng Date: Thu, 8 Aug 2024 11:50:16 +0100 Subject: [PATCH 01/13] Initial commit --- pyproject.toml | 1 + src/py/flwr/client/supernode/__init__.py | 2 ++ src/py/flwr/client/supernode/app.py | 35 ++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 7a176d4d87f..52a7274d4bd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,6 +59,7 @@ flower-supernode = "flwr.client:run_supernode" flower-client-app = "flwr.client:run_client_app" flower-server-app = "flwr.server:run_server_app" flower-simulation = "flwr.simulation.run_simulation:run_simulation_from_cli" +flower-exec-client-app = "flwr.client.supernode:exec_client_app" [tool.poetry.dependencies] python = "^3.8" diff --git a/src/py/flwr/client/supernode/__init__.py b/src/py/flwr/client/supernode/__init__.py index bc505f69387..8ab13f521dc 100644 --- a/src/py/flwr/client/supernode/__init__.py +++ b/src/py/flwr/client/supernode/__init__.py @@ -15,10 +15,12 @@ """Flower SuperNode.""" +from .app import exec_client_app as exec_client_app from .app import run_client_app as run_client_app from .app import run_supernode as run_supernode __all__ = [ + "exec_client_app", "run_client_app", "run_supernode", ] diff --git a/src/py/flwr/client/supernode/app.py b/src/py/flwr/client/supernode/app.py index 2c60f803f96..80faa73a78f 100644 --- a/src/py/flwr/client/supernode/app.py +++ b/src/py/flwr/client/supernode/app.py @@ -119,6 +119,17 @@ def run_client_app() -> None: register_exit_handlers(event_type=EventType.RUN_CLIENT_APP_LEAVE) +def exec_client_app() -> None: + """Run process-isolated Flower client app.""" + log(INFO, "Starting Flower ClientApp") + + event(EventType.RUN_CLIENT_APP_ENTER) + + # args = _parse_args_exec_client_app().parse_args() + + register_exit_handlers(event_type=EventType.RUN_CLIENT_APP_LEAVE) + + def _warn_deprecated_server_arg(args: argparse.Namespace) -> None: """Warn about the deprecated argument `--server`.""" if args.server != ADDRESS_FLEET_API_GRPC_RERE: @@ -275,6 +286,13 @@ def _parse_args_run_supernode() -> argparse.ArgumentParser: - `$HOME/.flwr/` in all other cases """, ) + parser.add_argument( + "--isolate", + action="store_true", + help="Run the ClientApp in an isolated process from the SuperNode." + "In this mode, the ClientApp and SuperNode communicate via gRPC." + "By default, both SuperNode and ClientApp run in the same process.", + ) return parser @@ -294,6 +312,23 @@ def _parse_args_run_client_app() -> argparse.ArgumentParser: return parser +def _parse_args_exec_client_app() -> argparse.ArgumentParser: + """Parse exec-client-app command line arguments.""" + parser = argparse.ArgumentParser( + description="Run a Flower client app", + ) + parser.add_argument( + "--address", + help="Address of SuperNode", + ) + parser.add_argument( + "--token", + help="Unique token generated by SuperNode for each client app execution", + ) + + return parser + + def _parse_args_common(parser: argparse.ArgumentParser) -> None: parser.add_argument( "--insecure", From eaed17b51a0dc479e9318fa35069f53f43d21eff Mon Sep 17 00:00:00 2001 From: Chong Shen Ng Date: Fri, 9 Aug 2024 10:20:01 +0100 Subject: [PATCH 02/13] Update internal command to flwr-clientapp --- pyproject.toml | 4 ++-- src/py/flwr/client/supernode/__init__.py | 4 ++-- src/py/flwr/client/supernode/app.py | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 52a7274d4bd..00416de5f21 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,7 +59,7 @@ flower-supernode = "flwr.client:run_supernode" flower-client-app = "flwr.client:run_client_app" flower-server-app = "flwr.server:run_server_app" flower-simulation = "flwr.simulation.run_simulation:run_simulation_from_cli" -flower-exec-client-app = "flwr.client.supernode:exec_client_app" +flwr-clientapp = "flwr.client.supernode:flwr_clientapp" [tool.poetry.dependencies] python = "^3.8" @@ -70,7 +70,7 @@ protobuf = "^4.25.2" cryptography = "^42.0.4" pycryptodome = "^3.18.0" iterators = "^0.0.2" -typer = { version = "^0.9.0", extras=["all"] } +typer = { version = "^0.9.0", extras = ["all"] } tomli = "^2.0.1" tomli-w = "^1.0.0" pathspec = "^0.12.1" diff --git a/src/py/flwr/client/supernode/__init__.py b/src/py/flwr/client/supernode/__init__.py index 8ab13f521dc..ffd7865ea71 100644 --- a/src/py/flwr/client/supernode/__init__.py +++ b/src/py/flwr/client/supernode/__init__.py @@ -15,12 +15,12 @@ """Flower SuperNode.""" -from .app import exec_client_app as exec_client_app from .app import run_client_app as run_client_app +from .app import run_clientapp as run_clientapp from .app import run_supernode as run_supernode __all__ = [ - "exec_client_app", + "run_clientapp", "run_client_app", "run_supernode", ] diff --git a/src/py/flwr/client/supernode/app.py b/src/py/flwr/client/supernode/app.py index f6128d312b7..ad407b86d4c 100644 --- a/src/py/flwr/client/supernode/app.py +++ b/src/py/flwr/client/supernode/app.py @@ -120,13 +120,13 @@ def run_client_app() -> None: register_exit_handlers(event_type=EventType.RUN_CLIENT_APP_LEAVE) -def exec_client_app() -> None: +def flwr_clientapp() -> None: """Run process-isolated Flower client app.""" log(INFO, "Starting Flower ClientApp") event(EventType.RUN_CLIENT_APP_ENTER) - # args = _parse_args_exec_client_app().parse_args() + # args = _parse_args_flwr_clientapp().parse_args() register_exit_handlers(event_type=EventType.RUN_CLIENT_APP_LEAVE) @@ -327,8 +327,8 @@ def _parse_args_run_client_app() -> argparse.ArgumentParser: return parser -def _parse_args_exec_client_app() -> argparse.ArgumentParser: - """Parse exec-client-app command line arguments.""" +def _parse_args_flwr_clientapp() -> argparse.ArgumentParser: + """Parse run-clientapp command line arguments.""" parser = argparse.ArgumentParser( description="Run a Flower client app", ) From 4b320779df15bba1018c6b86f2a38c9b4884d349 Mon Sep 17 00:00:00 2001 From: Chong Shen Ng Date: Fri, 9 Aug 2024 10:27:30 +0100 Subject: [PATCH 03/13] Update __init__.py --- src/py/flwr/client/supernode/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/py/flwr/client/supernode/__init__.py b/src/py/flwr/client/supernode/__init__.py index ffd7865ea71..128d0286d62 100644 --- a/src/py/flwr/client/supernode/__init__.py +++ b/src/py/flwr/client/supernode/__init__.py @@ -15,12 +15,12 @@ """Flower SuperNode.""" +from .app import flwr_clientapp as flwr_clientapp from .app import run_client_app as run_client_app -from .app import run_clientapp as run_clientapp from .app import run_supernode as run_supernode __all__ = [ - "run_clientapp", + "flwr_clientapp", "run_client_app", "run_supernode", ] From ed64df181df2157f53c7550960e6916ce7a93337 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Sun, 11 Aug 2024 01:56:55 +0200 Subject: [PATCH 04/13] Update src/py/flwr/client/supernode/app.py --- src/py/flwr/client/supernode/app.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/py/flwr/client/supernode/app.py b/src/py/flwr/client/supernode/app.py index ad407b86d4c..c8b7e23e100 100644 --- a/src/py/flwr/client/supernode/app.py +++ b/src/py/flwr/client/supernode/app.py @@ -124,12 +124,6 @@ def flwr_clientapp() -> None: """Run process-isolated Flower client app.""" log(INFO, "Starting Flower ClientApp") - event(EventType.RUN_CLIENT_APP_ENTER) - - # args = _parse_args_flwr_clientapp().parse_args() - - register_exit_handlers(event_type=EventType.RUN_CLIENT_APP_LEAVE) - def _warn_deprecated_server_arg(args: argparse.Namespace) -> None: """Warn about the deprecated argument `--server`.""" From 1a059ee886d65ac301db3cf92f646f171dd2cf70 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Sun, 11 Aug 2024 01:58:07 +0200 Subject: [PATCH 05/13] Update src/py/flwr/client/supernode/app.py --- src/py/flwr/client/supernode/app.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/py/flwr/client/supernode/app.py b/src/py/flwr/client/supernode/app.py index c8b7e23e100..727facccdb1 100644 --- a/src/py/flwr/client/supernode/app.py +++ b/src/py/flwr/client/supernode/app.py @@ -291,9 +291,9 @@ def _parse_args_run_supernode() -> argparse.ArgumentParser: parser.add_argument( "--isolate", action="store_true", - help="Run the ClientApp in an isolated process from the SuperNode." - "In this mode, the ClientApp and SuperNode communicate via gRPC." - "By default, both SuperNode and ClientApp run in the same process.", + help="Run `ClientApp` in an isolated process from the SuperNode." + "In this mode, `ClientApp` and SuperNode communicate via gRPC." + "By default, both SuperNode and `ClientApp` run in the same process.", ) return parser From e269e2e9791c40a4a94aa71dc3fed11823464a99 Mon Sep 17 00:00:00 2001 From: Chong Shen Ng Date: Sun, 11 Aug 2024 21:49:00 +0100 Subject: [PATCH 06/13] Address comments --- src/py/flwr/client/supernode/app.py | 44 +++++++++++++---------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/src/py/flwr/client/supernode/app.py b/src/py/flwr/client/supernode/app.py index 727facccdb1..d049bf3684c 100644 --- a/src/py/flwr/client/supernode/app.py +++ b/src/py/flwr/client/supernode/app.py @@ -124,6 +124,26 @@ def flwr_clientapp() -> None: """Run process-isolated Flower client app.""" log(INFO, "Starting Flower ClientApp") + parser = argparse.ArgumentParser( + description="Run a Flower client app", + ) + parser.add_argument( + "--address", + help="Address of SuperNode", + ) + parser.add_argument( + "--token", + help="Unique token generated by SuperNode for each client app execution", + ) + args = parser.parse_args() + log( + DEBUG, + "Staring isolated `ClientApp` connected to SuperNode at %s " + "with the following token %s.", + args.address, + args.token, + ) + def _warn_deprecated_server_arg(args: argparse.Namespace) -> None: """Warn about the deprecated argument `--server`.""" @@ -288,13 +308,6 @@ def _parse_args_run_supernode() -> argparse.ArgumentParser: - `$HOME/.flwr/` in all other cases """, ) - parser.add_argument( - "--isolate", - action="store_true", - help="Run `ClientApp` in an isolated process from the SuperNode." - "In this mode, `ClientApp` and SuperNode communicate via gRPC." - "By default, both SuperNode and `ClientApp` run in the same process.", - ) return parser @@ -321,23 +334,6 @@ def _parse_args_run_client_app() -> argparse.ArgumentParser: return parser -def _parse_args_flwr_clientapp() -> argparse.ArgumentParser: - """Parse run-clientapp command line arguments.""" - parser = argparse.ArgumentParser( - description="Run a Flower client app", - ) - parser.add_argument( - "--address", - help="Address of SuperNode", - ) - parser.add_argument( - "--token", - help="Unique token generated by SuperNode for each client app execution", - ) - - return parser - - def _parse_args_common(parser: argparse.ArgumentParser) -> None: parser.add_argument( "--insecure", From 76670273e1a4843f6f73f1a5639d65683854ff8b Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Mon, 12 Aug 2024 23:16:11 +0200 Subject: [PATCH 07/13] Update src/py/flwr/client/supernode/app.py --- src/py/flwr/client/supernode/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/supernode/app.py b/src/py/flwr/client/supernode/app.py index d049bf3684c..f86975cfeee 100644 --- a/src/py/flwr/client/supernode/app.py +++ b/src/py/flwr/client/supernode/app.py @@ -125,7 +125,7 @@ def flwr_clientapp() -> None: log(INFO, "Starting Flower ClientApp") parser = argparse.ArgumentParser( - description="Run a Flower client app", + description="Run a Flower ClientApp", ) parser.add_argument( "--address", From 28388d7cefeadb089748284670e4a10546a5b759 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Mon, 12 Aug 2024 23:16:33 +0200 Subject: [PATCH 08/13] Update src/py/flwr/client/supernode/app.py --- src/py/flwr/client/supernode/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/supernode/app.py b/src/py/flwr/client/supernode/app.py index f86975cfeee..88f23571467 100644 --- a/src/py/flwr/client/supernode/app.py +++ b/src/py/flwr/client/supernode/app.py @@ -121,7 +121,7 @@ def run_client_app() -> None: def flwr_clientapp() -> None: - """Run process-isolated Flower client app.""" + """Run process-isolated Flower ClientApp.""" log(INFO, "Starting Flower ClientApp") parser = argparse.ArgumentParser( From 11d155cdfabe0d19b89f5bed2a542fa49411709c Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Mon, 12 Aug 2024 23:17:31 +0200 Subject: [PATCH 09/13] Update src/py/flwr/client/supernode/app.py --- src/py/flwr/client/supernode/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/supernode/app.py b/src/py/flwr/client/supernode/app.py index 88f23571467..497367fabd2 100644 --- a/src/py/flwr/client/supernode/app.py +++ b/src/py/flwr/client/supernode/app.py @@ -129,7 +129,7 @@ def flwr_clientapp() -> None: ) parser.add_argument( "--address", - help="Address of SuperNode", + help="Address of SuperNode `ClientAppIo` gRPC servicer", ) parser.add_argument( "--token", From ed7b33d826a5e9a3e2b79e153b704bf1ceee4320 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Mon, 12 Aug 2024 23:17:51 +0200 Subject: [PATCH 10/13] Update src/py/flwr/client/supernode/app.py --- src/py/flwr/client/supernode/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/supernode/app.py b/src/py/flwr/client/supernode/app.py index 497367fabd2..be967ab3e74 100644 --- a/src/py/flwr/client/supernode/app.py +++ b/src/py/flwr/client/supernode/app.py @@ -133,7 +133,7 @@ def flwr_clientapp() -> None: ) parser.add_argument( "--token", - help="Unique token generated by SuperNode for each client app execution", + help="Unique token generated by SuperNode for each ClientApp execution", ) args = parser.parse_args() log( From e3d9365a78a5bb6a9409f69c0fdf90fc54e072af Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Mon, 12 Aug 2024 23:18:25 +0200 Subject: [PATCH 11/13] Update src/py/flwr/client/supernode/app.py --- src/py/flwr/client/supernode/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/supernode/app.py b/src/py/flwr/client/supernode/app.py index be967ab3e74..54f902b9b6c 100644 --- a/src/py/flwr/client/supernode/app.py +++ b/src/py/flwr/client/supernode/app.py @@ -138,7 +138,7 @@ def flwr_clientapp() -> None: args = parser.parse_args() log( DEBUG, - "Staring isolated `ClientApp` connected to SuperNode at %s " + "Staring isolated `ClientApp` connected to SuperNode ClientAppIo at %s " "with the following token %s.", args.address, args.token, From ba358ac442435265bea57a3852d70105307644ca Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Mon, 12 Aug 2024 23:19:04 +0200 Subject: [PATCH 12/13] Update src/py/flwr/client/supernode/app.py --- src/py/flwr/client/supernode/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/supernode/app.py b/src/py/flwr/client/supernode/app.py index 54f902b9b6c..1650d0fcfb1 100644 --- a/src/py/flwr/client/supernode/app.py +++ b/src/py/flwr/client/supernode/app.py @@ -139,7 +139,7 @@ def flwr_clientapp() -> None: log( DEBUG, "Staring isolated `ClientApp` connected to SuperNode ClientAppIo at %s " - "with the following token %s.", + "with the token %s", args.address, args.token, ) From d6654ba68f6859b3ee7c1354b8094f63ae3e50a7 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Mon, 12 Aug 2024 23:20:02 +0200 Subject: [PATCH 13/13] Update src/py/flwr/client/supernode/app.py --- src/py/flwr/client/supernode/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/supernode/app.py b/src/py/flwr/client/supernode/app.py index 1650d0fcfb1..5840b57c0ab 100644 --- a/src/py/flwr/client/supernode/app.py +++ b/src/py/flwr/client/supernode/app.py @@ -129,7 +129,7 @@ def flwr_clientapp() -> None: ) parser.add_argument( "--address", - help="Address of SuperNode `ClientAppIo` gRPC servicer", + help="Address of SuperNode ClientAppIo gRPC servicer", ) parser.add_argument( "--token",