flwr-nightly 1.11.0.dev20240724__py3-none-any.whl → 1.11.0.dev20240811__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 (59) hide show
  1. flwr/cli/build.py +22 -20
  2. flwr/cli/config_utils.py +27 -8
  3. flwr/cli/new/new.py +23 -22
  4. flwr/cli/new/templates/app/README.md.tpl +1 -1
  5. flwr/cli/new/templates/app/code/__init__.py.tpl +1 -1
  6. flwr/cli/new/templates/app/code/client.huggingface.py.tpl +1 -1
  7. flwr/cli/new/templates/app/code/client.jax.py.tpl +1 -1
  8. flwr/cli/new/templates/app/code/client.mlx.py.tpl +1 -1
  9. flwr/cli/new/templates/app/code/client.numpy.py.tpl +1 -1
  10. flwr/cli/new/templates/app/code/client.pytorch.py.tpl +9 -8
  11. flwr/cli/new/templates/app/code/client.sklearn.py.tpl +1 -1
  12. flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +5 -8
  13. flwr/cli/new/templates/app/code/server.huggingface.py.tpl +1 -1
  14. flwr/cli/new/templates/app/code/server.jax.py.tpl +1 -1
  15. flwr/cli/new/templates/app/code/server.mlx.py.tpl +1 -1
  16. flwr/cli/new/templates/app/code/server.numpy.py.tpl +1 -1
  17. flwr/cli/new/templates/app/code/server.pytorch.py.tpl +7 -6
  18. flwr/cli/new/templates/app/code/server.sklearn.py.tpl +1 -1
  19. flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +4 -5
  20. flwr/cli/new/templates/app/code/task.huggingface.py.tpl +1 -1
  21. flwr/cli/new/templates/app/code/task.jax.py.tpl +2 -2
  22. flwr/cli/new/templates/app/code/task.mlx.py.tpl +2 -1
  23. flwr/cli/new/templates/app/code/task.pytorch.py.tpl +14 -20
  24. flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +16 -4
  25. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +2 -2
  26. flwr/cli/new/templates/app/pyproject.jax.toml.tpl +1 -1
  27. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +3 -3
  28. flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +1 -1
  29. flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +3 -2
  30. flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +2 -2
  31. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +2 -2
  32. flwr/cli/run/run.py +15 -12
  33. flwr/client/grpc_rere_client/grpc_adapter.py +7 -0
  34. flwr/client/supernode/app.py +36 -28
  35. flwr/common/config.py +30 -0
  36. flwr/common/typing.py +8 -0
  37. flwr/proto/driver_pb2.py +22 -21
  38. flwr/proto/driver_pb2.pyi +7 -1
  39. flwr/proto/driver_pb2_grpc.py +35 -0
  40. flwr/proto/driver_pb2_grpc.pyi +14 -0
  41. flwr/proto/fab_pb2.py +6 -6
  42. flwr/proto/fab_pb2.pyi +8 -8
  43. flwr/proto/fleet_pb2.py +28 -27
  44. flwr/proto/fleet_pb2_grpc.py +35 -0
  45. flwr/proto/fleet_pb2_grpc.pyi +14 -0
  46. flwr/proto/run_pb2.py +8 -8
  47. flwr/proto/run_pb2.pyi +4 -1
  48. flwr/server/run_serverapp.py +28 -46
  49. flwr/server/superlink/driver/driver_servicer.py +7 -0
  50. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +7 -0
  51. flwr/server/superlink/fleet/vce/backend/backend.py +1 -1
  52. flwr/server/superlink/fleet/vce/backend/raybackend.py +4 -35
  53. flwr/server/superlink/fleet/vce/vce_api.py +3 -3
  54. flwr/superexec/simulation.py +15 -3
  55. {flwr_nightly-1.11.0.dev20240724.dist-info → flwr_nightly-1.11.0.dev20240811.dist-info}/METADATA +2 -2
  56. {flwr_nightly-1.11.0.dev20240724.dist-info → flwr_nightly-1.11.0.dev20240811.dist-info}/RECORD +59 -59
  57. {flwr_nightly-1.11.0.dev20240724.dist-info → flwr_nightly-1.11.0.dev20240811.dist-info}/LICENSE +0 -0
  58. {flwr_nightly-1.11.0.dev20240724.dist-info → flwr_nightly-1.11.0.dev20240811.dist-info}/WHEEL +0 -0
  59. {flwr_nightly-1.11.0.dev20240724.dist-info → flwr_nightly-1.11.0.dev20240811.dist-info}/entry_points.txt +0 -0
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.9.0,<2.0",
11
+ "flwr[simulation]>=1.10.0",
12
12
  "jax==0.4.13",
13
13
  "jaxlib==0.4.13",
14
14
  "scikit-learn==1.3.2",
@@ -8,9 +8,9 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.9.0,<2.0",
12
- "flwr-datasets[vision]>=0.0.2,<1.0.0",
13
- "mlx==0.10.0",
11
+ "flwr[simulation]>=1.10.0",
12
+ "flwr-datasets[vision]>=0.3.0",
13
+ "mlx==0.16.1",
14
14
  "numpy==1.24.4",
15
15
  ]
16
16
 
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.9.0,<2.0",
11
+ "flwr[simulation]>=1.10.0",
12
12
  "numpy>=1.21.0",
13
13
  ]
14
14
 
@@ -8,8 +8,8 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.9.0,<2.0",
12
- "flwr-datasets[vision]>=0.0.2,<1.0.0",
11
+ "flwr[simulation]>=1.10.0",
12
+ "flwr-datasets[vision]>=0.3.0",
13
13
  "torch==2.2.1",
14
14
  "torchvision==0.17.1",
15
15
  ]
@@ -26,6 +26,7 @@ clientapp = "$import_name.client_app:app"
26
26
 
27
27
  [tool.flwr.app.config]
28
28
  num-server-rounds = 3
29
+ fraction-fit = 0.5
29
30
  local-epochs = 1
30
31
 
31
32
  [tool.flwr.federations]
@@ -8,8 +8,8 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.9.0,<2.0",
12
- "flwr-datasets[vision]>=0.0.2,<1.0.0",
11
+ "flwr[simulation]>=1.10.0",
12
+ "flwr-datasets[vision]>=0.3.0",
13
13
  "scikit-learn>=1.1.1",
14
14
  ]
15
15
 
@@ -8,8 +8,8 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.9.0,<2.0",
12
- "flwr-datasets[vision]>=0.0.2,<1.0.0",
11
+ "flwr[simulation]>=1.10.0",
12
+ "flwr-datasets[vision]>=0.3.0",
13
13
  "tensorflow>=2.11.1",
14
14
  ]
15
15
 
flwr/cli/run/run.py CHANGED
@@ -35,9 +35,9 @@ from flwr.proto.exec_pb2_grpc import ExecStub
35
35
 
36
36
  # pylint: disable-next=too-many-locals
37
37
  def run(
38
- app_dir: Annotated[
38
+ app: Annotated[
39
39
  Path,
40
- typer.Argument(help="Path of the Flower project to run."),
40
+ typer.Argument(help="Path of the Flower App to run."),
41
41
  ] = Path("."),
42
42
  federation: Annotated[
43
43
  Optional[str],
@@ -55,10 +55,10 @@ def run(
55
55
  ),
56
56
  ] = None,
57
57
  ) -> None:
58
- """Run Flower project."""
58
+ """Run Flower App."""
59
59
  typer.secho("Loading project configuration... ", fg=typer.colors.BLUE)
60
60
 
61
- pyproject_path = app_dir / "pyproject.toml" if app_dir else None
61
+ pyproject_path = app / "pyproject.toml" if app else None
62
62
  config, errors, warnings = load_and_validate(path=pyproject_path)
63
63
 
64
64
  if config is None:
@@ -109,14 +109,14 @@ def run(
109
109
  raise typer.Exit(code=1)
110
110
 
111
111
  if "address" in federation_config:
112
- _run_with_superexec(federation_config, app_dir, config_overrides)
112
+ _run_with_superexec(app, federation_config, config_overrides)
113
113
  else:
114
- _run_without_superexec(app_dir, federation_config, federation, config_overrides)
114
+ _run_without_superexec(app, federation_config, config_overrides, federation)
115
115
 
116
116
 
117
117
  def _run_with_superexec(
118
+ app: Optional[Path],
118
119
  federation_config: Dict[str, Any],
119
- app_dir: Optional[Path],
120
120
  config_overrides: Optional[List[str]],
121
121
  ) -> None:
122
122
 
@@ -162,10 +162,10 @@ def _run_with_superexec(
162
162
  channel.subscribe(on_channel_state_change)
163
163
  stub = ExecStub(channel)
164
164
 
165
- fab_path = build(app_dir)
165
+ fab_path = Path(build(app))
166
166
 
167
167
  req = StartRunRequest(
168
- fab_file=Path(fab_path).read_bytes(),
168
+ fab_file=fab_path.read_bytes(),
169
169
  override_config=user_config_to_proto(
170
170
  parse_config_args(config_overrides, separator=",")
171
171
  ),
@@ -174,14 +174,17 @@ def _run_with_superexec(
174
174
  ),
175
175
  )
176
176
  res = stub.StartRun(req)
177
+
178
+ # Delete FAB file once it has been sent to the SuperExec
179
+ fab_path.unlink()
177
180
  typer.secho(f"🎊 Successfully started run {res.run_id}", fg=typer.colors.GREEN)
178
181
 
179
182
 
180
183
  def _run_without_superexec(
181
- app_path: Optional[Path],
184
+ app: Optional[Path],
182
185
  federation_config: Dict[str, Any],
183
- federation: str,
184
186
  config_overrides: Optional[List[str]],
187
+ federation: str,
185
188
  ) -> None:
186
189
  try:
187
190
  num_supernodes = federation_config["options"]["num-supernodes"]
@@ -200,7 +203,7 @@ def _run_without_superexec(
200
203
  command = [
201
204
  "flower-simulation",
202
205
  "--app",
203
- f"{app_path}",
206
+ f"{app}",
204
207
  "--num-supernodes",
205
208
  f"{num_supernodes}",
206
209
  ]
@@ -28,6 +28,7 @@ from flwr.common.constant import (
28
28
  GRPC_ADAPTER_METADATA_SHOULD_EXIT_KEY,
29
29
  )
30
30
  from flwr.common.version import package_version
31
+ from flwr.proto.fab_pb2 import GetFabRequest, GetFabResponse # pylint: disable=E0611
31
32
  from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
32
33
  CreateNodeRequest,
33
34
  CreateNodeResponse,
@@ -131,3 +132,9 @@ class GrpcAdapter:
131
132
  ) -> GetRunResponse:
132
133
  """."""
133
134
  return self._send_and_receive(request, GetRunResponse, **kwargs)
135
+
136
+ def GetFab( # pylint: disable=C0103
137
+ self, request: GetFabRequest, **kwargs: Any
138
+ ) -> GetFabResponse:
139
+ """."""
140
+ return self._send_and_receive(request, GetFabResponse, **kwargs)
@@ -31,6 +31,7 @@ from flwr.client.client_app import ClientApp, LoadClientAppError
31
31
  from flwr.common import EventType, event
32
32
  from flwr.common.config import (
33
33
  get_flwr_dir,
34
+ get_metadata_from_config,
34
35
  get_project_config,
35
36
  get_project_dir,
36
37
  parse_config_args,
@@ -61,8 +62,8 @@ def run_supernode() -> None:
61
62
 
62
63
  root_certificates = _get_certificates(args)
63
64
  load_fn = _get_load_client_app_fn(
64
- default_app_ref=getattr(args, "client-app"),
65
- project_dir=args.dir,
65
+ default_app_ref="",
66
+ app_path=args.app,
66
67
  flwr_dir=args.flwr_dir,
67
68
  multi_app=True,
68
69
  )
@@ -100,7 +101,7 @@ def run_client_app() -> None:
100
101
  root_certificates = _get_certificates(args)
101
102
  load_fn = _get_load_client_app_fn(
102
103
  default_app_ref=getattr(args, "client-app"),
103
- project_dir=args.dir,
104
+ app_path=args.dir,
104
105
  multi_app=False,
105
106
  )
106
107
  authentication_keys = _try_setup_client_authentication(args)
@@ -176,7 +177,7 @@ def _get_certificates(args: argparse.Namespace) -> Optional[bytes]:
176
177
 
177
178
  def _get_load_client_app_fn(
178
179
  default_app_ref: str,
179
- project_dir: str,
180
+ app_path: Optional[str],
180
181
  multi_app: bool,
181
182
  flwr_dir: Optional[str] = None,
182
183
  ) -> Callable[[str, str], ClientApp]:
@@ -196,34 +197,39 @@ def _get_load_client_app_fn(
196
197
  default_app_ref,
197
198
  )
198
199
 
199
- valid, error_msg = validate(default_app_ref, project_dir=project_dir)
200
+ valid, error_msg = validate(default_app_ref, project_dir=app_path)
200
201
  if not valid and error_msg:
201
202
  raise LoadClientAppError(error_msg) from None
202
203
 
203
204
  def _load(fab_id: str, fab_version: str) -> ClientApp:
204
- runtime_project_dir = Path(project_dir).absolute()
205
+ runtime_app_dir = Path(app_path if app_path else "").absolute()
205
206
  # If multi-app feature is disabled
206
207
  if not multi_app:
207
208
  # Set app reference
208
209
  client_app_ref = default_app_ref
209
- # If multi-app feature is enabled but the fab id is not specified
210
- elif fab_id == "":
211
- if default_app_ref == "":
210
+ # If multi-app feature is enabled but app directory is provided
211
+ elif app_path is not None:
212
+ config = get_project_config(runtime_app_dir)
213
+ this_fab_version, this_fab_id = get_metadata_from_config(config)
214
+
215
+ if this_fab_version != fab_version or this_fab_id != fab_id:
212
216
  raise LoadClientAppError(
213
- "Invalid FAB ID: The FAB ID is empty.",
217
+ f"FAB ID or version mismatch: Expected FAB ID '{this_fab_id}' and "
218
+ f"FAB version '{this_fab_version}', but received FAB ID '{fab_id}' "
219
+ f"and FAB version '{fab_version}'.",
214
220
  ) from None
215
221
 
216
- log(WARN, "FAB ID is not provided; the default ClientApp will be loaded.")
222
+ # log(WARN, "FAB ID is not provided; the default ClientApp will be loaded.")
217
223
 
218
224
  # Set app reference
219
- client_app_ref = default_app_ref
225
+ client_app_ref = config["tool"]["flwr"]["app"]["components"]["clientapp"]
220
226
  # If multi-app feature is enabled
221
227
  else:
222
228
  try:
223
- runtime_project_dir = get_project_dir(
229
+ runtime_app_dir = get_project_dir(
224
230
  fab_id, fab_version, get_flwr_dir(flwr_dir)
225
231
  )
226
- config = get_project_config(runtime_project_dir)
232
+ config = get_project_config(runtime_app_dir)
227
233
  except Exception as e:
228
234
  raise LoadClientAppError("Failed to load ClientApp") from e
229
235
 
@@ -236,7 +242,7 @@ def _get_load_client_app_fn(
236
242
  "Loading ClientApp `%s`",
237
243
  client_app_ref,
238
244
  )
239
- client_app = load_app(client_app_ref, LoadClientAppError, runtime_project_dir)
245
+ client_app = load_app(client_app_ref, LoadClientAppError, runtime_app_dir)
240
246
 
241
247
  if not isinstance(client_app, ClientApp):
242
248
  raise LoadClientAppError(
@@ -255,13 +261,15 @@ def _parse_args_run_supernode() -> argparse.ArgumentParser:
255
261
  )
256
262
 
257
263
  parser.add_argument(
258
- "client-app",
264
+ "app",
259
265
  nargs="?",
260
- default="",
261
- help="For example: `client:app` or `project.package.module:wrapper.app`. "
262
- "This is optional and serves as the default ClientApp to be loaded when "
263
- "the ServerApp does not specify `fab_id` and `fab_version`. "
264
- "If not provided, defaults to an empty string.",
266
+ default=None,
267
+ help="Specify the path of the Flower App to load and run the `ClientApp`. "
268
+ "The `pyproject.toml` file must be located in the root of this path. "
269
+ "When this argument is provided, the SuperNode will exclusively respond to "
270
+ "messages from the corresponding `ServerApp` by matching the FAB ID and FAB "
271
+ "version. An error will be raised if a message is received from any other "
272
+ "`ServerApp`.",
265
273
  )
266
274
  _parse_args_common(parser)
267
275
  parser.add_argument(
@@ -290,6 +298,13 @@ def _parse_args_run_client_app() -> argparse.ArgumentParser:
290
298
  help="For example: `client:app` or `project.package.module:wrapper.app`",
291
299
  )
292
300
  _parse_args_common(parser=parser)
301
+ parser.add_argument(
302
+ "--dir",
303
+ default="",
304
+ help="Add specified directory to the PYTHONPATH and load Flower "
305
+ "app from there."
306
+ " Default: current working directory.",
307
+ )
293
308
 
294
309
  return parser
295
310
 
@@ -357,13 +372,6 @@ def _parse_args_common(parser: argparse.ArgumentParser) -> None:
357
372
  "connect to the SuperLink in case of connection error. By default, it"
358
373
  "is set to None, meaning there is no limit to the total time.",
359
374
  )
360
- parser.add_argument(
361
- "--dir",
362
- default="",
363
- help="Add specified directory to the PYTHONPATH and load Flower "
364
- "app from there."
365
- " Default: current working directory.",
366
- )
367
375
  parser.add_argument(
368
376
  "--auth-supernode-private-key",
369
377
  type=str,
flwr/common/config.py CHANGED
@@ -105,11 +105,16 @@ def get_fused_config(run: Run, flwr_dir: Optional[Path]) -> UserConfig:
105
105
  Get the config using the fab_id and the fab_version, remove the nesting by adding
106
106
  the nested keys as prefixes separated by dots, and fuse it with the override dict.
107
107
  """
108
+ # Return empty dict if fab_id or fab_version is empty
108
109
  if not run.fab_id or not run.fab_version:
109
110
  return {}
110
111
 
111
112
  project_dir = get_project_dir(run.fab_id, run.fab_version, flwr_dir)
112
113
 
114
+ # Return empty dict if project directory does not exist
115
+ if not project_dir.is_dir():
116
+ return {}
117
+
113
118
  return get_fused_config_from_dir(project_dir, run.override_config)
114
119
 
115
120
 
@@ -136,6 +141,23 @@ def flatten_dict(
136
141
  return dict(items)
137
142
 
138
143
 
144
+ def unflatten_dict(flat_dict: Dict[str, Any]) -> Dict[str, Any]:
145
+ """Unflatten a dict with keys containing separators into a nested dict."""
146
+ unflattened_dict: Dict[str, Any] = {}
147
+ separator: str = "."
148
+
149
+ for key, value in flat_dict.items():
150
+ parts = key.split(separator)
151
+ d = unflattened_dict
152
+ for part in parts[:-1]:
153
+ if part not in d:
154
+ d[part] = {}
155
+ d = d[part]
156
+ d[parts[-1]] = value
157
+
158
+ return unflattened_dict
159
+
160
+
139
161
  def parse_config_args(
140
162
  config: Optional[List[str]],
141
163
  separator: str = ",",
@@ -161,3 +183,11 @@ def parse_config_args(
161
183
  overrides.update(tomli.loads(toml_str))
162
184
 
163
185
  return overrides
186
+
187
+
188
+ def get_metadata_from_config(config: Dict[str, Any]) -> Tuple[str, str]:
189
+ """Extract `fab_version` and `fab_id` from a project config."""
190
+ return (
191
+ config["project"]["version"],
192
+ f"{config['tool']['flwr']['app']['publisher']}/{config['project']['name']}",
193
+ )
flwr/common/typing.py CHANGED
@@ -199,3 +199,11 @@ class Run:
199
199
  fab_id: str
200
200
  fab_version: str
201
201
  override_config: UserConfig
202
+
203
+
204
+ @dataclass
205
+ class Fab:
206
+ """Fab file representation."""
207
+
208
+ hash_str: str
209
+ content: bytes
flwr/proto/driver_pb2.py CHANGED
@@ -15,10 +15,11 @@ _sym_db = _symbol_database.Default()
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
17
  from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2
18
+ from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
18
19
  from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2
19
20
 
20
21
 
21
- 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\x1a\x1a\x66lwr/proto/transport.proto\"\xcd\x01\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\x12I\n\x0foverride_config\x18\x03 \x03(\x0b\x32\x30.flwr.proto.CreateRunRequest.OverrideConfigEntry\x1aI\n\x13OverrideConfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\"#\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')
22
+ 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\x1a\x14\x66lwr/proto/fab.proto\x1a\x1a\x66lwr/proto/transport.proto\"\xeb\x01\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\x12I\n\x0foverride_config\x18\x03 \x03(\x0b\x32\x30.flwr.proto.CreateRunRequest.OverrideConfigEntry\x12\x1c\n\x03\x66\x61\x62\x18\x04 \x01(\x0b\x32\x0f.flwr.proto.Fab\x1aI\n\x13OverrideConfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\"#\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\xc7\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\x12\x41\n\x06GetFab\x12\x19.flwr.proto.GetFabRequest\x1a\x1a.flwr.proto.GetFabResponse\"\x00\x62\x06proto3')
22
23
 
23
24
  _globals = globals()
24
25
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -27,24 +28,24 @@ if _descriptor._USE_C_DESCRIPTORS == False:
27
28
  DESCRIPTOR._options = None
28
29
  _globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._options = None
29
30
  _globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_options = b'8\001'
30
- _globals['_CREATERUNREQUEST']._serialized_start=136
31
- _globals['_CREATERUNREQUEST']._serialized_end=341
32
- _globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_start=268
33
- _globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_end=341
34
- _globals['_CREATERUNRESPONSE']._serialized_start=343
35
- _globals['_CREATERUNRESPONSE']._serialized_end=378
36
- _globals['_GETNODESREQUEST']._serialized_start=380
37
- _globals['_GETNODESREQUEST']._serialized_end=413
38
- _globals['_GETNODESRESPONSE']._serialized_start=415
39
- _globals['_GETNODESRESPONSE']._serialized_end=466
40
- _globals['_PUSHTASKINSREQUEST']._serialized_start=468
41
- _globals['_PUSHTASKINSREQUEST']._serialized_end=532
42
- _globals['_PUSHTASKINSRESPONSE']._serialized_start=534
43
- _globals['_PUSHTASKINSRESPONSE']._serialized_end=573
44
- _globals['_PULLTASKRESREQUEST']._serialized_start=575
45
- _globals['_PULLTASKRESREQUEST']._serialized_end=645
46
- _globals['_PULLTASKRESRESPONSE']._serialized_start=647
47
- _globals['_PULLTASKRESRESPONSE']._serialized_end=712
48
- _globals['_DRIVER']._serialized_start=715
49
- _globals['_DRIVER']._serialized_end=1103
31
+ _globals['_CREATERUNREQUEST']._serialized_start=158
32
+ _globals['_CREATERUNREQUEST']._serialized_end=393
33
+ _globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_start=320
34
+ _globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_end=393
35
+ _globals['_CREATERUNRESPONSE']._serialized_start=395
36
+ _globals['_CREATERUNRESPONSE']._serialized_end=430
37
+ _globals['_GETNODESREQUEST']._serialized_start=432
38
+ _globals['_GETNODESREQUEST']._serialized_end=465
39
+ _globals['_GETNODESRESPONSE']._serialized_start=467
40
+ _globals['_GETNODESRESPONSE']._serialized_end=518
41
+ _globals['_PUSHTASKINSREQUEST']._serialized_start=520
42
+ _globals['_PUSHTASKINSREQUEST']._serialized_end=584
43
+ _globals['_PUSHTASKINSRESPONSE']._serialized_start=586
44
+ _globals['_PUSHTASKINSRESPONSE']._serialized_end=625
45
+ _globals['_PULLTASKRESREQUEST']._serialized_start=627
46
+ _globals['_PULLTASKRESREQUEST']._serialized_end=697
47
+ _globals['_PULLTASKRESRESPONSE']._serialized_start=699
48
+ _globals['_PULLTASKRESRESPONSE']._serialized_end=764
49
+ _globals['_DRIVER']._serialized_start=767
50
+ _globals['_DRIVER']._serialized_end=1222
50
51
  # @@protoc_insertion_point(module_scope)
flwr/proto/driver_pb2.pyi CHANGED
@@ -3,6 +3,7 @@
3
3
  isort:skip_file
4
4
  """
5
5
  import builtins
6
+ import flwr.proto.fab_pb2
6
7
  import flwr.proto.node_pb2
7
8
  import flwr.proto.task_pb2
8
9
  import flwr.proto.transport_pb2
@@ -35,17 +36,22 @@ class CreateRunRequest(google.protobuf.message.Message):
35
36
  FAB_ID_FIELD_NUMBER: builtins.int
36
37
  FAB_VERSION_FIELD_NUMBER: builtins.int
37
38
  OVERRIDE_CONFIG_FIELD_NUMBER: builtins.int
39
+ FAB_FIELD_NUMBER: builtins.int
38
40
  fab_id: typing.Text
39
41
  fab_version: typing.Text
40
42
  @property
41
43
  def override_config(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.transport_pb2.Scalar]: ...
44
+ @property
45
+ def fab(self) -> flwr.proto.fab_pb2.Fab: ...
42
46
  def __init__(self,
43
47
  *,
44
48
  fab_id: typing.Text = ...,
45
49
  fab_version: typing.Text = ...,
46
50
  override_config: typing.Optional[typing.Mapping[typing.Text, flwr.proto.transport_pb2.Scalar]] = ...,
51
+ fab: typing.Optional[flwr.proto.fab_pb2.Fab] = ...,
47
52
  ) -> None: ...
48
- def ClearField(self, field_name: typing_extensions.Literal["fab_id",b"fab_id","fab_version",b"fab_version","override_config",b"override_config"]) -> None: ...
53
+ def HasField(self, field_name: typing_extensions.Literal["fab",b"fab"]) -> builtins.bool: ...
54
+ def ClearField(self, field_name: typing_extensions.Literal["fab",b"fab","fab_id",b"fab_id","fab_version",b"fab_version","override_config",b"override_config"]) -> None: ...
49
55
  global___CreateRunRequest = CreateRunRequest
50
56
 
51
57
  class CreateRunResponse(google.protobuf.message.Message):
@@ -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 fab_pb2 as flwr_dot_proto_dot_fab__pb2
6
7
  from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2
7
8
 
8
9
 
@@ -40,6 +41,11 @@ class DriverStub(object):
40
41
  request_serializer=flwr_dot_proto_dot_run__pb2.GetRunRequest.SerializeToString,
41
42
  response_deserializer=flwr_dot_proto_dot_run__pb2.GetRunResponse.FromString,
42
43
  )
44
+ self.GetFab = channel.unary_unary(
45
+ '/flwr.proto.Driver/GetFab',
46
+ request_serializer=flwr_dot_proto_dot_fab__pb2.GetFabRequest.SerializeToString,
47
+ response_deserializer=flwr_dot_proto_dot_fab__pb2.GetFabResponse.FromString,
48
+ )
43
49
 
44
50
 
45
51
  class DriverServicer(object):
@@ -80,6 +86,13 @@ class DriverServicer(object):
80
86
  context.set_details('Method not implemented!')
81
87
  raise NotImplementedError('Method not implemented!')
82
88
 
89
+ def GetFab(self, request, context):
90
+ """Get FAB
91
+ """
92
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
93
+ context.set_details('Method not implemented!')
94
+ raise NotImplementedError('Method not implemented!')
95
+
83
96
 
84
97
  def add_DriverServicer_to_server(servicer, server):
85
98
  rpc_method_handlers = {
@@ -108,6 +121,11 @@ def add_DriverServicer_to_server(servicer, server):
108
121
  request_deserializer=flwr_dot_proto_dot_run__pb2.GetRunRequest.FromString,
109
122
  response_serializer=flwr_dot_proto_dot_run__pb2.GetRunResponse.SerializeToString,
110
123
  ),
124
+ 'GetFab': grpc.unary_unary_rpc_method_handler(
125
+ servicer.GetFab,
126
+ request_deserializer=flwr_dot_proto_dot_fab__pb2.GetFabRequest.FromString,
127
+ response_serializer=flwr_dot_proto_dot_fab__pb2.GetFabResponse.SerializeToString,
128
+ ),
111
129
  }
112
130
  generic_handler = grpc.method_handlers_generic_handler(
113
131
  'flwr.proto.Driver', rpc_method_handlers)
@@ -202,3 +220,20 @@ class Driver(object):
202
220
  flwr_dot_proto_dot_run__pb2.GetRunResponse.FromString,
203
221
  options, channel_credentials,
204
222
  insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
223
+
224
+ @staticmethod
225
+ def GetFab(request,
226
+ target,
227
+ options=(),
228
+ channel_credentials=None,
229
+ call_credentials=None,
230
+ insecure=False,
231
+ compression=None,
232
+ wait_for_ready=None,
233
+ timeout=None,
234
+ metadata=None):
235
+ return grpc.experimental.unary_unary(request, target, '/flwr.proto.Driver/GetFab',
236
+ flwr_dot_proto_dot_fab__pb2.GetFabRequest.SerializeToString,
237
+ flwr_dot_proto_dot_fab__pb2.GetFabResponse.FromString,
238
+ options, channel_credentials,
239
+ 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.fab_pb2
7
8
  import flwr.proto.run_pb2
8
9
  import grpc
9
10
 
@@ -34,6 +35,11 @@ class DriverStub:
34
35
  flwr.proto.run_pb2.GetRunResponse]
35
36
  """Get run details"""
36
37
 
38
+ GetFab: grpc.UnaryUnaryMultiCallable[
39
+ flwr.proto.fab_pb2.GetFabRequest,
40
+ flwr.proto.fab_pb2.GetFabResponse]
41
+ """Get FAB"""
42
+
37
43
 
38
44
  class DriverServicer(metaclass=abc.ABCMeta):
39
45
  @abc.abstractmethod
@@ -76,5 +82,13 @@ class DriverServicer(metaclass=abc.ABCMeta):
76
82
  """Get run details"""
77
83
  pass
78
84
 
85
+ @abc.abstractmethod
86
+ def GetFab(self,
87
+ request: flwr.proto.fab_pb2.GetFabRequest,
88
+ context: grpc.ServicerContext,
89
+ ) -> flwr.proto.fab_pb2.GetFabResponse:
90
+ """Get FAB"""
91
+ pass
92
+
79
93
 
80
94
  def add_DriverServicer_to_server(servicer: DriverServicer, server: grpc.Server) -> None: ...
flwr/proto/fab_pb2.py CHANGED
@@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
14
14
 
15
15
 
16
16
 
17
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x66lwr/proto/fab.proto\x12\nflwr.proto\"$\n\x03\x46\x61\x62\x12\x0c\n\x04hash\x18\x01 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\x0c\"\x1d\n\rGetFabRequest\x12\x0c\n\x04hash\x18\x01 \x01(\t\".\n\x0eGetFabResponse\x12\x1c\n\x03\x66\x61\x62\x18\x01 \x01(\x0b\x32\x0f.flwr.proto.Fabb\x06proto3')
17
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x66lwr/proto/fab.proto\x12\nflwr.proto\"(\n\x03\x46\x61\x62\x12\x10\n\x08hash_str\x18\x01 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\x0c\"!\n\rGetFabRequest\x12\x10\n\x08hash_str\x18\x01 \x01(\t\".\n\x0eGetFabResponse\x12\x1c\n\x03\x66\x61\x62\x18\x01 \x01(\x0b\x32\x0f.flwr.proto.Fabb\x06proto3')
18
18
 
19
19
  _globals = globals()
20
20
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -22,9 +22,9 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.fab_pb2', _globa
22
22
  if _descriptor._USE_C_DESCRIPTORS == False:
23
23
  DESCRIPTOR._options = None
24
24
  _globals['_FAB']._serialized_start=36
25
- _globals['_FAB']._serialized_end=72
26
- _globals['_GETFABREQUEST']._serialized_start=74
27
- _globals['_GETFABREQUEST']._serialized_end=103
28
- _globals['_GETFABRESPONSE']._serialized_start=105
29
- _globals['_GETFABRESPONSE']._serialized_end=151
25
+ _globals['_FAB']._serialized_end=76
26
+ _globals['_GETFABREQUEST']._serialized_start=78
27
+ _globals['_GETFABREQUEST']._serialized_end=111
28
+ _globals['_GETFABRESPONSE']._serialized_start=113
29
+ _globals['_GETFABRESPONSE']._serialized_end=159
30
30
  # @@protoc_insertion_point(module_scope)
flwr/proto/fab_pb2.pyi CHANGED
@@ -12,9 +12,9 @@ DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
12
12
 
13
13
  class Fab(google.protobuf.message.Message):
14
14
  DESCRIPTOR: google.protobuf.descriptor.Descriptor
15
- HASH_FIELD_NUMBER: builtins.int
15
+ HASH_STR_FIELD_NUMBER: builtins.int
16
16
  CONTENT_FIELD_NUMBER: builtins.int
17
- hash: typing.Text
17
+ hash_str: typing.Text
18
18
  """This field is the hash of the data field. It is used to identify the data.
19
19
  The hash is calculated using the SHA-256 algorithm and is represented as a
20
20
  hex string (sha256hex).
@@ -25,21 +25,21 @@ class Fab(google.protobuf.message.Message):
25
25
 
26
26
  def __init__(self,
27
27
  *,
28
- hash: typing.Text = ...,
28
+ hash_str: typing.Text = ...,
29
29
  content: builtins.bytes = ...,
30
30
  ) -> None: ...
31
- def ClearField(self, field_name: typing_extensions.Literal["content",b"content","hash",b"hash"]) -> None: ...
31
+ def ClearField(self, field_name: typing_extensions.Literal["content",b"content","hash_str",b"hash_str"]) -> None: ...
32
32
  global___Fab = Fab
33
33
 
34
34
  class GetFabRequest(google.protobuf.message.Message):
35
35
  DESCRIPTOR: google.protobuf.descriptor.Descriptor
36
- HASH_FIELD_NUMBER: builtins.int
37
- hash: typing.Text
36
+ HASH_STR_FIELD_NUMBER: builtins.int
37
+ hash_str: typing.Text
38
38
  def __init__(self,
39
39
  *,
40
- hash: typing.Text = ...,
40
+ hash_str: typing.Text = ...,
41
41
  ) -> None: ...
42
- def ClearField(self, field_name: typing_extensions.Literal["hash",b"hash"]) -> None: ...
42
+ def ClearField(self, field_name: typing_extensions.Literal["hash_str",b"hash_str"]) -> None: ...
43
43
  global___GetFabRequest = GetFabRequest
44
44
 
45
45
  class GetFabResponse(google.protobuf.message.Message):