flwr-nightly 1.13.0.dev20241106__py3-none-any.whl → 1.13.0.dev20241107__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.

flwr/cli/run/run.py CHANGED
@@ -29,10 +29,18 @@ from flwr.cli.config_utils import (
29
29
  validate_federation_in_project_config,
30
30
  validate_project_config,
31
31
  )
32
- from flwr.common.config import flatten_dict, parse_config_args
32
+ from flwr.common.config import (
33
+ flatten_dict,
34
+ parse_config_args,
35
+ user_config_to_configsrecord,
36
+ )
33
37
  from flwr.common.grpc import GRPC_MAX_MESSAGE_LENGTH, create_channel
34
38
  from flwr.common.logger import log
35
- from flwr.common.serde import fab_to_proto, user_config_to_proto
39
+ from flwr.common.serde import (
40
+ configs_record_to_proto,
41
+ fab_to_proto,
42
+ user_config_to_proto,
43
+ )
36
44
  from flwr.common.typing import Fab
37
45
  from flwr.proto.exec_pb2 import StartRunRequest # pylint: disable=E0611
38
46
  from flwr.proto.exec_pb2_grpc import ExecStub
@@ -94,6 +102,7 @@ def run(
94
102
  _run_without_exec_api(app, federation_config, config_overrides, federation)
95
103
 
96
104
 
105
+ # pylint: disable-next=too-many-locals
97
106
  def _run_with_exec_api(
98
107
  app: Path,
99
108
  federation_config: dict[str, Any],
@@ -118,12 +127,14 @@ def _run_with_exec_api(
118
127
  content = Path(fab_path).read_bytes()
119
128
  fab = Fab(fab_hash, content)
120
129
 
130
+ # Construct a `ConfigsRecord` out of a flattened `UserConfig`
131
+ fed_conf = flatten_dict(federation_config.get("options", {}))
132
+ c_record = user_config_to_configsrecord(fed_conf)
133
+
121
134
  req = StartRunRequest(
122
135
  fab=fab_to_proto(fab),
123
136
  override_config=user_config_to_proto(parse_config_args(config_overrides)),
124
- federation_config=user_config_to_proto(
125
- flatten_dict(federation_config.get("options"))
126
- ),
137
+ federation_options=configs_record_to_proto(c_record),
127
138
  )
128
139
  res = stub.StartRun(req)
129
140
 
flwr/client/app.py CHANGED
@@ -32,6 +32,7 @@ from flwr.cli.config_utils import get_fab_metadata
32
32
  from flwr.cli.install import install_from_fab
33
33
  from flwr.client.client import Client
34
34
  from flwr.client.client_app import ClientApp, LoadClientAppError
35
+ from flwr.client.nodestate.nodestate_factory import NodeStateFactory
35
36
  from flwr.client.typing import ClientFnExt
36
37
  from flwr.common import GRPC_MAX_MESSAGE_LENGTH, Context, EventType, Message, event
37
38
  from flwr.common.address import parse_address
@@ -365,6 +366,8 @@ def start_client_internal(
365
366
 
366
367
  # DeprecatedRunInfoStore gets initialized when the first connection is established
367
368
  run_info_store: Optional[DeprecatedRunInfoStore] = None
369
+ state_factory = NodeStateFactory()
370
+ state = state_factory.state()
368
371
 
369
372
  runs: dict[int, Run] = {}
370
373
 
@@ -396,13 +399,14 @@ def start_client_internal(
396
399
  )
397
400
  else:
398
401
  # Call create_node fn to register node
399
- node_id: Optional[int] = ( # pylint: disable=assignment-from-none
400
- create_node()
401
- ) # pylint: disable=not-callable
402
- if node_id is None:
403
- raise ValueError("Node registration failed")
402
+ # and store node_id in state
403
+ if (node_id := create_node()) is None:
404
+ raise ValueError(
405
+ "Failed to register SuperNode with the SuperLink"
406
+ )
407
+ state.set_node_id(node_id)
404
408
  run_info_store = DeprecatedRunInfoStore(
405
- node_id=node_id,
409
+ node_id=state.get_node_id(),
406
410
  node_config=node_config,
407
411
  )
408
412
 
@@ -0,0 +1,25 @@
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Flower NodeState."""
16
+
17
+ from .in_memory_nodestate import InMemoryNodeState as InMemoryNodeState
18
+ from .nodestate import NodeState as NodeState
19
+ from .nodestate_factory import NodeStateFactory as NodeStateFactory
20
+
21
+ __all__ = [
22
+ "InMemoryNodeState",
23
+ "NodeState",
24
+ "NodeStateFactory",
25
+ ]
@@ -0,0 +1,38 @@
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """In-memory NodeState implementation."""
16
+
17
+
18
+ from typing import Optional
19
+
20
+ from flwr.client.nodestate.nodestate import NodeState
21
+
22
+
23
+ class InMemoryNodeState(NodeState):
24
+ """In-memory NodeState implementation."""
25
+
26
+ def __init__(self) -> None:
27
+ # Store node_id
28
+ self.node_id: Optional[int] = None
29
+
30
+ def set_node_id(self, node_id: Optional[int]) -> None:
31
+ """Set the node ID."""
32
+ self.node_id = node_id
33
+
34
+ def get_node_id(self) -> int:
35
+ """Get the node ID."""
36
+ if self.node_id is None:
37
+ raise ValueError("Node ID not set")
38
+ return self.node_id
@@ -0,0 +1,30 @@
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Abstract base class NodeState."""
16
+
17
+ import abc
18
+ from typing import Optional
19
+
20
+
21
+ class NodeState(abc.ABC):
22
+ """Abstract NodeState."""
23
+
24
+ @abc.abstractmethod
25
+ def set_node_id(self, node_id: Optional[int]) -> None:
26
+ """Set the node ID."""
27
+
28
+ @abc.abstractmethod
29
+ def get_node_id(self) -> int:
30
+ """Get the node ID."""
@@ -0,0 +1,37 @@
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Factory class that creates NodeState instances."""
16
+
17
+ import threading
18
+ from typing import Optional
19
+
20
+ from .in_memory_nodestate import InMemoryNodeState
21
+ from .nodestate import NodeState
22
+
23
+
24
+ class NodeStateFactory:
25
+ """Factory class that creates NodeState instances."""
26
+
27
+ def __init__(self) -> None:
28
+ self.state_instance: Optional[NodeState] = None
29
+ self.lock = threading.RLock()
30
+
31
+ def state(self) -> NodeState:
32
+ """Return a State instance and create it, if necessary."""
33
+ # Lock access to NodeStateFactory to prevent returning different instances
34
+ with self.lock:
35
+ if self.state_instance is None:
36
+ self.state_instance = InMemoryNodeState()
37
+ return self.state_instance
flwr/common/config.py CHANGED
@@ -22,6 +22,7 @@ from typing import Any, Optional, Union, cast, get_args
22
22
  import tomli
23
23
 
24
24
  from flwr.cli.config_utils import get_fab_config, validate_fields
25
+ from flwr.common import ConfigsRecord
25
26
  from flwr.common.constant import (
26
27
  APP_DIR,
27
28
  FAB_CONFIG_FILE,
@@ -229,3 +230,12 @@ def get_metadata_from_config(config: dict[str, Any]) -> tuple[str, str]:
229
230
  config["project"]["version"],
230
231
  f"{config['tool']['flwr']['app']['publisher']}/{config['project']['name']}",
231
232
  )
233
+
234
+
235
+ def user_config_to_configsrecord(config: UserConfig) -> ConfigsRecord:
236
+ """Construct a `ConfigsRecord` out of a `UserConfig`."""
237
+ c_record = ConfigsRecord()
238
+ for k, v in config.items():
239
+ c_record[k] = v
240
+
241
+ return c_record
flwr/common/constant.py CHANGED
@@ -134,7 +134,6 @@ class ErrorCode:
134
134
  UNKNOWN = 0
135
135
  LOAD_CLIENT_APP_EXCEPTION = 1
136
136
  CLIENT_APP_RAISED_EXCEPTION = 2
137
- NODE_UNAVAILABLE = 3
138
137
 
139
138
  def __new__(cls) -> ErrorCode:
140
139
  """Prevent instantiation."""
flwr/common/object_ref.py CHANGED
@@ -55,8 +55,8 @@ def validate(
55
55
  specified attribute within it.
56
56
  project_dir : Optional[Union[str, Path]] (default: None)
57
57
  The directory containing the module. If None, the current working directory
58
- is used. If `check_module` is True, the `project_dir` will be inserted into
59
- the system path, and the previously inserted `project_dir` will be removed.
58
+ is used. If `check_module` is True, the `project_dir` will be temporarily
59
+ inserted into the system path and then removed after the validation is complete.
60
60
 
61
61
  Returns
62
62
  -------
@@ -66,8 +66,8 @@ def validate(
66
66
 
67
67
  Note
68
68
  ----
69
- This function will modify `sys.path` by inserting the provided `project_dir`
70
- and removing the previously inserted `project_dir`.
69
+ This function will temporarily modify `sys.path` by inserting the provided
70
+ `project_dir`, which will be removed after the validation is complete.
71
71
  """
72
72
  module_str, _, attributes_str = module_attribute_str.partition(":")
73
73
  if not module_str:
@@ -82,11 +82,19 @@ def validate(
82
82
  )
83
83
 
84
84
  if check_module:
85
+ if project_dir is None:
86
+ project_dir = Path.cwd()
87
+ project_dir = Path(project_dir).absolute()
85
88
  # Set the system path
86
- _set_sys_path(project_dir)
89
+ sys.path.insert(0, str(project_dir))
87
90
 
88
91
  # Load module
89
92
  module = find_spec(module_str)
93
+
94
+ # Unset the system path
95
+ sys.path.remove(str(project_dir))
96
+
97
+ # Check if the module and the attribute exist
90
98
  if module and module.origin:
91
99
  if not _find_attribute_in_module(module.origin, attributes_str):
92
100
  return (
@@ -133,8 +141,10 @@ def load_app( # pylint: disable= too-many-branches
133
141
 
134
142
  Note
135
143
  ----
136
- This function will modify `sys.path` by inserting the provided `project_dir`
137
- and removing the previously inserted `project_dir`.
144
+ - This function will unload all modules in the previously provided `project_dir`,
145
+ if it is invoked again.
146
+ - This function will modify `sys.path` by inserting the provided `project_dir`
147
+ and removing the previously inserted `project_dir`.
138
148
  """
139
149
  valid, error_msg = validate(module_attribute_str, check_module=False)
140
150
  if not valid and error_msg:
@@ -143,33 +153,21 @@ def load_app( # pylint: disable= too-many-branches
143
153
  module_str, _, attributes_str = module_attribute_str.partition(":")
144
154
 
145
155
  try:
156
+ if _current_sys_path:
157
+ # Hack: `tabnet` does not work with reloading
158
+ if "tabnet" in sys.modules:
159
+ log(
160
+ WARN,
161
+ "Cannot reload module `%s` from disk due to compatibility issues "
162
+ "with the `tabnet` library. The module will be loaded from the "
163
+ "cache instead. If you experience issues, consider restarting "
164
+ "the application.",
165
+ module_str,
166
+ )
167
+ else:
168
+ _unload_modules(Path(_current_sys_path))
146
169
  _set_sys_path(project_dir)
147
-
148
- if module_str not in sys.modules:
149
- module = importlib.import_module(module_str)
150
- # Hack: `tabnet` does not work with `importlib.reload`
151
- elif "tabnet" in sys.modules:
152
- log(
153
- WARN,
154
- "Cannot reload module `%s` from disk due to compatibility issues "
155
- "with the `tabnet` library. The module will be loaded from the "
156
- "cache instead. If you experience issues, consider restarting "
157
- "the application.",
158
- module_str,
159
- )
160
- module = sys.modules[module_str]
161
- else:
162
- module = sys.modules[module_str]
163
-
164
- if project_dir is None:
165
- project_dir = Path.cwd()
166
-
167
- # Reload cached modules in the project directory
168
- for m in list(sys.modules.values()):
169
- path: Optional[str] = getattr(m, "__file__", None)
170
- if path is not None and path.startswith(str(project_dir)):
171
- importlib.reload(m)
172
-
170
+ module = importlib.import_module(module_str)
173
171
  except ModuleNotFoundError as err:
174
172
  raise error_type(
175
173
  f"Unable to load module {module_str}{OBJECT_REF_HELP_STR}",
@@ -189,6 +187,15 @@ def load_app( # pylint: disable= too-many-branches
189
187
  return attribute
190
188
 
191
189
 
190
+ def _unload_modules(project_dir: Path) -> None:
191
+ """Unload modules from the project directory."""
192
+ dir_str = str(project_dir.absolute())
193
+ for name, m in list(sys.modules.items()):
194
+ path: Optional[str] = getattr(m, "__file__", None)
195
+ if path is not None and path.startswith(dir_str):
196
+ del sys.modules[name]
197
+
198
+
192
199
  def _set_sys_path(directory: Optional[Union[str, Path]]) -> None:
193
200
  """Set the system path."""
194
201
  if directory is None:
flwr/proto/exec_pb2.py CHANGED
@@ -14,9 +14,10 @@ _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 transport_pb2 as flwr_dot_proto_dot_transport__pb2
17
+ from flwr.proto import recordset_pb2 as flwr_dot_proto_dot_recordset__pb2
17
18
 
18
19
 
19
- 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\"\xdf\x02\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\x12L\n\x11\x66\x65\x64\x65ration_config\x18\x03 \x03(\x0b\x32\x31.flwr.proto.StartRunRequest.FederationConfigEntry\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\x1aK\n\x15\x46\x65\x64\x65rationConfigEntry\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')
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')
20
21
 
21
22
  _globals = globals()
22
23
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -25,20 +26,16 @@ if _descriptor._USE_C_DESCRIPTORS == False:
25
26
  DESCRIPTOR._options = None
26
27
  _globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._options = None
27
28
  _globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_options = b'8\001'
28
- _globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._options = None
29
- _globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._serialized_options = b'8\001'
30
- _globals['_STARTRUNREQUEST']._serialized_start=88
31
- _globals['_STARTRUNREQUEST']._serialized_end=439
32
- _globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_start=289
33
- _globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_end=362
34
- _globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._serialized_start=364
35
- _globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._serialized_end=439
36
- _globals['_STARTRUNRESPONSE']._serialized_start=441
37
- _globals['_STARTRUNRESPONSE']._serialized_end=475
38
- _globals['_STREAMLOGSREQUEST']._serialized_start=477
39
- _globals['_STREAMLOGSREQUEST']._serialized_end=537
40
- _globals['_STREAMLOGSRESPONSE']._serialized_start=539
41
- _globals['_STREAMLOGSRESPONSE']._serialized_end=605
42
- _globals['_EXEC']._serialized_start=608
43
- _globals['_EXEC']._serialized_end=768
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
44
41
  # @@protoc_insertion_point(module_scope)
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):
@@ -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
@@ -189,7 +189,7 @@ def run_serverapp( # pylint: disable=R0914, disable=W0212
189
189
  run = run_from_proto(res.run)
190
190
  fab = fab_from_proto(res.fab)
191
191
 
192
- driver.init_run(run.run_id)
192
+ driver.set_run(run.run_id)
193
193
 
194
194
  # Start log uploader for this run
195
195
  log_uploader = start_log_uploader(
@@ -40,7 +40,6 @@ from .utils import (
40
40
  generate_rand_int_from_bytes,
41
41
  has_valid_sub_status,
42
42
  is_valid_transition,
43
- make_node_unavailable_taskres,
44
43
  )
45
44
 
46
45
 
@@ -257,21 +256,6 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
257
256
  task_res_list.append(task_res)
258
257
  replied_task_ids.add(reply_to)
259
258
 
260
- # Check if the node is offline
261
- for task_id in task_ids - replied_task_ids:
262
- task_ins = self.task_ins_store.get(task_id)
263
- if task_ins is None:
264
- continue
265
- node_id = task_ins.task.consumer.node_id
266
- online_until, _ = self.node_ids[node_id]
267
- # Generate a TaskRes containing an error reply if the node is offline.
268
- if online_until < time.time():
269
- err_taskres = make_node_unavailable_taskres(
270
- ref_taskins=task_ins,
271
- )
272
- self.task_res_store[UUID(err_taskres.task_id)] = err_taskres
273
- task_res_list.append(err_taskres)
274
-
275
259
  # Mark all of them as delivered
276
260
  delivered_at = now().isoformat()
277
261
  for task_res in task_res_list:
@@ -57,7 +57,6 @@ from .utils import (
57
57
  generate_rand_int_from_bytes,
58
58
  has_valid_sub_status,
59
59
  is_valid_transition,
60
- make_node_unavailable_taskres,
61
60
  )
62
61
 
63
62
  SQL_CREATE_TABLE_NODE = """
@@ -640,20 +639,6 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
640
639
  data = {f"id_{i}": str(node_id) for i, node_id in enumerate(offline_node_ids)}
641
640
  task_ins_rows = self.query(query, data)
642
641
 
643
- # Make TaskRes containing node unavailabe error
644
- for row in task_ins_rows:
645
- for row in rows:
646
- # Convert values from sint64 to uint64
647
- convert_sint64_values_in_dict_to_uint64(
648
- row, ["run_id", "producer_node_id", "consumer_node_id"]
649
- )
650
-
651
- task_ins = dict_to_task_ins(row)
652
- err_taskres = make_node_unavailable_taskres(
653
- ref_taskins=task_ins,
654
- )
655
- result.append(err_taskres)
656
-
657
642
  return result
658
643
 
659
644
  def num_task_ins(self) -> int:
@@ -15,21 +15,15 @@
15
15
  """Utility functions for State."""
16
16
 
17
17
 
18
- import time
19
- from logging import ERROR
20
18
  from os import urandom
21
- from uuid import uuid4
22
19
 
23
- from flwr.common import ConfigsRecord, Context, log, serde
24
- from flwr.common.constant import ErrorCode, Status, SubStatus
20
+ from flwr.common import ConfigsRecord, Context, serde
21
+ from flwr.common.constant import Status, SubStatus
25
22
  from flwr.common.typing import RunStatus
26
- from flwr.proto.error_pb2 import Error # pylint: disable=E0611
27
23
  from flwr.proto.message_pb2 import Context as ProtoContext # pylint: disable=E0611
28
- from flwr.proto.node_pb2 import Node # pylint: disable=E0611
29
24
 
30
25
  # pylint: disable=E0611
31
26
  from flwr.proto.recordset_pb2 import ConfigsRecord as ProtoConfigsRecord
32
- from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611
33
27
 
34
28
  NODE_UNAVAILABLE_ERROR_REASON = (
35
29
  "Error: Node Unavailable - The destination node is currently unavailable. "
@@ -161,31 +155,6 @@ def configsrecord_from_bytes(configsrecord_bytes: bytes) -> ConfigsRecord:
161
155
  )
162
156
 
163
157
 
164
- def make_node_unavailable_taskres(ref_taskins: TaskIns) -> TaskRes:
165
- """Generate a TaskRes with a node unavailable error from a TaskIns."""
166
- current_time = time.time()
167
- ttl = ref_taskins.task.ttl - (current_time - ref_taskins.task.created_at)
168
- if ttl < 0:
169
- log(ERROR, "Creating TaskRes for TaskIns that exceeds its TTL.")
170
- ttl = 0
171
- return TaskRes(
172
- task_id=str(uuid4()),
173
- group_id=ref_taskins.group_id,
174
- run_id=ref_taskins.run_id,
175
- task=Task(
176
- producer=Node(node_id=ref_taskins.task.consumer.node_id, anonymous=False),
177
- consumer=Node(node_id=ref_taskins.task.producer.node_id, anonymous=False),
178
- created_at=current_time,
179
- ttl=ttl,
180
- ancestry=[ref_taskins.task_id],
181
- task_type=ref_taskins.task.task_type,
182
- error=Error(
183
- code=ErrorCode.NODE_UNAVAILABLE, reason=NODE_UNAVAILABLE_ERROR_REASON
184
- ),
185
- ),
186
- )
187
-
188
-
189
158
  def is_valid_transition(current_status: RunStatus, new_status: RunStatus) -> bool:
190
159
  """Check if a transition between two run statuses is valid.
191
160
 
@@ -347,7 +347,7 @@ def _main_loop(
347
347
 
348
348
  # Initialize Driver
349
349
  driver = InMemoryDriver(state_factory=state_factory)
350
- driver.init_run(run_id=run.run_id)
350
+ driver.set_run(run_id=run.run_id)
351
351
 
352
352
  # Get and run ServerApp thread
353
353
  serverapp_th = run_serverapp_th(
@@ -153,7 +153,7 @@ class DeploymentEngine(Executor):
153
153
  self,
154
154
  fab_file: bytes,
155
155
  override_config: UserConfig,
156
- federation_config: UserConfig,
156
+ federation_options: ConfigsRecord,
157
157
  ) -> Optional[int]:
158
158
  """Start run using the Flower Deployment Engine."""
159
159
  run_id = None
@@ -24,7 +24,7 @@ import grpc
24
24
 
25
25
  from flwr.common.constant import LOG_STREAM_INTERVAL, Status
26
26
  from flwr.common.logger import log
27
- from flwr.common.serde import user_config_from_proto
27
+ from flwr.common.serde import configs_record_from_proto, user_config_from_proto
28
28
  from flwr.proto import exec_pb2_grpc # pylint: disable=E0611
29
29
  from flwr.proto.exec_pb2 import ( # pylint: disable=E0611
30
30
  StartRunRequest,
@@ -61,7 +61,7 @@ class ExecServicer(exec_pb2_grpc.ExecServicer):
61
61
  run_id = self.executor.start_run(
62
62
  request.fab.content,
63
63
  user_config_from_proto(request.override_config),
64
- user_config_from_proto(request.federation_config),
64
+ configs_record_from_proto(request.federation_options),
65
65
  )
66
66
 
67
67
  if run_id is None:
@@ -19,6 +19,7 @@ from dataclasses import dataclass, field
19
19
  from subprocess import Popen
20
20
  from typing import Optional
21
21
 
22
+ from flwr.common import ConfigsRecord
22
23
  from flwr.common.typing import UserConfig
23
24
  from flwr.server.superlink.ffs.ffs_factory import FfsFactory
24
25
  from flwr.server.superlink.linkstate import LinkStateFactory
@@ -71,7 +72,7 @@ class Executor(ABC):
71
72
  self,
72
73
  fab_file: bytes,
73
74
  override_config: UserConfig,
74
- federation_config: UserConfig,
75
+ federation_options: ConfigsRecord,
75
76
  ) -> Optional[int]:
76
77
  """Start a run using the given Flower FAB ID and version.
77
78
 
@@ -84,8 +85,8 @@ class Executor(ABC):
84
85
  The Flower App Bundle file bytes.
85
86
  override_config: UserConfig
86
87
  The config overrides dict sent by the user (using `flwr run`).
87
- federation_config: UserConfig
88
- The federation options dict sent by the user (using `flwr run`).
88
+ federation_options: ConfigsRecord
89
+ The federation options sent by the user (using `flwr run`).
89
90
 
90
91
  Returns
91
92
  -------
@@ -25,6 +25,7 @@ from typing_extensions import override
25
25
 
26
26
  from flwr.cli.config_utils import load_and_validate
27
27
  from flwr.cli.install import install_from_fab
28
+ from flwr.common import ConfigsRecord
28
29
  from flwr.common.config import unflatten_dict
29
30
  from flwr.common.constant import RUN_ID_NUM_BYTES
30
31
  from flwr.common.logger import log
@@ -124,7 +125,7 @@ class SimulationEngine(Executor):
124
125
  self,
125
126
  fab_file: bytes,
126
127
  override_config: UserConfig,
127
- federation_config: UserConfig,
128
+ federation_options: ConfigsRecord,
128
129
  ) -> Optional[int]:
129
130
  """Start run using the Flower Simulation Engine."""
130
131
  if self.num_supernodes is None:
@@ -163,14 +164,13 @@ class SimulationEngine(Executor):
163
164
  "Config extracted from FAB's pyproject.toml is not valid"
164
165
  )
165
166
 
166
- # Flatten federated config
167
- federation_config_flat = unflatten_dict(federation_config)
167
+ # Unflatten underlaying dict
168
+ fed_opt = unflatten_dict({**federation_options})
168
169
 
169
- num_supernodes = federation_config_flat.get(
170
- "num-supernodes", self.num_supernodes
171
- )
172
- backend_cfg = federation_config_flat.get("backend", {})
173
- verbose: Optional[bool] = federation_config_flat.get("verbose")
170
+ # Read data
171
+ num_supernodes = fed_opt.get("num-supernodes", self.num_supernodes)
172
+ backend_cfg = fed_opt.get("backend", {})
173
+ verbose: Optional[bool] = fed_opt.get("verbose")
174
174
 
175
175
  # In Simulation there is no SuperLink, still we create a run_id
176
176
  run_id = generate_rand_int_from_bytes(RUN_ID_NUM_BYTES)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flwr-nightly
3
- Version: 1.13.0.dev20241106
3
+ Version: 1.13.0.dev20241107
4
4
  Summary: Flower: A Friendly Federated Learning Framework
5
5
  Home-page: https://flower.ai
6
6
  License: Apache-2.0
@@ -61,10 +61,10 @@ flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl,sha256=LUsQsEVhCgGzKEBB5Ie
61
61
  flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl,sha256=BiZPOKEoGiZOuxSHQY_nQHj3KH7wH7QAiVmpxGutOgk,686
62
62
  flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl,sha256=6R_bIGyPvXlCtLABF8fHLmGBNlIptG8QrYM69_Fy_nk,710
63
63
  flwr/cli/run/__init__.py,sha256=oCd6HmQDx-sqver1gecgx-uMA38BLTSiiKpl7RGNceg,789
64
- flwr/cli/run/run.py,sha256=FCdETDR3d_Aqw3Bn-oGogiAjOqH87AWLtcwifgJLAcQ,6034
64
+ flwr/cli/run/run.py,sha256=TQm7M0a-oSeNXPCsn75qYrkGB0IPbk0HulcYk1gwmR0,6293
65
65
  flwr/cli/utils.py,sha256=emMUdthvoHBTB0iGQp-oFBmA5wV46lw3y3FmfXQPCsc,4500
66
66
  flwr/client/__init__.py,sha256=DGDoO0AEAfz-0CUFmLdyUUweAS64-07AOnmDfWUefK4,1192
67
- flwr/client/app.py,sha256=fEUTXz_uNwZe-otCbUf5F3sJozGfvkrMNS3u7DE6sOo,32808
67
+ flwr/client/app.py,sha256=zpYl6I6_1-5BEv93IqGIBX_FDpEvOSYFhDidWjq0K8U,32975
68
68
  flwr/client/client.py,sha256=gy6WVlMUFAp8oevN4xpQPX30vPOIYGVqdbuFlTWkyG4,9080
69
69
  flwr/client/client_app.py,sha256=cTig-N00YzTucbo9zNi6I21J8PlbflU_8J_f5CI-Wpw,10390
70
70
  flwr/client/clientapp/__init__.py,sha256=kZqChGnTChQ1WGSUkIlW2S5bc0d0mzDubCAmZUGRpEY,800
@@ -92,6 +92,10 @@ flwr/client/mod/secure_aggregation/__init__.py,sha256=A7DzZ3uvXTUkuHBzrxJMWQQD4R
92
92
  flwr/client/mod/secure_aggregation/secagg_mod.py,sha256=wI9tuIEvMUETz-wVIEbPYvh-1nK9CEylBLGoVpNhL94,1095
93
93
  flwr/client/mod/secure_aggregation/secaggplus_mod.py,sha256=7cNXsY07ZA0M5_9VSc52F8JUoAoGaraNDA2rgaLvvFo,19680
94
94
  flwr/client/mod/utils.py,sha256=dFcTHOjUuuiw34fcQlvyzytYD0sCv1w9x8fQX1Yo8Oc,1201
95
+ flwr/client/nodestate/__init__.py,sha256=UBK-iI4BTiiFi3v6SBo2cizaRRhZzTzkXOhbAZB7cs8,975
96
+ flwr/client/nodestate/in_memory_nodestate.py,sha256=MKI3jVPARPWJmNGw61k1-9LIXROkTx2PrhWjDM8cpHk,1291
97
+ flwr/client/nodestate/nodestate.py,sha256=2sSziyHK65ygayLcEoR78erqyrRe10tZ2tB-QISdRB4,1023
98
+ flwr/client/nodestate/nodestate_factory.py,sha256=LipmYzjYlN2U-CYN20d8Kk0PXyCAJq3L3VQFc6QscJc,1429
95
99
  flwr/client/numpy_client.py,sha256=tqGyhIkeeZQGr65BR03B7TWgx4rW3FA7G2874D8z_VU,11167
96
100
  flwr/client/rest_client/__init__.py,sha256=5KGlp7pjc1dhNRkKlaNtUfQmg8wrRFh9lS3P3uRS-7Q,735
97
101
  flwr/client/rest_client/connection.py,sha256=k-RqgUFqidACAGlMFPIUM8aawXI5h2LvKUri2OAK7Bg,12817
@@ -101,8 +105,8 @@ flwr/client/supernode/app.py,sha256=JN24tRBHLbFJ0KeCTA8eS24KUJHCl9J2xGwWjyPQ7Vg,
101
105
  flwr/client/typing.py,sha256=dxoTBnTMfqXr5J7G3y-uNjqxYCddvxhu89spfj4Lm2U,1048
102
106
  flwr/common/__init__.py,sha256=TVaoFEJE158aui1TPZQiJCDZX4RNHRyI8I55VC80HhI,3901
103
107
  flwr/common/address.py,sha256=7kM2Rqjw86-c8aKwAvrXerWqznnVv4TFJ62aSAeTn10,3017
104
- flwr/common/config.py,sha256=nYA1vjiiqSWx5JjSdlQd1i_0N_Dh9kEGUse1Qze3JMs,7803
105
- flwr/common/constant.py,sha256=-YsUgUiaScB3vvoppQ3h8_Ww-bkaNgLK72wwi2qZj6M,4756
108
+ flwr/common/config.py,sha256=qC1QvGAGr4faBtg3Y5dWhfyK5FggyWUMjPqg-Rx_FW4,8083
109
+ flwr/common/constant.py,sha256=D7MNLl1u-P7tJAMdT67xIujSeCibc2QzqtFoqCagoco,4731
106
110
  flwr/common/context.py,sha256=uJ-mnoC_8y_udEb3kAX-r8CPphNTWM72z1AlsvQEu54,2403
107
111
  flwr/common/date.py,sha256=uTvLmCkd3uVQuD4MviPHnIXMGyheL16mEI_UlOsv_R8,894
108
112
  flwr/common/differential_privacy.py,sha256=XwcJ3rWr8S8BZUocc76vLSJAXIf6OHnWkBV6-xlIRuw,6106
@@ -112,7 +116,7 @@ flwr/common/exit_handlers.py,sha256=MracJaBeoCOC7TaXK9zCJQxhrMSx9ZtczK237qvhBpU,
112
116
  flwr/common/grpc.py,sha256=6Yi28JjAll19nxYJlOT9B03RN8dvJZP9zUoR3RSmxoY,2487
113
117
  flwr/common/logger.py,sha256=AJNu-cymiQUp4Dw1zkw5xww_HVkUAhHvtYxwzUtuohM,11065
114
118
  flwr/common/message.py,sha256=4O1m0OWXBAYZz05gKgEtnoJ94J1gjo7hCNHyUXThxRo,13831
115
- flwr/common/object_ref.py,sha256=5lgWqYaJR28UdFc-iirWw9YqFXMfgkOOAdfJc1AVibE,8711
119
+ flwr/common/object_ref.py,sha256=DiTvqzx_WNmNmiPXFexvADTeODhRD0Vg2dpqsH4aS44,9064
116
120
  flwr/common/parameter.py,sha256=-bFAUayToYDF50FZGrBC1hQYJCQDtB2bbr3ZuVLMtdE,2095
117
121
  flwr/common/pyproject.py,sha256=EI_ovbCHGmhYrdPx0RSDi5EkFZFof-8m1PA54c0ZTjc,1385
118
122
  flwr/common/record/__init__.py,sha256=ejDBQOIA0OkwZAC5cK_tTPHA4oAM0Ju7Oi13-NneMlE,1054
@@ -153,8 +157,8 @@ flwr/proto/error_pb2.py,sha256=LarjKL90LbwkXKlhzNrDssgl4DXcvIPve8NVCXHpsKA,1084
153
157
  flwr/proto/error_pb2.pyi,sha256=ZNH4HhJTU_KfMXlyCeg8FwU-fcUYxTqEmoJPtWtHikc,734
154
158
  flwr/proto/error_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
155
159
  flwr/proto/error_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
156
- flwr/proto/exec_pb2.py,sha256=jrPfFdZrT7L6kI-MGu6Ej2rYpd8sgen27bm6njrTrrk,3335
157
- flwr/proto/exec_pb2.pyi,sha256=rvf6cp7YXGQiltzjhd7ZeZmyAeHexDKTp_5kyavZYsA,4612
160
+ flwr/proto/exec_pb2.py,sha256=e6a-KKc5o7bI5BpdfxmZR-nIj2_RMcIBUVOUnaUU_vA,2976
161
+ flwr/proto/exec_pb2.pyi,sha256=bz1Ld0GmofBRrkr04ustaRToCAWx1AWShxjhJYiwAo0,3906
158
162
  flwr/proto/exec_pb2_grpc.py,sha256=faAN19XEMP8GTKrcIU6jvlWkN44n2KiUsZh_OG0sYcg,4072
159
163
  flwr/proto/exec_pb2_grpc.pyi,sha256=VrFhT1Um3Nb8UC2YqnR9GIiM-Yyx0FqaxVOWljh-G_w,1208
160
164
  flwr/proto/fab_pb2.py,sha256=3QSDq9pjbZoqVxsmCRDwHO5PrSjzn2vixjYxE-qPmb0,1589
@@ -217,16 +221,16 @@ flwr/server/compat/driver_client_proxy.py,sha256=Af0bRUEVZNcCYRxt3DjpLPdvVYpTgz6
217
221
  flwr/server/compat/legacy_context.py,sha256=wBzBcfV6YO6IQGriM_FdJ5XZfiBBEEJdS_OdAiF47dY,1804
218
222
  flwr/server/criterion.py,sha256=ypbAexbztzGUxNen9RCHF91QeqiEQix4t4Ih3E-42MM,1061
219
223
  flwr/server/driver/__init__.py,sha256=bikRv6CjTwSvYh7tf10gziU5o2YotOWhhftz2tr3KDc,886
220
- flwr/server/driver/driver.py,sha256=gHHO8oFkFWYf1J9wn4aKCcnzx7hXsmY_JO5jr004s68,5702
221
- flwr/server/driver/grpc_driver.py,sha256=ziRzquh1fuC-joaalHKI_zcqm9k1kDpZYDIzGa33TsI,9629
222
- flwr/server/driver/inmemory_driver.py,sha256=DcWFhV57p2OGgVYIdNlB65_o2lviClk9yVp_4XtdYPg,6458
224
+ flwr/server/driver/driver.py,sha256=u_fMfqLYTroTafGCNwKPHI4lttRL-Z5CqeT3_FHSq-Q,5701
225
+ flwr/server/driver/grpc_driver.py,sha256=4_bJGbeiLV2FTrJseClnsFf2TgitwjwYNO_5sm2FltY,9533
226
+ flwr/server/driver/inmemory_driver.py,sha256=gfB4jmkk1indhRa9XCdKCXghVcWBF1qBD-tAxMUyQm0,6404
223
227
  flwr/server/history.py,sha256=qSb5_pPTrwofpSYGsZWzMPkl_4uJ4mJFWesxXDrEvDU,5026
224
- flwr/server/run_serverapp.py,sha256=lYaslawycvJ0A8GD-h9Q2etp8ZgYzmEhcP_Bo91qjtQ,10561
228
+ flwr/server/run_serverapp.py,sha256=zvH7XEJt0WpTeDTTf-67VvugCRuaItMm7klSOcbhFIU,10559
225
229
  flwr/server/server.py,sha256=1ZsFEptmAV-L2vP2etNC9Ed5CLSxpuKzUFkAPQ4l5Xc,17893
226
230
  flwr/server/server_app.py,sha256=RsgS6PRS5Z74cMUAHzsm8r3LWddwn00MjRs6rlacHt8,6297
227
231
  flwr/server/server_config.py,sha256=CZaHVAsMvGLjpWVcLPkiYxgJN4xfIyAiUrCI3fETKY4,1349
228
232
  flwr/server/serverapp/__init__.py,sha256=L0K-94UDdTyEZ8LDtYybGIIIv3HW6AhSVjXMUfYJQnQ,800
229
- flwr/server/serverapp/app.py,sha256=-OUdiyNjnPwibznlc-1hQ54oUT2EowdPVheXUKCW6LM,8988
233
+ flwr/server/serverapp/app.py,sha256=yRHrTLpwRBOtcQd_VttHy8RR12LhlqFjV70H4FxQRMY,8987
230
234
  flwr/server/serverapp_components.py,sha256=-IV_CitOfrJclJj2jNdbN1Q65PyFmtKtrTIg1hc6WQw,2118
231
235
  flwr/server/strategy/__init__.py,sha256=tQer2SwjDnvgFFuJMZM-S01Z615N5XK6MaCvpm4BMU0,2836
232
236
  flwr/server/strategy/aggregate.py,sha256=iFZ8lp7PV_a2m9kywV-FK0iM33ofxavOs5TIaEQY8nU,13961
@@ -281,11 +285,11 @@ flwr/server/superlink/fleet/vce/backend/backend.py,sha256=LBAQxnbfPAphVOVIvYMj0Q
281
285
  flwr/server/superlink/fleet/vce/backend/raybackend.py,sha256=7kB3re3mR53b7E6L6DPSioTSKD3YGtS3uJsPD7Hn2Fw,7155
282
286
  flwr/server/superlink/fleet/vce/vce_api.py,sha256=VL6e_Jwf4uxA-X1EelxJZMv6Eji-_p2J9D0MdHG10a4,13029
283
287
  flwr/server/superlink/linkstate/__init__.py,sha256=v-2JyJlCB3qyhMNwMjmcNVOq4rkooqFU0LHH8Zo1jls,1064
284
- flwr/server/superlink/linkstate/in_memory_linkstate.py,sha256=7teZcDU__Ni5l1mDh7j4P_-GlFVxvwaxelhy7TkM6ZU,21974
288
+ flwr/server/superlink/linkstate/in_memory_linkstate.py,sha256=SxJYOrzHVLWFO8qg3LhoD4PUmCP4ItFiqv6bDWApoxo,21197
285
289
  flwr/server/superlink/linkstate/linkstate.py,sha256=ylDV9I_j6a4LtWq-d-VWQyh8ipCob6DT7QcY6A7-LAo,12021
286
290
  flwr/server/superlink/linkstate/linkstate_factory.py,sha256=ISSMjDlwuN7swxjOeYlTNpI_kuZ8PGkMcJnf1dbhUSE,2069
287
- flwr/server/superlink/linkstate/sqlite_linkstate.py,sha256=KLGfrJQOqCbkwC4oqeQgn0oyTyU5fm9Kv0-4v6ftenA,45159
288
- flwr/server/superlink/linkstate/utils.py,sha256=cr6HM77pefdAdhkd0dg6MIWkfwBpvedbJId5uwCPZmE,7458
291
+ flwr/server/superlink/linkstate/sqlite_linkstate.py,sha256=OndEO8VjUHXw09fDw2t65fN1Ong9QBR56N2SyOlirAE,44604
292
+ flwr/server/superlink/linkstate/utils.py,sha256=emryyCNnsSodqhxuxJ3vBLglwHZ_eIA_rawdL7dDVCA,6204
289
293
  flwr/server/superlink/simulation/__init__.py,sha256=mg-oapC9dkzEfjXPQFior5lpWj4g9kwbLovptyYM_g0,718
290
294
  flwr/server/superlink/simulation/simulationio_grpc.py,sha256=5wflYW_TS0mjmPG6OYuHMJwXD2_cYmUNhFkdOU0jMWQ,2237
291
295
  flwr/server/superlink/simulation/simulationio_servicer.py,sha256=KRdgPt9vYGQorRgXwmCs65hpk7LHwMRU5RSk40m8t9I,5067
@@ -305,17 +309,17 @@ flwr/simulation/ray_transport/__init__.py,sha256=wzcEEwUUlulnXsg6raCA1nGpP3LlAQD
305
309
  flwr/simulation/ray_transport/ray_actor.py,sha256=9-XBguAm5IFqm2ddPFsQtnuuFN6lzqdb00SnCxGUGBo,18996
306
310
  flwr/simulation/ray_transport/ray_client_proxy.py,sha256=2vjOKoom3B74C6XU-jC3N6DwYmsLdB-lmkHZ_Xrv96o,7367
307
311
  flwr/simulation/ray_transport/utils.py,sha256=TYdtfg1P9VfTdLMOJlifInGpxWHYs9UfUqIv2wfkRLA,2392
308
- flwr/simulation/run_simulation.py,sha256=Wnu5ivU0Fee8lCSWggXNR2e3wudvHCr-GTinm4Xb_Bk,20248
312
+ flwr/simulation/run_simulation.py,sha256=BoG0lwaixe3g-xL4RZPl_6P47PKj2TiPHsDUtcNztkk,20247
309
313
  flwr/simulation/simulationio_connection.py,sha256=Uqtm2pRuZqEM8SxKS2TdBgsMUABSabhVIx9zzCPb_qc,3195
310
314
  flwr/superexec/__init__.py,sha256=fcj366jh4RFby_vDwLroU4kepzqbnJgseZD_jUr_Mko,715
311
315
  flwr/superexec/app.py,sha256=Tt3GonnTwHrMmicwx9XaP-crP78-bf4DUWl-N5cG6zY,1841
312
- flwr/superexec/deployment.py,sha256=cyaFosL_ue8LHu7y0EDAqbvz7npmQzfIrooR1ChKF14,6507
316
+ flwr/superexec/deployment.py,sha256=C-NNclLE9OVJST6VRemtXv5N_vOoZeb77AQcMptCP6M,6511
313
317
  flwr/superexec/exec_grpc.py,sha256=OuhBAk7hiky9rjGceinLGIXqchtzGPQThZnwyYv6Ei0,2241
314
- flwr/superexec/exec_servicer.py,sha256=6dUCijBYhrntZeQj82q2kVOUNFu_tsFOwT5HkkLYn9Q,3927
315
- flwr/superexec/executor.py,sha256=QA2_hQJxmN3zc75oEkDs-zkWAHesz59jE0P5lem-5VU,3073
316
- flwr/superexec/simulation.py,sha256=Ny3MJnNlgzW4K3NbgsgDM0LKKcoCd_q3LqNqb0GhWLI,7640
317
- flwr_nightly-1.13.0.dev20241106.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
318
- flwr_nightly-1.13.0.dev20241106.dist-info/METADATA,sha256=Llp8R-V25ySynw2F_c3igw4PHVRfkRa8sbS63ydH248,15618
319
- flwr_nightly-1.13.0.dev20241106.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
320
- flwr_nightly-1.13.0.dev20241106.dist-info/entry_points.txt,sha256=FxJQ96pmcNF2OvkTH6XF-Ip2PNrHvykjArkvkjQC7Mk,486
321
- flwr_nightly-1.13.0.dev20241106.dist-info/RECORD,,
318
+ flwr/superexec/exec_servicer.py,sha256=zNcdPkqLXgJIANKvE9uGIzgxocIs31WAj1YDnwqI6jo,3958
319
+ flwr/superexec/executor.py,sha256=zH3_53il6Jh0ZscIVEB9f4GNnXMeBbCGyCoBCxLgiG0,3114
320
+ flwr/superexec/simulation.py,sha256=prqEgAKnejHcYEj_euK1ICaHHt3QgLa3jnZJkDA7qqI,7623
321
+ flwr_nightly-1.13.0.dev20241107.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
322
+ flwr_nightly-1.13.0.dev20241107.dist-info/METADATA,sha256=7aLEvmo7nOuBJYOVCCHQcLyzcjVEzMzZbHb6Vrd0hDQ,15618
323
+ flwr_nightly-1.13.0.dev20241107.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
324
+ flwr_nightly-1.13.0.dev20241107.dist-info/entry_points.txt,sha256=FxJQ96pmcNF2OvkTH6XF-Ip2PNrHvykjArkvkjQC7Mk,486
325
+ flwr_nightly-1.13.0.dev20241107.dist-info/RECORD,,