flwr-nightly 1.13.0.dev20241106__py3-none-any.whl → 1.13.0.dev20241111__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 (45) hide show
  1. flwr/cli/run/run.py +16 -5
  2. flwr/client/app.py +10 -6
  3. flwr/client/clientapp/app.py +21 -16
  4. flwr/client/nodestate/__init__.py +25 -0
  5. flwr/client/nodestate/in_memory_nodestate.py +38 -0
  6. flwr/client/nodestate/nodestate.py +30 -0
  7. flwr/client/nodestate/nodestate_factory.py +37 -0
  8. flwr/common/args.py +83 -0
  9. flwr/common/config.py +10 -0
  10. flwr/common/constant.py +0 -1
  11. flwr/common/logger.py +6 -2
  12. flwr/common/object_ref.py +47 -16
  13. flwr/common/typing.py +1 -1
  14. flwr/proto/exec_pb2.py +14 -17
  15. flwr/proto/exec_pb2.pyi +6 -20
  16. flwr/proto/run_pb2.py +32 -27
  17. flwr/proto/run_pb2.pyi +26 -0
  18. flwr/proto/simulationio_pb2.py +2 -2
  19. flwr/proto/simulationio_pb2_grpc.py +34 -0
  20. flwr/proto/simulationio_pb2_grpc.pyi +13 -0
  21. flwr/server/app.py +45 -20
  22. flwr/server/driver/driver.py +1 -1
  23. flwr/server/driver/grpc_driver.py +2 -6
  24. flwr/server/driver/inmemory_driver.py +1 -3
  25. flwr/server/run_serverapp.py +2 -2
  26. flwr/server/serverapp/app.py +16 -72
  27. flwr/server/strategy/aggregate.py +4 -4
  28. flwr/server/superlink/linkstate/in_memory_linkstate.py +5 -16
  29. flwr/server/superlink/linkstate/linkstate.py +5 -4
  30. flwr/server/superlink/linkstate/sqlite_linkstate.py +6 -15
  31. flwr/server/superlink/linkstate/utils.py +2 -33
  32. flwr/server/superlink/simulation/simulationio_servicer.py +22 -1
  33. flwr/simulation/__init__.py +3 -1
  34. flwr/simulation/app.py +273 -345
  35. flwr/simulation/legacy_app.py +382 -0
  36. flwr/simulation/run_simulation.py +1 -1
  37. flwr/superexec/deployment.py +1 -1
  38. flwr/superexec/exec_servicer.py +2 -2
  39. flwr/superexec/executor.py +4 -3
  40. flwr/superexec/simulation.py +44 -102
  41. {flwr_nightly-1.13.0.dev20241106.dist-info → flwr_nightly-1.13.0.dev20241111.dist-info}/METADATA +5 -4
  42. {flwr_nightly-1.13.0.dev20241106.dist-info → flwr_nightly-1.13.0.dev20241111.dist-info}/RECORD +45 -39
  43. {flwr_nightly-1.13.0.dev20241106.dist-info → flwr_nightly-1.13.0.dev20241111.dist-info}/entry_points.txt +1 -0
  44. {flwr_nightly-1.13.0.dev20241106.dist-info → flwr_nightly-1.13.0.dev20241111.dist-info}/LICENSE +0 -0
  45. {flwr_nightly-1.13.0.dev20241106.dist-info → flwr_nightly-1.13.0.dev20241111.dist-info}/WHEEL +0 -0
flwr/proto/exec_pb2.pyi CHANGED
@@ -4,6 +4,7 @@ isort:skip_file
4
4
  """
5
5
  import builtins
6
6
  import flwr.proto.fab_pb2
7
+ import flwr.proto.recordset_pb2
7
8
  import flwr.proto.transport_pb2
8
9
  import google.protobuf.descriptor
9
10
  import google.protobuf.internal.containers
@@ -30,38 +31,23 @@ class StartRunRequest(google.protobuf.message.Message):
30
31
  def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ...
31
32
  def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
32
33
 
33
- class FederationConfigEntry(google.protobuf.message.Message):
34
- DESCRIPTOR: google.protobuf.descriptor.Descriptor
35
- KEY_FIELD_NUMBER: builtins.int
36
- VALUE_FIELD_NUMBER: builtins.int
37
- key: typing.Text
38
- @property
39
- def value(self) -> flwr.proto.transport_pb2.Scalar: ...
40
- def __init__(self,
41
- *,
42
- key: typing.Text = ...,
43
- value: typing.Optional[flwr.proto.transport_pb2.Scalar] = ...,
44
- ) -> None: ...
45
- def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ...
46
- def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
47
-
48
34
  FAB_FIELD_NUMBER: builtins.int
49
35
  OVERRIDE_CONFIG_FIELD_NUMBER: builtins.int
50
- FEDERATION_CONFIG_FIELD_NUMBER: builtins.int
36
+ FEDERATION_OPTIONS_FIELD_NUMBER: builtins.int
51
37
  @property
52
38
  def fab(self) -> flwr.proto.fab_pb2.Fab: ...
53
39
  @property
54
40
  def override_config(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.transport_pb2.Scalar]: ...
55
41
  @property
56
- def federation_config(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.transport_pb2.Scalar]: ...
42
+ def federation_options(self) -> flwr.proto.recordset_pb2.ConfigsRecord: ...
57
43
  def __init__(self,
58
44
  *,
59
45
  fab: typing.Optional[flwr.proto.fab_pb2.Fab] = ...,
60
46
  override_config: typing.Optional[typing.Mapping[typing.Text, flwr.proto.transport_pb2.Scalar]] = ...,
61
- federation_config: typing.Optional[typing.Mapping[typing.Text, flwr.proto.transport_pb2.Scalar]] = ...,
47
+ federation_options: typing.Optional[flwr.proto.recordset_pb2.ConfigsRecord] = ...,
62
48
  ) -> None: ...
63
- def HasField(self, field_name: typing_extensions.Literal["fab",b"fab"]) -> builtins.bool: ...
64
- def ClearField(self, field_name: typing_extensions.Literal["fab",b"fab","federation_config",b"federation_config","override_config",b"override_config"]) -> None: ...
49
+ def HasField(self, field_name: typing_extensions.Literal["fab",b"fab","federation_options",b"federation_options"]) -> builtins.bool: ...
50
+ def ClearField(self, field_name: typing_extensions.Literal["fab",b"fab","federation_options",b"federation_options","override_config",b"override_config"]) -> None: ...
65
51
  global___StartRunRequest = StartRunRequest
66
52
 
67
53
  class StartRunResponse(google.protobuf.message.Message):
flwr/proto/run_pb2.py CHANGED
@@ -14,10 +14,11 @@ _sym_db = _symbol_database.Default()
14
14
 
15
15
  from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
16
16
  from flwr.proto import node_pb2 as flwr_dot_proto_dot_node__pb2
17
+ from flwr.proto import recordset_pb2 as flwr_dot_proto_dot_recordset__pb2
17
18
  from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2
18
19
 
19
20
 
20
- 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/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\x62\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\"\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
22
 
22
23
  _globals = globals()
23
24
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -30,30 +31,34 @@ if _descriptor._USE_C_DESCRIPTORS == False:
30
31
  _globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_options = b'8\001'
31
32
  _globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._options = None
32
33
  _globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._serialized_options = b'8\001'
33
- _globals['_RUN']._serialized_start=110
34
- _globals['_RUN']._serialized_end=323
35
- _globals['_RUN_OVERRIDECONFIGENTRY']._serialized_start=250
36
- _globals['_RUN_OVERRIDECONFIGENTRY']._serialized_end=323
37
- _globals['_RUNSTATUS']._serialized_start=325
38
- _globals['_RUNSTATUS']._serialized_end=389
39
- _globals['_CREATERUNREQUEST']._serialized_start=392
40
- _globals['_CREATERUNREQUEST']._serialized_end=627
41
- _globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_start=250
42
- _globals['_CREATERUNREQUEST_OVERRIDECONFIGENTRY']._serialized_end=323
43
- _globals['_CREATERUNRESPONSE']._serialized_start=629
44
- _globals['_CREATERUNRESPONSE']._serialized_end=664
45
- _globals['_GETRUNREQUEST']._serialized_start=666
46
- _globals['_GETRUNREQUEST']._serialized_end=729
47
- _globals['_GETRUNRESPONSE']._serialized_start=731
48
- _globals['_GETRUNRESPONSE']._serialized_end=777
49
- _globals['_UPDATERUNSTATUSREQUEST']._serialized_start=779
50
- _globals['_UPDATERUNSTATUSREQUEST']._serialized_end=862
51
- _globals['_UPDATERUNSTATUSRESPONSE']._serialized_start=864
52
- _globals['_UPDATERUNSTATUSRESPONSE']._serialized_end=889
53
- _globals['_GETRUNSTATUSREQUEST']._serialized_start=891
54
- _globals['_GETRUNSTATUSREQUEST']._serialized_end=961
55
- _globals['_GETRUNSTATUSRESPONSE']._serialized_start=964
56
- _globals['_GETRUNSTATUSRESPONSE']._serialized_end=1141
57
- _globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._serialized_start=1066
58
- _globals['_GETRUNSTATUSRESPONSE_RUNSTATUSDICTENTRY']._serialized_end=1141
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
59
64
  # @@protoc_insertion_point(module_scope)
flwr/proto/run_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.node_pb2
8
+ import flwr.proto.recordset_pb2
8
9
  import flwr.proto.transport_pb2
9
10
  import google.protobuf.descriptor
10
11
  import google.protobuf.internal.containers
@@ -223,3 +224,28 @@ class GetRunStatusResponse(google.protobuf.message.Message):
223
224
  ) -> None: ...
224
225
  def ClearField(self, field_name: typing_extensions.Literal["run_status_dict",b"run_status_dict"]) -> None: ...
225
226
  global___GetRunStatusResponse = GetRunStatusResponse
227
+
228
+ class GetFederationOptionsRequest(google.protobuf.message.Message):
229
+ """Get Federation Options associated with run"""
230
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
231
+ RUN_ID_FIELD_NUMBER: builtins.int
232
+ run_id: builtins.int
233
+ def __init__(self,
234
+ *,
235
+ run_id: builtins.int = ...,
236
+ ) -> None: ...
237
+ def ClearField(self, field_name: typing_extensions.Literal["run_id",b"run_id"]) -> None: ...
238
+ global___GetFederationOptionsRequest = GetFederationOptionsRequest
239
+
240
+ class GetFederationOptionsResponse(google.protobuf.message.Message):
241
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
242
+ FEDERATION_OPTIONS_FIELD_NUMBER: builtins.int
243
+ @property
244
+ def federation_options(self) -> flwr.proto.recordset_pb2.ConfigsRecord: ...
245
+ def __init__(self,
246
+ *,
247
+ federation_options: typing.Optional[flwr.proto.recordset_pb2.ConfigsRecord] = ...,
248
+ ) -> None: ...
249
+ def HasField(self, field_name: typing_extensions.Literal["federation_options",b"federation_options"]) -> builtins.bool: ...
250
+ def ClearField(self, field_name: typing_extensions.Literal["federation_options",b"federation_options"]) -> None: ...
251
+ global___GetFederationOptionsResponse = GetFederationOptionsResponse
@@ -18,7 +18,7 @@ from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2
18
18
  from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
19
19
 
20
20
 
21
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x66lwr/proto/simulationio.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/log.proto\x1a\x18\x66lwr/proto/message.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\"\x1d\n\x1bPullSimulationInputsRequest\"\x80\x01\n\x1cPullSimulationInputsResponse\x12$\n\x07\x63ontext\x18\x01 \x01(\x0b\x32\x13.flwr.proto.Context\x12\x1c\n\x03run\x18\x02 \x01(\x0b\x32\x0f.flwr.proto.Run\x12\x1c\n\x03\x66\x61\x62\x18\x03 \x01(\x0b\x32\x0f.flwr.proto.Fab\"T\n\x1cPushSimulationOutputsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12$\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x13.flwr.proto.Context\"\x1f\n\x1dPushSimulationOutputsResponse2\x92\x03\n\x0cSimulationIo\x12k\n\x14PullSimulationInputs\x12\'.flwr.proto.PullSimulationInputsRequest\x1a(.flwr.proto.PullSimulationInputsResponse\"\x00\x12n\n\x15PushSimulationOutputs\x12(.flwr.proto.PushSimulationOutputsRequest\x1a).flwr.proto.PushSimulationOutputsResponse\"\x00\x12\\\n\x0fUpdateRunStatus\x12\".flwr.proto.UpdateRunStatusRequest\x1a#.flwr.proto.UpdateRunStatusResponse\"\x00\x12G\n\x08PushLogs\x12\x1b.flwr.proto.PushLogsRequest\x1a\x1c.flwr.proto.PushLogsResponse\"\x00\x62\x06proto3')
21
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x66lwr/proto/simulationio.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/log.proto\x1a\x18\x66lwr/proto/message.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\"\x1d\n\x1bPullSimulationInputsRequest\"\x80\x01\n\x1cPullSimulationInputsResponse\x12$\n\x07\x63ontext\x18\x01 \x01(\x0b\x32\x13.flwr.proto.Context\x12\x1c\n\x03run\x18\x02 \x01(\x0b\x32\x0f.flwr.proto.Run\x12\x1c\n\x03\x66\x61\x62\x18\x03 \x01(\x0b\x32\x0f.flwr.proto.Fab\"T\n\x1cPushSimulationOutputsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12$\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x13.flwr.proto.Context\"\x1f\n\x1dPushSimulationOutputsResponse2\xff\x03\n\x0cSimulationIo\x12k\n\x14PullSimulationInputs\x12\'.flwr.proto.PullSimulationInputsRequest\x1a(.flwr.proto.PullSimulationInputsResponse\"\x00\x12n\n\x15PushSimulationOutputs\x12(.flwr.proto.PushSimulationOutputsRequest\x1a).flwr.proto.PushSimulationOutputsResponse\"\x00\x12\\\n\x0fUpdateRunStatus\x12\".flwr.proto.UpdateRunStatusRequest\x1a#.flwr.proto.UpdateRunStatusResponse\"\x00\x12G\n\x08PushLogs\x12\x1b.flwr.proto.PushLogsRequest\x1a\x1c.flwr.proto.PushLogsResponse\"\x00\x12k\n\x14GetFederationOptions\x12\'.flwr.proto.GetFederationOptionsRequest\x1a(.flwr.proto.GetFederationOptionsResponse\"\x00\x62\x06proto3')
22
22
 
23
23
  _globals = globals()
24
24
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -34,5 +34,5 @@ if _descriptor._USE_C_DESCRIPTORS == False:
34
34
  _globals['_PUSHSIMULATIONOUTPUTSRESPONSE']._serialized_start=385
35
35
  _globals['_PUSHSIMULATIONOUTPUTSRESPONSE']._serialized_end=416
36
36
  _globals['_SIMULATIONIO']._serialized_start=419
37
- _globals['_SIMULATIONIO']._serialized_end=821
37
+ _globals['_SIMULATIONIO']._serialized_end=930
38
38
  # @@protoc_insertion_point(module_scope)
@@ -36,6 +36,11 @@ class SimulationIoStub(object):
36
36
  request_serializer=flwr_dot_proto_dot_log__pb2.PushLogsRequest.SerializeToString,
37
37
  response_deserializer=flwr_dot_proto_dot_log__pb2.PushLogsResponse.FromString,
38
38
  )
39
+ self.GetFederationOptions = channel.unary_unary(
40
+ '/flwr.proto.SimulationIo/GetFederationOptions',
41
+ request_serializer=flwr_dot_proto_dot_run__pb2.GetFederationOptionsRequest.SerializeToString,
42
+ response_deserializer=flwr_dot_proto_dot_run__pb2.GetFederationOptionsResponse.FromString,
43
+ )
39
44
 
40
45
 
41
46
  class SimulationIoServicer(object):
@@ -69,6 +74,13 @@ class SimulationIoServicer(object):
69
74
  context.set_details('Method not implemented!')
70
75
  raise NotImplementedError('Method not implemented!')
71
76
 
77
+ def GetFederationOptions(self, request, context):
78
+ """Get Federation Options
79
+ """
80
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
81
+ context.set_details('Method not implemented!')
82
+ raise NotImplementedError('Method not implemented!')
83
+
72
84
 
73
85
  def add_SimulationIoServicer_to_server(servicer, server):
74
86
  rpc_method_handlers = {
@@ -92,6 +104,11 @@ def add_SimulationIoServicer_to_server(servicer, server):
92
104
  request_deserializer=flwr_dot_proto_dot_log__pb2.PushLogsRequest.FromString,
93
105
  response_serializer=flwr_dot_proto_dot_log__pb2.PushLogsResponse.SerializeToString,
94
106
  ),
107
+ 'GetFederationOptions': grpc.unary_unary_rpc_method_handler(
108
+ servicer.GetFederationOptions,
109
+ request_deserializer=flwr_dot_proto_dot_run__pb2.GetFederationOptionsRequest.FromString,
110
+ response_serializer=flwr_dot_proto_dot_run__pb2.GetFederationOptionsResponse.SerializeToString,
111
+ ),
95
112
  }
96
113
  generic_handler = grpc.method_handlers_generic_handler(
97
114
  'flwr.proto.SimulationIo', rpc_method_handlers)
@@ -169,3 +186,20 @@ class SimulationIo(object):
169
186
  flwr_dot_proto_dot_log__pb2.PushLogsResponse.FromString,
170
187
  options, channel_credentials,
171
188
  insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
189
+
190
+ @staticmethod
191
+ def GetFederationOptions(request,
192
+ target,
193
+ options=(),
194
+ channel_credentials=None,
195
+ call_credentials=None,
196
+ insecure=False,
197
+ compression=None,
198
+ wait_for_ready=None,
199
+ timeout=None,
200
+ metadata=None):
201
+ return grpc.experimental.unary_unary(request, target, '/flwr.proto.SimulationIo/GetFederationOptions',
202
+ flwr_dot_proto_dot_run__pb2.GetFederationOptionsRequest.SerializeToString,
203
+ flwr_dot_proto_dot_run__pb2.GetFederationOptionsResponse.FromString,
204
+ options, channel_credentials,
205
+ insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@@ -30,6 +30,11 @@ class SimulationIoStub:
30
30
  flwr.proto.log_pb2.PushLogsResponse]
31
31
  """Push ServerApp logs"""
32
32
 
33
+ GetFederationOptions: grpc.UnaryUnaryMultiCallable[
34
+ flwr.proto.run_pb2.GetFederationOptionsRequest,
35
+ flwr.proto.run_pb2.GetFederationOptionsResponse]
36
+ """Get Federation Options"""
37
+
33
38
 
34
39
  class SimulationIoServicer(metaclass=abc.ABCMeta):
35
40
  @abc.abstractmethod
@@ -64,5 +69,13 @@ class SimulationIoServicer(metaclass=abc.ABCMeta):
64
69
  """Push ServerApp logs"""
65
70
  pass
66
71
 
72
+ @abc.abstractmethod
73
+ def GetFederationOptions(self,
74
+ request: flwr.proto.run_pb2.GetFederationOptionsRequest,
75
+ context: grpc.ServicerContext,
76
+ ) -> flwr.proto.run_pb2.GetFederationOptionsResponse:
77
+ """Get Federation Options"""
78
+ pass
79
+
67
80
 
68
81
  def add_SimulationIoServicer_to_server(servicer: SimulationIoServicer, server: grpc.Server) -> None: ...
flwr/server/app.py CHANGED
@@ -215,6 +215,12 @@ def run_superlink() -> None:
215
215
 
216
216
  event(EventType.RUN_SUPERLINK_ENTER)
217
217
 
218
+ # Warn unused options
219
+ if args.flwr_dir is not None:
220
+ log(
221
+ WARN, "The `--flwr-dir` option is currently not in use and will be ignored."
222
+ )
223
+
218
224
  # Parse IP addresses
219
225
  serverappio_address, _, _ = _format_address(args.serverappio_api_address)
220
226
  exec_address, _, _ = _format_address(args.exec_api_address)
@@ -359,18 +365,23 @@ def run_superlink() -> None:
359
365
  else:
360
366
  raise ValueError(f"Unknown fleet_api_type: {args.fleet_api_type}")
361
367
 
362
- if args.isolation == ISOLATION_MODE_SUBPROCESS:
363
- # Scheduler thread
364
- scheduler_th = threading.Thread(
365
- target=_flwr_serverapp_scheduler,
366
- args=(
367
- state_factory,
368
- args.serverappio_api_address,
369
- args.ssl_ca_certfile,
370
- ),
371
- )
372
- scheduler_th.start()
373
- bckg_threads.append(scheduler_th)
368
+ if args.isolation == ISOLATION_MODE_SUBPROCESS:
369
+
370
+ address = simulationio_address if sim_exec else serverappio_address
371
+ cmd = "flwr-simulation" if sim_exec else "flwr-serverapp"
372
+
373
+ # Scheduler thread
374
+ scheduler_th = threading.Thread(
375
+ target=_flwr_scheduler,
376
+ args=(
377
+ state_factory,
378
+ address,
379
+ args.ssl_ca_certfile,
380
+ cmd,
381
+ ),
382
+ )
383
+ scheduler_th.start()
384
+ bckg_threads.append(scheduler_th)
374
385
 
375
386
  # Graceful shutdown
376
387
  register_exit_handlers(
@@ -388,12 +399,13 @@ def run_superlink() -> None:
388
399
  exec_server.wait_for_termination(timeout=1)
389
400
 
390
401
 
391
- def _flwr_serverapp_scheduler(
402
+ def _flwr_scheduler(
392
403
  state_factory: LinkStateFactory,
393
- serverappio_api_address: str,
404
+ io_api_address: str,
394
405
  ssl_ca_certfile: Optional[str],
406
+ cmd: str,
395
407
  ) -> None:
396
- log(DEBUG, "Started flwr-serverapp scheduler thread.")
408
+ log(DEBUG, "Started %s scheduler thread.", cmd)
397
409
 
398
410
  state = state_factory.state()
399
411
 
@@ -406,14 +418,16 @@ def _flwr_serverapp_scheduler(
406
418
 
407
419
  log(
408
420
  INFO,
409
- "Launching `flwr-serverapp` subprocess. Connects to SuperLink on %s",
410
- serverappio_api_address,
421
+ "Launching %s subprocess. Connects to SuperLink on %s",
422
+ cmd,
423
+ io_api_address,
411
424
  )
412
- # Start ServerApp subprocess
425
+ # Start subprocess
413
426
  command = [
414
- "flwr-serverapp",
427
+ cmd,
428
+ "--run-once",
415
429
  "--superlink",
416
- serverappio_api_address,
430
+ io_api_address,
417
431
  ]
418
432
  if ssl_ca_certfile:
419
433
  command.append("--root-certificates")
@@ -694,6 +708,17 @@ def _add_args_common(parser: argparse.ArgumentParser) -> None:
694
708
  "paths are provided. By default, the server runs with HTTPS enabled. "
695
709
  "Use this flag only if you understand the risks.",
696
710
  )
711
+ parser.add_argument(
712
+ "--flwr-dir",
713
+ default=None,
714
+ help="""The path containing installed Flower Apps.
715
+ The default directory is:
716
+
717
+ - `$FLWR_HOME/` if `$FLWR_HOME` is defined
718
+ - `$XDG_DATA_HOME/.flwr/` if `$XDG_DATA_HOME` is defined
719
+ - `$HOME/.flwr/` in all other cases
720
+ """,
721
+ )
697
722
  parser.add_argument(
698
723
  "--ssl-certfile",
699
724
  help="Fleet API server SSL certificate file (as a path str) "
@@ -27,7 +27,7 @@ class Driver(ABC):
27
27
  """Abstract base Driver class for the ServerAppIo API."""
28
28
 
29
29
  @abstractmethod
30
- def init_run(self, run_id: int) -> None:
30
+ def set_run(self, run_id: int) -> None:
31
31
  """Request a run to the SuperLink with a given `run_id`.
32
32
 
33
33
  If a Run with the specified `run_id` exists, a local Run
@@ -112,12 +112,8 @@ class GrpcDriver(Driver):
112
112
  channel.close()
113
113
  log(DEBUG, "[Driver] Disconnected")
114
114
 
115
- def init_run(self, run_id: int) -> None:
116
- """Initialize the run."""
117
- # Check if is initialized
118
- if self._run is not None:
119
- return
120
-
115
+ def set_run(self, run_id: int) -> None:
116
+ """Set the run."""
121
117
  # Get the run info
122
118
  req = GetRunRequest(run_id=run_id)
123
119
  res: GetRunResponse = self._stub.GetRun(req)
@@ -62,10 +62,8 @@ class InMemoryDriver(Driver):
62
62
  ):
63
63
  raise ValueError(f"Invalid message: {message}")
64
64
 
65
- def init_run(self, run_id: int) -> None:
65
+ def set_run(self, run_id: int) -> None:
66
66
  """Initialize the run."""
67
- if self._run is not None:
68
- return
69
67
  run = self.state.get_run(run_id)
70
68
  if run is None:
71
69
  raise RuntimeError(f"Cannot find the run with ID: {run_id}")
@@ -174,7 +174,7 @@ def run_server_app() -> None:
174
174
  root_certificates=root_certificates,
175
175
  )
176
176
  flwr_dir = get_flwr_dir(args.flwr_dir)
177
- driver.init_run(args.run_id)
177
+ driver.set_run(args.run_id)
178
178
  run_ = driver.run
179
179
  if not run_.fab_hash:
180
180
  raise ValueError("FAB hash not provided.")
@@ -204,7 +204,7 @@ def run_server_app() -> None:
204
204
  req = CreateRunRequest(fab_id=fab_id, fab_version=fab_version)
205
205
  res: CreateRunResponse = driver._stub.CreateRun(req) # pylint: disable=W0212
206
206
  # Fetch full `Run` using `run_id`
207
- driver.init_run(res.run_id) # pylint: disable=W0212
207
+ driver.set_run(res.run_id) # pylint: disable=W0212
208
208
  run_id = res.run_id
209
209
 
210
210
  # Obtain server app reference and the run config
@@ -15,9 +15,7 @@
15
15
  """Flower ServerApp process."""
16
16
 
17
17
  import argparse
18
- import sys
19
- from logging import DEBUG, ERROR, INFO, WARN
20
- from os.path import isfile
18
+ from logging import DEBUG, ERROR, INFO
21
19
  from pathlib import Path
22
20
  from queue import Queue
23
21
  from time import sleep
@@ -25,6 +23,7 @@ from typing import Optional
25
23
 
26
24
  from flwr.cli.config_utils import get_fab_metadata
27
25
  from flwr.cli.install import install_from_fab
26
+ from flwr.common.args import add_args_flwr_app_common, try_obtain_certificates
28
27
  from flwr.common.config import (
29
28
  get_flwr_dir,
30
29
  get_fused_config_from_dir,
@@ -69,54 +68,30 @@ def flwr_serverapp() -> None:
69
68
  parser.add_argument(
70
69
  "--superlink",
71
70
  type=str,
72
- help="Address of SuperLink's DriverAPI",
71
+ help="Address of SuperLink's ServerAppIo API",
73
72
  )
74
73
  parser.add_argument(
75
74
  "--run-once",
76
75
  action="store_true",
77
- help="When set, this process will start a single ServerApp "
78
- "for a pending Run. If no pending run the process will exit. ",
79
- )
80
- parser.add_argument(
81
- "--flwr-dir",
82
- default=None,
83
- help="""The path containing installed Flower Apps.
84
- By default, this value is equal to:
85
-
86
- - `$FLWR_HOME/` if `$FLWR_HOME` is defined
87
- - `$XDG_DATA_HOME/.flwr/` if `$XDG_DATA_HOME` is defined
88
- - `$HOME/.flwr/` in all other cases
89
- """,
90
- )
91
- parser.add_argument(
92
- "--insecure",
93
- action="store_true",
94
- help="Run the server without HTTPS, regardless of whether certificate "
95
- "paths are provided. By default, the server runs with HTTPS enabled. "
96
- "Use this flag only if you understand the risks.",
97
- )
98
- parser.add_argument(
99
- "--root-certificates",
100
- metavar="ROOT_CERT",
101
- type=str,
102
- help="Specifies the path to the PEM-encoded root certificate file for "
103
- "establishing secure HTTPS connections.",
76
+ help="When set, this process will start a single ServerApp for a pending Run. "
77
+ "If there is no pending Run, the process will exit.",
104
78
  )
79
+ add_args_flwr_app_common(parser=parser)
105
80
  args = parser.parse_args()
106
81
 
107
82
  log(INFO, "Starting Flower ServerApp")
108
- certificates = _try_obtain_certificates(args)
83
+ certificates = try_obtain_certificates(args)
109
84
 
110
85
  log(
111
86
  DEBUG,
112
- "Staring isolated `ServerApp` connected to SuperLink DriverAPI at %s",
87
+ "Starting isolated `ServerApp` connected to SuperLink's ServerAppIo API at %s",
113
88
  args.superlink,
114
89
  )
115
90
  run_serverapp(
116
91
  superlink=args.superlink,
117
92
  log_queue=log_queue,
118
93
  run_once=args.run_once,
119
- flwr_dir_=args.flwr_dir,
94
+ flwr_dir=args.flwr_dir,
120
95
  certificates=certificates,
121
96
  )
122
97
 
@@ -124,44 +99,11 @@ def flwr_serverapp() -> None:
124
99
  restore_output()
125
100
 
126
101
 
127
- def _try_obtain_certificates(
128
- args: argparse.Namespace,
129
- ) -> Optional[bytes]:
130
-
131
- if args.insecure:
132
- if args.root_certificates is not None:
133
- sys.exit(
134
- "Conflicting options: The '--insecure' flag disables HTTPS, "
135
- "but '--root-certificates' was also specified. Please remove "
136
- "the '--root-certificates' option when running in insecure mode, "
137
- "or omit '--insecure' to use HTTPS."
138
- )
139
- log(
140
- WARN,
141
- "Option `--insecure` was set. Starting insecure HTTP channel to %s.",
142
- args.superlink,
143
- )
144
- root_certificates = None
145
- else:
146
- # Load the certificates if provided, or load the system certificates
147
- if not isfile(args.root_certificates):
148
- sys.exit("Path argument `--root-certificates` does not point to a file.")
149
- root_certificates = Path(args.root_certificates).read_bytes()
150
- log(
151
- DEBUG,
152
- "Starting secure HTTPS channel to %s "
153
- "with the following certificates: %s.",
154
- args.superlink,
155
- args.root_certificates,
156
- )
157
- return root_certificates
158
-
159
-
160
102
  def run_serverapp( # pylint: disable=R0914, disable=W0212
161
103
  superlink: str,
162
104
  log_queue: Queue[Optional[str]],
163
105
  run_once: bool,
164
- flwr_dir_: Optional[str] = None,
106
+ flwr_dir: Optional[str] = None,
165
107
  certificates: Optional[bytes] = None,
166
108
  ) -> None:
167
109
  """Run Flower ServerApp process."""
@@ -171,7 +113,7 @@ def run_serverapp( # pylint: disable=R0914, disable=W0212
171
113
  )
172
114
 
173
115
  # Resolve directory where FABs are installed
174
- flwr_dir = get_flwr_dir(flwr_dir_)
116
+ flwr_dir_ = get_flwr_dir(flwr_dir)
175
117
  log_uploader = None
176
118
 
177
119
  while True:
@@ -189,7 +131,7 @@ def run_serverapp( # pylint: disable=R0914, disable=W0212
189
131
  run = run_from_proto(res.run)
190
132
  fab = fab_from_proto(res.fab)
191
133
 
192
- driver.init_run(run.run_id)
134
+ driver.set_run(run.run_id)
193
135
 
194
136
  # Start log uploader for this run
195
137
  log_uploader = start_log_uploader(
@@ -200,11 +142,13 @@ def run_serverapp( # pylint: disable=R0914, disable=W0212
200
142
  )
201
143
 
202
144
  log(DEBUG, "ServerApp process starts FAB installation.")
203
- install_from_fab(fab.content, flwr_dir=flwr_dir, skip_prompt=True)
145
+ install_from_fab(fab.content, flwr_dir=flwr_dir_, skip_prompt=True)
204
146
 
205
147
  fab_id, fab_version = get_fab_metadata(fab.content)
206
148
 
207
- app_path = str(get_project_dir(fab_id, fab_version, fab.hash_str, flwr_dir))
149
+ app_path = str(
150
+ get_project_dir(fab_id, fab_version, fab.hash_str, flwr_dir_)
151
+ )
208
152
  config = get_project_config(app_path)
209
153
 
210
154
  # Obtain server app reference and the run config
@@ -48,12 +48,12 @@ def aggregate_inplace(results: list[tuple[ClientProxy, FitRes]]) -> NDArrays:
48
48
  num_examples_total = sum(fit_res.num_examples for (_, fit_res) in results)
49
49
 
50
50
  # Compute scaling factors for each result
51
- scaling_factors = [
52
- fit_res.num_examples / num_examples_total for _, fit_res in results
53
- ]
51
+ scaling_factors = np.asarray(
52
+ [fit_res.num_examples / num_examples_total for _, fit_res in results]
53
+ )
54
54
 
55
55
  def _try_inplace(
56
- x: NDArray, y: Union[NDArray, float], np_binary_op: np.ufunc
56
+ x: NDArray, y: Union[NDArray, np.float64], np_binary_op: np.ufunc
57
57
  ) -> NDArray:
58
58
  return ( # type: ignore[no-any-return]
59
59
  np_binary_op(x, y, out=x)