flwr-nightly 1.10.0.dev20240611__py3-none-any.whl → 1.10.0.dev20240613__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.

Potentially problematic release.


This version of flwr-nightly might be problematic. Click here for more details.

Files changed (42) hide show
  1. flwr/cli/app.py +2 -0
  2. flwr/cli/build.py +4 -15
  3. flwr/cli/config_utils.py +64 -7
  4. flwr/cli/install.py +211 -0
  5. flwr/cli/utils.py +14 -0
  6. flwr/client/app.py +18 -10
  7. flwr/client/grpc_rere_client/client_interceptor.py +1 -1
  8. flwr/client/grpc_rere_client/connection.py +1 -2
  9. flwr/client/rest_client/connection.py +1 -2
  10. flwr/client/supernode/app.py +141 -38
  11. flwr/common/config.py +28 -0
  12. flwr/common/constant.py +2 -0
  13. flwr/common/object_ref.py +13 -9
  14. flwr/common/telemetry.py +4 -0
  15. flwr/proto/driver_pb2.py +20 -19
  16. flwr/proto/driver_pb2_grpc.py +35 -0
  17. flwr/proto/driver_pb2_grpc.pyi +14 -0
  18. flwr/proto/exec_pb2.py +30 -0
  19. flwr/proto/exec_pb2.pyi +32 -0
  20. flwr/proto/exec_pb2_grpc.py +67 -0
  21. flwr/proto/exec_pb2_grpc.pyi +27 -0
  22. flwr/proto/fleet_pb2.py +28 -33
  23. flwr/proto/fleet_pb2.pyi +0 -42
  24. flwr/proto/fleet_pb2_grpc.py +7 -6
  25. flwr/proto/fleet_pb2_grpc.pyi +5 -4
  26. flwr/proto/run_pb2.py +30 -0
  27. flwr/proto/run_pb2.pyi +52 -0
  28. flwr/proto/run_pb2_grpc.py +4 -0
  29. flwr/proto/run_pb2_grpc.pyi +4 -0
  30. flwr/server/__init__.py +0 -4
  31. flwr/server/app.py +16 -186
  32. flwr/server/superlink/driver/driver_servicer.py +7 -0
  33. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +1 -2
  34. flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +1 -2
  35. flwr/server/superlink/fleet/message_handler/message_handler.py +5 -3
  36. flwr/server/superlink/fleet/rest_rere/rest_api.py +1 -1
  37. flwr/superexec/__init__.py +19 -0
  38. {flwr_nightly-1.10.0.dev20240611.dist-info → flwr_nightly-1.10.0.dev20240613.dist-info}/METADATA +1 -1
  39. {flwr_nightly-1.10.0.dev20240611.dist-info → flwr_nightly-1.10.0.dev20240613.dist-info}/RECORD +42 -31
  40. {flwr_nightly-1.10.0.dev20240611.dist-info → flwr_nightly-1.10.0.dev20240613.dist-info}/entry_points.txt +1 -2
  41. {flwr_nightly-1.10.0.dev20240611.dist-info → flwr_nightly-1.10.0.dev20240613.dist-info}/LICENSE +0 -0
  42. {flwr_nightly-1.10.0.dev20240611.dist-info → flwr_nightly-1.10.0.dev20240613.dist-info}/WHEEL +0 -0
@@ -20,6 +20,7 @@ from logging import DEBUG, INFO, WARN
20
20
  from pathlib import Path
21
21
  from typing import Callable, Optional, Tuple
22
22
 
23
+ import tomli
23
24
  from cryptography.exceptions import UnsupportedAlgorithm
24
25
  from cryptography.hazmat.primitives.asymmetric import ec
25
26
  from cryptography.hazmat.primitives.serialization import (
@@ -27,8 +28,10 @@ from cryptography.hazmat.primitives.serialization import (
27
28
  load_ssh_public_key,
28
29
  )
29
30
 
31
+ from flwr.cli.config_utils import validate_fields
30
32
  from flwr.client.client_app import ClientApp, LoadClientAppError
31
33
  from flwr.common import EventType, event
34
+ from flwr.common.config import get_flwr_dir
32
35
  from flwr.common.exit_handlers import register_exit_handlers
33
36
  from flwr.common.logger import log, warn_deprecated_feature
34
37
  from flwr.common.object_ref import load_app, validate
@@ -44,11 +47,23 @@ def run_supernode() -> None:
44
47
 
45
48
  event(EventType.RUN_SUPERNODE_ENTER)
46
49
 
47
- _ = _parse_args_run_supernode().parse_args()
50
+ args = _parse_args_run_supernode().parse_args()
48
51
 
49
- log(
50
- DEBUG,
51
- "Flower SuperNode starting...",
52
+ _warn_deprecated_server_arg(args)
53
+
54
+ root_certificates = _get_certificates(args)
55
+ load_fn = _get_load_client_app_fn(args, multi_app=True)
56
+ authentication_keys = _try_setup_client_authentication(args)
57
+
58
+ _start_client_internal(
59
+ server_address=args.server,
60
+ load_client_app_fn=load_fn,
61
+ transport="rest" if args.rest else "grpc-rere",
62
+ root_certificates=root_certificates,
63
+ insecure=args.insecure,
64
+ authentication_keys=authentication_keys,
65
+ max_retries=args.max_retries,
66
+ max_wait_time=args.max_wait_time,
52
67
  )
53
68
 
54
69
  # Graceful shutdown
@@ -65,6 +80,27 @@ def run_client_app() -> None:
65
80
 
66
81
  args = _parse_args_run_client_app().parse_args()
67
82
 
83
+ _warn_deprecated_server_arg(args)
84
+
85
+ root_certificates = _get_certificates(args)
86
+ load_fn = _get_load_client_app_fn(args, multi_app=False)
87
+ authentication_keys = _try_setup_client_authentication(args)
88
+
89
+ _start_client_internal(
90
+ server_address=args.superlink,
91
+ load_client_app_fn=load_fn,
92
+ transport="rest" if args.rest else "grpc-rere",
93
+ root_certificates=root_certificates,
94
+ insecure=args.insecure,
95
+ authentication_keys=authentication_keys,
96
+ max_retries=args.max_retries,
97
+ max_wait_time=args.max_wait_time,
98
+ )
99
+ register_exit_handlers(event_type=EventType.RUN_CLIENT_APP_LEAVE)
100
+
101
+
102
+ def _warn_deprecated_server_arg(args: argparse.Namespace) -> None:
103
+ """Warn about the deprecated argument `--server`."""
68
104
  if args.server != ADDRESS_FLEET_API_GRPC_RERE:
69
105
  warn = "Passing flag --server is deprecated. Use --superlink instead."
70
106
  warn_deprecated_feature(warn)
@@ -82,27 +118,6 @@ def run_client_app() -> None:
82
118
  else:
83
119
  args.superlink = args.server
84
120
 
85
- root_certificates = _get_certificates(args)
86
- log(
87
- DEBUG,
88
- "Flower will load ClientApp `%s`",
89
- getattr(args, "client-app"),
90
- )
91
- load_fn = _get_load_client_app_fn(args)
92
- authentication_keys = _try_setup_client_authentication(args)
93
-
94
- _start_client_internal(
95
- server_address=args.superlink,
96
- load_client_app_fn=load_fn,
97
- transport="rest" if args.rest else "grpc-rere",
98
- root_certificates=root_certificates,
99
- insecure=args.insecure,
100
- authentication_keys=authentication_keys,
101
- max_retries=args.max_retries,
102
- max_wait_time=args.max_wait_time,
103
- )
104
- register_exit_handlers(event_type=EventType.RUN_CLIENT_APP_LEAVE)
105
-
106
121
 
107
122
  def _get_certificates(args: argparse.Namespace) -> Optional[bytes]:
108
123
  """Load certificates if specified in args."""
@@ -140,24 +155,112 @@ def _get_certificates(args: argparse.Namespace) -> Optional[bytes]:
140
155
 
141
156
 
142
157
  def _get_load_client_app_fn(
143
- args: argparse.Namespace,
144
- ) -> Callable[[], ClientApp]:
145
- """Get the load_client_app_fn function."""
146
- client_app_dir = args.dir
147
- if client_app_dir is not None:
148
- sys.path.insert(0, client_app_dir)
158
+ args: argparse.Namespace, multi_app: bool
159
+ ) -> Callable[[str, str], ClientApp]:
160
+ """Get the load_client_app_fn function.
161
+
162
+ If `multi_app` is True, this function loads the specified ClientApp
163
+ based on `fab_id` and `fab_version`. If `fab_id` is empty, a default
164
+ ClientApp will be loaded.
165
+
166
+ If `multi_app` is False, it ignores `fab_id` and `fab_version` and
167
+ loads a default ClientApp.
168
+ """
169
+ # Find the Flower directory containing Flower Apps (only for multi-app)
170
+ flwr_dir = Path("")
171
+ if "flwr_dir" in args:
172
+ if args.flwr_dir is None:
173
+ flwr_dir = get_flwr_dir()
174
+ else:
175
+ flwr_dir = Path(args.flwr_dir)
176
+
177
+ sys.path.insert(0, str(flwr_dir))
149
178
 
150
- app_ref: str = getattr(args, "client-app")
151
- valid, error_msg = validate(app_ref)
152
- if not valid and error_msg:
153
- raise LoadClientAppError(error_msg) from None
179
+ default_app_ref: str = getattr(args, "client-app")
154
180
 
155
- def _load() -> ClientApp:
156
- client_app = load_app(app_ref, LoadClientAppError)
181
+ if not multi_app:
182
+ log(
183
+ DEBUG,
184
+ "Flower SuperNode will load and validate ClientApp `%s`",
185
+ getattr(args, "client-app"),
186
+ )
187
+ valid, error_msg = validate(default_app_ref)
188
+ if not valid and error_msg:
189
+ raise LoadClientAppError(error_msg) from None
190
+
191
+ def _load(fab_id: str, fab_version: str) -> ClientApp:
192
+ # If multi-app feature is disabled
193
+ if not multi_app:
194
+ # Set sys.path
195
+ sys.path[0] = args.dir
196
+
197
+ # Set app reference
198
+ client_app_ref = default_app_ref
199
+ # If multi-app feature is enabled but the fab id is not specified
200
+ elif fab_id == "":
201
+ if default_app_ref == "":
202
+ raise LoadClientAppError(
203
+ "Invalid FAB ID: The FAB ID is empty.",
204
+ ) from None
205
+
206
+ log(WARN, "FAB ID is not provided; the default ClientApp will be loaded.")
207
+ # Set sys.path
208
+ sys.path[0] = args.dir
209
+
210
+ # Set app reference
211
+ client_app_ref = default_app_ref
212
+ # If multi-app feature is enabled
213
+ else:
214
+ # Check the fab_id
215
+ if fab_id.count("/") != 1:
216
+ raise LoadClientAppError(
217
+ f"Invalid FAB ID: {fab_id}",
218
+ ) from None
219
+ username, project_name = fab_id.split("/")
220
+
221
+ # Locate the directory
222
+ project_dir = flwr_dir / "apps" / username / project_name / fab_version
223
+
224
+ # Check if the directory exists
225
+ if not project_dir.exists():
226
+ raise LoadClientAppError(
227
+ f"Invalid Flower App directory: {project_dir}",
228
+ ) from None
229
+
230
+ # Load pyproject.toml file
231
+ toml_path = project_dir / "pyproject.toml"
232
+ if not toml_path.is_file():
233
+ raise LoadClientAppError(
234
+ f"Cannot find pyproject.toml in {project_dir}",
235
+ ) from None
236
+ with open(toml_path, encoding="utf-8") as toml_file:
237
+ config = tomli.loads(toml_file.read())
238
+
239
+ # Validate pyproject.toml fields
240
+ is_valid, errors, _ = validate_fields(config)
241
+ if not is_valid:
242
+ error_msg = "\n".join([f" - {error}" for error in errors])
243
+ raise LoadClientAppError(
244
+ f"Invalid pyproject.toml:\n{error_msg}",
245
+ ) from None
246
+
247
+ # Set sys.path
248
+ sys.path[0] = str(project_dir)
249
+
250
+ # Set app reference
251
+ client_app_ref = config["flower"]["components"]["clientapp"]
252
+
253
+ # Load ClientApp
254
+ log(
255
+ DEBUG,
256
+ "Loading ClientApp `%s`",
257
+ client_app_ref,
258
+ )
259
+ client_app = load_app(client_app_ref, LoadClientAppError)
157
260
 
158
261
  if not isinstance(client_app, ClientApp):
159
262
  raise LoadClientAppError(
160
- f"Attribute {app_ref} is not of type {ClientApp}",
263
+ f"Attribute {client_app_ref} is not of type {ClientApp}",
161
264
  ) from None
162
265
 
163
266
  return client_app
flwr/common/config.py ADDED
@@ -0,0 +1,28 @@
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Provide functions for managing global Flower config."""
16
+
17
+ import os
18
+ from pathlib import Path
19
+
20
+
21
+ def get_flwr_dir() -> Path:
22
+ """Return the Flower home directory based on env variables."""
23
+ return Path(
24
+ os.getenv(
25
+ "FLWR_HOME",
26
+ f"{os.getenv('XDG_DATA_HOME', os.getenv('HOME'))}/.flwr",
27
+ )
28
+ )
flwr/common/constant.py CHANGED
@@ -36,6 +36,8 @@ TRANSPORT_TYPES = [
36
36
  TRANSPORT_TYPE_VCE,
37
37
  ]
38
38
 
39
+ SUPEREXEC_DEFAULT_ADDRESS = "0.0.0.0:9093"
40
+
39
41
  # Constants for ping
40
42
  PING_DEFAULT_INTERVAL = 30
41
43
  PING_CALL_TIMEOUT = 5
flwr/common/object_ref.py CHANGED
@@ -30,6 +30,7 @@ attribute.
30
30
 
31
31
  def validate(
32
32
  module_attribute_str: str,
33
+ check_module: bool = True,
33
34
  ) -> Tuple[bool, Optional[str]]:
34
35
  """Validate object reference.
35
36
 
@@ -56,15 +57,18 @@ def validate(
56
57
  f"Missing attribute in {module_attribute_str}{OBJECT_REF_HELP_STR}",
57
58
  )
58
59
 
59
- # Load module
60
- module = find_spec(module_str)
61
- if module and module.origin:
62
- if not _find_attribute_in_module(module.origin, attributes_str):
63
- return (
64
- False,
65
- f"Unable to find attribute {attributes_str} in module {module_str}"
66
- f"{OBJECT_REF_HELP_STR}",
67
- )
60
+ if check_module:
61
+ # Load module
62
+ module = find_spec(module_str)
63
+ if module and module.origin:
64
+ if not _find_attribute_in_module(module.origin, attributes_str):
65
+ return (
66
+ False,
67
+ f"Unable to find attribute {attributes_str} in module {module_str}"
68
+ f"{OBJECT_REF_HELP_STR}",
69
+ )
70
+ return (True, None)
71
+ else:
68
72
  return (True, None)
69
73
 
70
74
  return (
flwr/common/telemetry.py CHANGED
@@ -164,6 +164,10 @@ class EventType(str, Enum):
164
164
  RUN_SUPERNODE_ENTER = auto()
165
165
  RUN_SUPERNODE_LEAVE = auto()
166
166
 
167
+ # SuperExec
168
+ RUN_SUPEREXEC_ENTER = auto()
169
+ RUN_SUPEREXEC_LEAVE = auto()
170
+
167
171
 
168
172
  # Use the ThreadPoolExecutor with max_workers=1 to have a queue
169
173
  # and also ensure that telemetry calls are not blocking.
flwr/proto/driver_pb2.py CHANGED
@@ -14,31 +14,32 @@ _sym_db = _symbol_database.Default()
14
14
 
15
15
  from flwr.proto import node_pb2 as flwr_dot_proto_dot_node__pb2
16
16
  from flwr.proto import task_pb2 as flwr_dot_proto_dot_task__pb2
17
+ from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2
17
18
 
18
19
 
19
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x66lwr/proto/driver.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x15\x66lwr/proto/task.proto\"7\n\x10\x43reateRunRequest\x12\x0e\n\x06\x66\x61\x62_id\x18\x01 \x01(\t\x12\x13\n\x0b\x66\x61\x62_version\x18\x02 \x01(\t\"#\n\x11\x43reateRunResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\x12\"!\n\x0fGetNodesRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x12\"3\n\x10GetNodesResponse\x12\x1f\n\x05nodes\x18\x01 \x03(\x0b\x32\x10.flwr.proto.Node\"@\n\x12PushTaskInsRequest\x12*\n\rtask_ins_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.TaskIns\"\'\n\x13PushTaskInsResponse\x12\x10\n\x08task_ids\x18\x02 \x03(\t\"F\n\x12PullTaskResRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x10\n\x08task_ids\x18\x02 \x03(\t\"A\n\x13PullTaskResResponse\x12*\n\rtask_res_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.TaskRes2\xc1\x02\n\x06\x44river\x12J\n\tCreateRun\x12\x1c.flwr.proto.CreateRunRequest\x1a\x1d.flwr.proto.CreateRunResponse\"\x00\x12G\n\x08GetNodes\x12\x1b.flwr.proto.GetNodesRequest\x1a\x1c.flwr.proto.GetNodesResponse\"\x00\x12P\n\x0bPushTaskIns\x12\x1e.flwr.proto.PushTaskInsRequest\x1a\x1f.flwr.proto.PushTaskInsResponse\"\x00\x12P\n\x0bPullTaskRes\x12\x1e.flwr.proto.PullTaskResRequest\x1a\x1f.flwr.proto.PullTaskResResponse\"\x00\x62\x06proto3')
20
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x66lwr/proto/driver.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x15\x66lwr/proto/task.proto\x1a\x14\x66lwr/proto/run.proto\"7\n\x10\x43reateRunRequest\x12\x0e\n\x06\x66\x61\x62_id\x18\x01 \x01(\t\x12\x13\n\x0b\x66\x61\x62_version\x18\x02 \x01(\t\"#\n\x11\x43reateRunResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\x12\"!\n\x0fGetNodesRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x12\"3\n\x10GetNodesResponse\x12\x1f\n\x05nodes\x18\x01 \x03(\x0b\x32\x10.flwr.proto.Node\"@\n\x12PushTaskInsRequest\x12*\n\rtask_ins_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.TaskIns\"\'\n\x13PushTaskInsResponse\x12\x10\n\x08task_ids\x18\x02 \x03(\t\"F\n\x12PullTaskResRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x10\n\x08task_ids\x18\x02 \x03(\t\"A\n\x13PullTaskResResponse\x12*\n\rtask_res_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.TaskRes2\x84\x03\n\x06\x44river\x12J\n\tCreateRun\x12\x1c.flwr.proto.CreateRunRequest\x1a\x1d.flwr.proto.CreateRunResponse\"\x00\x12G\n\x08GetNodes\x12\x1b.flwr.proto.GetNodesRequest\x1a\x1c.flwr.proto.GetNodesResponse\"\x00\x12P\n\x0bPushTaskIns\x12\x1e.flwr.proto.PushTaskInsRequest\x1a\x1f.flwr.proto.PushTaskInsResponse\"\x00\x12P\n\x0bPullTaskRes\x12\x1e.flwr.proto.PullTaskResRequest\x1a\x1f.flwr.proto.PullTaskResResponse\"\x00\x12\x41\n\x06GetRun\x12\x19.flwr.proto.GetRunRequest\x1a\x1a.flwr.proto.GetRunResponse\"\x00\x62\x06proto3')
20
21
 
21
22
  _globals = globals()
22
23
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
23
24
  _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.driver_pb2', _globals)
24
25
  if _descriptor._USE_C_DESCRIPTORS == False:
25
26
  DESCRIPTOR._options = None
26
- _globals['_CREATERUNREQUEST']._serialized_start=85
27
- _globals['_CREATERUNREQUEST']._serialized_end=140
28
- _globals['_CREATERUNRESPONSE']._serialized_start=142
29
- _globals['_CREATERUNRESPONSE']._serialized_end=177
30
- _globals['_GETNODESREQUEST']._serialized_start=179
31
- _globals['_GETNODESREQUEST']._serialized_end=212
32
- _globals['_GETNODESRESPONSE']._serialized_start=214
33
- _globals['_GETNODESRESPONSE']._serialized_end=265
34
- _globals['_PUSHTASKINSREQUEST']._serialized_start=267
35
- _globals['_PUSHTASKINSREQUEST']._serialized_end=331
36
- _globals['_PUSHTASKINSRESPONSE']._serialized_start=333
37
- _globals['_PUSHTASKINSRESPONSE']._serialized_end=372
38
- _globals['_PULLTASKRESREQUEST']._serialized_start=374
39
- _globals['_PULLTASKRESREQUEST']._serialized_end=444
40
- _globals['_PULLTASKRESRESPONSE']._serialized_start=446
41
- _globals['_PULLTASKRESRESPONSE']._serialized_end=511
42
- _globals['_DRIVER']._serialized_start=514
43
- _globals['_DRIVER']._serialized_end=835
27
+ _globals['_CREATERUNREQUEST']._serialized_start=107
28
+ _globals['_CREATERUNREQUEST']._serialized_end=162
29
+ _globals['_CREATERUNRESPONSE']._serialized_start=164
30
+ _globals['_CREATERUNRESPONSE']._serialized_end=199
31
+ _globals['_GETNODESREQUEST']._serialized_start=201
32
+ _globals['_GETNODESREQUEST']._serialized_end=234
33
+ _globals['_GETNODESRESPONSE']._serialized_start=236
34
+ _globals['_GETNODESRESPONSE']._serialized_end=287
35
+ _globals['_PUSHTASKINSREQUEST']._serialized_start=289
36
+ _globals['_PUSHTASKINSREQUEST']._serialized_end=353
37
+ _globals['_PUSHTASKINSRESPONSE']._serialized_start=355
38
+ _globals['_PUSHTASKINSRESPONSE']._serialized_end=394
39
+ _globals['_PULLTASKRESREQUEST']._serialized_start=396
40
+ _globals['_PULLTASKRESREQUEST']._serialized_end=466
41
+ _globals['_PULLTASKRESRESPONSE']._serialized_start=468
42
+ _globals['_PULLTASKRESRESPONSE']._serialized_end=533
43
+ _globals['_DRIVER']._serialized_start=536
44
+ _globals['_DRIVER']._serialized_end=924
44
45
  # @@protoc_insertion_point(module_scope)
@@ -3,6 +3,7 @@
3
3
  import grpc
4
4
 
5
5
  from flwr.proto import driver_pb2 as flwr_dot_proto_dot_driver__pb2
6
+ from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2
6
7
 
7
8
 
8
9
  class DriverStub(object):
@@ -34,6 +35,11 @@ class DriverStub(object):
34
35
  request_serializer=flwr_dot_proto_dot_driver__pb2.PullTaskResRequest.SerializeToString,
35
36
  response_deserializer=flwr_dot_proto_dot_driver__pb2.PullTaskResResponse.FromString,
36
37
  )
38
+ self.GetRun = channel.unary_unary(
39
+ '/flwr.proto.Driver/GetRun',
40
+ request_serializer=flwr_dot_proto_dot_run__pb2.GetRunRequest.SerializeToString,
41
+ response_deserializer=flwr_dot_proto_dot_run__pb2.GetRunResponse.FromString,
42
+ )
37
43
 
38
44
 
39
45
  class DriverServicer(object):
@@ -67,6 +73,13 @@ class DriverServicer(object):
67
73
  context.set_details('Method not implemented!')
68
74
  raise NotImplementedError('Method not implemented!')
69
75
 
76
+ def GetRun(self, request, context):
77
+ """Get run details
78
+ """
79
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
80
+ context.set_details('Method not implemented!')
81
+ raise NotImplementedError('Method not implemented!')
82
+
70
83
 
71
84
  def add_DriverServicer_to_server(servicer, server):
72
85
  rpc_method_handlers = {
@@ -90,6 +103,11 @@ def add_DriverServicer_to_server(servicer, server):
90
103
  request_deserializer=flwr_dot_proto_dot_driver__pb2.PullTaskResRequest.FromString,
91
104
  response_serializer=flwr_dot_proto_dot_driver__pb2.PullTaskResResponse.SerializeToString,
92
105
  ),
106
+ 'GetRun': grpc.unary_unary_rpc_method_handler(
107
+ servicer.GetRun,
108
+ request_deserializer=flwr_dot_proto_dot_run__pb2.GetRunRequest.FromString,
109
+ response_serializer=flwr_dot_proto_dot_run__pb2.GetRunResponse.SerializeToString,
110
+ ),
93
111
  }
94
112
  generic_handler = grpc.method_handlers_generic_handler(
95
113
  'flwr.proto.Driver', rpc_method_handlers)
@@ -167,3 +185,20 @@ class Driver(object):
167
185
  flwr_dot_proto_dot_driver__pb2.PullTaskResResponse.FromString,
168
186
  options, channel_credentials,
169
187
  insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
188
+
189
+ @staticmethod
190
+ def GetRun(request,
191
+ target,
192
+ options=(),
193
+ channel_credentials=None,
194
+ call_credentials=None,
195
+ insecure=False,
196
+ compression=None,
197
+ wait_for_ready=None,
198
+ timeout=None,
199
+ metadata=None):
200
+ return grpc.experimental.unary_unary(request, target, '/flwr.proto.Driver/GetRun',
201
+ flwr_dot_proto_dot_run__pb2.GetRunRequest.SerializeToString,
202
+ flwr_dot_proto_dot_run__pb2.GetRunResponse.FromString,
203
+ options, channel_credentials,
204
+ insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@@ -4,6 +4,7 @@ isort:skip_file
4
4
  """
5
5
  import abc
6
6
  import flwr.proto.driver_pb2
7
+ import flwr.proto.run_pb2
7
8
  import grpc
8
9
 
9
10
  class DriverStub:
@@ -28,6 +29,11 @@ class DriverStub:
28
29
  flwr.proto.driver_pb2.PullTaskResResponse]
29
30
  """Get task results"""
30
31
 
32
+ GetRun: grpc.UnaryUnaryMultiCallable[
33
+ flwr.proto.run_pb2.GetRunRequest,
34
+ flwr.proto.run_pb2.GetRunResponse]
35
+ """Get run details"""
36
+
31
37
 
32
38
  class DriverServicer(metaclass=abc.ABCMeta):
33
39
  @abc.abstractmethod
@@ -62,5 +68,13 @@ class DriverServicer(metaclass=abc.ABCMeta):
62
68
  """Get task results"""
63
69
  pass
64
70
 
71
+ @abc.abstractmethod
72
+ def GetRun(self,
73
+ request: flwr.proto.run_pb2.GetRunRequest,
74
+ context: grpc.ServicerContext,
75
+ ) -> flwr.proto.run_pb2.GetRunResponse:
76
+ """Get run details"""
77
+ pass
78
+
65
79
 
66
80
  def add_DriverServicer_to_server(servicer: DriverServicer, server: grpc.Server) -> None: ...
flwr/proto/exec_pb2.py ADDED
@@ -0,0 +1,30 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # source: flwr/proto/exec.proto
4
+ # Protobuf Python Version: 4.25.0
5
+ """Generated protocol buffer code."""
6
+ from google.protobuf import descriptor as _descriptor
7
+ from google.protobuf import descriptor_pool as _descriptor_pool
8
+ from google.protobuf import symbol_database as _symbol_database
9
+ from google.protobuf.internal import builder as _builder
10
+ # @@protoc_insertion_point(imports)
11
+
12
+ _sym_db = _symbol_database.Default()
13
+
14
+
15
+
16
+
17
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/exec.proto\x12\nflwr.proto\"#\n\x0fStartRunRequest\x12\x10\n\x08\x66\x61\x62_file\x18\x01 \x01(\x0c\"\"\n\x10StartRunResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\x12\x32O\n\x04\x45xec\x12G\n\x08StartRun\x12\x1b.flwr.proto.StartRunRequest\x1a\x1c.flwr.proto.StartRunResponse\"\x00\x62\x06proto3')
18
+
19
+ _globals = globals()
20
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
21
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.exec_pb2', _globals)
22
+ if _descriptor._USE_C_DESCRIPTORS == False:
23
+ DESCRIPTOR._options = None
24
+ _globals['_STARTRUNREQUEST']._serialized_start=37
25
+ _globals['_STARTRUNREQUEST']._serialized_end=72
26
+ _globals['_STARTRUNRESPONSE']._serialized_start=74
27
+ _globals['_STARTRUNRESPONSE']._serialized_end=108
28
+ _globals['_EXEC']._serialized_start=110
29
+ _globals['_EXEC']._serialized_end=189
30
+ # @@protoc_insertion_point(module_scope)
@@ -0,0 +1,32 @@
1
+ """
2
+ @generated by mypy-protobuf. Do not edit manually!
3
+ isort:skip_file
4
+ """
5
+ import builtins
6
+ import google.protobuf.descriptor
7
+ import google.protobuf.message
8
+ import typing_extensions
9
+
10
+ DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
11
+
12
+ class StartRunRequest(google.protobuf.message.Message):
13
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
14
+ FAB_FILE_FIELD_NUMBER: builtins.int
15
+ fab_file: builtins.bytes
16
+ def __init__(self,
17
+ *,
18
+ fab_file: builtins.bytes = ...,
19
+ ) -> None: ...
20
+ def ClearField(self, field_name: typing_extensions.Literal["fab_file",b"fab_file"]) -> None: ...
21
+ global___StartRunRequest = StartRunRequest
22
+
23
+ class StartRunResponse(google.protobuf.message.Message):
24
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
25
+ RUN_ID_FIELD_NUMBER: builtins.int
26
+ run_id: builtins.int
27
+ def __init__(self,
28
+ *,
29
+ run_id: builtins.int = ...,
30
+ ) -> None: ...
31
+ def ClearField(self, field_name: typing_extensions.Literal["run_id",b"run_id"]) -> None: ...
32
+ global___StartRunResponse = StartRunResponse
@@ -0,0 +1,67 @@
1
+ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
2
+ """Client and server classes corresponding to protobuf-defined services."""
3
+ import grpc
4
+
5
+ from flwr.proto import exec_pb2 as flwr_dot_proto_dot_exec__pb2
6
+
7
+
8
+ class ExecStub(object):
9
+ """Missing associated documentation comment in .proto file."""
10
+
11
+ def __init__(self, channel):
12
+ """Constructor.
13
+
14
+ Args:
15
+ channel: A grpc.Channel.
16
+ """
17
+ self.StartRun = channel.unary_unary(
18
+ '/flwr.proto.Exec/StartRun',
19
+ request_serializer=flwr_dot_proto_dot_exec__pb2.StartRunRequest.SerializeToString,
20
+ response_deserializer=flwr_dot_proto_dot_exec__pb2.StartRunResponse.FromString,
21
+ )
22
+
23
+
24
+ class ExecServicer(object):
25
+ """Missing associated documentation comment in .proto file."""
26
+
27
+ def StartRun(self, request, context):
28
+ """Start run upon request
29
+ """
30
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
31
+ context.set_details('Method not implemented!')
32
+ raise NotImplementedError('Method not implemented!')
33
+
34
+
35
+ def add_ExecServicer_to_server(servicer, server):
36
+ rpc_method_handlers = {
37
+ 'StartRun': grpc.unary_unary_rpc_method_handler(
38
+ servicer.StartRun,
39
+ request_deserializer=flwr_dot_proto_dot_exec__pb2.StartRunRequest.FromString,
40
+ response_serializer=flwr_dot_proto_dot_exec__pb2.StartRunResponse.SerializeToString,
41
+ ),
42
+ }
43
+ generic_handler = grpc.method_handlers_generic_handler(
44
+ 'flwr.proto.Exec', rpc_method_handlers)
45
+ server.add_generic_rpc_handlers((generic_handler,))
46
+
47
+
48
+ # This class is part of an EXPERIMENTAL API.
49
+ class Exec(object):
50
+ """Missing associated documentation comment in .proto file."""
51
+
52
+ @staticmethod
53
+ def StartRun(request,
54
+ target,
55
+ options=(),
56
+ channel_credentials=None,
57
+ call_credentials=None,
58
+ insecure=False,
59
+ compression=None,
60
+ wait_for_ready=None,
61
+ timeout=None,
62
+ metadata=None):
63
+ return grpc.experimental.unary_unary(request, target, '/flwr.proto.Exec/StartRun',
64
+ flwr_dot_proto_dot_exec__pb2.StartRunRequest.SerializeToString,
65
+ flwr_dot_proto_dot_exec__pb2.StartRunResponse.FromString,
66
+ options, channel_credentials,
67
+ insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@@ -0,0 +1,27 @@
1
+ """
2
+ @generated by mypy-protobuf. Do not edit manually!
3
+ isort:skip_file
4
+ """
5
+ import abc
6
+ import flwr.proto.exec_pb2
7
+ import grpc
8
+
9
+ class ExecStub:
10
+ def __init__(self, channel: grpc.Channel) -> None: ...
11
+ StartRun: grpc.UnaryUnaryMultiCallable[
12
+ flwr.proto.exec_pb2.StartRunRequest,
13
+ flwr.proto.exec_pb2.StartRunResponse]
14
+ """Start run upon request"""
15
+
16
+
17
+ class ExecServicer(metaclass=abc.ABCMeta):
18
+ @abc.abstractmethod
19
+ def StartRun(self,
20
+ request: flwr.proto.exec_pb2.StartRunRequest,
21
+ context: grpc.ServicerContext,
22
+ ) -> flwr.proto.exec_pb2.StartRunResponse:
23
+ """Start run upon request"""
24
+ pass
25
+
26
+
27
+ def add_ExecServicer_to_server(servicer: ExecServicer, server: grpc.Server) -> None: ...