flwr-nightly 1.10.0.dev20240612__py3-none-any.whl → 1.10.0.dev20240624__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 (130) hide show
  1. flwr/cli/app.py +3 -0
  2. flwr/cli/build.py +6 -8
  3. flwr/cli/config_utils.py +53 -3
  4. flwr/cli/install.py +35 -20
  5. flwr/cli/new/new.py +104 -28
  6. flwr/cli/new/templates/app/README.flowertune.md.tpl +56 -0
  7. flwr/cli/new/templates/app/code/flwr_tune/__init__.py +15 -0
  8. flwr/cli/new/templates/app/code/flwr_tune/app.py.tpl +86 -0
  9. flwr/cli/new/templates/app/code/flwr_tune/client.py.tpl +124 -0
  10. flwr/cli/new/templates/app/code/flwr_tune/config.yaml.tpl +34 -0
  11. flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +57 -0
  12. flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +59 -0
  13. flwr/cli/new/templates/app/code/flwr_tune/server.py.tpl +48 -0
  14. flwr/cli/new/templates/app/code/flwr_tune/static_config.yaml.tpl +11 -0
  15. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +42 -0
  16. flwr/cli/run/run.py +46 -2
  17. flwr/client/__init__.py +1 -1
  18. flwr/client/app.py +22 -10
  19. flwr/client/client_app.py +1 -1
  20. flwr/client/dpfedavg_numpy_client.py +1 -1
  21. flwr/client/grpc_adapter_client/__init__.py +15 -0
  22. flwr/client/grpc_adapter_client/connection.py +94 -0
  23. flwr/client/grpc_client/connection.py +5 -1
  24. flwr/client/grpc_rere_client/__init__.py +1 -1
  25. flwr/client/grpc_rere_client/connection.py +9 -2
  26. flwr/client/grpc_rere_client/grpc_adapter.py +133 -0
  27. flwr/client/message_handler/__init__.py +1 -1
  28. flwr/client/message_handler/message_handler.py +1 -1
  29. flwr/client/mod/__init__.py +4 -4
  30. flwr/client/mod/secure_aggregation/__init__.py +1 -1
  31. flwr/client/mod/utils.py +1 -1
  32. flwr/client/rest_client/__init__.py +1 -1
  33. flwr/client/rest_client/connection.py +10 -2
  34. flwr/client/supernode/app.py +141 -41
  35. flwr/common/__init__.py +12 -12
  36. flwr/common/address.py +1 -1
  37. flwr/common/config.py +73 -0
  38. flwr/common/constant.py +16 -1
  39. flwr/common/date.py +1 -1
  40. flwr/common/dp.py +1 -1
  41. flwr/common/grpc.py +1 -1
  42. flwr/common/object_ref.py +39 -5
  43. flwr/common/record/__init__.py +1 -1
  44. flwr/common/secure_aggregation/__init__.py +1 -1
  45. flwr/common/secure_aggregation/crypto/__init__.py +1 -1
  46. flwr/common/secure_aggregation/crypto/shamir.py +1 -1
  47. flwr/common/secure_aggregation/crypto/symmetric_encryption.py +1 -1
  48. flwr/common/secure_aggregation/ndarrays_arithmetic.py +1 -1
  49. flwr/common/secure_aggregation/quantization.py +1 -1
  50. flwr/common/secure_aggregation/secaggplus_constants.py +1 -1
  51. flwr/common/secure_aggregation/secaggplus_utils.py +1 -1
  52. flwr/common/telemetry.py +4 -0
  53. flwr/common/typing.py +9 -0
  54. flwr/common/version.py +14 -0
  55. flwr/proto/exec_pb2.py +34 -0
  56. flwr/proto/exec_pb2.pyi +55 -0
  57. flwr/proto/exec_pb2_grpc.py +101 -0
  58. flwr/proto/exec_pb2_grpc.pyi +41 -0
  59. flwr/proto/fab_pb2.py +30 -0
  60. flwr/proto/fab_pb2.pyi +56 -0
  61. flwr/proto/fab_pb2_grpc.py +4 -0
  62. flwr/proto/fab_pb2_grpc.pyi +4 -0
  63. flwr/server/__init__.py +2 -2
  64. flwr/server/app.py +62 -25
  65. flwr/server/compat/app.py +1 -1
  66. flwr/server/compat/app_utils.py +1 -1
  67. flwr/server/compat/driver_client_proxy.py +1 -1
  68. flwr/server/driver/driver.py +6 -0
  69. flwr/server/driver/grpc_driver.py +85 -63
  70. flwr/server/driver/inmemory_driver.py +28 -26
  71. flwr/server/run_serverapp.py +65 -20
  72. flwr/server/strategy/__init__.py +2 -2
  73. flwr/server/strategy/bulyan.py +1 -1
  74. flwr/server/strategy/dpfedavg_adaptive.py +1 -1
  75. flwr/server/strategy/dpfedavg_fixed.py +1 -1
  76. flwr/server/strategy/fedadagrad.py +1 -1
  77. flwr/server/strategy/fedadam.py +1 -1
  78. flwr/server/strategy/fedavg_android.py +1 -1
  79. flwr/server/strategy/fedavgm.py +1 -1
  80. flwr/server/strategy/fedmedian.py +1 -1
  81. flwr/server/strategy/fedopt.py +1 -1
  82. flwr/server/strategy/fedprox.py +1 -1
  83. flwr/server/strategy/fedxgb_bagging.py +1 -1
  84. flwr/server/strategy/fedxgb_cyclic.py +1 -1
  85. flwr/server/strategy/fedxgb_nn_avg.py +1 -1
  86. flwr/server/strategy/fedyogi.py +1 -1
  87. flwr/server/strategy/krum.py +1 -1
  88. flwr/server/strategy/qfedavg.py +1 -1
  89. flwr/server/superlink/driver/__init__.py +1 -1
  90. flwr/server/superlink/driver/driver_grpc.py +1 -1
  91. flwr/server/superlink/driver/driver_servicer.py +15 -3
  92. flwr/server/superlink/fleet/__init__.py +1 -1
  93. flwr/server/superlink/fleet/grpc_adapter/__init__.py +15 -0
  94. flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +131 -0
  95. flwr/server/superlink/fleet/grpc_bidi/__init__.py +1 -1
  96. flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +1 -1
  97. flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +1 -1
  98. flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +1 -1
  99. flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +5 -1
  100. flwr/server/superlink/fleet/grpc_rere/__init__.py +1 -1
  101. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +1 -1
  102. flwr/server/superlink/fleet/message_handler/__init__.py +1 -1
  103. flwr/server/superlink/fleet/message_handler/message_handler.py +4 -4
  104. flwr/server/superlink/fleet/rest_rere/__init__.py +1 -1
  105. flwr/server/superlink/fleet/rest_rere/rest_api.py +1 -1
  106. flwr/server/superlink/fleet/vce/backend/raybackend.py +44 -25
  107. flwr/server/superlink/fleet/vce/vce_api.py +3 -1
  108. flwr/server/superlink/state/__init__.py +1 -1
  109. flwr/server/superlink/state/in_memory_state.py +9 -6
  110. flwr/server/superlink/state/sqlite_state.py +7 -4
  111. flwr/server/superlink/state/state.py +6 -5
  112. flwr/server/superlink/state/state_factory.py +11 -2
  113. flwr/server/utils/__init__.py +1 -1
  114. flwr/server/utils/tensorboard.py +1 -1
  115. flwr/simulation/__init__.py +5 -2
  116. flwr/simulation/app.py +1 -1
  117. flwr/simulation/ray_transport/__init__.py +1 -1
  118. flwr/simulation/ray_transport/ray_actor.py +0 -6
  119. flwr/simulation/ray_transport/ray_client_proxy.py +1 -1
  120. flwr/simulation/run_simulation.py +63 -22
  121. flwr/superexec/__init__.py +21 -0
  122. flwr/superexec/app.py +178 -0
  123. flwr/superexec/exec_grpc.py +51 -0
  124. flwr/superexec/exec_servicer.py +65 -0
  125. flwr/superexec/executor.py +54 -0
  126. {flwr_nightly-1.10.0.dev20240612.dist-info → flwr_nightly-1.10.0.dev20240624.dist-info}/METADATA +2 -1
  127. {flwr_nightly-1.10.0.dev20240612.dist-info → flwr_nightly-1.10.0.dev20240624.dist-info}/RECORD +130 -101
  128. {flwr_nightly-1.10.0.dev20240612.dist-info → flwr_nightly-1.10.0.dev20240624.dist-info}/entry_points.txt +1 -0
  129. {flwr_nightly-1.10.0.dev20240612.dist-info → flwr_nightly-1.10.0.dev20240624.dist-info}/LICENSE +0 -0
  130. {flwr_nightly-1.10.0.dev20240612.dist-info → flwr_nightly-1.10.0.dev20240624.dist-info}/WHEEL +0 -0
@@ -22,10 +22,13 @@ from pathlib import Path
22
22
  from typing import Optional
23
23
 
24
24
  from flwr.common import Context, EventType, RecordSet, event
25
+ from flwr.common.config import get_flwr_dir, get_project_config, get_project_dir
25
26
  from flwr.common.logger import log, update_console_handler, warn_deprecated_feature
26
27
  from flwr.common.object_ref import load_app
28
+ from flwr.proto.driver_pb2 import CreateRunRequest # pylint: disable=E0611
27
29
 
28
- from .driver import Driver, GrpcDriver
30
+ from .driver import Driver
31
+ from .driver.grpc_driver import GrpcDriver, GrpcDriverStub
29
32
  from .server_app import LoadServerAppError, ServerApp
30
33
 
31
34
  ADDRESS_DRIVER_API = "0.0.0.0:9091"
@@ -41,16 +44,18 @@ def run(
41
44
  if not (server_app_attr is None) ^ (loaded_server_app is None):
42
45
  raise ValueError(
43
46
  "Either `server_app_attr` or `loaded_server_app` should be set "
44
- "but not both. "
47
+ "but not both."
45
48
  )
46
49
 
47
50
  if server_app_dir is not None:
48
- sys.path.insert(0, server_app_dir)
51
+ sys.path.insert(0, str(Path(server_app_dir).absolute()))
49
52
 
50
53
  # Load ServerApp if needed
51
54
  def _load() -> ServerApp:
52
55
  if server_app_attr:
53
- server_app: ServerApp = load_app(server_app_attr, LoadServerAppError)
56
+ server_app: ServerApp = load_app(
57
+ server_app_attr, LoadServerAppError, server_app_dir
58
+ )
54
59
 
55
60
  if not isinstance(server_app, ServerApp):
56
61
  raise LoadServerAppError(
@@ -72,7 +77,7 @@ def run(
72
77
  log(DEBUG, "ServerApp finished running.")
73
78
 
74
79
 
75
- def run_server_app() -> None:
80
+ def run_server_app() -> None: # pylint: disable=too-many-branches
76
81
  """Run Flower server app."""
77
82
  event(EventType.RUN_SERVER_APP_ENTER)
78
83
 
@@ -132,11 +137,43 @@ def run_server_app() -> None:
132
137
  cert_path,
133
138
  )
134
139
 
135
- log(
136
- DEBUG,
137
- "Flower will load ServerApp `%s`",
138
- getattr(args, "server-app"),
140
+ server_app_attr: Optional[str] = getattr(args, "server-app")
141
+ if not (server_app_attr is None) ^ (args.run_id is None):
142
+ raise sys.exit(
143
+ "Please provide either a ServerApp reference or a Run ID, but not both. "
144
+ "For more details, use: ``flower-server-app -h``"
145
+ )
146
+
147
+ stub = GrpcDriverStub(
148
+ driver_service_address=args.superlink, root_certificates=root_certificates
139
149
  )
150
+ if args.run_id is not None:
151
+ # User provided `--run-id`, but not `server-app`
152
+ run_id = args.run_id
153
+ else:
154
+ # User provided `server-app`, but not `--run-id`
155
+ # Create run if run_id is not provided
156
+ stub.connect()
157
+ req = CreateRunRequest(fab_id=args.fab_id, fab_version=args.fab_version)
158
+ res = stub.create_run(req)
159
+ run_id = res.run_id
160
+
161
+ # Initialize GrpcDriver
162
+ driver = GrpcDriver(run_id=run_id, stub=stub)
163
+
164
+ # Dynamically obtain ServerApp path based on run_id
165
+ if args.run_id is not None:
166
+ # User provided `--run-id`, but not `server-app`
167
+ flwr_dir = get_flwr_dir(args.flwr_dir)
168
+ run_ = driver.run
169
+ server_app_dir = str(get_project_dir(run_.fab_id, run_.fab_version, flwr_dir))
170
+ config = get_project_config(server_app_dir)
171
+ server_app_attr = config["flower"]["components"]["serverapp"]
172
+ else:
173
+ # User provided `server-app`, but not `--run-id`
174
+ server_app_dir = str(Path(args.dir).absolute())
175
+
176
+ log(DEBUG, "Flower will load ServerApp `%s` in %s", server_app_attr, server_app_dir)
140
177
 
141
178
  log(
142
179
  DEBUG,
@@ -144,17 +181,6 @@ def run_server_app() -> None:
144
181
  root_certificates,
145
182
  )
146
183
 
147
- server_app_dir = args.dir
148
- server_app_attr = getattr(args, "server-app")
149
-
150
- # Initialize GrpcDriver
151
- driver = GrpcDriver(
152
- driver_service_address=args.superlink,
153
- root_certificates=root_certificates,
154
- fab_id=args.fab_id,
155
- fab_version=args.fab_version,
156
- )
157
-
158
184
  # Run the ServerApp with the Driver
159
185
  run(driver=driver, server_app_dir=server_app_dir, server_app_attr=server_app_attr)
160
186
 
@@ -172,6 +198,8 @@ def _parse_args_run_server_app() -> argparse.ArgumentParser:
172
198
 
173
199
  parser.add_argument(
174
200
  "server-app",
201
+ nargs="?",
202
+ default=None,
175
203
  help="For example: `server:app` or `project.package.module:wrapper.app`",
176
204
  )
177
205
  parser.add_argument(
@@ -221,5 +249,22 @@ def _parse_args_run_server_app() -> argparse.ArgumentParser:
221
249
  type=str,
222
250
  help="The version of the FAB used in the run.",
223
251
  )
252
+ parser.add_argument(
253
+ "--run-id",
254
+ default=None,
255
+ type=int,
256
+ help="The identifier of the run.",
257
+ )
258
+ parser.add_argument(
259
+ "--flwr-dir",
260
+ default=None,
261
+ help="""The path containing installed Flower Apps.
262
+ By default, this value is equal to:
263
+
264
+ - `$FLWR_HOME/` if `$FLWR_HOME` is defined
265
+ - `$XDG_DATA_HOME/.flwr/` if `$XDG_DATA_HOME` is defined
266
+ - `$HOME/.flwr/` in all other cases
267
+ """,
268
+ )
224
269
 
225
270
  return parser
@@ -53,9 +53,10 @@ __all__ = [
53
53
  "DPFedAvgAdaptive",
54
54
  "DPFedAvgFixed",
55
55
  "DifferentialPrivacyClientSideAdaptiveClipping",
56
- "DifferentialPrivacyServerSideAdaptiveClipping",
57
56
  "DifferentialPrivacyClientSideFixedClipping",
57
+ "DifferentialPrivacyServerSideAdaptiveClipping",
58
58
  "DifferentialPrivacyServerSideFixedClipping",
59
+ "FaultTolerantFedAvg",
59
60
  "FedAdagrad",
60
61
  "FedAdam",
61
62
  "FedAvg",
@@ -69,7 +70,6 @@ __all__ = [
69
70
  "FedXgbCyclic",
70
71
  "FedXgbNnAvg",
71
72
  "FedYogi",
72
- "FaultTolerantFedAvg",
73
73
  "Krum",
74
74
  "QFedAvg",
75
75
  "Strategy",
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2023 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2022 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2022 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2021 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2021 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2021 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2022 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2022 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2021 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2023 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2023 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2023 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2023 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2021 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2022 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2021 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2022 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -35,7 +35,11 @@ from flwr.proto.driver_pb2 import ( # pylint: disable=E0611
35
35
  PushTaskInsResponse,
36
36
  )
37
37
  from flwr.proto.node_pb2 import Node # pylint: disable=E0611
38
- from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611
38
+ from flwr.proto.run_pb2 import ( # pylint: disable=E0611
39
+ GetRunRequest,
40
+ GetRunResponse,
41
+ Run,
42
+ )
39
43
  from flwr.proto.task_pb2 import TaskRes # pylint: disable=E0611
40
44
  from flwr.server.superlink.state import State, StateFactory
41
45
  from flwr.server.utils.validator import validate_task_ins_or_res
@@ -134,7 +138,15 @@ class DriverServicer(driver_pb2_grpc.DriverServicer):
134
138
  self, request: GetRunRequest, context: grpc.ServicerContext
135
139
  ) -> GetRunResponse:
136
140
  """Get run information."""
137
- raise NotImplementedError
141
+ log(DEBUG, "DriverServicer.GetRun")
142
+
143
+ # Init state
144
+ state: State = self.state_factory.state()
145
+
146
+ # Retrieve run information
147
+ run = state.get_run(request.run_id)
148
+ run_proto = None if run is None else Run(**vars(run))
149
+ return GetRunResponse(run=run_proto)
138
150
 
139
151
 
140
152
  def _raise_if(validation_error: bool, detail: str) -> None:
@@ -1,4 +1,4 @@
1
- # Copyright 2022 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -0,0 +1,15 @@
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
+ """Server-side part of the GrpcAdapter transport layer."""
@@ -0,0 +1,131 @@
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
+ """Fleet API gRPC adapter servicer."""
16
+
17
+
18
+ from logging import DEBUG, INFO
19
+ from typing import Callable, Type, TypeVar
20
+
21
+ import grpc
22
+ from google.protobuf.message import Message as GrpcMessage
23
+
24
+ from flwr.common.logger import log
25
+ from flwr.proto import grpcadapter_pb2_grpc # pylint: disable=E0611
26
+ from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
27
+ CreateNodeRequest,
28
+ CreateNodeResponse,
29
+ DeleteNodeRequest,
30
+ DeleteNodeResponse,
31
+ PingRequest,
32
+ PingResponse,
33
+ PullTaskInsRequest,
34
+ PullTaskInsResponse,
35
+ PushTaskResRequest,
36
+ PushTaskResResponse,
37
+ )
38
+ from flwr.proto.grpcadapter_pb2 import MessageContainer # pylint: disable=E0611
39
+ from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611
40
+ from flwr.server.superlink.fleet.message_handler import message_handler
41
+ from flwr.server.superlink.state import StateFactory
42
+
43
+ T = TypeVar("T", bound=GrpcMessage)
44
+
45
+
46
+ def _handle(
47
+ msg_container: MessageContainer,
48
+ request_type: Type[T],
49
+ handler: Callable[[T], GrpcMessage],
50
+ ) -> MessageContainer:
51
+ req = request_type.FromString(msg_container.grpc_message_content)
52
+ res = handler(req)
53
+ return MessageContainer(
54
+ metadata={},
55
+ grpc_message_name=res.__class__.__qualname__,
56
+ grpc_message_content=res.SerializeToString(),
57
+ )
58
+
59
+
60
+ class GrpcAdapterServicer(grpcadapter_pb2_grpc.GrpcAdapterServicer):
61
+ """Fleet API via GrpcAdapter servicer."""
62
+
63
+ def __init__(self, state_factory: StateFactory) -> None:
64
+ self.state_factory = state_factory
65
+
66
+ def SendReceive(
67
+ self, request: MessageContainer, context: grpc.ServicerContext
68
+ ) -> MessageContainer:
69
+ """."""
70
+ log(DEBUG, "GrpcAdapterServicer.SendReceive")
71
+ if request.grpc_message_name == CreateNodeRequest.__qualname__:
72
+ return _handle(request, CreateNodeRequest, self._create_node)
73
+ if request.grpc_message_name == DeleteNodeRequest.__qualname__:
74
+ return _handle(request, DeleteNodeRequest, self._delete_node)
75
+ if request.grpc_message_name == PingRequest.__qualname__:
76
+ return _handle(request, PingRequest, self._ping)
77
+ if request.grpc_message_name == PullTaskInsRequest.__qualname__:
78
+ return _handle(request, PullTaskInsRequest, self._pull_task_ins)
79
+ if request.grpc_message_name == PushTaskResRequest.__qualname__:
80
+ return _handle(request, PushTaskResRequest, self._push_task_res)
81
+ if request.grpc_message_name == GetRunRequest.__qualname__:
82
+ return _handle(request, GetRunRequest, self._get_run)
83
+ raise ValueError(f"Invalid grpc_message_name: {request.grpc_message_name}")
84
+
85
+ def _create_node(self, request: CreateNodeRequest) -> CreateNodeResponse:
86
+ """."""
87
+ log(INFO, "GrpcAdapter.CreateNode")
88
+ return message_handler.create_node(
89
+ request=request,
90
+ state=self.state_factory.state(),
91
+ )
92
+
93
+ def _delete_node(self, request: DeleteNodeRequest) -> DeleteNodeResponse:
94
+ """."""
95
+ log(INFO, "GrpcAdapter.DeleteNode")
96
+ return message_handler.delete_node(
97
+ request=request,
98
+ state=self.state_factory.state(),
99
+ )
100
+
101
+ def _ping(self, request: PingRequest) -> PingResponse:
102
+ """."""
103
+ log(DEBUG, "GrpcAdapter.Ping")
104
+ return message_handler.ping(
105
+ request=request,
106
+ state=self.state_factory.state(),
107
+ )
108
+
109
+ def _pull_task_ins(self, request: PullTaskInsRequest) -> PullTaskInsResponse:
110
+ """Pull TaskIns."""
111
+ log(INFO, "GrpcAdapter.PullTaskIns")
112
+ return message_handler.pull_task_ins(
113
+ request=request,
114
+ state=self.state_factory.state(),
115
+ )
116
+
117
+ def _push_task_res(self, request: PushTaskResRequest) -> PushTaskResResponse:
118
+ """Push TaskRes."""
119
+ log(INFO, "GrpcAdapter.PushTaskRes")
120
+ return message_handler.push_task_res(
121
+ request=request,
122
+ state=self.state_factory.state(),
123
+ )
124
+
125
+ def _get_run(self, request: GetRunRequest) -> GetRunResponse:
126
+ """Get run information."""
127
+ log(INFO, "GrpcAdapter.GetRun")
128
+ return message_handler.get_run(
129
+ request=request,
130
+ state=self.state_factory.state(),
131
+ )
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -29,6 +29,9 @@ from flwr.proto.transport_pb2_grpc import ( # pylint: disable=E0611
29
29
  )
30
30
  from flwr.server.client_manager import ClientManager
31
31
  from flwr.server.superlink.driver.driver_servicer import DriverServicer
32
+ from flwr.server.superlink.fleet.grpc_adapter.grpc_adapter_servicer import (
33
+ GrpcAdapterServicer,
34
+ )
32
35
  from flwr.server.superlink.fleet.grpc_bidi.flower_service_servicer import (
33
36
  FlowerServiceServicer,
34
37
  )
@@ -154,6 +157,7 @@ def start_grpc_server( # pylint: disable=too-many-arguments
154
157
  def generic_create_grpc_server( # pylint: disable=too-many-arguments
155
158
  servicer_and_add_fn: Union[
156
159
  Tuple[FleetServicer, AddServicerToServerFn],
160
+ Tuple[GrpcAdapterServicer, AddServicerToServerFn],
157
161
  Tuple[FlowerServiceServicer, AddServicerToServerFn],
158
162
  Tuple[DriverServicer, AddServicerToServerFn],
159
163
  ],
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -112,6 +112,6 @@ def get_run(
112
112
  request: GetRunRequest, state: State # pylint: disable=W0613
113
113
  ) -> GetRunResponse:
114
114
  """Get run information."""
115
- run_id, fab_id, fab_version = state.get_run(request.run_id)
116
- run = Run(run_id=run_id, fab_id=fab_id, fab_version=fab_version)
117
- return GetRunResponse(run=run)
115
+ run = state.get_run(request.run_id)
116
+ run_proto = None if run is None else Run(**vars(run))
117
+ return GetRunResponse(run=run_proto)
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.