flwr-nightly 1.17.0.dev20250318__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 CHANGED
@@ -61,6 +61,7 @@ PING_CALL_TIMEOUT = 5
61
61
  PING_BASE_MULTIPLIER = 0.8
62
62
  PING_RANDOM_RANGE = (-0.1, 0.1)
63
63
  PING_MAX_INTERVAL = 1e300
64
+ PING_PATIENCE = 2
64
65
 
65
66
  # IDs
66
67
  RUN_ID_NUM_BYTES = 8
@@ -166,6 +167,7 @@ class ErrorCode:
166
167
  CLIENT_APP_RAISED_EXCEPTION = 2
167
168
  MESSAGE_UNAVAILABLE = 3
168
169
  REPLY_MESSAGE_UNAVAILABLE = 4
170
+ NODE_UNAVAILABLE = 5
169
171
 
170
172
  def __new__(cls) -> ErrorCode:
171
173
  """Prevent instantiation."""
flwr/common/logger.py CHANGED
@@ -250,9 +250,9 @@ def warn_deprecated_feature_with_example(
250
250
  log(
251
251
  WARN,
252
252
  """FEATURE UPDATE: %s
253
- ------------------------------------------------------------
253
+ ------------------------------------------------------------
254
254
  %s
255
- ------------------------------------------------------------
255
+ ------------------------------------------------------------
256
256
  """,
257
257
  example_message,
258
258
  code_example,
flwr/server/__init__.py CHANGED
@@ -22,6 +22,7 @@ from .client_manager import ClientManager as ClientManager
22
22
  from .client_manager import SimpleClientManager as SimpleClientManager
23
23
  from .compat import LegacyContext as LegacyContext
24
24
  from .grid import Driver as Driver
25
+ from .grid import Grid as Grid
25
26
  from .history import History as History
26
27
  from .server import Server as Server
27
28
  from .server_app import ServerApp as ServerApp
@@ -31,6 +32,7 @@ from .serverapp_components import ServerAppComponents as ServerAppComponents
31
32
  __all__ = [
32
33
  "ClientManager",
33
34
  "Driver",
35
+ "Grid",
34
36
  "History",
35
37
  "LegacyContext",
36
38
  "Server",
@@ -15,10 +15,10 @@
15
15
  """Flower ServerApp compatibility package."""
16
16
 
17
17
 
18
- from .app import start_driver as start_driver
18
+ from .app import start_grid as start_grid
19
19
  from .legacy_context import LegacyContext as LegacyContext
20
20
 
21
21
  __all__ = [
22
22
  "LegacyContext",
23
- "start_driver",
23
+ "start_grid",
24
24
  ]
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 driver app."""
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 ..grid import Driver
28
+ from ..grid import Grid
29
29
  from .app_utils import start_update_client_manager_thread
30
30
 
31
31
 
32
- def start_driver( # pylint: disable=too-many-arguments, too-many-locals
32
+ def start_grid( # pylint: disable=too-many-arguments, too-many-locals
33
33
  *,
34
- driver: Driver,
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 Driver API server.
40
+ """Start a Flower server.
41
41
 
42
42
  Parameters
43
43
  ----------
44
- driver : Driver
45
- The Driver object to use.
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 `start_driver` will create
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 `start_driver` will use
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 Driver API server and config
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
- driver, initialized_server.client_manager()
83
+ grid, initialized_server.client_manager()
84
84
  )
85
85
 
86
86
  # Wait until the node registration done
@@ -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 `start_driver`."""
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 ..grid import Driver
24
- from .grid_client_proxy import DriverClientProxy
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
- driver: Driver,
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 driver to
34
- get all node_ids. Each node_id is then converted into a `DriverClientProxy`
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
- driver : Driver
44
- The Driver object to use.
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
- driver,
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
- driver: Driver,
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 driver is disconnected
82
- registered_nodes: dict[int, DriverClientProxy] = {}
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(driver.get_node_ids())
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 = DriverClientProxy(
100
+ client_proxy = GridClientProxy(
101
101
  node_id=node_id,
102
- driver=driver,
103
- run_id=driver.run.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
@@ -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 for Driver API."""
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 ..grid.grid import Driver
25
+ from ..grid.grid import Grid
26
26
 
27
27
 
28
- class DriverClientProxy(ClientProxy):
29
- """Flower client proxy which delegates work using the Driver API."""
28
+ class GridClientProxy(ClientProxy):
29
+ """Flower client proxy which delegates work using Grid."""
30
30
 
31
- def __init__(self, node_id: int, driver: Driver, run_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.driver = driver
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.driver.create_message(
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.driver.send_and_receive(messages=[message]))
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:
@@ -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 driver SDK."""
15
+ """Flower grid SDK."""
16
16
 
17
17
 
18
- from .grid import Driver
19
- from .grpc_grid import GrpcDriver
20
- from .inmemory_grid import InMemoryDriver
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
- "GrpcDriver",
25
- "InMemoryDriver",
24
+ "Grid",
25
+ "GrpcGrid",
26
+ "InMemoryGrid",
26
27
  ]
flwr/server/grid/grid.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
- """Driver (abstract base class)."""
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 Driver(ABC):
27
- """Abstract base Driver class for the ServerAppIo API."""
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 `run_id` exists, a local Run
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 driver, such as sending `Messages`.
35
+ in the grid, such as sending ``Message``s.
36
36
 
37
37
  Parameters
38
38
  ----------
39
39
  run_id : int
40
- The `run_id` of the Run this Driver object operates in.
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 `Message` with given content and metadata.
60
- The `run_id` and `src_node_id` will be set automatically.
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 FL round.
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., `common.DEFAULT_TTL`) will be used.
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 `dst_node_id`.
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 `push_messages` to send the messages and `pull_messages`
158
- to collect the replies. If `timeout` is set, the method may not return
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 `timeout`.
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
+ """
@@ -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 gRPC Driver."""
15
+ """Flower gRPC Grid."""
16
16
 
17
17
 
18
18
  import time
@@ -45,11 +45,11 @@ from flwr.proto.serverappio_pb2 import ( # pylint: disable=E0611
45
45
  )
46
46
  from flwr.proto.serverappio_pb2_grpc import ServerAppIoStub # pylint: disable=E0611
47
47
 
48
- from .grid import Driver
48
+ from .grid import Grid
49
49
 
50
50
  ERROR_MESSAGE_PUSH_MESSAGES_RESOURCE_EXHAUSTED = """
51
51
 
52
- [Driver.push_messages] gRPC error occurred:
52
+ [Grid.push_messages] gRPC error occurred:
53
53
 
54
54
  The 2GB gRPC limit has been reached. Consider reducing the number of messages pushed
55
55
  at once, or push messages individually, for example:
@@ -57,13 +57,13 @@ at once, or push messages individually, for example:
57
57
  > msgs = [msg1, msg2, msg3]
58
58
  > msg_ids = []
59
59
  > for msg in msgs:
60
- > msg_id = driver.push_messages([msg])
60
+ > msg_id = grid.push_messages([msg])
61
61
  > msg_ids.extend(msg_id)
62
62
  """
63
63
 
64
64
  ERROR_MESSAGE_PULL_MESSAGES_RESOURCE_EXHAUSTED = """
65
65
 
66
- [Driver.pull_messages] gRPC error occurred:
66
+ [Grid.pull_messages] gRPC error occurred:
67
67
 
68
68
  The 2GB gRPC limit has been reached. Consider reducing the number of messages pulled
69
69
  at once, or pull messages individually, for example:
@@ -71,13 +71,13 @@ at once, or pull messages individually, for example:
71
71
  > msgs_ids = [msg_id1, msg_id2, msg_id3]
72
72
  > msgs = []
73
73
  > for msg_id in msg_ids:
74
- > msg = driver.pull_messages([msg_id])
74
+ > msg = grid.pull_messages([msg_id])
75
75
  > msgs.extend(msg)
76
76
  """
77
77
 
78
78
 
79
- class GrpcDriver(Driver):
80
- """`GrpcDriver` provides an interface to the ServerAppIo API.
79
+ class GrpcGrid(Grid):
80
+ """`GrpcGrid` provides an interface to the ServerAppIo API.
81
81
 
82
82
  Parameters
83
83
  ----------
@@ -101,6 +101,7 @@ class GrpcDriver(Driver):
101
101
  self._channel: Optional[grpc.Channel] = None
102
102
  self.node = Node(node_id=SUPERLINK_NODE_ID)
103
103
  self._retry_invoker = _make_simple_grpc_retry_invoker()
104
+ super().__init__()
104
105
 
105
106
  @property
106
107
  def _is_connected(self) -> bool:
@@ -197,7 +198,7 @@ class GrpcDriver(Driver):
197
198
 
198
199
  def get_node_ids(self) -> Iterable[int]:
199
200
  """Get node IDs."""
200
- # Call GrpcDriverStub method
201
+ # Call GrpcServerAppIoStub method
201
202
  res: GetNodesResponse = self._stub.GetNodes(
202
203
  GetNodesRequest(run_id=cast(Run, self._run).run_id)
203
204
  )
@@ -220,7 +221,7 @@ class GrpcDriver(Driver):
220
221
  message_proto_list.append(msg_proto)
221
222
 
222
223
  try:
223
- # Call GrpcDriverStub method
224
+ # Call GrpcServerAppIoStub method
224
225
  res: PushInsMessagesResponse = self._stub.PushMessages(
225
226
  PushInsMessagesRequest(
226
227
  messages_list=message_proto_list, run_id=cast(Run, self._run).run_id
@@ -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 in-memory Driver."""
15
+ """Flower in-memory Grid."""
16
16
 
17
17
 
18
18
  import time
@@ -26,16 +26,16 @@ from flwr.common.typing import Run
26
26
  from flwr.proto.node_pb2 import Node # pylint: disable=E0611
27
27
  from flwr.server.superlink.linkstate import LinkStateFactory
28
28
 
29
- from .grid import Driver
29
+ from .grid import Grid
30
30
 
31
31
 
32
- class InMemoryDriver(Driver):
33
- """`InMemoryDriver` class provides an interface to the ServerAppIo API.
32
+ class InMemoryGrid(Grid):
33
+ """`InMemoryGrid` class provides an interface to the ServerAppIo API.
34
34
 
35
35
  Parameters
36
36
  ----------
37
37
  state_factory : StateFactory
38
- A StateFactory embedding a state that this driver can interface with.
38
+ A StateFactory embedding a state that this grid can interface with.
39
39
  pull_interval : float (default=0.1)
40
40
  Sleep duration between calls to `pull_messages`.
41
41
  """
@@ -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 .grid import Driver
25
+ from .grid import Grid
26
26
  from .server_app import LoadServerAppError, ServerApp
27
27
 
28
28
 
29
29
  def run(
30
- driver: Driver,
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 Driver."""
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(driver=driver, context=context)
62
+ server_app(grid=grid, context=context)
63
63
 
64
64
  log(DEBUG, "ServerApp finished running.")
65
65
  return context
flwr/server/server_app.py CHANGED
@@ -15,6 +15,7 @@
15
15
  """Flower ServerApp."""
16
16
 
17
17
 
18
+ import inspect
18
19
  from collections.abc import Iterator
19
20
  from contextlib import contextmanager
20
21
  from typing import Callable, Optional
@@ -24,8 +25,8 @@ from flwr.common.logger import warn_deprecated_feature_with_example
24
25
  from flwr.server.strategy import Strategy
25
26
 
26
27
  from .client_manager import ClientManager
27
- from .compat import start_driver
28
- from .grid import Driver
28
+ from .compat import start_grid
29
+ from .grid import Driver, Grid
29
30
  from .server import Server
30
31
  from .server_config import ServerConfig
31
32
  from .typing import ServerAppCallable, ServerFn
@@ -43,6 +44,21 @@ SERVER_FN_USAGE_EXAMPLE = """
43
44
  app = ServerApp(server_fn=server_fn)
44
45
  """
45
46
 
47
+ GRID_USAGE_EXAMPLE = """
48
+ app = ServerApp()
49
+
50
+ @app.main()
51
+ def main(grid: Grid, context: Context) -> None:
52
+ # Your existing ServerApp code ...
53
+ """
54
+
55
+ DRIVER_DEPRECATION_MSG = """
56
+ The `Driver` class is deprecated, it will be removed in a future release.
57
+ """
58
+ DRIVER_EXAMPLE_MSG = """
59
+ Instead, use `Grid` in the signature of your `ServerApp`. For example:
60
+ """
61
+
46
62
 
47
63
  @contextmanager
48
64
  def _empty_lifespan(_: Context) -> Iterator[None]:
@@ -54,7 +70,7 @@ class ServerApp: # pylint: disable=too-many-instance-attributes
54
70
 
55
71
  Examples
56
72
  --------
57
- Use the `ServerApp` with an existing `Strategy`:
73
+ Use the ``ServerApp`` with an existing ``Strategy``:
58
74
 
59
75
  >>> def server_fn(context: Context):
60
76
  >>> server_config = ServerConfig(num_rounds=3)
@@ -66,12 +82,12 @@ class ServerApp: # pylint: disable=too-many-instance-attributes
66
82
  >>>
67
83
  >>> app = ServerApp(server_fn=server_fn)
68
84
 
69
- Use the `ServerApp` with a custom main function:
85
+ Use the ``ServerApp`` with a custom main function:
70
86
 
71
87
  >>> app = ServerApp()
72
88
  >>>
73
89
  >>> @app.main()
74
- >>> def main(driver: Driver, context: Context) -> None:
90
+ >>> def main(grid: Grid, context: Context) -> None:
75
91
  >>> print("ServerApp running")
76
92
  """
77
93
 
@@ -111,7 +127,7 @@ class ServerApp: # pylint: disable=too-many-instance-attributes
111
127
  self._main: Optional[ServerAppCallable] = None
112
128
  self._lifespan = _empty_lifespan
113
129
 
114
- def __call__(self, driver: Driver, context: Context) -> None:
130
+ def __call__(self, grid: Grid, context: Context) -> None:
115
131
  """Execute `ServerApp`."""
116
132
  with self._lifespan(context):
117
133
  # Compatibility mode
@@ -123,17 +139,17 @@ class ServerApp: # pylint: disable=too-many-instance-attributes
123
139
  self._config = components.config
124
140
  self._strategy = components.strategy
125
141
  self._client_manager = components.client_manager
126
- start_driver(
142
+ start_grid(
127
143
  server=self._server,
128
144
  config=self._config,
129
145
  strategy=self._strategy,
130
146
  client_manager=self._client_manager,
131
- driver=driver,
147
+ grid=grid,
132
148
  )
133
149
  return
134
150
 
135
151
  # New execution mode
136
- self._main(driver, context)
152
+ self._main(grid, context)
137
153
 
138
154
  def main(self) -> Callable[[ServerAppCallable], ServerAppCallable]:
139
155
  """Return a decorator that registers the main fn with the server app.
@@ -143,7 +159,7 @@ class ServerApp: # pylint: disable=too-many-instance-attributes
143
159
  >>> app = ServerApp()
144
160
  >>>
145
161
  >>> @app.main()
146
- >>> def main(driver: Driver, context: Context) -> None:
162
+ >>> def main(grid: Grid, context: Context) -> None:
147
163
  >>> print("ServerApp running")
148
164
  """
149
165
 
@@ -168,11 +184,21 @@ class ServerApp: # pylint: disable=too-many-instance-attributes
168
184
  >>> app = ServerApp()
169
185
  >>>
170
186
  >>> @app.main()
171
- >>> def main(driver: Driver, context: Context) -> None:
187
+ >>> def main(grid: Grid, context: Context) -> None:
172
188
  >>> print("ServerApp running")
173
189
  """,
174
190
  )
175
191
 
192
+ sig = inspect.signature(main_fn)
193
+ param = list(sig.parameters.values())[0]
194
+ # Check if parameter name or the annotation should be updated
195
+ if param.name == "driver" or param.annotation is Driver:
196
+ warn_deprecated_feature_with_example(
197
+ deprecation_message=DRIVER_DEPRECATION_MSG,
198
+ example_message=DRIVER_EXAMPLE_MSG,
199
+ code_example=GRID_USAGE_EXAMPLE,
200
+ )
201
+
176
202
  # Register provided function with the ServerApp object
177
203
  self._main = main_fn
178
204