flwr-nightly 1.13.0.dev20241113__py3-none-any.whl → 1.13.0.dev20241115__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 (36) hide show
  1. flwr/cli/app.py +2 -0
  2. flwr/cli/ls.py +228 -0
  3. flwr/client/app.py +58 -13
  4. flwr/client/clientapp/app.py +34 -23
  5. flwr/client/grpc_rere_client/connection.py +2 -12
  6. flwr/client/rest_client/connection.py +4 -14
  7. flwr/client/supernode/app.py +56 -18
  8. flwr/common/constant.py +21 -6
  9. flwr/common/serde.py +10 -0
  10. flwr/common/typing.py +31 -10
  11. flwr/proto/exec_pb2.py +22 -13
  12. flwr/proto/exec_pb2.pyi +44 -0
  13. flwr/proto/exec_pb2_grpc.py +34 -0
  14. flwr/proto/exec_pb2_grpc.pyi +13 -0
  15. flwr/proto/run_pb2.py +30 -30
  16. flwr/proto/run_pb2.pyi +18 -1
  17. flwr/server/app.py +37 -12
  18. flwr/server/driver/grpc_driver.py +4 -14
  19. flwr/server/run_serverapp.py +8 -238
  20. flwr/server/serverapp/app.py +33 -22
  21. flwr/server/superlink/fleet/rest_rere/rest_api.py +10 -9
  22. flwr/server/superlink/linkstate/in_memory_linkstate.py +71 -46
  23. flwr/server/superlink/linkstate/linkstate.py +19 -5
  24. flwr/server/superlink/linkstate/sqlite_linkstate.py +79 -111
  25. flwr/server/superlink/linkstate/utils.py +182 -3
  26. flwr/simulation/app.py +3 -3
  27. flwr/simulation/legacy_app.py +21 -1
  28. flwr/simulation/run_simulation.py +7 -18
  29. flwr/simulation/simulationio_connection.py +2 -2
  30. flwr/superexec/deployment.py +9 -5
  31. flwr/superexec/exec_servicer.py +31 -2
  32. {flwr_nightly-1.13.0.dev20241113.dist-info → flwr_nightly-1.13.0.dev20241115.dist-info}/METADATA +2 -1
  33. {flwr_nightly-1.13.0.dev20241113.dist-info → flwr_nightly-1.13.0.dev20241115.dist-info}/RECORD +36 -35
  34. {flwr_nightly-1.13.0.dev20241113.dist-info → flwr_nightly-1.13.0.dev20241115.dist-info}/LICENSE +0 -0
  35. {flwr_nightly-1.13.0.dev20241113.dist-info → flwr_nightly-1.13.0.dev20241115.dist-info}/WHEEL +0 -0
  36. {flwr_nightly-1.13.0.dev20241113.dist-info → flwr_nightly-1.13.0.dev20241115.dist-info}/entry_points.txt +0 -0
@@ -28,9 +28,13 @@ from cryptography.hazmat.primitives.serialization import (
28
28
  )
29
29
 
30
30
  from flwr.common import EventType, event
31
- from flwr.common.args import try_obtain_root_certificates
31
+ from flwr.common.args import (
32
+ try_obtain_root_certificates,
33
+ try_obtain_server_certificates,
34
+ )
32
35
  from flwr.common.config import parse_config_args
33
36
  from flwr.common.constant import (
37
+ CLIENTAPPIO_API_DEFAULT_SERVER_ADDRESS,
34
38
  FLEET_API_GRPC_RERE_DEFAULT_ADDRESS,
35
39
  ISOLATION_MODE_PROCESS,
36
40
  ISOLATION_MODE_SUBPROCESS,
@@ -62,10 +66,23 @@ def run_supernode() -> None:
62
66
  "Ignoring `--flwr-dir`.",
63
67
  )
64
68
 
69
+ # Exit if unsupported argument is passed by the user
70
+ if args.app is not None:
71
+ log(
72
+ ERROR,
73
+ "The `app` argument is deprecated. The SuperNode now automatically "
74
+ "uses the ClientApp delivered from the SuperLink. Providing the app "
75
+ "directory manually is no longer supported. Please remove the `app` "
76
+ "argument from your command.",
77
+ )
78
+ sys.exit(1)
79
+
65
80
  root_certificates = try_obtain_root_certificates(args, args.superlink)
81
+ # Obtain certificates for ClientAppIo API server
82
+ server_certificates = try_obtain_server_certificates(args, TRANSPORT_TYPE_GRPC_RERE)
66
83
  load_fn = get_load_client_app_fn(
67
84
  default_app_ref="",
68
- app_path=args.app,
85
+ app_path=None,
69
86
  flwr_dir=args.flwr_dir,
70
87
  multi_app=True,
71
88
  )
@@ -87,7 +104,9 @@ def run_supernode() -> None:
87
104
  ),
88
105
  flwr_path=args.flwr_dir,
89
106
  isolation=args.isolation,
90
- supernode_address=args.supernode_address,
107
+ clientappio_api_address=args.clientappio_api_address,
108
+ certificates=server_certificates,
109
+ ssl_ca_certfile=args.ssl_ca_certfile,
91
110
  )
92
111
 
93
112
  # Graceful shutdown
@@ -137,12 +156,12 @@ def _parse_args_run_supernode() -> argparse.ArgumentParser:
137
156
  "app",
138
157
  nargs="?",
139
158
  default=None,
140
- help="Specify the path of the Flower App to load and run the `ClientApp`. "
141
- "The `pyproject.toml` file must be located in the root of this path. "
142
- "When this argument is provided, the SuperNode will exclusively respond to "
143
- "messages from the corresponding `ServerApp` by matching the FAB ID and FAB "
144
- "version. An error will be raised if a message is received from any other "
145
- "`ServerApp`.",
159
+ help=(
160
+ "(REMOVED) This argument is removed. The SuperNode now automatically "
161
+ "uses the ClientApp delivered from the SuperLink, so there is no need to "
162
+ "provide the app directory manually. This argument will be removed in a "
163
+ "future version."
164
+ ),
146
165
  )
147
166
  _parse_args_common(parser)
148
167
  parser.add_argument(
@@ -158,22 +177,22 @@ def _parse_args_run_supernode() -> argparse.ArgumentParser:
158
177
  )
159
178
  parser.add_argument(
160
179
  "--isolation",
161
- default=None,
180
+ default=ISOLATION_MODE_SUBPROCESS,
162
181
  required=False,
163
182
  choices=[
164
183
  ISOLATION_MODE_SUBPROCESS,
165
184
  ISOLATION_MODE_PROCESS,
166
185
  ],
167
- help="Isolation mode when running a `ClientApp` (optional, possible values: "
168
- "`subprocess`, `process`). By default, a `ClientApp` runs in the same process "
169
- "that executes the SuperNode. Use `subprocess` to configure SuperNode to run "
170
- "a `ClientApp` in a subprocess. Use `process` to indicate that a separate "
171
- "independent process gets created outside of SuperNode.",
186
+ help="Isolation mode when running a `ClientApp` (`subprocess` by default, "
187
+ "possible values: `subprocess`, `process`). Use `subprocess` to configure "
188
+ "SuperNode to run a `ClientApp` in a subprocess. Use `process` to indicate "
189
+ "that a separate independent process gets created outside of SuperNode.",
172
190
  )
173
191
  parser.add_argument(
174
- "--supernode-address",
175
- default="0.0.0.0:9094",
176
- help="Set the SuperNode gRPC server address. Defaults to `0.0.0.0:9094`.",
192
+ "--clientappio-api-address",
193
+ default=CLIENTAPPIO_API_DEFAULT_SERVER_ADDRESS,
194
+ help="ClientAppIo API (gRPC) server address (IPv4, IPv6, or a domain name). "
195
+ f"By default, it is set to {CLIENTAPPIO_API_DEFAULT_SERVER_ADDRESS}.",
177
196
  )
178
197
 
179
198
  return parser
@@ -216,6 +235,25 @@ def _parse_args_common(parser: argparse.ArgumentParser) -> None:
216
235
  help="Specifies the path to the PEM-encoded root certificate file for "
217
236
  "establishing secure HTTPS connections.",
218
237
  )
238
+ parser.add_argument(
239
+ "--ssl-certfile",
240
+ help="ClientAppIo API server SSL certificate file (as a path str) "
241
+ "to create a secure connection.",
242
+ type=str,
243
+ default=None,
244
+ )
245
+ parser.add_argument(
246
+ "--ssl-keyfile",
247
+ help="ClientAppIo API server SSL private key file (as a path str) "
248
+ "to create a secure connection.",
249
+ type=str,
250
+ )
251
+ parser.add_argument(
252
+ "--ssl-ca-certfile",
253
+ help="ClientAppIo API server SSL CA certificate file (as a path str) "
254
+ "to create a secure connection.",
255
+ type=str,
256
+ )
219
257
  parser.add_argument(
220
258
  "--server",
221
259
  default=FLEET_API_GRPC_RERE_DEFAULT_ADDRESS,
flwr/common/constant.py CHANGED
@@ -38,17 +38,30 @@ TRANSPORT_TYPES = [
38
38
  ]
39
39
 
40
40
  # Addresses
41
+ # Ports
42
+ CLIENTAPPIO_PORT = "9094"
43
+ SERVERAPPIO_PORT = "9091"
44
+ FLEETAPI_GRPC_RERE_PORT = "9092"
45
+ FLEETAPI_PORT = "9095"
46
+ EXEC_API_PORT = "9093"
47
+ SIMULATIONIO_PORT = "9096"
48
+ # Octets
49
+ SERVER_OCTET = "0.0.0.0"
50
+ CLIENT_OCTET = "127.0.0.1"
41
51
  # SuperNode
42
- CLIENTAPPIO_API_DEFAULT_ADDRESS = "0.0.0.0:9094"
52
+ CLIENTAPPIO_API_DEFAULT_SERVER_ADDRESS = f"{SERVER_OCTET}:{CLIENTAPPIO_PORT}"
53
+ CLIENTAPPIO_API_DEFAULT_CLIENT_ADDRESS = f"{CLIENT_OCTET}:{CLIENTAPPIO_PORT}"
43
54
  # SuperLink
44
- SERVERAPPIO_API_DEFAULT_ADDRESS = "0.0.0.0:9091"
45
- FLEET_API_GRPC_RERE_DEFAULT_ADDRESS = "0.0.0.0:9092"
55
+ SERVERAPPIO_API_DEFAULT_SERVER_ADDRESS = f"{SERVER_OCTET}:{SERVERAPPIO_PORT}"
56
+ SERVERAPPIO_API_DEFAULT_CLIENT_ADDRESS = f"{CLIENT_OCTET}:{SERVERAPPIO_PORT}"
57
+ FLEET_API_GRPC_RERE_DEFAULT_ADDRESS = f"{SERVER_OCTET}:{FLEETAPI_GRPC_RERE_PORT}"
46
58
  FLEET_API_GRPC_BIDI_DEFAULT_ADDRESS = (
47
59
  "[::]:8080" # IPv6 to keep start_server compatible
48
60
  )
49
- FLEET_API_REST_DEFAULT_ADDRESS = "0.0.0.0:9095"
50
- EXEC_API_DEFAULT_ADDRESS = "0.0.0.0:9093"
51
- SIMULATIONIO_API_DEFAULT_ADDRESS = "0.0.0.0:9096"
61
+ FLEET_API_REST_DEFAULT_ADDRESS = f"{SERVER_OCTET}:{FLEETAPI_PORT}"
62
+ EXEC_API_DEFAULT_SERVER_ADDRESS = f"{SERVER_OCTET}:{EXEC_API_PORT}"
63
+ SIMULATIONIO_API_DEFAULT_SERVER_ADDRESS = f"{SERVER_OCTET}:{SIMULATIONIO_PORT}"
64
+ SIMULATIONIO_API_DEFAULT_CLIENT_ADDRESS = f"{CLIENT_OCTET}:{SIMULATIONIO_PORT}"
52
65
 
53
66
  # Constants for ping
54
67
  PING_DEFAULT_INTERVAL = 30
@@ -134,6 +147,8 @@ class ErrorCode:
134
147
  UNKNOWN = 0
135
148
  LOAD_CLIENT_APP_EXCEPTION = 1
136
149
  CLIENT_APP_RAISED_EXCEPTION = 2
150
+ MESSAGE_UNAVAILABLE = 3
151
+ REPLY_MESSAGE_UNAVAILABLE = 4
137
152
 
138
153
  def __new__(cls) -> ErrorCode:
139
154
  """Prevent instantiation."""
flwr/common/serde.py CHANGED
@@ -872,6 +872,11 @@ def run_to_proto(run: typing.Run) -> ProtoRun:
872
872
  fab_version=run.fab_version,
873
873
  fab_hash=run.fab_hash,
874
874
  override_config=user_config_to_proto(run.override_config),
875
+ pending_at=run.pending_at,
876
+ starting_at=run.starting_at,
877
+ running_at=run.running_at,
878
+ finished_at=run.finished_at,
879
+ status=run_status_to_proto(run.status),
875
880
  )
876
881
  return proto
877
882
 
@@ -884,6 +889,11 @@ def run_from_proto(run_proto: ProtoRun) -> typing.Run:
884
889
  fab_version=run_proto.fab_version,
885
890
  fab_hash=run_proto.fab_hash,
886
891
  override_config=user_config_from_proto(run_proto.override_config),
892
+ pending_at=run_proto.pending_at,
893
+ starting_at=run_proto.starting_at,
894
+ running_at=run_proto.running_at,
895
+ finished_at=run_proto.finished_at,
896
+ status=run_status_from_proto(run_proto.status),
887
897
  )
888
898
  return run
889
899
 
flwr/common/typing.py CHANGED
@@ -208,7 +208,16 @@ class ClientMessage:
208
208
 
209
209
 
210
210
  @dataclass
211
- class Run:
211
+ class RunStatus:
212
+ """Run status information."""
213
+
214
+ status: str
215
+ sub_status: str
216
+ details: str
217
+
218
+
219
+ @dataclass
220
+ class Run: # pylint: disable=too-many-instance-attributes
212
221
  """Run details."""
213
222
 
214
223
  run_id: int
@@ -216,15 +225,27 @@ class Run:
216
225
  fab_version: str
217
226
  fab_hash: str
218
227
  override_config: UserConfig
219
-
220
-
221
- @dataclass
222
- class RunStatus:
223
- """Run status information."""
224
-
225
- status: str
226
- sub_status: str
227
- details: str
228
+ pending_at: str
229
+ starting_at: str
230
+ running_at: str
231
+ finished_at: str
232
+ status: RunStatus
233
+
234
+ @classmethod
235
+ def create_empty(cls, run_id: int) -> "Run":
236
+ """Return an empty Run instance."""
237
+ return cls(
238
+ run_id=run_id,
239
+ fab_id="",
240
+ fab_version="",
241
+ fab_hash="",
242
+ override_config={},
243
+ pending_at="",
244
+ starting_at="",
245
+ running_at="",
246
+ finished_at="",
247
+ status=RunStatus(status="", sub_status="", details=""),
248
+ )
228
249
 
229
250
 
230
251
  @dataclass
flwr/proto/exec_pb2.py CHANGED
@@ -15,9 +15,10 @@ _sym_db = _symbol_database.Default()
15
15
  from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
16
16
  from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2
17
17
  from flwr.proto import recordset_pb2 as flwr_dot_proto_dot_recordset__pb2
18
+ from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2
18
19
 
19
20
 
20
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/exec.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x1a\x66lwr/proto/transport.proto\x1a\x1a\x66lwr/proto/recordset.proto\"\xfb\x01\n\x0fStartRunRequest\x12\x1c\n\x03\x66\x61\x62\x18\x01 \x01(\x0b\x32\x0f.flwr.proto.Fab\x12H\n\x0foverride_config\x18\x02 \x03(\x0b\x32/.flwr.proto.StartRunRequest.OverrideConfigEntry\x12\x35\n\x12\x66\x65\x64\x65ration_options\x18\x03 \x01(\x0b\x32\x19.flwr.proto.ConfigsRecord\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\x10StartRunResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\"<\n\x11StreamLogsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12\x17\n\x0f\x61\x66ter_timestamp\x18\x02 \x01(\x01\"B\n\x12StreamLogsResponse\x12\x12\n\nlog_output\x18\x01 \x01(\t\x12\x18\n\x10latest_timestamp\x18\x02 \x01(\x01\x32\xa0\x01\n\x04\x45xec\x12G\n\x08StartRun\x12\x1b.flwr.proto.StartRunRequest\x1a\x1c.flwr.proto.StartRunResponse\"\x00\x12O\n\nStreamLogs\x12\x1d.flwr.proto.StreamLogsRequest\x1a\x1e.flwr.proto.StreamLogsResponse\"\x00\x30\x01\x62\x06proto3')
21
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/exec.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x1a\x66lwr/proto/transport.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x14\x66lwr/proto/run.proto\"\xfb\x01\n\x0fStartRunRequest\x12\x1c\n\x03\x66\x61\x62\x18\x01 \x01(\x0b\x32\x0f.flwr.proto.Fab\x12H\n\x0foverride_config\x18\x02 \x03(\x0b\x32/.flwr.proto.StartRunRequest.OverrideConfigEntry\x12\x35\n\x12\x66\x65\x64\x65ration_options\x18\x03 \x01(\x0b\x32\x19.flwr.proto.ConfigsRecord\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\x10StartRunResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\"<\n\x11StreamLogsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12\x17\n\x0f\x61\x66ter_timestamp\x18\x02 \x01(\x01\"B\n\x12StreamLogsResponse\x12\x12\n\nlog_output\x18\x01 \x01(\t\x12\x18\n\x10latest_timestamp\x18\x02 \x01(\x01\"1\n\x0fListRunsRequest\x12\x13\n\x06run_id\x18\x01 \x01(\x04H\x00\x88\x01\x01\x42\t\n\x07_run_id\"\x9d\x01\n\x10ListRunsResponse\x12;\n\x08run_dict\x18\x01 \x03(\x0b\x32).flwr.proto.ListRunsResponse.RunDictEntry\x12\x0b\n\x03now\x18\x02 \x01(\t\x1a?\n\x0cRunDictEntry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\x1e\n\x05value\x18\x02 \x01(\x0b\x32\x0f.flwr.proto.Run:\x02\x38\x01\x32\xe9\x01\n\x04\x45xec\x12G\n\x08StartRun\x12\x1b.flwr.proto.StartRunRequest\x1a\x1c.flwr.proto.StartRunResponse\"\x00\x12O\n\nStreamLogs\x12\x1d.flwr.proto.StreamLogsRequest\x1a\x1e.flwr.proto.StreamLogsResponse\"\x00\x30\x01\x12G\n\x08ListRuns\x12\x1b.flwr.proto.ListRunsRequest\x1a\x1c.flwr.proto.ListRunsResponse\"\x00\x62\x06proto3')
21
22
 
22
23
  _globals = globals()
23
24
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -26,16 +27,24 @@ if _descriptor._USE_C_DESCRIPTORS == False:
26
27
  DESCRIPTOR._options = None
27
28
  _globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._options = None
28
29
  _globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_options = b'8\001'
29
- _globals['_STARTRUNREQUEST']._serialized_start=116
30
- _globals['_STARTRUNREQUEST']._serialized_end=367
31
- _globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_start=294
32
- _globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_end=367
33
- _globals['_STARTRUNRESPONSE']._serialized_start=369
34
- _globals['_STARTRUNRESPONSE']._serialized_end=403
35
- _globals['_STREAMLOGSREQUEST']._serialized_start=405
36
- _globals['_STREAMLOGSREQUEST']._serialized_end=465
37
- _globals['_STREAMLOGSRESPONSE']._serialized_start=467
38
- _globals['_STREAMLOGSRESPONSE']._serialized_end=533
39
- _globals['_EXEC']._serialized_start=536
40
- _globals['_EXEC']._serialized_end=696
30
+ _globals['_LISTRUNSRESPONSE_RUNDICTENTRY']._options = None
31
+ _globals['_LISTRUNSRESPONSE_RUNDICTENTRY']._serialized_options = b'8\001'
32
+ _globals['_STARTRUNREQUEST']._serialized_start=138
33
+ _globals['_STARTRUNREQUEST']._serialized_end=389
34
+ _globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_start=316
35
+ _globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_end=389
36
+ _globals['_STARTRUNRESPONSE']._serialized_start=391
37
+ _globals['_STARTRUNRESPONSE']._serialized_end=425
38
+ _globals['_STREAMLOGSREQUEST']._serialized_start=427
39
+ _globals['_STREAMLOGSREQUEST']._serialized_end=487
40
+ _globals['_STREAMLOGSRESPONSE']._serialized_start=489
41
+ _globals['_STREAMLOGSRESPONSE']._serialized_end=555
42
+ _globals['_LISTRUNSREQUEST']._serialized_start=557
43
+ _globals['_LISTRUNSREQUEST']._serialized_end=606
44
+ _globals['_LISTRUNSRESPONSE']._serialized_start=609
45
+ _globals['_LISTRUNSRESPONSE']._serialized_end=766
46
+ _globals['_LISTRUNSRESPONSE_RUNDICTENTRY']._serialized_start=703
47
+ _globals['_LISTRUNSRESPONSE_RUNDICTENTRY']._serialized_end=766
48
+ _globals['_EXEC']._serialized_start=769
49
+ _globals['_EXEC']._serialized_end=1002
41
50
  # @@protoc_insertion_point(module_scope)
flwr/proto/exec_pb2.pyi CHANGED
@@ -5,6 +5,7 @@ isort:skip_file
5
5
  import builtins
6
6
  import flwr.proto.fab_pb2
7
7
  import flwr.proto.recordset_pb2
8
+ import flwr.proto.run_pb2
8
9
  import flwr.proto.transport_pb2
9
10
  import google.protobuf.descriptor
10
11
  import google.protobuf.internal.containers
@@ -88,3 +89,46 @@ class StreamLogsResponse(google.protobuf.message.Message):
88
89
  ) -> None: ...
89
90
  def ClearField(self, field_name: typing_extensions.Literal["latest_timestamp",b"latest_timestamp","log_output",b"log_output"]) -> None: ...
90
91
  global___StreamLogsResponse = StreamLogsResponse
92
+
93
+ class ListRunsRequest(google.protobuf.message.Message):
94
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
95
+ RUN_ID_FIELD_NUMBER: builtins.int
96
+ run_id: builtins.int
97
+ def __init__(self,
98
+ *,
99
+ run_id: typing.Optional[builtins.int] = ...,
100
+ ) -> None: ...
101
+ def HasField(self, field_name: typing_extensions.Literal["_run_id",b"_run_id","run_id",b"run_id"]) -> builtins.bool: ...
102
+ def ClearField(self, field_name: typing_extensions.Literal["_run_id",b"_run_id","run_id",b"run_id"]) -> None: ...
103
+ def WhichOneof(self, oneof_group: typing_extensions.Literal["_run_id",b"_run_id"]) -> typing.Optional[typing_extensions.Literal["run_id"]]: ...
104
+ global___ListRunsRequest = ListRunsRequest
105
+
106
+ class ListRunsResponse(google.protobuf.message.Message):
107
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
108
+ class RunDictEntry(google.protobuf.message.Message):
109
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
110
+ KEY_FIELD_NUMBER: builtins.int
111
+ VALUE_FIELD_NUMBER: builtins.int
112
+ key: builtins.int
113
+ @property
114
+ def value(self) -> flwr.proto.run_pb2.Run: ...
115
+ def __init__(self,
116
+ *,
117
+ key: builtins.int = ...,
118
+ value: typing.Optional[flwr.proto.run_pb2.Run] = ...,
119
+ ) -> None: ...
120
+ def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ...
121
+ def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
122
+
123
+ RUN_DICT_FIELD_NUMBER: builtins.int
124
+ NOW_FIELD_NUMBER: builtins.int
125
+ @property
126
+ def run_dict(self) -> google.protobuf.internal.containers.MessageMap[builtins.int, flwr.proto.run_pb2.Run]: ...
127
+ now: typing.Text
128
+ def __init__(self,
129
+ *,
130
+ run_dict: typing.Optional[typing.Mapping[builtins.int, flwr.proto.run_pb2.Run]] = ...,
131
+ now: typing.Text = ...,
132
+ ) -> None: ...
133
+ def ClearField(self, field_name: typing_extensions.Literal["now",b"now","run_dict",b"run_dict"]) -> None: ...
134
+ global___ListRunsResponse = ListRunsResponse
@@ -24,6 +24,11 @@ class ExecStub(object):
24
24
  request_serializer=flwr_dot_proto_dot_exec__pb2.StreamLogsRequest.SerializeToString,
25
25
  response_deserializer=flwr_dot_proto_dot_exec__pb2.StreamLogsResponse.FromString,
26
26
  )
27
+ self.ListRuns = channel.unary_unary(
28
+ '/flwr.proto.Exec/ListRuns',
29
+ request_serializer=flwr_dot_proto_dot_exec__pb2.ListRunsRequest.SerializeToString,
30
+ response_deserializer=flwr_dot_proto_dot_exec__pb2.ListRunsResponse.FromString,
31
+ )
27
32
 
28
33
 
29
34
  class ExecServicer(object):
@@ -43,6 +48,13 @@ class ExecServicer(object):
43
48
  context.set_details('Method not implemented!')
44
49
  raise NotImplementedError('Method not implemented!')
45
50
 
51
+ def ListRuns(self, request, context):
52
+ """flwr ls command
53
+ """
54
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
55
+ context.set_details('Method not implemented!')
56
+ raise NotImplementedError('Method not implemented!')
57
+
46
58
 
47
59
  def add_ExecServicer_to_server(servicer, server):
48
60
  rpc_method_handlers = {
@@ -56,6 +68,11 @@ def add_ExecServicer_to_server(servicer, server):
56
68
  request_deserializer=flwr_dot_proto_dot_exec__pb2.StreamLogsRequest.FromString,
57
69
  response_serializer=flwr_dot_proto_dot_exec__pb2.StreamLogsResponse.SerializeToString,
58
70
  ),
71
+ 'ListRuns': grpc.unary_unary_rpc_method_handler(
72
+ servicer.ListRuns,
73
+ request_deserializer=flwr_dot_proto_dot_exec__pb2.ListRunsRequest.FromString,
74
+ response_serializer=flwr_dot_proto_dot_exec__pb2.ListRunsResponse.SerializeToString,
75
+ ),
59
76
  }
60
77
  generic_handler = grpc.method_handlers_generic_handler(
61
78
  'flwr.proto.Exec', rpc_method_handlers)
@@ -99,3 +116,20 @@ class Exec(object):
99
116
  flwr_dot_proto_dot_exec__pb2.StreamLogsResponse.FromString,
100
117
  options, channel_credentials,
101
118
  insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
119
+
120
+ @staticmethod
121
+ def ListRuns(request,
122
+ target,
123
+ options=(),
124
+ channel_credentials=None,
125
+ call_credentials=None,
126
+ insecure=False,
127
+ compression=None,
128
+ wait_for_ready=None,
129
+ timeout=None,
130
+ metadata=None):
131
+ return grpc.experimental.unary_unary(request, target, '/flwr.proto.Exec/ListRuns',
132
+ flwr_dot_proto_dot_exec__pb2.ListRunsRequest.SerializeToString,
133
+ flwr_dot_proto_dot_exec__pb2.ListRunsResponse.FromString,
134
+ options, channel_credentials,
135
+ insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@@ -19,6 +19,11 @@ class ExecStub:
19
19
  flwr.proto.exec_pb2.StreamLogsResponse]
20
20
  """Start log stream upon request"""
21
21
 
22
+ ListRuns: grpc.UnaryUnaryMultiCallable[
23
+ flwr.proto.exec_pb2.ListRunsRequest,
24
+ flwr.proto.exec_pb2.ListRunsResponse]
25
+ """flwr ls command"""
26
+
22
27
 
23
28
  class ExecServicer(metaclass=abc.ABCMeta):
24
29
  @abc.abstractmethod
@@ -37,5 +42,13 @@ class ExecServicer(metaclass=abc.ABCMeta):
37
42
  """Start log stream upon request"""
38
43
  pass
39
44
 
45
+ @abc.abstractmethod
46
+ def ListRuns(self,
47
+ request: flwr.proto.exec_pb2.ListRunsRequest,
48
+ context: grpc.ServicerContext,
49
+ ) -> flwr.proto.exec_pb2.ListRunsResponse:
50
+ """flwr ls command"""
51
+ pass
52
+
40
53
 
41
54
  def add_ExecServicer_to_server(servicer: ExecServicer, server: grpc.Server) -> None: ...
flwr/proto/run_pb2.py CHANGED
@@ -18,7 +18,7 @@ from flwr.proto import recordset_pb2 as flwr_dot_proto_dot_recordset__pb2
18
18
  from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2
19
19
 
20
20
 
21
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x66lwr/proto/run.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x1a\x66lwr/proto/transport.proto\"\xd5\x01\n\x03Run\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12\x0e\n\x06\x66\x61\x62_id\x18\x02 \x01(\t\x12\x13\n\x0b\x66\x61\x62_version\x18\x03 \x01(\t\x12<\n\x0foverride_config\x18\x04 \x03(\x0b\x32#.flwr.proto.Run.OverrideConfigEntry\x12\x10\n\x08\x66\x61\x62_hash\x18\x05 \x01(\t\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\tRunStatus\x12\x0e\n\x06status\x18\x01 \x01(\t\x12\x12\n\nsub_status\x18\x02 \x01(\t\x12\x0f\n\x07\x64\x65tails\x18\x03 \x01(\t\"\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(\x04\"?\n\rGetRunRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x0e\n\x06run_id\x18\x02 \x01(\x04\".\n\x0eGetRunResponse\x12\x1c\n\x03run\x18\x01 \x01(\x0b\x32\x0f.flwr.proto.Run\"S\n\x16UpdateRunStatusRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12)\n\nrun_status\x18\x02 \x01(\x0b\x32\x15.flwr.proto.RunStatus\"\x19\n\x17UpdateRunStatusResponse\"F\n\x13GetRunStatusRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x0f\n\x07run_ids\x18\x02 \x03(\x04\"\xb1\x01\n\x14GetRunStatusResponse\x12L\n\x0frun_status_dict\x18\x01 \x03(\x0b\x32\x33.flwr.proto.GetRunStatusResponse.RunStatusDictEntry\x1aK\n\x12RunStatusDictEntry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.flwr.proto.RunStatus:\x02\x38\x01\"-\n\x1bGetFederationOptionsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\"U\n\x1cGetFederationOptionsResponse\x12\x35\n\x12\x66\x65\x64\x65ration_options\x18\x01 \x01(\x0b\x32\x19.flwr.proto.ConfigsRecordb\x06proto3')
21
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x66lwr/proto/run.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x1a\x66lwr/proto/transport.proto\"\xce\x02\n\x03Run\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12\x0e\n\x06\x66\x61\x62_id\x18\x02 \x01(\t\x12\x13\n\x0b\x66\x61\x62_version\x18\x03 \x01(\t\x12<\n\x0foverride_config\x18\x04 \x03(\x0b\x32#.flwr.proto.Run.OverrideConfigEntry\x12\x10\n\x08\x66\x61\x62_hash\x18\x05 \x01(\t\x12\x12\n\npending_at\x18\x06 \x01(\t\x12\x13\n\x0bstarting_at\x18\x07 \x01(\t\x12\x12\n\nrunning_at\x18\x08 \x01(\t\x12\x13\n\x0b\x66inished_at\x18\t \x01(\t\x12%\n\x06status\x18\n \x01(\x0b\x32\x15.flwr.proto.RunStatus\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\tRunStatus\x12\x0e\n\x06status\x18\x01 \x01(\t\x12\x12\n\nsub_status\x18\x02 \x01(\t\x12\x0f\n\x07\x64\x65tails\x18\x03 \x01(\t\"\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(\x04\"?\n\rGetRunRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x0e\n\x06run_id\x18\x02 \x01(\x04\".\n\x0eGetRunResponse\x12\x1c\n\x03run\x18\x01 \x01(\x0b\x32\x0f.flwr.proto.Run\"S\n\x16UpdateRunStatusRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12)\n\nrun_status\x18\x02 \x01(\x0b\x32\x15.flwr.proto.RunStatus\"\x19\n\x17UpdateRunStatusResponse\"F\n\x13GetRunStatusRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x0f\n\x07run_ids\x18\x02 \x03(\x04\"\xb1\x01\n\x14GetRunStatusResponse\x12L\n\x0frun_status_dict\x18\x01 \x03(\x0b\x32\x33.flwr.proto.GetRunStatusResponse.RunStatusDictEntry\x1aK\n\x12RunStatusDictEntry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.flwr.proto.RunStatus:\x02\x38\x01\"-\n\x1bGetFederationOptionsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\"U\n\x1cGetFederationOptionsResponse\x12\x35\n\x12\x66\x65\x64\x65ration_options\x18\x01 \x01(\x0b\x32\x19.flwr.proto.ConfigsRecordb\x06proto3')
22
22
 
23
23
  _globals = globals()
24
24
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -32,33 +32,33 @@ if _descriptor._USE_C_DESCRIPTORS == False:
32
32
  _globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._options = None
33
33
  _globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._serialized_options = b'8\001'
34
34
  _globals['_RUN']._serialized_start=138
35
- _globals['_RUN']._serialized_end=351
36
- _globals['_RUN_OVERRIDECONFIGENTRY']._serialized_start=278
37
- _globals['_RUN_OVERRIDECONFIGENTRY']._serialized_end=351
38
- _globals['_RUNSTATUS']._serialized_start=353
39
- _globals['_RUNSTATUS']._serialized_end=417
40
- _globals['_CREATERUNREQUEST']._serialized_start=420
41
- _globals['_CREATERUNREQUEST']._serialized_end=655
42
- _globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_start=278
43
- _globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_end=351
44
- _globals['_CREATERUNRESPONSE']._serialized_start=657
45
- _globals['_CREATERUNRESPONSE']._serialized_end=692
46
- _globals['_GETRUNREQUEST']._serialized_start=694
47
- _globals['_GETRUNREQUEST']._serialized_end=757
48
- _globals['_GETRUNRESPONSE']._serialized_start=759
49
- _globals['_GETRUNRESPONSE']._serialized_end=805
50
- _globals['_UPDATERUNSTATUSREQUEST']._serialized_start=807
51
- _globals['_UPDATERUNSTATUSREQUEST']._serialized_end=890
52
- _globals['_UPDATERUNSTATUSRESPONSE']._serialized_start=892
53
- _globals['_UPDATERUNSTATUSRESPONSE']._serialized_end=917
54
- _globals['_GETRUNSTATUSREQUEST']._serialized_start=919
55
- _globals['_GETRUNSTATUSREQUEST']._serialized_end=989
56
- _globals['_GETRUNSTATUSRESPONSE']._serialized_start=992
57
- _globals['_GETRUNSTATUSRESPONSE']._serialized_end=1169
58
- _globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._serialized_start=1094
59
- _globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._serialized_end=1169
60
- _globals['_GETFEDERATIONOPTIONSREQUEST']._serialized_start=1171
61
- _globals['_GETFEDERATIONOPTIONSREQUEST']._serialized_end=1216
62
- _globals['_GETFEDERATIONOPTIONSRESPONSE']._serialized_start=1218
63
- _globals['_GETFEDERATIONOPTIONSRESPONSE']._serialized_end=1303
35
+ _globals['_RUN']._serialized_end=472
36
+ _globals['_RUN_OVERRIDECONFIGENTRY']._serialized_start=399
37
+ _globals['_RUN_OVERRIDECONFIGENTRY']._serialized_end=472
38
+ _globals['_RUNSTATUS']._serialized_start=474
39
+ _globals['_RUNSTATUS']._serialized_end=538
40
+ _globals['_CREATERUNREQUEST']._serialized_start=541
41
+ _globals['_CREATERUNREQUEST']._serialized_end=776
42
+ _globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_start=399
43
+ _globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_end=472
44
+ _globals['_CREATERUNRESPONSE']._serialized_start=778
45
+ _globals['_CREATERUNRESPONSE']._serialized_end=813
46
+ _globals['_GETRUNREQUEST']._serialized_start=815
47
+ _globals['_GETRUNREQUEST']._serialized_end=878
48
+ _globals['_GETRUNRESPONSE']._serialized_start=880
49
+ _globals['_GETRUNRESPONSE']._serialized_end=926
50
+ _globals['_UPDATERUNSTATUSREQUEST']._serialized_start=928
51
+ _globals['_UPDATERUNSTATUSREQUEST']._serialized_end=1011
52
+ _globals['_UPDATERUNSTATUSRESPONSE']._serialized_start=1013
53
+ _globals['_UPDATERUNSTATUSRESPONSE']._serialized_end=1038
54
+ _globals['_GETRUNSTATUSREQUEST']._serialized_start=1040
55
+ _globals['_GETRUNSTATUSREQUEST']._serialized_end=1110
56
+ _globals['_GETRUNSTATUSRESPONSE']._serialized_start=1113
57
+ _globals['_GETRUNSTATUSRESPONSE']._serialized_end=1290
58
+ _globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._serialized_start=1215
59
+ _globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._serialized_end=1290
60
+ _globals['_GETFEDERATIONOPTIONSREQUEST']._serialized_start=1292
61
+ _globals['_GETFEDERATIONOPTIONSREQUEST']._serialized_end=1337
62
+ _globals['_GETFEDERATIONOPTIONSRESPONSE']._serialized_start=1339
63
+ _globals['_GETFEDERATIONOPTIONSRESPONSE']._serialized_end=1424
64
64
  # @@protoc_insertion_point(module_scope)
flwr/proto/run_pb2.pyi CHANGED
@@ -37,12 +37,23 @@ class Run(google.protobuf.message.Message):
37
37
  FAB_VERSION_FIELD_NUMBER: builtins.int
38
38
  OVERRIDE_CONFIG_FIELD_NUMBER: builtins.int
39
39
  FAB_HASH_FIELD_NUMBER: builtins.int
40
+ PENDING_AT_FIELD_NUMBER: builtins.int
41
+ STARTING_AT_FIELD_NUMBER: builtins.int
42
+ RUNNING_AT_FIELD_NUMBER: builtins.int
43
+ FINISHED_AT_FIELD_NUMBER: builtins.int
44
+ STATUS_FIELD_NUMBER: builtins.int
40
45
  run_id: builtins.int
41
46
  fab_id: typing.Text
42
47
  fab_version: typing.Text
43
48
  @property
44
49
  def override_config(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.transport_pb2.Scalar]: ...
45
50
  fab_hash: typing.Text
51
+ pending_at: typing.Text
52
+ starting_at: typing.Text
53
+ running_at: typing.Text
54
+ finished_at: typing.Text
55
+ @property
56
+ def status(self) -> global___RunStatus: ...
46
57
  def __init__(self,
47
58
  *,
48
59
  run_id: builtins.int = ...,
@@ -50,8 +61,14 @@ class Run(google.protobuf.message.Message):
50
61
  fab_version: typing.Text = ...,
51
62
  override_config: typing.Optional[typing.Mapping[typing.Text, flwr.proto.transport_pb2.Scalar]] = ...,
52
63
  fab_hash: typing.Text = ...,
64
+ pending_at: typing.Text = ...,
65
+ starting_at: typing.Text = ...,
66
+ running_at: typing.Text = ...,
67
+ finished_at: typing.Text = ...,
68
+ status: typing.Optional[global___RunStatus] = ...,
53
69
  ) -> None: ...
54
- def ClearField(self, field_name: typing_extensions.Literal["fab_hash",b"fab_hash","fab_id",b"fab_id","fab_version",b"fab_version","override_config",b"override_config","run_id",b"run_id"]) -> None: ...
70
+ def HasField(self, field_name: typing_extensions.Literal["status",b"status"]) -> builtins.bool: ...
71
+ def ClearField(self, field_name: typing_extensions.Literal["fab_hash",b"fab_hash","fab_id",b"fab_id","fab_version",b"fab_version","finished_at",b"finished_at","override_config",b"override_config","pending_at",b"pending_at","run_id",b"run_id","running_at",b"running_at","starting_at",b"starting_at","status",b"status"]) -> None: ...
55
72
  global___Run = Run
56
73
 
57
74
  class RunStatus(google.protobuf.message.Message):