flwr-nightly 1.15.0.dev20250128__py3-none-any.whl → 1.15.0.dev20250129__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/cli/utils.py CHANGED
@@ -20,7 +20,6 @@ import json
20
20
  import re
21
21
  from collections.abc import Iterator
22
22
  from contextlib import contextmanager
23
- from logging import DEBUG
24
23
  from pathlib import Path
25
24
  from typing import Any, Callable, Optional, Union, cast
26
25
 
@@ -30,8 +29,11 @@ import typer
30
29
  from flwr.cli.cli_user_auth_interceptor import CliUserAuthInterceptor
31
30
  from flwr.common.auth_plugin import CliAuthPlugin
32
31
  from flwr.common.constant import AUTH_TYPE_KEY, CREDENTIALS_DIR, FLWR_DIR
33
- from flwr.common.grpc import GRPC_MAX_MESSAGE_LENGTH, create_channel
34
- from flwr.common.logger import log
32
+ from flwr.common.grpc import (
33
+ GRPC_MAX_MESSAGE_LENGTH,
34
+ create_channel,
35
+ on_channel_state_change,
36
+ )
35
37
 
36
38
  from .auth_plugin import get_cli_auth_plugins
37
39
  from .config_utils import validate_certificate_in_federation_config
@@ -264,11 +266,6 @@ def init_channel(
264
266
  app: Path, federation_config: dict[str, Any], auth_plugin: Optional[CliAuthPlugin]
265
267
  ) -> grpc.Channel:
266
268
  """Initialize gRPC channel to the Exec API."""
267
-
268
- def on_channel_state_change(channel_connectivity: str) -> None:
269
- """Log channel connectivity."""
270
- log(DEBUG, channel_connectivity)
271
-
272
269
  insecure, root_certificates_bytes = validate_certificate_in_federation_config(
273
270
  app, federation_config
274
271
  )
@@ -29,7 +29,7 @@ from flwr.common.args import add_args_flwr_app_common
29
29
  from flwr.common.config import get_flwr_dir
30
30
  from flwr.common.constant import CLIENTAPPIO_API_DEFAULT_CLIENT_ADDRESS, ErrorCode
31
31
  from flwr.common.exit import ExitCode, flwr_exit
32
- from flwr.common.grpc import create_channel
32
+ from flwr.common.grpc import create_channel, on_channel_state_change
33
33
  from flwr.common.logger import log
34
34
  from flwr.common.message import Error
35
35
  from flwr.common.retry_invoker import _make_simple_grpc_retry_invoker, _wrap_stub
@@ -66,11 +66,11 @@ def flwr_clientapp() -> None:
66
66
  "flwr-clientapp does not support TLS yet.",
67
67
  )
68
68
 
69
- log(INFO, "Starting Flower ClientApp")
69
+ log(INFO, "Start `flwr-clientapp` process")
70
70
  log(
71
71
  DEBUG,
72
- "Starting isolated `ClientApp` connected to SuperNode's ClientAppIo API at %s "
73
- "with token %s",
72
+ "`flwr-clientapp` will attempt to connect to SuperNode's "
73
+ "ClientAppIo API at %s with token %s",
74
74
  args.clientappio_api_address,
75
75
  args.token,
76
76
  )
@@ -83,11 +83,6 @@ def flwr_clientapp() -> None:
83
83
  )
84
84
 
85
85
 
86
- def on_channel_state_change(channel_connectivity: str) -> None:
87
- """Log channel connectivity."""
88
- log(DEBUG, channel_connectivity)
89
-
90
-
91
86
  def run_clientapp( # pylint: disable=R0914
92
87
  clientappio_api_address: str,
93
88
  run_once: bool,
@@ -116,11 +111,11 @@ def run_clientapp( # pylint: disable=R0914
116
111
  time.sleep(1)
117
112
 
118
113
  # Pull Message, Context, Run and (optional) FAB from SuperNode
119
- message, context, run, fab = pull_message(stub=stub, token=token)
114
+ message, context, run, fab = pull_clientappinputs(stub=stub, token=token)
120
115
 
121
116
  # Install FAB, if provided
122
117
  if fab:
123
- log(DEBUG, "Flower ClientApp starts FAB installation.")
118
+ log(DEBUG, "[flwr-clientapp] Start FAB installation.")
124
119
  install_from_fab(fab.content, flwr_dir=flwr_dir_, skip_prompt=True)
125
120
 
126
121
  load_client_app_fn = get_load_client_app_fn(
@@ -132,6 +127,7 @@ def run_clientapp( # pylint: disable=R0914
132
127
 
133
128
  try:
134
129
  # Load ClientApp
130
+ log(DEBUG, "[flwr-clientapp] Start `ClientApp` Loading.")
135
131
  client_app: ClientApp = load_client_app_fn(
136
132
  run.fab_id, run.fab_version, fab.hash_str if fab else ""
137
133
  )
@@ -160,7 +156,7 @@ def run_clientapp( # pylint: disable=R0914
160
156
  )
161
157
 
162
158
  # Push Message and Context to SuperNode
163
- _ = push_message(
159
+ _ = push_clientappoutputs(
164
160
  stub=stub, token=token, message=reply_message, context=context
165
161
  )
166
162
 
@@ -183,7 +179,7 @@ def run_clientapp( # pylint: disable=R0914
183
179
 
184
180
  def get_token(stub: grpc.Channel) -> Optional[int]:
185
181
  """Get a token from SuperNode."""
186
- log(DEBUG, "Flower ClientApp process requests token")
182
+ log(DEBUG, "[flwr-clientapp] Request token")
187
183
  try:
188
184
  res: GetTokenResponse = stub.GetToken(GetTokenRequest())
189
185
  log(DEBUG, "[GetToken] Received token: %s", res.token)
@@ -196,11 +192,11 @@ def get_token(stub: grpc.Channel) -> Optional[int]:
196
192
  return None
197
193
 
198
194
 
199
- def pull_message(
195
+ def pull_clientappinputs(
200
196
  stub: grpc.Channel, token: int
201
197
  ) -> tuple[Message, Context, Run, Optional[Fab]]:
202
- """Pull message from SuperNode to ClientApp."""
203
- log(INFO, "Pulling ClientAppInputs for token %s", token)
198
+ """Pull ClientAppInputs from SuperNode."""
199
+ log(INFO, "[flwr-clientapp] Pull `ClientAppInputs` for token %s", token)
204
200
  try:
205
201
  res: PullClientAppInputsResponse = stub.PullClientAppInputs(
206
202
  PullClientAppInputsRequest(token=token)
@@ -215,11 +211,11 @@ def pull_message(
215
211
  raise e
216
212
 
217
213
 
218
- def push_message(
214
+ def push_clientappoutputs(
219
215
  stub: grpc.Channel, token: int, message: Message, context: Context
220
216
  ) -> PushClientAppOutputsResponse:
221
- """Push message to SuperNode from ClientApp."""
222
- log(INFO, "Pushing ClientAppOutputs for token %s", token)
217
+ """Push ClientAppOutputs to SuperNode."""
218
+ log(INFO, "[flwr-clientapp] Push `ClientAppOutputs` for token %s", token)
223
219
  proto_message = message_to_proto(message)
224
220
  proto_context = context_to_proto(context)
225
221
 
@@ -36,7 +36,7 @@ from flwr.common import (
36
36
  from flwr.common import recordset_compat as compat
37
37
  from flwr.common import serde
38
38
  from flwr.common.constant import MessageType, MessageTypeLegacy
39
- from flwr.common.grpc import create_channel
39
+ from flwr.common.grpc import create_channel, on_channel_state_change
40
40
  from flwr.common.logger import log
41
41
  from flwr.common.retry_invoker import RetryInvoker
42
42
  from flwr.common.typing import Fab, Run
@@ -48,11 +48,6 @@ from flwr.proto.transport_pb2 import ( # pylint: disable=E0611
48
48
  from flwr.proto.transport_pb2_grpc import FlowerServiceStub # pylint: disable=E0611
49
49
 
50
50
 
51
- def on_channel_state_change(channel_connectivity: str) -> None:
52
- """Log channel connectivity."""
53
- log(DEBUG, channel_connectivity)
54
-
55
-
56
51
  @contextmanager
57
52
  def grpc_connection( # pylint: disable=R0913,R0915,too-many-positional-arguments
58
53
  server_address: str,
@@ -20,7 +20,7 @@ import threading
20
20
  from collections.abc import Iterator, Sequence
21
21
  from contextlib import contextmanager
22
22
  from copy import copy
23
- from logging import DEBUG, ERROR
23
+ from logging import ERROR
24
24
  from pathlib import Path
25
25
  from typing import Callable, Optional, Union, cast
26
26
 
@@ -36,10 +36,13 @@ from flwr.common.constant import (
36
36
  PING_DEFAULT_INTERVAL,
37
37
  PING_RANDOM_RANGE,
38
38
  )
39
- from flwr.common.grpc import create_channel
39
+ from flwr.common.grpc import create_channel, on_channel_state_change
40
40
  from flwr.common.logger import log
41
41
  from flwr.common.message import Message, Metadata
42
42
  from flwr.common.retry_invoker import RetryInvoker
43
+ from flwr.common.secure_aggregation.crypto.symmetric_encryption import (
44
+ generate_key_pairs,
45
+ )
43
46
  from flwr.common.serde import message_from_proto, message_to_proto, run_from_proto
44
47
  from flwr.common.typing import Fab, Run, RunNotRunningException
45
48
  from flwr.proto.fab_pb2 import GetFabRequest, GetFabResponse # pylint: disable=E0611
@@ -60,11 +63,6 @@ from .client_interceptor import AuthenticateClientInterceptor
60
63
  from .grpc_adapter import GrpcAdapter
61
64
 
62
65
 
63
- def on_channel_state_change(channel_connectivity: str) -> None:
64
- """Log channel connectivity."""
65
- log(DEBUG, channel_connectivity)
66
-
67
-
68
66
  @contextmanager
69
67
  def grpc_request_response( # pylint: disable=R0913,R0914,R0915,R0917
70
68
  server_address: str,
@@ -130,12 +128,14 @@ def grpc_request_response( # pylint: disable=R0913,R0914,R0915,R0917
130
128
  if isinstance(root_certificates, str):
131
129
  root_certificates = Path(root_certificates).read_bytes()
132
130
 
133
- interceptors: Optional[Sequence[grpc.UnaryUnaryClientInterceptor]] = None
134
- if authentication_keys is not None:
135
- interceptors = AuthenticateClientInterceptor(
136
- authentication_keys[0], authentication_keys[1]
137
- )
131
+ # Automatic node auth: generate keys if user didn't provide any
132
+ if authentication_keys is None:
133
+ authentication_keys = generate_key_pairs()
138
134
 
135
+ # Always configure auth interceptor, with either user-provided or generated keys
136
+ interceptors: Sequence[grpc.UnaryUnaryClientInterceptor] = [
137
+ AuthenticateClientInterceptor(*authentication_keys),
138
+ ]
139
139
  channel = create_channel(
140
140
  server_address=server_address,
141
141
  insecure=insecure,
@@ -42,12 +42,8 @@ from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
42
42
  PingResponse,
43
43
  PullMessagesRequest,
44
44
  PullMessagesResponse,
45
- PullTaskInsRequest,
46
- PullTaskInsResponse,
47
45
  PushMessagesRequest,
48
46
  PushMessagesResponse,
49
- PushTaskResRequest,
50
- PushTaskResResponse,
51
47
  )
52
48
  from flwr.proto.grpcadapter_pb2 import MessageContainer # pylint: disable=E0611
53
49
  from flwr.proto.grpcadapter_pb2_grpc import GrpcAdapterStub
@@ -130,24 +126,12 @@ class GrpcAdapter:
130
126
  """."""
131
127
  return self._send_and_receive(request, PingResponse, **kwargs)
132
128
 
133
- def PullTaskIns( # pylint: disable=C0103
134
- self, request: PullTaskInsRequest, **kwargs: Any
135
- ) -> PullTaskInsResponse:
136
- """."""
137
- return self._send_and_receive(request, PullTaskInsResponse, **kwargs)
138
-
139
129
  def PullMessages( # pylint: disable=C0103
140
130
  self, request: PullMessagesRequest, **kwargs: Any
141
131
  ) -> PullMessagesResponse:
142
132
  """."""
143
133
  return self._send_and_receive(request, PullMessagesResponse, **kwargs)
144
134
 
145
- def PushTaskRes( # pylint: disable=C0103
146
- self, request: PushTaskResRequest, **kwargs: Any
147
- ) -> PushTaskResResponse:
148
- """."""
149
- return self._send_and_receive(request, PushTaskResResponse, **kwargs)
150
-
151
135
  def PushMessages( # pylint: disable=C0103
152
136
  self, request: PushMessagesRequest, **kwargs: Any
153
137
  ) -> PushMessagesResponse:
@@ -15,9 +15,6 @@
15
15
  """Task handling."""
16
16
 
17
17
 
18
- from typing import Optional
19
-
20
- from flwr.proto.fleet_pb2 import PullTaskInsResponse # pylint: disable=E0611
21
18
  from flwr.proto.task_pb2 import TaskIns # pylint: disable=E0611
22
19
 
23
20
 
@@ -38,17 +35,3 @@ def validate_task_ins(task_ins: TaskIns) -> bool:
38
35
  if not (task_ins.HasField("task") and task_ins.task.HasField("recordset")):
39
36
  return False
40
37
  return True
41
-
42
-
43
- def get_task_ins(
44
- pull_task_ins_response: PullTaskInsResponse,
45
- ) -> Optional[TaskIns]:
46
- """Get the first TaskIns, if available."""
47
- # Extract a single ServerMessage from the response, if possible
48
- if len(pull_task_ins_response.task_ins_list) == 0:
49
- return None
50
-
51
- # Only evaluate the first message
52
- task_ins: TaskIns = pull_task_ins_response.task_ins_list[0]
53
-
54
- return task_ins
@@ -39,7 +39,8 @@ def get_norm(input_arrays: NDArrays) -> float:
39
39
  def add_gaussian_noise_inplace(input_arrays: NDArrays, std_dev: float) -> None:
40
40
  """Add Gaussian noise to each element of the input arrays."""
41
41
  for array in input_arrays:
42
- array += np.random.normal(0, std_dev, array.shape)
42
+ noise = np.random.normal(0, std_dev, array.shape).astype(array.dtype)
43
+ array += noise
43
44
 
44
45
 
45
46
  def clip_inputs_inplace(input_arrays: NDArrays, clipping_norm: float) -> None:
flwr/common/grpc.py CHANGED
@@ -80,7 +80,7 @@ def create_channel(
80
80
  log(DEBUG, "Opened secure gRPC connection using certificates")
81
81
 
82
82
  if interceptors is not None:
83
- channel = grpc.intercept_channel(channel, interceptors)
83
+ channel = grpc.intercept_channel(channel, *interceptors)
84
84
 
85
85
  return channel
86
86
 
@@ -224,3 +224,8 @@ def generic_create_grpc_server( # pylint: disable=too-many-arguments,R0917
224
224
  server.add_insecure_port(server_address)
225
225
 
226
226
  return server
227
+
228
+
229
+ def on_channel_state_change(channel_connectivity: str) -> None:
230
+ """Log channel connectivity."""
231
+ log(DEBUG, channel_connectivity)
flwr/proto/fleet_pb2.py CHANGED
@@ -23,57 +23,44 @@ _sym_db = _symbol_database.Default()
23
23
 
24
24
 
25
25
  from flwr.proto import node_pb2 as flwr_dot_proto_dot_node__pb2
26
- from flwr.proto import task_pb2 as flwr_dot_proto_dot_task__pb2
27
26
  from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2
28
27
  from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
29
28
  from flwr.proto import message_pb2 as flwr_dot_proto_dot_message__pb2
30
29
 
31
30
 
32
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66lwr/proto/fleet.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x15\x66lwr/proto/task.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x18\x66lwr/proto/message.proto\"*\n\x11\x43reateNodeRequest\x12\x15\n\rping_interval\x18\x01 \x01(\x01\"4\n\x12\x43reateNodeResponse\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"3\n\x11\x44\x65leteNodeRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"\x14\n\x12\x44\x65leteNodeResponse\"D\n\x0bPingRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x15\n\rping_interval\x18\x02 \x01(\x01\"\x1f\n\x0cPingResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"F\n\x12PullTaskInsRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x10\n\x08task_ids\x18\x02 \x03(\t\"k\n\x13PullTaskInsResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rtask_ins_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.TaskIns\"`\n\x12PushTaskResRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12*\n\rtask_res_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.TaskRes\"\xae\x01\n\x13PushTaskResResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12=\n\x07results\x18\x02 \x03(\x0b\x32,.flwr.proto.PushTaskResResponse.ResultsEntry\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"J\n\x13PullMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x13\n\x0bmessage_ids\x18\x02 \x03(\t\"l\n\x14PullMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\"a\n\x13PushMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\"\xb0\x01\n\x14PushMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12>\n\x07results\x18\x02 \x03(\x0b\x32-.flwr.proto.PushMessagesResponse.ResultsEntry\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x1e\n\tReconnect\x12\x11\n\treconnect\x18\x01 \x01(\x04\x32\xb6\x05\n\x05\x46leet\x12M\n\nCreateNode\x12\x1d.flwr.proto.CreateNodeRequest\x1a\x1e.flwr.proto.CreateNodeResponse\"\x00\x12M\n\nDeleteNode\x12\x1d.flwr.proto.DeleteNodeRequest\x1a\x1e.flwr.proto.DeleteNodeResponse\"\x00\x12;\n\x04Ping\x12\x17.flwr.proto.PingRequest\x1a\x18.flwr.proto.PingResponse\"\x00\x12P\n\x0bPullTaskIns\x12\x1e.flwr.proto.PullTaskInsRequest\x1a\x1f.flwr.proto.PullTaskInsResponse\"\x00\x12S\n\x0cPullMessages\x12\x1f.flwr.proto.PullMessagesRequest\x1a .flwr.proto.PullMessagesResponse\"\x00\x12P\n\x0bPushTaskRes\x12\x1e.flwr.proto.PushTaskResRequest\x1a\x1f.flwr.proto.PushTaskResResponse\"\x00\x12S\n\x0cPushMessages\x12\x1f.flwr.proto.PushMessagesRequest\x1a .flwr.proto.PushMessagesResponse\"\x00\x12\x41\n\x06GetRun\x12\x19.flwr.proto.GetRunRequest\x1a\x1a.flwr.proto.GetRunResponse\"\x00\x12\x41\n\x06GetFab\x12\x19.flwr.proto.GetFabRequest\x1a\x1a.flwr.proto.GetFabResponse\"\x00\x62\x06proto3')
31
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66lwr/proto/fleet.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x18\x66lwr/proto/message.proto\"*\n\x11\x43reateNodeRequest\x12\x15\n\rping_interval\x18\x01 \x01(\x01\"4\n\x12\x43reateNodeResponse\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"3\n\x11\x44\x65leteNodeRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"\x14\n\x12\x44\x65leteNodeResponse\"D\n\x0bPingRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x15\n\rping_interval\x18\x02 \x01(\x01\"\x1f\n\x0cPingResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"J\n\x13PullMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x13\n\x0bmessage_ids\x18\x02 \x03(\t\"l\n\x14PullMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\"a\n\x13PushMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\"\xb0\x01\n\x14PushMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12>\n\x07results\x18\x02 \x03(\x0b\x32-.flwr.proto.PushMessagesResponse.ResultsEntry\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x1e\n\tReconnect\x12\x11\n\treconnect\x18\x01 \x01(\x04\x32\x92\x04\n\x05\x46leet\x12M\n\nCreateNode\x12\x1d.flwr.proto.CreateNodeRequest\x1a\x1e.flwr.proto.CreateNodeResponse\"\x00\x12M\n\nDeleteNode\x12\x1d.flwr.proto.DeleteNodeRequest\x1a\x1e.flwr.proto.DeleteNodeResponse\"\x00\x12;\n\x04Ping\x12\x17.flwr.proto.PingRequest\x1a\x18.flwr.proto.PingResponse\"\x00\x12S\n\x0cPullMessages\x12\x1f.flwr.proto.PullMessagesRequest\x1a .flwr.proto.PullMessagesResponse\"\x00\x12S\n\x0cPushMessages\x12\x1f.flwr.proto.PushMessagesRequest\x1a .flwr.proto.PushMessagesResponse\"\x00\x12\x41\n\x06GetRun\x12\x19.flwr.proto.GetRunRequest\x1a\x1a.flwr.proto.GetRunResponse\"\x00\x12\x41\n\x06GetFab\x12\x19.flwr.proto.GetFabRequest\x1a\x1a.flwr.proto.GetFabResponse\"\x00\x62\x06proto3')
33
32
 
34
33
  _globals = globals()
35
34
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
36
35
  _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.fleet_pb2', _globals)
37
36
  if not _descriptor._USE_C_DESCRIPTORS:
38
37
  DESCRIPTOR._loaded_options = None
39
- _globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._loaded_options = None
40
- _globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._serialized_options = b'8\001'
41
38
  _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._loaded_options = None
42
39
  _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_options = b'8\001'
43
- _globals['_CREATENODEREQUEST']._serialized_start=154
44
- _globals['_CREATENODEREQUEST']._serialized_end=196
45
- _globals['_CREATENODERESPONSE']._serialized_start=198
46
- _globals['_CREATENODERESPONSE']._serialized_end=250
47
- _globals['_DELETENODEREQUEST']._serialized_start=252
48
- _globals['_DELETENODEREQUEST']._serialized_end=303
49
- _globals['_DELETENODERESPONSE']._serialized_start=305
50
- _globals['_DELETENODERESPONSE']._serialized_end=325
51
- _globals['_PINGREQUEST']._serialized_start=327
52
- _globals['_PINGREQUEST']._serialized_end=395
53
- _globals['_PINGRESPONSE']._serialized_start=397
54
- _globals['_PINGRESPONSE']._serialized_end=428
55
- _globals['_PULLTASKINSREQUEST']._serialized_start=430
56
- _globals['_PULLTASKINSREQUEST']._serialized_end=500
57
- _globals['_PULLTASKINSRESPONSE']._serialized_start=502
58
- _globals['_PULLTASKINSRESPONSE']._serialized_end=609
59
- _globals['_PUSHTASKRESREQUEST']._serialized_start=611
60
- _globals['_PUSHTASKRESREQUEST']._serialized_end=707
61
- _globals['_PUSHTASKRESRESPONSE']._serialized_start=710
62
- _globals['_PUSHTASKRESRESPONSE']._serialized_end=884
63
- _globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._serialized_start=838
64
- _globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._serialized_end=884
65
- _globals['_PULLMESSAGESREQUEST']._serialized_start=886
66
- _globals['_PULLMESSAGESREQUEST']._serialized_end=960
67
- _globals['_PULLMESSAGESRESPONSE']._serialized_start=962
68
- _globals['_PULLMESSAGESRESPONSE']._serialized_end=1070
69
- _globals['_PUSHMESSAGESREQUEST']._serialized_start=1072
70
- _globals['_PUSHMESSAGESREQUEST']._serialized_end=1169
71
- _globals['_PUSHMESSAGESRESPONSE']._serialized_start=1172
72
- _globals['_PUSHMESSAGESRESPONSE']._serialized_end=1348
73
- _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_start=838
74
- _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_end=884
75
- _globals['_RECONNECT']._serialized_start=1350
76
- _globals['_RECONNECT']._serialized_end=1380
77
- _globals['_FLEET']._serialized_start=1383
78
- _globals['_FLEET']._serialized_end=2077
40
+ _globals['_CREATENODEREQUEST']._serialized_start=131
41
+ _globals['_CREATENODEREQUEST']._serialized_end=173
42
+ _globals['_CREATENODERESPONSE']._serialized_start=175
43
+ _globals['_CREATENODERESPONSE']._serialized_end=227
44
+ _globals['_DELETENODEREQUEST']._serialized_start=229
45
+ _globals['_DELETENODEREQUEST']._serialized_end=280
46
+ _globals['_DELETENODERESPONSE']._serialized_start=282
47
+ _globals['_DELETENODERESPONSE']._serialized_end=302
48
+ _globals['_PINGREQUEST']._serialized_start=304
49
+ _globals['_PINGREQUEST']._serialized_end=372
50
+ _globals['_PINGRESPONSE']._serialized_start=374
51
+ _globals['_PINGRESPONSE']._serialized_end=405
52
+ _globals['_PULLMESSAGESREQUEST']._serialized_start=407
53
+ _globals['_PULLMESSAGESREQUEST']._serialized_end=481
54
+ _globals['_PULLMESSAGESRESPONSE']._serialized_start=483
55
+ _globals['_PULLMESSAGESRESPONSE']._serialized_end=591
56
+ _globals['_PUSHMESSAGESREQUEST']._serialized_start=593
57
+ _globals['_PUSHMESSAGESREQUEST']._serialized_end=690
58
+ _globals['_PUSHMESSAGESRESPONSE']._serialized_start=693
59
+ _globals['_PUSHMESSAGESRESPONSE']._serialized_end=869
60
+ _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_start=823
61
+ _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_end=869
62
+ _globals['_RECONNECT']._serialized_start=871
63
+ _globals['_RECONNECT']._serialized_end=901
64
+ _globals['_FLEET']._serialized_start=904
65
+ _globals['_FLEET']._serialized_end=1434
79
66
  # @@protoc_insertion_point(module_scope)
flwr/proto/fleet_pb2.pyi CHANGED
@@ -5,7 +5,6 @@ isort:skip_file
5
5
  import builtins
6
6
  import flwr.proto.message_pb2
7
7
  import flwr.proto.node_pb2
8
- import flwr.proto.task_pb2
9
8
  import google.protobuf.descriptor
10
9
  import google.protobuf.internal.containers
11
10
  import google.protobuf.message
@@ -87,89 +86,6 @@ class PingResponse(google.protobuf.message.Message):
87
86
  def ClearField(self, field_name: typing_extensions.Literal["success",b"success"]) -> None: ...
88
87
  global___PingResponse = PingResponse
89
88
 
90
- class PullTaskInsRequest(google.protobuf.message.Message):
91
- """PullTaskIns messages"""
92
- DESCRIPTOR: google.protobuf.descriptor.Descriptor
93
- NODE_FIELD_NUMBER: builtins.int
94
- TASK_IDS_FIELD_NUMBER: builtins.int
95
- @property
96
- def node(self) -> flwr.proto.node_pb2.Node: ...
97
- @property
98
- def task_ids(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: ...
99
- def __init__(self,
100
- *,
101
- node: typing.Optional[flwr.proto.node_pb2.Node] = ...,
102
- task_ids: typing.Optional[typing.Iterable[typing.Text]] = ...,
103
- ) -> None: ...
104
- def HasField(self, field_name: typing_extensions.Literal["node",b"node"]) -> builtins.bool: ...
105
- def ClearField(self, field_name: typing_extensions.Literal["node",b"node","task_ids",b"task_ids"]) -> None: ...
106
- global___PullTaskInsRequest = PullTaskInsRequest
107
-
108
- class PullTaskInsResponse(google.protobuf.message.Message):
109
- DESCRIPTOR: google.protobuf.descriptor.Descriptor
110
- RECONNECT_FIELD_NUMBER: builtins.int
111
- TASK_INS_LIST_FIELD_NUMBER: builtins.int
112
- @property
113
- def reconnect(self) -> global___Reconnect: ...
114
- @property
115
- def task_ins_list(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[flwr.proto.task_pb2.TaskIns]: ...
116
- def __init__(self,
117
- *,
118
- reconnect: typing.Optional[global___Reconnect] = ...,
119
- task_ins_list: typing.Optional[typing.Iterable[flwr.proto.task_pb2.TaskIns]] = ...,
120
- ) -> None: ...
121
- def HasField(self, field_name: typing_extensions.Literal["reconnect",b"reconnect"]) -> builtins.bool: ...
122
- def ClearField(self, field_name: typing_extensions.Literal["reconnect",b"reconnect","task_ins_list",b"task_ins_list"]) -> None: ...
123
- global___PullTaskInsResponse = PullTaskInsResponse
124
-
125
- class PushTaskResRequest(google.protobuf.message.Message):
126
- """PushTaskRes messages"""
127
- DESCRIPTOR: google.protobuf.descriptor.Descriptor
128
- NODE_FIELD_NUMBER: builtins.int
129
- TASK_RES_LIST_FIELD_NUMBER: builtins.int
130
- @property
131
- def node(self) -> flwr.proto.node_pb2.Node: ...
132
- @property
133
- def task_res_list(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[flwr.proto.task_pb2.TaskRes]: ...
134
- def __init__(self,
135
- *,
136
- node: typing.Optional[flwr.proto.node_pb2.Node] = ...,
137
- task_res_list: typing.Optional[typing.Iterable[flwr.proto.task_pb2.TaskRes]] = ...,
138
- ) -> None: ...
139
- def HasField(self, field_name: typing_extensions.Literal["node",b"node"]) -> builtins.bool: ...
140
- def ClearField(self, field_name: typing_extensions.Literal["node",b"node","task_res_list",b"task_res_list"]) -> None: ...
141
- global___PushTaskResRequest = PushTaskResRequest
142
-
143
- class PushTaskResResponse(google.protobuf.message.Message):
144
- DESCRIPTOR: google.protobuf.descriptor.Descriptor
145
- class ResultsEntry(google.protobuf.message.Message):
146
- DESCRIPTOR: google.protobuf.descriptor.Descriptor
147
- KEY_FIELD_NUMBER: builtins.int
148
- VALUE_FIELD_NUMBER: builtins.int
149
- key: typing.Text
150
- value: builtins.int
151
- def __init__(self,
152
- *,
153
- key: typing.Text = ...,
154
- value: builtins.int = ...,
155
- ) -> None: ...
156
- def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
157
-
158
- RECONNECT_FIELD_NUMBER: builtins.int
159
- RESULTS_FIELD_NUMBER: builtins.int
160
- @property
161
- def reconnect(self) -> global___Reconnect: ...
162
- @property
163
- def results(self) -> google.protobuf.internal.containers.ScalarMap[typing.Text, builtins.int]: ...
164
- def __init__(self,
165
- *,
166
- reconnect: typing.Optional[global___Reconnect] = ...,
167
- results: typing.Optional[typing.Mapping[typing.Text, builtins.int]] = ...,
168
- ) -> None: ...
169
- def HasField(self, field_name: typing_extensions.Literal["reconnect",b"reconnect"]) -> builtins.bool: ...
170
- def ClearField(self, field_name: typing_extensions.Literal["reconnect",b"reconnect","results",b"results"]) -> None: ...
171
- global___PushTaskResResponse = PushTaskResResponse
172
-
173
89
  class PullMessagesRequest(google.protobuf.message.Message):
174
90
  """PullMessages messages"""
175
91
  DESCRIPTOR: google.protobuf.descriptor.Descriptor
@@ -51,21 +51,11 @@ class FleetStub(object):
51
51
  request_serializer=flwr_dot_proto_dot_fleet__pb2.PingRequest.SerializeToString,
52
52
  response_deserializer=flwr_dot_proto_dot_fleet__pb2.PingResponse.FromString,
53
53
  _registered_method=True)
54
- self.PullTaskIns = channel.unary_unary(
55
- '/flwr.proto.Fleet/PullTaskIns',
56
- request_serializer=flwr_dot_proto_dot_fleet__pb2.PullTaskInsRequest.SerializeToString,
57
- response_deserializer=flwr_dot_proto_dot_fleet__pb2.PullTaskInsResponse.FromString,
58
- _registered_method=True)
59
54
  self.PullMessages = channel.unary_unary(
60
55
  '/flwr.proto.Fleet/PullMessages',
61
56
  request_serializer=flwr_dot_proto_dot_fleet__pb2.PullMessagesRequest.SerializeToString,
62
57
  response_deserializer=flwr_dot_proto_dot_fleet__pb2.PullMessagesResponse.FromString,
63
58
  _registered_method=True)
64
- self.PushTaskRes = channel.unary_unary(
65
- '/flwr.proto.Fleet/PushTaskRes',
66
- request_serializer=flwr_dot_proto_dot_fleet__pb2.PushTaskResRequest.SerializeToString,
67
- response_deserializer=flwr_dot_proto_dot_fleet__pb2.PushTaskResResponse.FromString,
68
- _registered_method=True)
69
59
  self.PushMessages = channel.unary_unary(
70
60
  '/flwr.proto.Fleet/PushMessages',
71
61
  request_serializer=flwr_dot_proto_dot_fleet__pb2.PushMessagesRequest.SerializeToString,
@@ -104,33 +94,19 @@ class FleetServicer(object):
104
94
  context.set_details('Method not implemented!')
105
95
  raise NotImplementedError('Method not implemented!')
106
96
 
107
- def PullTaskIns(self, request, context):
108
- """Retrieve one or more tasks, if possible
109
-
110
- HTTP API path: /api/v1/fleet/pull-task-ins
111
- """
112
- context.set_code(grpc.StatusCode.UNIMPLEMENTED)
113
- context.set_details('Method not implemented!')
114
- raise NotImplementedError('Method not implemented!')
115
-
116
97
  def PullMessages(self, request, context):
117
- """HTTP API path: /api/v1/fleet/pull-messages
118
- """
119
- context.set_code(grpc.StatusCode.UNIMPLEMENTED)
120
- context.set_details('Method not implemented!')
121
- raise NotImplementedError('Method not implemented!')
98
+ """Retrieve one or more messages, if possible
122
99
 
123
- def PushTaskRes(self, request, context):
124
- """Complete one or more tasks, if possible
125
-
126
- HTTP API path: /api/v1/fleet/push-task-res
100
+ HTTP API path: /api/v1/fleet/pull-messages
127
101
  """
128
102
  context.set_code(grpc.StatusCode.UNIMPLEMENTED)
129
103
  context.set_details('Method not implemented!')
130
104
  raise NotImplementedError('Method not implemented!')
131
105
 
132
106
  def PushMessages(self, request, context):
133
- """HTTP API path: /api/v1/fleet/push-messages
107
+ """Complete one or more messages, if possible
108
+
109
+ HTTP API path: /api/v1/fleet/push-messages
134
110
  """
135
111
  context.set_code(grpc.StatusCode.UNIMPLEMENTED)
136
112
  context.set_details('Method not implemented!')
@@ -167,21 +143,11 @@ def add_FleetServicer_to_server(servicer, server):
167
143
  request_deserializer=flwr_dot_proto_dot_fleet__pb2.PingRequest.FromString,
168
144
  response_serializer=flwr_dot_proto_dot_fleet__pb2.PingResponse.SerializeToString,
169
145
  ),
170
- 'PullTaskIns': grpc.unary_unary_rpc_method_handler(
171
- servicer.PullTaskIns,
172
- request_deserializer=flwr_dot_proto_dot_fleet__pb2.PullTaskInsRequest.FromString,
173
- response_serializer=flwr_dot_proto_dot_fleet__pb2.PullTaskInsResponse.SerializeToString,
174
- ),
175
146
  'PullMessages': grpc.unary_unary_rpc_method_handler(
176
147
  servicer.PullMessages,
177
148
  request_deserializer=flwr_dot_proto_dot_fleet__pb2.PullMessagesRequest.FromString,
178
149
  response_serializer=flwr_dot_proto_dot_fleet__pb2.PullMessagesResponse.SerializeToString,
179
150
  ),
180
- 'PushTaskRes': grpc.unary_unary_rpc_method_handler(
181
- servicer.PushTaskRes,
182
- request_deserializer=flwr_dot_proto_dot_fleet__pb2.PushTaskResRequest.FromString,
183
- response_serializer=flwr_dot_proto_dot_fleet__pb2.PushTaskResResponse.SerializeToString,
184
- ),
185
151
  'PushMessages': grpc.unary_unary_rpc_method_handler(
186
152
  servicer.PushMessages,
187
153
  request_deserializer=flwr_dot_proto_dot_fleet__pb2.PushMessagesRequest.FromString,
@@ -289,33 +255,6 @@ class Fleet(object):
289
255
  metadata,
290
256
  _registered_method=True)
291
257
 
292
- @staticmethod
293
- def PullTaskIns(request,
294
- target,
295
- options=(),
296
- channel_credentials=None,
297
- call_credentials=None,
298
- insecure=False,
299
- compression=None,
300
- wait_for_ready=None,
301
- timeout=None,
302
- metadata=None):
303
- return grpc.experimental.unary_unary(
304
- request,
305
- target,
306
- '/flwr.proto.Fleet/PullTaskIns',
307
- flwr_dot_proto_dot_fleet__pb2.PullTaskInsRequest.SerializeToString,
308
- flwr_dot_proto_dot_fleet__pb2.PullTaskInsResponse.FromString,
309
- options,
310
- channel_credentials,
311
- insecure,
312
- call_credentials,
313
- compression,
314
- wait_for_ready,
315
- timeout,
316
- metadata,
317
- _registered_method=True)
318
-
319
258
  @staticmethod
320
259
  def PullMessages(request,
321
260
  target,
@@ -343,33 +282,6 @@ class Fleet(object):
343
282
  metadata,
344
283
  _registered_method=True)
345
284
 
346
- @staticmethod
347
- def PushTaskRes(request,
348
- target,
349
- options=(),
350
- channel_credentials=None,
351
- call_credentials=None,
352
- insecure=False,
353
- compression=None,
354
- wait_for_ready=None,
355
- timeout=None,
356
- metadata=None):
357
- return grpc.experimental.unary_unary(
358
- request,
359
- target,
360
- '/flwr.proto.Fleet/PushTaskRes',
361
- flwr_dot_proto_dot_fleet__pb2.PushTaskResRequest.SerializeToString,
362
- flwr_dot_proto_dot_fleet__pb2.PushTaskResResponse.FromString,
363
- options,
364
- channel_credentials,
365
- insecure,
366
- call_credentials,
367
- compression,
368
- wait_for_ready,
369
- timeout,
370
- metadata,
371
- _registered_method=True)
372
-
373
285
  @staticmethod
374
286
  def PushMessages(request,
375
287
  target,
@@ -22,31 +22,21 @@ class FleetStub:
22
22
  flwr.proto.fleet_pb2.PingRequest,
23
23
  flwr.proto.fleet_pb2.PingResponse]
24
24
 
25
- PullTaskIns: grpc.UnaryUnaryMultiCallable[
26
- flwr.proto.fleet_pb2.PullTaskInsRequest,
27
- flwr.proto.fleet_pb2.PullTaskInsResponse]
28
- """Retrieve one or more tasks, if possible
29
-
30
- HTTP API path: /api/v1/fleet/pull-task-ins
31
- """
32
-
33
25
  PullMessages: grpc.UnaryUnaryMultiCallable[
34
26
  flwr.proto.fleet_pb2.PullMessagesRequest,
35
27
  flwr.proto.fleet_pb2.PullMessagesResponse]
36
- """HTTP API path: /api/v1/fleet/pull-messages"""
28
+ """Retrieve one or more messages, if possible
37
29
 
38
- PushTaskRes: grpc.UnaryUnaryMultiCallable[
39
- flwr.proto.fleet_pb2.PushTaskResRequest,
40
- flwr.proto.fleet_pb2.PushTaskResResponse]
41
- """Complete one or more tasks, if possible
42
-
43
- HTTP API path: /api/v1/fleet/push-task-res
30
+ HTTP API path: /api/v1/fleet/pull-messages
44
31
  """
45
32
 
46
33
  PushMessages: grpc.UnaryUnaryMultiCallable[
47
34
  flwr.proto.fleet_pb2.PushMessagesRequest,
48
35
  flwr.proto.fleet_pb2.PushMessagesResponse]
49
- """HTTP API path: /api/v1/fleet/push-messages"""
36
+ """Complete one or more messages, if possible
37
+
38
+ HTTP API path: /api/v1/fleet/push-messages
39
+ """
50
40
 
51
41
  GetRun: grpc.UnaryUnaryMultiCallable[
52
42
  flwr.proto.run_pb2.GetRunRequest,
@@ -77,33 +67,14 @@ class FleetServicer(metaclass=abc.ABCMeta):
77
67
  context: grpc.ServicerContext,
78
68
  ) -> flwr.proto.fleet_pb2.PingResponse: ...
79
69
 
80
- @abc.abstractmethod
81
- def PullTaskIns(self,
82
- request: flwr.proto.fleet_pb2.PullTaskInsRequest,
83
- context: grpc.ServicerContext,
84
- ) -> flwr.proto.fleet_pb2.PullTaskInsResponse:
85
- """Retrieve one or more tasks, if possible
86
-
87
- HTTP API path: /api/v1/fleet/pull-task-ins
88
- """
89
- pass
90
-
91
70
  @abc.abstractmethod
92
71
  def PullMessages(self,
93
72
  request: flwr.proto.fleet_pb2.PullMessagesRequest,
94
73
  context: grpc.ServicerContext,
95
74
  ) -> flwr.proto.fleet_pb2.PullMessagesResponse:
96
- """HTTP API path: /api/v1/fleet/pull-messages"""
97
- pass
75
+ """Retrieve one or more messages, if possible
98
76
 
99
- @abc.abstractmethod
100
- def PushTaskRes(self,
101
- request: flwr.proto.fleet_pb2.PushTaskResRequest,
102
- context: grpc.ServicerContext,
103
- ) -> flwr.proto.fleet_pb2.PushTaskResResponse:
104
- """Complete one or more tasks, if possible
105
-
106
- HTTP API path: /api/v1/fleet/push-task-res
77
+ HTTP API path: /api/v1/fleet/pull-messages
107
78
  """
108
79
  pass
109
80
 
@@ -112,7 +83,10 @@ class FleetServicer(metaclass=abc.ABCMeta):
112
83
  request: flwr.proto.fleet_pb2.PushMessagesRequest,
113
84
  context: grpc.ServicerContext,
114
85
  ) -> flwr.proto.fleet_pb2.PushMessagesResponse:
115
- """HTTP API path: /api/v1/fleet/push-messages"""
86
+ """Complete one or more messages, if possible
87
+
88
+ HTTP API path: /api/v1/fleet/push-messages
89
+ """
116
90
  pass
117
91
 
118
92
  @abc.abstractmethod
flwr/server/app.py CHANGED
@@ -374,8 +374,9 @@ def run_superlink() -> None:
374
374
  bckg_threads.append(fleet_thread)
375
375
  elif args.fleet_api_type == TRANSPORT_TYPE_GRPC_RERE:
376
376
  node_public_keys = _try_load_public_keys_node_authentication(args)
377
- interceptors: Optional[Sequence[grpc.ServerInterceptor]] = None
377
+ auto_auth = True
378
378
  if node_public_keys is not None:
379
+ auto_auth = False
379
380
  state = state_factory.state()
380
381
  state.clear_supernode_auth_keys()
381
382
  state.store_node_public_keys(node_public_keys)
@@ -384,7 +385,10 @@ def run_superlink() -> None:
384
385
  "Node authentication enabled with %d known public keys",
385
386
  len(node_public_keys),
386
387
  )
387
- interceptors = [AuthenticateServerInterceptor(state_factory)]
388
+ else:
389
+ log(DEBUG, "Automatic node authentication enabled")
390
+
391
+ interceptors = [AuthenticateServerInterceptor(state_factory, auto_auth)]
388
392
 
389
393
  fleet_server = _run_fleet_api_grpc_rere(
390
394
  address=fleet_address,
@@ -28,7 +28,7 @@ from flwr.common.constant import (
28
28
  SERVERAPPIO_API_DEFAULT_CLIENT_ADDRESS,
29
29
  SUPERLINK_NODE_ID,
30
30
  )
31
- from flwr.common.grpc import create_channel
31
+ from flwr.common.grpc import create_channel, on_channel_state_change
32
32
  from flwr.common.logger import log
33
33
  from flwr.common.retry_invoker import _make_simple_grpc_retry_invoker, _wrap_stub
34
34
  from flwr.common.serde import message_from_proto, message_to_proto, run_from_proto
@@ -100,6 +100,7 @@ class GrpcDriver(Driver):
100
100
  insecure=(self._cert is None),
101
101
  root_certificates=self._cert,
102
102
  )
103
+ self._channel.subscribe(on_channel_state_change)
103
104
  self._grpc_stub = ServerAppIoStub(self._channel)
104
105
  _wrap_stub(self._grpc_stub, self._retry_invoker)
105
106
  log(DEBUG, "[flwr-serverapp] Connected to %s", self._addr)
@@ -72,7 +72,7 @@ def flwr_serverapp() -> None:
72
72
 
73
73
  args = _parse_args_run_flwr_serverapp().parse_args()
74
74
 
75
- log(INFO, "Starting Flower ServerApp")
75
+ log(INFO, "Start `flwr-serverapp` process")
76
76
 
77
77
  if not args.insecure:
78
78
  flwr_exit(
@@ -82,7 +82,8 @@ def flwr_serverapp() -> None:
82
82
 
83
83
  log(
84
84
  DEBUG,
85
- "Starting isolated `ServerApp` connected to SuperLink's ServerAppIo API at %s",
85
+ "`flwr-serverapp` will attempt to connect to SuperLink's "
86
+ "ServerAppIo API at %s",
86
87
  args.serverappio_api_address,
87
88
  )
88
89
  run_serverapp(
@@ -121,8 +122,8 @@ def run_serverapp( # pylint: disable=R0914, disable=W0212, disable=R0915
121
122
  try:
122
123
  # Pull ServerAppInputs from LinkState
123
124
  req = PullServerAppInputsRequest()
125
+ log(DEBUG, "[flwr-serverapp] Pull ServerAppInputs")
124
126
  res: PullServerAppInputsResponse = driver._stub.PullServerAppInputs(req)
125
- log(DEBUG, "flwr-serverapp: PullServerAppInputs")
126
127
  if not res.HasField("run"):
127
128
  sleep(3)
128
129
  run_status = None
@@ -144,7 +145,7 @@ def run_serverapp( # pylint: disable=R0914, disable=W0212, disable=R0915
144
145
  stub=driver._stub,
145
146
  )
146
147
 
147
- log(DEBUG, "ServerApp process starts FAB installation.")
148
+ log(DEBUG, "[flwr-serverapp] Start FAB installation.")
148
149
  install_from_fab(fab.content, flwr_dir=flwr_dir_, skip_prompt=True)
149
150
 
150
151
  fab_id, fab_version = get_fab_metadata(fab.content)
@@ -165,7 +166,7 @@ def run_serverapp( # pylint: disable=R0914, disable=W0212, disable=R0915
165
166
 
166
167
  log(
167
168
  DEBUG,
168
- "Flower will load ServerApp `%s` in %s",
169
+ "[flwr-serverapp] Will load ServerApp `%s` in %s",
169
170
  server_app_attr,
170
171
  app_path,
171
172
  )
@@ -191,6 +192,7 @@ def run_serverapp( # pylint: disable=R0914, disable=W0212, disable=R0915
191
192
 
192
193
  # Send resulting context
193
194
  context_proto = context_to_proto(updated_context)
195
+ log(DEBUG, "[flwr-serverapp] Will push ServerAppOutputs")
194
196
  out_req = PushServerAppOutputsRequest(
195
197
  run_id=run.run_id, context=context_proto
196
198
  )
@@ -18,6 +18,7 @@
18
18
  from logging import DEBUG, INFO
19
19
 
20
20
  import grpc
21
+ from google.protobuf.json_format import MessageToDict
21
22
 
22
23
  from flwr.common.logger import log
23
24
  from flwr.common.typing import InvalidRunStatusException
@@ -32,12 +33,8 @@ from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
32
33
  PingResponse,
33
34
  PullMessagesRequest,
34
35
  PullMessagesResponse,
35
- PullTaskInsRequest,
36
- PullTaskInsResponse,
37
36
  PushMessagesRequest,
38
37
  PushMessagesResponse,
39
- PushTaskResRequest,
40
- PushTaskResResponse,
41
38
  )
42
39
  from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611
43
40
  from flwr.server.superlink.ffs.ffs_factory import FfsFactory
@@ -60,13 +57,13 @@ class FleetServicer(fleet_pb2_grpc.FleetServicer):
60
57
  ) -> CreateNodeResponse:
61
58
  """."""
62
59
  log(INFO, "[Fleet.CreateNode] Request ping_interval=%s", request.ping_interval)
63
- log(DEBUG, "[Fleet.CreateNode] Request: %s", request)
60
+ log(DEBUG, "[Fleet.CreateNode] Request: %s", MessageToDict(request))
64
61
  response = message_handler.create_node(
65
62
  request=request,
66
63
  state=self.state_factory.state(),
67
64
  )
68
65
  log(INFO, "[Fleet.CreateNode] Created node_id=%s", response.node.node_id)
69
- log(DEBUG, "[Fleet.CreateNode] Response: %s", response)
66
+ log(DEBUG, "[Fleet.CreateNode] Response: %s", MessageToDict(response))
70
67
  return response
71
68
 
72
69
  def DeleteNode(
@@ -74,7 +71,7 @@ class FleetServicer(fleet_pb2_grpc.FleetServicer):
74
71
  ) -> DeleteNodeResponse:
75
72
  """."""
76
73
  log(INFO, "[Fleet.DeleteNode] Delete node_id=%s", request.node.node_id)
77
- log(DEBUG, "[Fleet.DeleteNode] Request: %s", request)
74
+ log(DEBUG, "[Fleet.DeleteNode] Request: %s", MessageToDict(request))
78
75
  return message_handler.delete_node(
79
76
  request=request,
80
77
  state=self.state_factory.state(),
@@ -82,57 +79,23 @@ class FleetServicer(fleet_pb2_grpc.FleetServicer):
82
79
 
83
80
  def Ping(self, request: PingRequest, context: grpc.ServicerContext) -> PingResponse:
84
81
  """."""
85
- log(DEBUG, "[Fleet.Ping] Request: %s", request)
82
+ log(DEBUG, "[Fleet.Ping] Request: %s", MessageToDict(request))
86
83
  return message_handler.ping(
87
84
  request=request,
88
85
  state=self.state_factory.state(),
89
86
  )
90
87
 
91
- def PullTaskIns(
92
- self, request: PullTaskInsRequest, context: grpc.ServicerContext
93
- ) -> PullTaskInsResponse:
94
- """Pull TaskIns."""
95
- log(INFO, "[Fleet.PullTaskIns] node_id=%s", request.node.node_id)
96
- log(DEBUG, "[Fleet.PullTaskIns] Request: %s", request)
97
- return message_handler.pull_task_ins(
98
- request=request,
99
- state=self.state_factory.state(),
100
- )
101
-
102
88
  def PullMessages(
103
89
  self, request: PullMessagesRequest, context: grpc.ServicerContext
104
90
  ) -> PullMessagesResponse:
105
91
  """Pull Messages."""
106
92
  log(INFO, "[Fleet.PullMessages] node_id=%s", request.node.node_id)
107
- log(DEBUG, "[Fleet.PullMessages] Request: %s", request)
93
+ log(DEBUG, "[Fleet.PullMessages] Request: %s", MessageToDict(request))
108
94
  return message_handler.pull_messages(
109
95
  request=request,
110
96
  state=self.state_factory.state(),
111
97
  )
112
98
 
113
- def PushTaskRes(
114
- self, request: PushTaskResRequest, context: grpc.ServicerContext
115
- ) -> PushTaskResResponse:
116
- """Push TaskRes."""
117
- if request.task_res_list:
118
- log(
119
- INFO,
120
- "[Fleet.PushTaskRes] Push results from node_id=%s",
121
- request.task_res_list[0].task.producer.node_id,
122
- )
123
- else:
124
- log(INFO, "[Fleet.PushTaskRes] No task results to push")
125
-
126
- try:
127
- res = message_handler.push_task_res(
128
- request=request,
129
- state=self.state_factory.state(),
130
- )
131
- except InvalidRunStatusException as e:
132
- abort_grpc_context(e.message, context)
133
-
134
- return res
135
-
136
99
  def PushMessages(
137
100
  self, request: PushMessagesRequest, context: grpc.ServicerContext
138
101
  ) -> PushMessagesResponse:
@@ -106,6 +106,8 @@ class AuthenticateServerInterceptor(grpc.ServerInterceptor): # type: ignore
106
106
  # Continue the RPC call
107
107
  expected_node_id = state.get_node_id(node_pk_bytes)
108
108
  if not handler_call_details.method.endswith("CreateNode"):
109
+ # All calls, except for `CreateNode`, must provide a public key that is
110
+ # already mapped to a `node_id` (in `LinkState`)
109
111
  if expected_node_id is None:
110
112
  return _unary_unary_rpc_terminator("Invalid node ID")
111
113
  # One of the method handlers in
@@ -39,12 +39,8 @@ from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
39
39
  PingResponse,
40
40
  PullMessagesRequest,
41
41
  PullMessagesResponse,
42
- PullTaskInsRequest,
43
- PullTaskInsResponse,
44
42
  PushMessagesRequest,
45
43
  PushMessagesResponse,
46
- PushTaskResRequest,
47
- PushTaskResResponse,
48
44
  Reconnect,
49
45
  )
50
46
  from flwr.proto.node_pb2 import Node # pylint: disable=E0611
@@ -53,7 +49,7 @@ from flwr.proto.run_pb2 import ( # pylint: disable=E0611
53
49
  GetRunResponse,
54
50
  Run,
55
51
  )
56
- from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611
52
+ from flwr.proto.task_pb2 import TaskIns # pylint: disable=E0611
57
53
  from flwr.server.superlink.ffs.ffs import Ffs
58
54
  from flwr.server.superlink.linkstate import LinkState
59
55
  from flwr.server.superlink.utils import check_abort
@@ -89,21 +85,6 @@ def ping(
89
85
  return PingResponse(success=res)
90
86
 
91
87
 
92
- def pull_task_ins(request: PullTaskInsRequest, state: LinkState) -> PullTaskInsResponse:
93
- """Pull TaskIns handler."""
94
- node = request.node # pylint: disable=no-member
95
- node_id: int = node.node_id
96
-
97
- # Retrieve TaskIns from State
98
- task_ins_list: list[TaskIns] = state.get_task_ins(node_id=node_id, limit=1)
99
-
100
- # Build response
101
- response = PullTaskInsResponse(
102
- task_ins_list=task_ins_list,
103
- )
104
- return response
105
-
106
-
107
88
  def pull_messages(
108
89
  request: PullMessagesRequest, state: LinkState
109
90
  ) -> PullMessagesResponse:
@@ -124,35 +105,6 @@ def pull_messages(
124
105
  return PullMessagesResponse(messages_list=msg_proto)
125
106
 
126
107
 
127
- def push_task_res(request: PushTaskResRequest, state: LinkState) -> PushTaskResResponse:
128
- """Push TaskRes handler."""
129
- # pylint: disable=no-member
130
- task_res: TaskRes = request.task_res_list[0]
131
- # pylint: enable=no-member
132
-
133
- # Abort if the run is not running
134
- abort_msg = check_abort(
135
- task_res.run_id,
136
- [Status.PENDING, Status.STARTING, Status.FINISHED],
137
- state,
138
- )
139
- if abort_msg:
140
- raise InvalidRunStatusException(abort_msg)
141
-
142
- # Set pushed_at (timestamp in seconds)
143
- task_res.task.pushed_at = time.time()
144
-
145
- # Store TaskRes in State
146
- task_id: Optional[UUID] = state.store_task_res(task_res=task_res)
147
-
148
- # Build response
149
- response = PushTaskResResponse(
150
- reconnect=Reconnect(reconnect=5),
151
- results={str(task_id): 0},
152
- )
153
- return response
154
-
155
-
156
108
  def push_messages(
157
109
  request: PushMessagesRequest, state: LinkState
158
110
  ) -> PushMessagesResponse:
@@ -33,12 +33,8 @@ from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
33
33
  PingResponse,
34
34
  PullMessagesRequest,
35
35
  PullMessagesResponse,
36
- PullTaskInsRequest,
37
- PullTaskInsResponse,
38
36
  PushMessagesRequest,
39
37
  PushMessagesResponse,
40
- PushTaskResRequest,
41
- PushTaskResResponse,
42
38
  )
43
39
  from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611
44
40
  from flwr.server.superlink.ffs.ffs import Ffs
@@ -110,16 +106,6 @@ async def delete_node(request: DeleteNodeRequest) -> DeleteNodeResponse:
110
106
  return message_handler.delete_node(request=request, state=state)
111
107
 
112
108
 
113
- @rest_request_response(PullTaskInsRequest)
114
- async def pull_task_ins(request: PullTaskInsRequest) -> PullTaskInsResponse:
115
- """Pull TaskIns."""
116
- # Get state from app
117
- state: LinkState = cast(LinkStateFactory, app.state.STATE_FACTORY).state()
118
-
119
- # Handle message
120
- return message_handler.pull_task_ins(request=request, state=state)
121
-
122
-
123
109
  @rest_request_response(PullMessagesRequest)
124
110
  async def pull_message(request: PullMessagesRequest) -> PullMessagesResponse:
125
111
  """Pull PullMessages."""
@@ -130,17 +116,6 @@ async def pull_message(request: PullMessagesRequest) -> PullMessagesResponse:
130
116
  return message_handler.pull_messages(request=request, state=state)
131
117
 
132
118
 
133
- # Check if token is needed here
134
- @rest_request_response(PushTaskResRequest)
135
- async def push_task_res(request: PushTaskResRequest) -> PushTaskResResponse:
136
- """Push TaskRes."""
137
- # Get state from app
138
- state: LinkState = cast(LinkStateFactory, app.state.STATE_FACTORY).state()
139
-
140
- # Handle message
141
- return message_handler.push_task_res(request=request, state=state)
142
-
143
-
144
119
  @rest_request_response(PushMessagesRequest)
145
120
  async def push_message(request: PushMessagesRequest) -> PushMessagesResponse:
146
121
  """Pull PushMessages."""
@@ -187,9 +162,7 @@ async def get_fab(request: GetFabRequest) -> GetFabResponse:
187
162
  routes = [
188
163
  Route("/api/v0/fleet/create-node", create_node, methods=["POST"]),
189
164
  Route("/api/v0/fleet/delete-node", delete_node, methods=["POST"]),
190
- Route("/api/v0/fleet/pull-task-ins", pull_task_ins, methods=["POST"]),
191
165
  Route("/api/v0/fleet/pull-messages", pull_message, methods=["POST"]),
192
- Route("/api/v0/fleet/push-task-res", push_task_res, methods=["POST"]),
193
166
  Route("/api/v0/fleet/push-messages", push_message, methods=["POST"]),
194
167
  Route("/api/v0/fleet/ping", ping, methods=["POST"]),
195
168
  Route("/api/v0/fleet/get-run", get_run, methods=["POST"]),
@@ -21,7 +21,7 @@ from typing import Optional, cast
21
21
  import grpc
22
22
 
23
23
  from flwr.common.constant import SIMULATIONIO_API_DEFAULT_CLIENT_ADDRESS
24
- from flwr.common.grpc import create_channel
24
+ from flwr.common.grpc import create_channel, on_channel_state_change
25
25
  from flwr.common.logger import log
26
26
  from flwr.common.retry_invoker import _make_simple_grpc_retry_invoker, _wrap_stub
27
27
  from flwr.proto.simulationio_pb2_grpc import SimulationIoStub # pylint: disable=E0611
@@ -73,6 +73,7 @@ class SimulationIoConnection:
73
73
  insecure=(self._cert is None),
74
74
  root_certificates=self._cert,
75
75
  )
76
+ self._channel.subscribe(on_channel_state_change)
76
77
  self._grpc_stub = SimulationIoStub(self._channel)
77
78
  _wrap_stub(self._grpc_stub, self._retry_invoker)
78
79
  log(DEBUG, "[SimulationIO] Connected to %s", self._addr)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flwr-nightly
3
- Version: 1.15.0.dev20250128
3
+ Version: 1.15.0.dev20250129
4
4
  Summary: Flower: A Friendly Federated AI Framework
5
5
  Home-page: https://flower.ai
6
6
  License: Apache-2.0
@@ -70,28 +70,28 @@ flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl,sha256=r0SZnvoR5a5mEWKJ
70
70
  flwr/cli/run/__init__.py,sha256=cCsKVB0SFzh2b3QmGba6BHckB85xlhjh3mh4pBpACtY,790
71
71
  flwr/cli/run/run.py,sha256=kEOYKin9qPJy8SODxcAvIWk-OskKPsxvcbvhDhf2VD4,8299
72
72
  flwr/cli/stop.py,sha256=DBCKg9AhB1WcJsyqfkHKR1_V_yT7D32zqa9QhmX9IAU,4926
73
- flwr/cli/utils.py,sha256=D6XmroF6iu-AT02xbp2vWK6nGGgAPBLPRlJw9Cmx0SA,11390
73
+ flwr/cli/utils.py,sha256=MODJi_r7NmGWSqNmqHjJS_4Zj_uhSnNg68YoSs1vAuw,11220
74
74
  flwr/client/__init__.py,sha256=DGDoO0AEAfz-0CUFmLdyUUweAS64-07AOnmDfWUefK4,1192
75
75
  flwr/client/app.py,sha256=tNnef5wGVfqMiiGiWzAuULyy1QpvCKukiRmNi_a2cQc,34261
76
76
  flwr/client/client.py,sha256=8o58nd9o6ZFcMIaVYPGcV4MSjBG4H0oFgWiv8ZEO3oA,7895
77
77
  flwr/client/client_app.py,sha256=cTig-N00YzTucbo9zNi6I21J8PlbflU_8J_f5CI-Wpw,10390
78
78
  flwr/client/clientapp/__init__.py,sha256=kZqChGnTChQ1WGSUkIlW2S5bc0d0mzDubCAmZUGRpEY,800
79
- flwr/client/clientapp/app.py,sha256=O2dghU6PBXeU6kK5Ihj2-8cKAzXIC1efyZv4aulqHU4,8952
79
+ flwr/client/clientapp/app.py,sha256=Us5Mw3wvGd_6P1zHOf3TNcRGBBulVZDo3LuZOs17WgM,8963
80
80
  flwr/client/clientapp/clientappio_servicer.py,sha256=5L6bjw_j3Mnx9kRFwYwxDNABKurBO5q1jZOWE_X11wQ,8522
81
81
  flwr/client/clientapp/utils.py,sha256=qqTw9PKPCldGnnbAbMhtS-Qs_GcqADE1eOtVPXeKYAo,4344
82
82
  flwr/client/dpfedavg_numpy_client.py,sha256=4KsEvzavDKyVDU1V0kMqffTwu1lNdUCYQN-i0DTYVN8,7404
83
83
  flwr/client/grpc_adapter_client/__init__.py,sha256=QyNWIbsq9DpyMk7oemiO1P3TBFfkfkctnJ1JoAkTl3s,742
84
84
  flwr/client/grpc_adapter_client/connection.py,sha256=nV-hPd5q5Eblg6PgUrGGYj74mbE1a0qjfN8G3wzJVAc,4006
85
85
  flwr/client/grpc_client/__init__.py,sha256=LsnbqXiJhgQcB0XzAlUQgPx011Uf7Y7yabIC1HxivJ8,735
86
- flwr/client/grpc_client/connection.py,sha256=Y6VDDDEHCPlGxSf-bEyBua_khnY_F1OoXD-8gpIcYhE,9171
86
+ flwr/client/grpc_client/connection.py,sha256=HK_y1xfoaypozo6UQJsYJ8mZWXkknf2qx7gjpzuxys8,9057
87
87
  flwr/client/grpc_rere_client/__init__.py,sha256=MK-oSoV3kwUEQnIwl0GN4OpiHR7eLOrMA8ikunET130,752
88
88
  flwr/client/grpc_rere_client/client_interceptor.py,sha256=8yX2jhwfX9r1PO76ZdME4tPefutnQqWPi7kELriBMUo,2451
89
- flwr/client/grpc_rere_client/connection.py,sha256=9XBcTn4myN_pgAGM6QFQ2Q35clSqxfgY8irrChQuF6I,11668
90
- flwr/client/grpc_rere_client/grpc_adapter.py,sha256=VrSqHosRcWv8xDLKEabuzyHpVnRhjAEJf_MUFQxhDh8,6155
89
+ flwr/client/grpc_rere_client/connection.py,sha256=CHC5ssg7SMIN78JsWFKHg2P_fT2G_Ng3rtR869hLmoQ,11777
90
+ flwr/client/grpc_rere_client/grpc_adapter.py,sha256=4EixBCeceM-nLu-eqB1jr0pXaGdkvoSbKmrY1ushQok,5601
91
91
  flwr/client/heartbeat.py,sha256=cx37mJBH8LyoIN4Lks85wtqT1mnU5GulQnr4pGCvAq0,2404
92
92
  flwr/client/message_handler/__init__.py,sha256=QxxQuBNpFPTHx3KiUNvQSlqMKlEnbRR1kFfc1KVje08,719
93
93
  flwr/client/message_handler/message_handler.py,sha256=s7FEfYJp5QB259Pj1L94_9AC24Kh5JyKC2U-E6eNkkY,6492
94
- flwr/client/message_handler/task_handler.py,sha256=ZDJBKmrn2grRMNl1rU1iGs7FiMHL5VmZiSp_6h9GHVU,1824
94
+ flwr/client/message_handler/task_handler.py,sha256=zr5H2jJNKBTSI4hNGpMxbBAKUP0wSdHCJPAYjQYCxDw,1310
95
95
  flwr/client/mod/__init__.py,sha256=37XeXZLFq_tzFVKVtC9JaigM2bSAU7BrGQvMPCE3Q28,1159
96
96
  flwr/client/mod/centraldp_mods.py,sha256=UGwNuqpmOWfLdfJITFgdi1TG-nLjuSb-cbEyoyfDgxQ,5415
97
97
  flwr/client/mod/comms_mods.py,sha256=s_H57ZXUPaWFifodCbRCOZW06IZRsilcOr9F-yWBtxg,2625
@@ -120,14 +120,14 @@ flwr/common/config.py,sha256=n6T5Vi6BUFul37GUpKp9Doqnz35phJqSud_G3ySWlIQ,13336
120
120
  flwr/common/constant.py,sha256=mw2H-rTFI5Lwv8EK2dlW5RDAynQWeSawcwup2p0vLN4,6419
121
121
  flwr/common/context.py,sha256=uJ-mnoC_8y_udEb3kAX-r8CPphNTWM72z1AlsvQEu54,2403
122
122
  flwr/common/date.py,sha256=NHHpESce5wYqEwoDXf09gp9U9l_5Bmlh2BsOcwS-kDM,1554
123
- flwr/common/differential_privacy.py,sha256=XwcJ3rWr8S8BZUocc76vLSJAXIf6OHnWkBV6-xlIRuw,6106
123
+ flwr/common/differential_privacy.py,sha256=YA01NqjddKNAEVmf7hXmOVxOjhekgzvJudk3mBGq-2k,6148
124
124
  flwr/common/differential_privacy_constants.py,sha256=c7b7tqgvT7yMK0XN9ndiTBs4mQf6d3qk6K7KBZGlV4Q,1074
125
125
  flwr/common/dp.py,sha256=vddkvyjV2FhRoN4VuU2LeAM1UBn7dQB8_W-Qdiveal8,1978
126
126
  flwr/common/exit/__init__.py,sha256=-ZOJYLaNnR729a7VzZiFsLiqngzKQh3xc27svYStZ_Q,826
127
127
  flwr/common/exit/exit.py,sha256=DmZFyksp-w1sFDQekq5Z-qfnr-ivCAv78aQkqj-TDps,3458
128
128
  flwr/common/exit/exit_code.py,sha256=PNEnCrZfOILjfDAFu5m-2YWEJBrk97xglq4zCUlqV7E,3470
129
129
  flwr/common/exit_handlers.py,sha256=Dke87CC6d6b6kqkC2mF0I4JsP4mHhlQTFxkS4sKKgyw,3308
130
- flwr/common/grpc.py,sha256=GCdiTCppW-clhzOo7OIJbsKIWKnJ9pqNTsAKhj7y4So,9646
130
+ flwr/common/grpc.py,sha256=K60AIvIqH0CvkkiqBfw5HoxQfbFOL2DrhKPjbZ8raIE,9786
131
131
  flwr/common/logger.py,sha256=xgS-oEN6U54vEYoWdX0U0ymqMfndhK0-ePiGtmjHdmU,12852
132
132
  flwr/common/message.py,sha256=Zv4ID2BLQsbff0F03DI_MeFoHbSqVZAdDD9NcKYv6Zo,13832
133
133
  flwr/common/object_ref.py,sha256=fIXf8aP5mG6Nuni7dvcKK5Di3zRfRWGs4ljvqIXplds,10115
@@ -171,10 +171,10 @@ flwr/proto/fab_pb2.py,sha256=Q2-yT---MrRdzxVddy_xxQUtBIkrPU-odQ3qYaOfBwc,1870
171
171
  flwr/proto/fab_pb2.pyi,sha256=AMXpiDK0fo3nZWjxsC2E4otSaVjyQbU7iiWKrsSZavs,2395
172
172
  flwr/proto/fab_pb2_grpc.py,sha256=VO-wNfkShf9z8sb8T4UUq2Pp2jKb8pjnexaSkWh2Xp4,895
173
173
  flwr/proto/fab_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
174
- flwr/proto/fleet_pb2.py,sha256=L2HLL669B2hlacC0HmHCFFZk2X3vNGarDqKQj4pNSSM,6842
175
- flwr/proto/fleet_pb2.pyi,sha256=XT8Y79QB9ZWljt30hGmytkxJbu6H_D7ltkYopJQFM4o,12004
176
- flwr/proto/fleet_pb2_grpc.py,sha256=hl2PqMcT-QH6kDoN_VBF9yvW8UKZlffrCMQigZDERso,17842
177
- flwr/proto/fleet_pb2_grpc.pyi,sha256=sZXIu_9zp2OImuCMgMFS5mpx8qFdsgJ9Lzy3S_OWn30,4166
174
+ flwr/proto/fleet_pb2.py,sha256=SMaSOshdZ65iFU5LpR2T0hl3_1KZ6OuFbTyP9wcBeg4,5070
175
+ flwr/proto/fleet_pb2.pyi,sha256=wmDweUv8CLErbPXXrvhUAbUH9JBR9z39y7hOSplXAD4,7895
176
+ flwr/proto/fleet_pb2_grpc.py,sha256=tCQRfdm1kz9w1RbqnfLhOkr59Mo5V0jNCmBRDpXdg_4,14264
177
+ flwr/proto/fleet_pb2_grpc.pyi,sha256=y9XDpCUW626CnNvAjwzeorEN2thVlJ7OF1LeUnUPIwo,3240
178
178
  flwr/proto/grpcadapter_pb2.py,sha256=sPB1FbcNIjw5plvQqhd_vynO0-59n9U7G882l6o1z6Y,2101
179
179
  flwr/proto/grpcadapter_pb2.pyi,sha256=AR77gDsF6f8zqSIQp3877DUd7S8lP95lFak5Ir_WPkw,1716
180
180
  flwr/proto/grpcadapter_pb2_grpc.py,sha256=BLQLCtfra5qGlwyN9VeWpmYKhfxe8POfhYKhrPnhYso,3636
@@ -217,7 +217,7 @@ flwr/proto/transport_pb2_grpc.py,sha256=Nvn7oxzm1g1fPiGCGhyKxILDZHYG0CcgjySTzxq-
217
217
  flwr/proto/transport_pb2_grpc.pyi,sha256=AGXf8RiIiW2J5IKMlm_3qT3AzcDa4F3P5IqUjve_esA,766
218
218
  flwr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
219
219
  flwr/server/__init__.py,sha256=cEg1oecBu4cKB69iJCqWEylC8b5XW47bl7rQiJsdTvM,1528
220
- flwr/server/app.py,sha256=ZHtoXbMzvTf82z96__WDv_ZaPqAYwVtCAZylwVXjOuE,30606
220
+ flwr/server/app.py,sha256=_WxQwMtaiihPcoZ27b4upnv1zAQN_NT9VMXARuYNFfU,30687
221
221
  flwr/server/client_manager.py,sha256=7Ese0tgrH-i-ms363feYZJKwB8gWnXSmg_hYF2Bju4U,6227
222
222
  flwr/server/client_proxy.py,sha256=4G-oTwhb45sfWLx2uZdcXD98IZwdTS6F88xe3akCdUg,2399
223
223
  flwr/server/compat/__init__.py,sha256=VxnJtJyOjNFQXMNi9hIuzNlZM5n0Hj1p3aq_Pm2udw4,892
@@ -228,7 +228,7 @@ flwr/server/compat/legacy_context.py,sha256=wBzBcfV6YO6IQGriM_FdJ5XZfiBBEEJdS_Od
228
228
  flwr/server/criterion.py,sha256=ypbAexbztzGUxNen9RCHF91QeqiEQix4t4Ih3E-42MM,1061
229
229
  flwr/server/driver/__init__.py,sha256=bikRv6CjTwSvYh7tf10gziU5o2YotOWhhftz2tr3KDc,886
230
230
  flwr/server/driver/driver.py,sha256=u_fMfqLYTroTafGCNwKPHI4lttRL-Z5CqeT3_FHSq-Q,5701
231
- flwr/server/driver/grpc_driver.py,sha256=iI7e-V-GYNtlY56DPtdPaS8XUzd9NG_YD3LPgl2bTMI,9782
231
+ flwr/server/driver/grpc_driver.py,sha256=3mSws0l83fWD4aq9-MmHFnIfyf4REoAXUkWfyJDHros,9864
232
232
  flwr/server/driver/inmemory_driver.py,sha256=b1U1PrB_Vpn--vav8SX-sn0THD9BTlV9UFIpuWTWLro,6665
233
233
  flwr/server/history.py,sha256=qSb5_pPTrwofpSYGsZWzMPkl_4uJ4mJFWesxXDrEvDU,5026
234
234
  flwr/server/run_serverapp.py,sha256=vIPhvJx0i5sEZO4IKM6ruCXmx4ncat76rh0B4KhdhhM,2446
@@ -236,7 +236,7 @@ flwr/server/server.py,sha256=1ZsFEptmAV-L2vP2etNC9Ed5CLSxpuKzUFkAPQ4l5Xc,17893
236
236
  flwr/server/server_app.py,sha256=RsgS6PRS5Z74cMUAHzsm8r3LWddwn00MjRs6rlacHt8,6297
237
237
  flwr/server/server_config.py,sha256=CZaHVAsMvGLjpWVcLPkiYxgJN4xfIyAiUrCI3fETKY4,1349
238
238
  flwr/server/serverapp/__init__.py,sha256=L0K-94UDdTyEZ8LDtYybGIIIv3HW6AhSVjXMUfYJQnQ,800
239
- flwr/server/serverapp/app.py,sha256=hRGtvx2bYxcrDh4poqdy-CNkzBtVcr2Hc5gOjgD3J4s,8554
239
+ flwr/server/serverapp/app.py,sha256=5nFRYYzC2vh0l1fKJofBfKwFam93In4b80wvH9eFfQ8,8651
240
240
  flwr/server/serverapp_components.py,sha256=-IV_CitOfrJclJj2jNdbN1Q65PyFmtKtrTIg1hc6WQw,2118
241
241
  flwr/server/strategy/__init__.py,sha256=tQer2SwjDnvgFFuJMZM-S01Z615N5XK6MaCvpm4BMU0,2836
242
242
  flwr/server/strategy/aggregate.py,sha256=PDvekufza13s9AsVmz9WASunaBs3yCtl8JVliFx9j6Q,13978
@@ -279,12 +279,12 @@ flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py,sha256=JkAH_nIZaqe_9kntrg26
279
279
  flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py,sha256=h3EhqgelegVC4EjOXH5birmAnMoCBJcP7jpHYCnHZPk,4887
280
280
  flwr/server/superlink/fleet/grpc_bidi/grpc_server.py,sha256=mxPxyEF0IW0vV41Bqk1zfKOdRDEvXPwzJyMiRMg7nTI,5173
281
281
  flwr/server/superlink/fleet/grpc_rere/__init__.py,sha256=j2hyC342am-_Hgp1g80Y3fGDzfTI6n8QOOn2PyWf4eg,758
282
- flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py,sha256=EVx3rHX8WjUXVX7Svki5ihsA1aIZkpOMLv0aQv9Rjjw,6656
283
- flwr/server/superlink/fleet/grpc_rere/server_interceptor.py,sha256=zf58FXJ4S-k4kUh-LWcz6O6AWRcxs_ZGNQtUDDM7FVw,6307
282
+ flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py,sha256=syWWZgsU3PHvIuvSoJxUTbEdkOtyV6psXAbRowNE_yY,5533
283
+ flwr/server/superlink/fleet/grpc_rere/server_interceptor.py,sha256=A41vZaK7QHXaZsKy9Uvqe_fqynOkbW8xYjTJBjbPP4w,6452
284
284
  flwr/server/superlink/fleet/message_handler/__init__.py,sha256=h8oLD7uo5lKICPy0rRdKRjTYe62u8PKkT_fA4xF5JPA,731
285
- flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=5QRqE0w8Kb-M2cEiPNIdKkPc17CEGHvNYjMpGOfgOlE,6886
285
+ flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=DM53K4yLOmzXikTe6i6KJ0v8IvlJKDifvFEV09GFKhI,5510
286
286
  flwr/server/superlink/fleet/rest_rere/__init__.py,sha256=5jbYbAn75sGv-gBwOPDySE0kz96F6dTYLeMrGqNi4lM,735
287
- flwr/server/superlink/fleet/rest_rere/rest_api.py,sha256=xj3knuVkhecT2KPz-0kQ8NlDMIsGcnDoCTGyNmLdIzM,7676
287
+ flwr/server/superlink/fleet/rest_rere/rest_api.py,sha256=L7sg9Uyp7l1bViYNWjnpaDvcG_j7FYKWC1XL-8bMpsg,6710
288
288
  flwr/server/superlink/fleet/vce/__init__.py,sha256=TZJsKTpYO_djv2EXx9Ji62I8TA0JiZF8jvRyJRZkAes,784
289
289
  flwr/server/superlink/fleet/vce/backend/__init__.py,sha256=cGgal5qpd0_MwEdIqjJbHHSIgGa6GSPoI5_byUwtG_k,1437
290
290
  flwr/server/superlink/fleet/vce/backend/backend.py,sha256=LBAQxnbfPAphVOVIvYMj0QIvVP5O-RQxKQlUGNUj974,2194
@@ -318,7 +318,7 @@ flwr/simulation/ray_transport/ray_actor.py,sha256=k11yoAPQzFGQU-KnCCP0ZrfPPdUPXX
318
318
  flwr/simulation/ray_transport/ray_client_proxy.py,sha256=2vjOKoom3B74C6XU-jC3N6DwYmsLdB-lmkHZ_Xrv96o,7367
319
319
  flwr/simulation/ray_transport/utils.py,sha256=wtbQhKQ4jGoiQDLJNQP17m1DSfL22ERhDBGuoeUFaAQ,2393
320
320
  flwr/simulation/run_simulation.py,sha256=KFpdL_RxE8NHZ68ZdghmFS6rccmWkO_iQ-kLLE1WUn8,20336
321
- flwr/simulation/simulationio_connection.py,sha256=8aAh6MKQkQPMSnWEqA5vua_QzZtoMxG-_-AB23RPhS4,3412
321
+ flwr/simulation/simulationio_connection.py,sha256=lcbEmdjb9RVEF2W5vSbf_J1zlTuv_ZAT_HLox1mqcfY,3494
322
322
  flwr/superexec/__init__.py,sha256=fcj366jh4RFby_vDwLroU4kepzqbnJgseZD_jUr_Mko,715
323
323
  flwr/superexec/app.py,sha256=Z6kYHWd62YL0Q4YKyCAbt_BcefNfbKH6V-jCC-1NkZM,1842
324
324
  flwr/superexec/deployment.py,sha256=wZ9G42gGS91knfplswh95MnQ83Fzu-rs6wcuNgDmmvY,6735
@@ -327,8 +327,8 @@ flwr/superexec/exec_servicer.py,sha256=X10ILT-AoGMrB3IgI2mBe9i-QcIVUAl9bucuqVOPY
327
327
  flwr/superexec/exec_user_auth_interceptor.py,sha256=K06OU-l4LnYhTDg071hGJuOaQWEJbZsYi5qxUmmtiG0,3704
328
328
  flwr/superexec/executor.py,sha256=_B55WW2TD1fBINpabSSDRenVHXYmvlfhv-k8hJKU4lQ,3115
329
329
  flwr/superexec/simulation.py,sha256=WQDon15oqpMopAZnwRZoTICYCfHqtkvFSqiTQ2hLD_g,4088
330
- flwr_nightly-1.15.0.dev20250128.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
331
- flwr_nightly-1.15.0.dev20250128.dist-info/METADATA,sha256=02RbG86fQY9wlFDKjH9WRDcNPECHXeDi0G3eyYgTnq0,15864
332
- flwr_nightly-1.15.0.dev20250128.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
333
- flwr_nightly-1.15.0.dev20250128.dist-info/entry_points.txt,sha256=JlNxX3qhaV18_2yj5a3kJW1ESxm31cal9iS_N_pf1Rk,538
334
- flwr_nightly-1.15.0.dev20250128.dist-info/RECORD,,
330
+ flwr_nightly-1.15.0.dev20250129.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
331
+ flwr_nightly-1.15.0.dev20250129.dist-info/METADATA,sha256=yfW_B81uq7vAhgMljZTUikcjy12hk04sFloMNJHY_z8,15864
332
+ flwr_nightly-1.15.0.dev20250129.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
333
+ flwr_nightly-1.15.0.dev20250129.dist-info/entry_points.txt,sha256=JlNxX3qhaV18_2yj5a3kJW1ESxm31cal9iS_N_pf1Rk,538
334
+ flwr_nightly-1.15.0.dev20250129.dist-info/RECORD,,