flwr-nightly 1.17.0.dev20250317__py3-none-any.whl → 1.17.0.dev20250319__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.
- flwr/common/constant.py +5 -0
- flwr/common/logger.py +2 -2
- flwr/common/record/parametersrecord.py +336 -92
- flwr/server/__init__.py +3 -1
- flwr/server/app.py +1 -1
- flwr/server/compat/__init__.py +2 -2
- flwr/server/compat/app.py +11 -11
- flwr/server/compat/app_utils.py +16 -16
- flwr/server/compat/{driver_client_proxy.py → grid_client_proxy.py} +9 -9
- flwr/server/{driver → grid}/__init__.py +8 -7
- flwr/server/{driver/driver.py → grid/grid.py} +44 -15
- flwr/server/{driver/grpc_driver.py → grid/grpc_grid.py} +12 -20
- flwr/server/{driver/inmemory_driver.py → grid/inmemory_grid.py} +6 -14
- flwr/server/run_serverapp.py +4 -4
- flwr/server/server_app.py +38 -12
- flwr/server/serverapp/app.py +10 -10
- flwr/server/superlink/linkstate/in_memory_linkstate.py +28 -3
- flwr/server/superlink/linkstate/sqlite_linkstate.py +40 -2
- flwr/server/superlink/linkstate/utils.py +67 -10
- flwr/server/superlink/{driver → serverappio}/__init__.py +1 -1
- flwr/server/superlink/{driver → serverappio}/serverappio_grpc.py +1 -1
- flwr/server/superlink/{driver → serverappio}/serverappio_servicer.py +1 -1
- flwr/server/typing.py +3 -3
- flwr/server/workflow/default_workflows.py +17 -19
- flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +15 -15
- flwr/simulation/run_simulation.py +10 -10
- {flwr_nightly-1.17.0.dev20250317.dist-info → flwr_nightly-1.17.0.dev20250319.dist-info}/METADATA +1 -1
- {flwr_nightly-1.17.0.dev20250317.dist-info → flwr_nightly-1.17.0.dev20250319.dist-info}/RECORD +31 -31
- {flwr_nightly-1.17.0.dev20250317.dist-info → flwr_nightly-1.17.0.dev20250319.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.17.0.dev20250317.dist-info → flwr_nightly-1.17.0.dev20250319.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.17.0.dev20250317.dist-info → flwr_nightly-1.17.0.dev20250319.dist-info}/entry_points.txt +0 -0
flwr/server/compat/app.py
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
# ==============================================================================
|
15
|
-
"""Flower
|
15
|
+
"""Flower grid app."""
|
16
16
|
|
17
17
|
|
18
18
|
from logging import INFO
|
@@ -25,27 +25,27 @@ from flwr.server.server import Server, init_defaults, run_fl
|
|
25
25
|
from flwr.server.server_config import ServerConfig
|
26
26
|
from flwr.server.strategy import Strategy
|
27
27
|
|
28
|
-
from ..
|
28
|
+
from ..grid import Grid
|
29
29
|
from .app_utils import start_update_client_manager_thread
|
30
30
|
|
31
31
|
|
32
|
-
def
|
32
|
+
def start_grid( # pylint: disable=too-many-arguments, too-many-locals
|
33
33
|
*,
|
34
|
-
|
34
|
+
grid: Grid,
|
35
35
|
server: Optional[Server] = None,
|
36
36
|
config: Optional[ServerConfig] = None,
|
37
37
|
strategy: Optional[Strategy] = None,
|
38
38
|
client_manager: Optional[ClientManager] = None,
|
39
39
|
) -> History:
|
40
|
-
"""Start a Flower
|
40
|
+
"""Start a Flower server.
|
41
41
|
|
42
42
|
Parameters
|
43
43
|
----------
|
44
|
-
|
45
|
-
The
|
44
|
+
grid : Grid
|
45
|
+
The Grid object to use.
|
46
46
|
server : Optional[flwr.server.Server] (default: None)
|
47
47
|
A server implementation, either `flwr.server.Server` or a subclass
|
48
|
-
thereof. If no instance is provided, then `
|
48
|
+
thereof. If no instance is provided, then `start_grid` will create
|
49
49
|
one.
|
50
50
|
config : Optional[ServerConfig] (default: None)
|
51
51
|
Currently supported values are `num_rounds` (int, default: 1) and
|
@@ -56,7 +56,7 @@ def start_driver( # pylint: disable=too-many-arguments, too-many-locals
|
|
56
56
|
`start_server` will use `flwr.server.strategy.FedAvg`.
|
57
57
|
client_manager : Optional[flwr.server.ClientManager] (default: None)
|
58
58
|
An implementation of the class `flwr.server.ClientManager`. If no
|
59
|
-
implementation is provided, then `
|
59
|
+
implementation is provided, then `start_grid` will use
|
60
60
|
`flwr.server.SimpleClientManager`.
|
61
61
|
|
62
62
|
Returns
|
@@ -64,7 +64,7 @@ def start_driver( # pylint: disable=too-many-arguments, too-many-locals
|
|
64
64
|
hist : flwr.server.history.History
|
65
65
|
Object containing training and evaluation metrics.
|
66
66
|
"""
|
67
|
-
# Initialize the
|
67
|
+
# Initialize the server and config
|
68
68
|
initialized_server, initialized_config = init_defaults(
|
69
69
|
server=server,
|
70
70
|
config=config,
|
@@ -80,7 +80,7 @@ def start_driver( # pylint: disable=too-many-arguments, too-many-locals
|
|
80
80
|
|
81
81
|
# Start the thread updating nodes
|
82
82
|
thread, f_stop, c_done = start_update_client_manager_thread(
|
83
|
-
|
83
|
+
grid, initialized_server.client_manager()
|
84
84
|
)
|
85
85
|
|
86
86
|
# Wait until the node registration done
|
flwr/server/compat/app_utils.py
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
# ==============================================================================
|
15
|
-
"""Utility functions for the `
|
15
|
+
"""Utility functions for the `start_grid`."""
|
16
16
|
|
17
17
|
|
18
18
|
import threading
|
@@ -20,18 +20,18 @@ import threading
|
|
20
20
|
from flwr.common.typing import RunNotRunningException
|
21
21
|
|
22
22
|
from ..client_manager import ClientManager
|
23
|
-
from ..
|
24
|
-
from
|
23
|
+
from ..grid import Grid
|
24
|
+
from .grid_client_proxy import GridClientProxy
|
25
25
|
|
26
26
|
|
27
27
|
def start_update_client_manager_thread(
|
28
|
-
|
28
|
+
grid: Grid,
|
29
29
|
client_manager: ClientManager,
|
30
30
|
) -> tuple[threading.Thread, threading.Event, threading.Event]:
|
31
31
|
"""Periodically update the nodes list in the client manager in a thread.
|
32
32
|
|
33
|
-
This function starts a thread that periodically uses the associated
|
34
|
-
get all node_ids. Each node_id is then converted into a `
|
33
|
+
This function starts a thread that periodically uses the associated grid to
|
34
|
+
get all node_ids. Each node_id is then converted into a `GridClientProxy`
|
35
35
|
instance and stored in the `registered_nodes` dictionary with node_id as key.
|
36
36
|
|
37
37
|
New nodes will be added to the ClientManager via `client_manager.register()`,
|
@@ -40,8 +40,8 @@ def start_update_client_manager_thread(
|
|
40
40
|
|
41
41
|
Parameters
|
42
42
|
----------
|
43
|
-
|
44
|
-
The
|
43
|
+
grid : Grid
|
44
|
+
The Grid object to use.
|
45
45
|
client_manager : ClientManager
|
46
46
|
The ClientManager object to be updated.
|
47
47
|
|
@@ -59,7 +59,7 @@ def start_update_client_manager_thread(
|
|
59
59
|
thread = threading.Thread(
|
60
60
|
target=_update_client_manager,
|
61
61
|
args=(
|
62
|
-
|
62
|
+
grid,
|
63
63
|
client_manager,
|
64
64
|
f_stop,
|
65
65
|
c_done,
|
@@ -72,17 +72,17 @@ def start_update_client_manager_thread(
|
|
72
72
|
|
73
73
|
|
74
74
|
def _update_client_manager(
|
75
|
-
|
75
|
+
grid: Grid,
|
76
76
|
client_manager: ClientManager,
|
77
77
|
f_stop: threading.Event,
|
78
78
|
c_done: threading.Event,
|
79
79
|
) -> None:
|
80
80
|
"""Update the nodes list in the client manager."""
|
81
|
-
# Loop until the
|
82
|
-
registered_nodes: dict[int,
|
81
|
+
# Loop until the grid is disconnected
|
82
|
+
registered_nodes: dict[int, GridClientProxy] = {}
|
83
83
|
while not f_stop.is_set():
|
84
84
|
try:
|
85
|
-
all_node_ids = set(
|
85
|
+
all_node_ids = set(grid.get_node_ids())
|
86
86
|
except RunNotRunningException:
|
87
87
|
f_stop.set()
|
88
88
|
break
|
@@ -97,10 +97,10 @@ def _update_client_manager(
|
|
97
97
|
|
98
98
|
# Register new nodes
|
99
99
|
for node_id in new_nodes:
|
100
|
-
client_proxy =
|
100
|
+
client_proxy = GridClientProxy(
|
101
101
|
node_id=node_id,
|
102
|
-
|
103
|
-
run_id=
|
102
|
+
grid=grid,
|
103
|
+
run_id=grid.run.run_id,
|
104
104
|
)
|
105
105
|
if client_manager.register(client_proxy):
|
106
106
|
registered_nodes[node_id] = client_proxy
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright
|
1
|
+
# Copyright 2025 Flower Labs GmbH. All Rights Reserved.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -12,7 +12,7 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
# ==============================================================================
|
15
|
-
"""Flower ClientProxy implementation
|
15
|
+
"""Flower ClientProxy implementation using Grid."""
|
16
16
|
|
17
17
|
|
18
18
|
from typing import Optional
|
@@ -22,16 +22,16 @@ from flwr.common import Message, MessageType, MessageTypeLegacy, RecordSet
|
|
22
22
|
from flwr.common import recordset_compat as compat
|
23
23
|
from flwr.server.client_proxy import ClientProxy
|
24
24
|
|
25
|
-
from ..
|
25
|
+
from ..grid.grid import Grid
|
26
26
|
|
27
27
|
|
28
|
-
class
|
29
|
-
"""Flower client proxy which delegates work using
|
28
|
+
class GridClientProxy(ClientProxy):
|
29
|
+
"""Flower client proxy which delegates work using Grid."""
|
30
30
|
|
31
|
-
def __init__(self, node_id: int,
|
31
|
+
def __init__(self, node_id: int, grid: Grid, run_id: int):
|
32
32
|
super().__init__(str(node_id))
|
33
33
|
self.node_id = node_id
|
34
|
-
self.
|
34
|
+
self.grid = grid
|
35
35
|
self.run_id = run_id
|
36
36
|
|
37
37
|
def get_properties(
|
@@ -110,7 +110,7 @@ class DriverClientProxy(ClientProxy):
|
|
110
110
|
) -> RecordSet:
|
111
111
|
|
112
112
|
# Create message
|
113
|
-
message = self.
|
113
|
+
message = self.grid.create_message(
|
114
114
|
content=recordset,
|
115
115
|
message_type=message_type,
|
116
116
|
dst_node_id=self.node_id,
|
@@ -119,7 +119,7 @@ class DriverClientProxy(ClientProxy):
|
|
119
119
|
)
|
120
120
|
|
121
121
|
# Send message and wait for reply
|
122
|
-
messages = list(self.
|
122
|
+
messages = list(self.grid.send_and_receive(messages=[message]))
|
123
123
|
|
124
124
|
# A single reply is expected
|
125
125
|
if len(messages) != 1:
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright
|
1
|
+
# Copyright 2025 Flower Labs GmbH. All Rights Reserved.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -12,15 +12,16 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
# ==============================================================================
|
15
|
-
"""Flower
|
15
|
+
"""Flower grid SDK."""
|
16
16
|
|
17
17
|
|
18
|
-
from .
|
19
|
-
from .
|
20
|
-
from .
|
18
|
+
from .grid import Driver, Grid
|
19
|
+
from .grpc_grid import GrpcGrid
|
20
|
+
from .inmemory_grid import InMemoryGrid
|
21
21
|
|
22
22
|
__all__ = [
|
23
23
|
"Driver",
|
24
|
-
"
|
25
|
-
"
|
24
|
+
"Grid",
|
25
|
+
"GrpcGrid",
|
26
|
+
"InMemoryGrid",
|
26
27
|
]
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright
|
1
|
+
# Copyright 2025 Flower Labs GmbH. All Rights Reserved.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -12,7 +12,7 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
# ==============================================================================
|
15
|
-
"""
|
15
|
+
"""Grid (abstract base class)."""
|
16
16
|
|
17
17
|
|
18
18
|
from abc import ABC, abstractmethod
|
@@ -23,21 +23,21 @@ from flwr.common import Message, RecordSet
|
|
23
23
|
from flwr.common.typing import Run
|
24
24
|
|
25
25
|
|
26
|
-
class
|
27
|
-
"""Abstract base
|
26
|
+
class Grid(ABC):
|
27
|
+
"""Abstract base class Grid to send/receive messages."""
|
28
28
|
|
29
29
|
@abstractmethod
|
30
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
|
-
If a Run with the specified
|
33
|
+
If a ``Run`` with the specified ``run_id`` exists, a local ``Run``
|
34
34
|
object will be created. It enables further functionality
|
35
|
-
in the
|
35
|
+
in the grid, such as sending ``Message``s.
|
36
36
|
|
37
37
|
Parameters
|
38
38
|
----------
|
39
39
|
run_id : int
|
40
|
-
The
|
40
|
+
The ``run_id`` of the ``Run`` this ``Grid`` object operates in.
|
41
41
|
"""
|
42
42
|
|
43
43
|
@property
|
@@ -56,8 +56,8 @@ class Driver(ABC):
|
|
56
56
|
) -> Message:
|
57
57
|
"""Create a new message with specified parameters.
|
58
58
|
|
59
|
-
This method constructs a new
|
60
|
-
The
|
59
|
+
This method constructs a new ``Message`` with given content and metadata.
|
60
|
+
The ``run_id`` and ``src_node_id`` will be set automatically.
|
61
61
|
|
62
62
|
Parameters
|
63
63
|
----------
|
@@ -71,12 +71,12 @@ class Driver(ABC):
|
|
71
71
|
The ID of the destination node to which the message is being sent.
|
72
72
|
group_id : str
|
73
73
|
The ID of the group to which this message is associated. In some settings,
|
74
|
-
this is used as the
|
74
|
+
this is used as the federated learning round.
|
75
75
|
ttl : Optional[float] (default: None)
|
76
76
|
Time-to-live for the round trip of this message, i.e., the time from sending
|
77
77
|
this message to receiving a reply. It specifies in seconds the duration for
|
78
78
|
which the message and its potential reply are considered valid. If unset,
|
79
|
-
the default TTL (i.e.,
|
79
|
+
the default TTL (i.e., ``common.DEFAULT_TTL``) will be used.
|
80
80
|
|
81
81
|
Returns
|
82
82
|
-------
|
@@ -93,7 +93,7 @@ class Driver(ABC):
|
|
93
93
|
"""Push messages to specified node IDs.
|
94
94
|
|
95
95
|
This method takes an iterable of messages and sends each message
|
96
|
-
to the node specified in
|
96
|
+
to the node specified in ``dst_node_id``.
|
97
97
|
|
98
98
|
Parameters
|
99
99
|
----------
|
@@ -154,8 +154,37 @@ class Driver(ABC):
|
|
154
154
|
|
155
155
|
Notes
|
156
156
|
-----
|
157
|
-
This method uses
|
158
|
-
to collect the replies. If
|
157
|
+
This method uses ``push_messages`` to send the messages and ``pull_messages``
|
158
|
+
to collect the replies. If ``timeout`` is set, the method may not return
|
159
159
|
replies for all sent messages. A message remains valid until its TTL,
|
160
|
-
which is not affected by
|
160
|
+
which is not affected by ``timeout``.
|
161
161
|
"""
|
162
|
+
|
163
|
+
|
164
|
+
class Driver(Grid):
|
165
|
+
"""Deprecated abstract base class ``Driver``, use ``Grid`` instead.
|
166
|
+
|
167
|
+
This class is provided solely for backward compatibility with legacy
|
168
|
+
code that previously relied on the ``Driver`` class. It has been deprecated
|
169
|
+
in favor of the updated abstract base class ``Grid``, which now encompasses
|
170
|
+
all communication-related functionality and improvements between the
|
171
|
+
ServerApp and the SuperLink.
|
172
|
+
|
173
|
+
.. warning::
|
174
|
+
``Driver`` is deprecated and will be removed in a future release.
|
175
|
+
Use `Grid` in the signature of your ServerApp.
|
176
|
+
|
177
|
+
Examples
|
178
|
+
--------
|
179
|
+
Legacy (deprecated) usage::
|
180
|
+
|
181
|
+
@app.main()
|
182
|
+
def main(driver: Driver, context: Context) -> None:
|
183
|
+
...
|
184
|
+
|
185
|
+
Updated usage::
|
186
|
+
|
187
|
+
@app.main()
|
188
|
+
def main(grid: Grid, context: Context) -> None:
|
189
|
+
...
|
190
|
+
"""
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright
|
1
|
+
# Copyright 2025 Flower Labs GmbH. All Rights Reserved.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -12,11 +12,10 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
# ==============================================================================
|
15
|
-
"""Flower gRPC
|
15
|
+
"""Flower gRPC Grid."""
|
16
16
|
|
17
17
|
|
18
18
|
import time
|
19
|
-
import warnings
|
20
19
|
from collections.abc import Iterable
|
21
20
|
from logging import DEBUG, ERROR, WARNING
|
22
21
|
from typing import Optional, cast
|
@@ -46,11 +45,11 @@ from flwr.proto.serverappio_pb2 import ( # pylint: disable=E0611
|
|
46
45
|
)
|
47
46
|
from flwr.proto.serverappio_pb2_grpc import ServerAppIoStub # pylint: disable=E0611
|
48
47
|
|
49
|
-
from .
|
48
|
+
from .grid import Grid
|
50
49
|
|
51
50
|
ERROR_MESSAGE_PUSH_MESSAGES_RESOURCE_EXHAUSTED = """
|
52
51
|
|
53
|
-
[
|
52
|
+
[Grid.push_messages] gRPC error occurred:
|
54
53
|
|
55
54
|
The 2GB gRPC limit has been reached. Consider reducing the number of messages pushed
|
56
55
|
at once, or push messages individually, for example:
|
@@ -58,13 +57,13 @@ at once, or push messages individually, for example:
|
|
58
57
|
> msgs = [msg1, msg2, msg3]
|
59
58
|
> msg_ids = []
|
60
59
|
> for msg in msgs:
|
61
|
-
> msg_id =
|
60
|
+
> msg_id = grid.push_messages([msg])
|
62
61
|
> msg_ids.extend(msg_id)
|
63
62
|
"""
|
64
63
|
|
65
64
|
ERROR_MESSAGE_PULL_MESSAGES_RESOURCE_EXHAUSTED = """
|
66
65
|
|
67
|
-
[
|
66
|
+
[Grid.pull_messages] gRPC error occurred:
|
68
67
|
|
69
68
|
The 2GB gRPC limit has been reached. Consider reducing the number of messages pulled
|
70
69
|
at once, or pull messages individually, for example:
|
@@ -72,13 +71,13 @@ at once, or pull messages individually, for example:
|
|
72
71
|
> msgs_ids = [msg_id1, msg_id2, msg_id3]
|
73
72
|
> msgs = []
|
74
73
|
> for msg_id in msg_ids:
|
75
|
-
> msg =
|
74
|
+
> msg = grid.pull_messages([msg_id])
|
76
75
|
> msgs.extend(msg)
|
77
76
|
"""
|
78
77
|
|
79
78
|
|
80
|
-
class
|
81
|
-
"""`
|
79
|
+
class GrpcGrid(Grid):
|
80
|
+
"""`GrpcGrid` provides an interface to the ServerAppIo API.
|
82
81
|
|
83
82
|
Parameters
|
84
83
|
----------
|
@@ -102,6 +101,7 @@ class GrpcDriver(Driver):
|
|
102
101
|
self._channel: Optional[grpc.Channel] = None
|
103
102
|
self.node = Node(node_id=SUPERLINK_NODE_ID)
|
104
103
|
self._retry_invoker = _make_simple_grpc_retry_invoker()
|
104
|
+
super().__init__()
|
105
105
|
|
106
106
|
@property
|
107
107
|
def _is_connected(self) -> bool:
|
@@ -183,14 +183,6 @@ class GrpcDriver(Driver):
|
|
183
183
|
This method constructs a new `Message` with given content and metadata.
|
184
184
|
The `run_id` and `src_node_id` will be set automatically.
|
185
185
|
"""
|
186
|
-
if ttl:
|
187
|
-
warnings.warn(
|
188
|
-
"A custom TTL was set, but note that the SuperLink does not enforce "
|
189
|
-
"the TTL yet. The SuperLink will start enforcing the TTL in a future "
|
190
|
-
"version of Flower.",
|
191
|
-
stacklevel=2,
|
192
|
-
)
|
193
|
-
|
194
186
|
ttl_ = DEFAULT_TTL if ttl is None else ttl
|
195
187
|
metadata = Metadata(
|
196
188
|
run_id=cast(Run, self._run).run_id,
|
@@ -206,7 +198,7 @@ class GrpcDriver(Driver):
|
|
206
198
|
|
207
199
|
def get_node_ids(self) -> Iterable[int]:
|
208
200
|
"""Get node IDs."""
|
209
|
-
# Call
|
201
|
+
# Call GrpcServerAppIoStub method
|
210
202
|
res: GetNodesResponse = self._stub.GetNodes(
|
211
203
|
GetNodesRequest(run_id=cast(Run, self._run).run_id)
|
212
204
|
)
|
@@ -229,7 +221,7 @@ class GrpcDriver(Driver):
|
|
229
221
|
message_proto_list.append(msg_proto)
|
230
222
|
|
231
223
|
try:
|
232
|
-
# Call
|
224
|
+
# Call GrpcServerAppIoStub method
|
233
225
|
res: PushInsMessagesResponse = self._stub.PushMessages(
|
234
226
|
PushInsMessagesRequest(
|
235
227
|
messages_list=message_proto_list, run_id=cast(Run, self._run).run_id
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright
|
1
|
+
# Copyright 2025 Flower Labs GmbH. All Rights Reserved.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -12,11 +12,10 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
# ==============================================================================
|
15
|
-
"""Flower in-memory
|
15
|
+
"""Flower in-memory Grid."""
|
16
16
|
|
17
17
|
|
18
18
|
import time
|
19
|
-
import warnings
|
20
19
|
from collections.abc import Iterable
|
21
20
|
from typing import Optional, cast
|
22
21
|
from uuid import UUID
|
@@ -27,16 +26,16 @@ from flwr.common.typing import Run
|
|
27
26
|
from flwr.proto.node_pb2 import Node # pylint: disable=E0611
|
28
27
|
from flwr.server.superlink.linkstate import LinkStateFactory
|
29
28
|
|
30
|
-
from .
|
29
|
+
from .grid import Grid
|
31
30
|
|
32
31
|
|
33
|
-
class
|
34
|
-
"""`
|
32
|
+
class InMemoryGrid(Grid):
|
33
|
+
"""`InMemoryGrid` class provides an interface to the ServerAppIo API.
|
35
34
|
|
36
35
|
Parameters
|
37
36
|
----------
|
38
37
|
state_factory : StateFactory
|
39
|
-
A StateFactory embedding a state that this
|
38
|
+
A StateFactory embedding a state that this grid can interface with.
|
40
39
|
pull_interval : float (default=0.1)
|
41
40
|
Sleep duration between calls to `pull_messages`.
|
42
41
|
"""
|
@@ -88,13 +87,6 @@ class InMemoryDriver(Driver):
|
|
88
87
|
This method constructs a new `Message` with given content and metadata.
|
89
88
|
The `run_id` and `src_node_id` will be set automatically.
|
90
89
|
"""
|
91
|
-
if ttl:
|
92
|
-
warnings.warn(
|
93
|
-
"A custom TTL was set, but note that the SuperLink does not enforce "
|
94
|
-
"the TTL yet. The SuperLink will start enforcing the TTL in a future "
|
95
|
-
"version of Flower.",
|
96
|
-
stacklevel=2,
|
97
|
-
)
|
98
90
|
ttl_ = DEFAULT_TTL if ttl is None else ttl
|
99
91
|
|
100
92
|
metadata = Metadata(
|
flwr/server/run_serverapp.py
CHANGED
@@ -22,18 +22,18 @@ from flwr.common import Context
|
|
22
22
|
from flwr.common.logger import log
|
23
23
|
from flwr.common.object_ref import load_app
|
24
24
|
|
25
|
-
from .
|
25
|
+
from .grid import Grid
|
26
26
|
from .server_app import LoadServerAppError, ServerApp
|
27
27
|
|
28
28
|
|
29
29
|
def run(
|
30
|
-
|
30
|
+
grid: Grid,
|
31
31
|
context: Context,
|
32
32
|
server_app_dir: str,
|
33
33
|
server_app_attr: Optional[str] = None,
|
34
34
|
loaded_server_app: Optional[ServerApp] = None,
|
35
35
|
) -> Context:
|
36
|
-
"""Run ServerApp with a given
|
36
|
+
"""Run ServerApp with a given Grid."""
|
37
37
|
if not (server_app_attr is None) ^ (loaded_server_app is None):
|
38
38
|
raise ValueError(
|
39
39
|
"Either `server_app_attr` or `loaded_server_app` should be set "
|
@@ -59,7 +59,7 @@ def run(
|
|
59
59
|
server_app = _load()
|
60
60
|
|
61
61
|
# Call ServerApp
|
62
|
-
server_app(
|
62
|
+
server_app(grid=grid, context=context)
|
63
63
|
|
64
64
|
log(DEBUG, "ServerApp finished running.")
|
65
65
|
return context
|