flwr-nightly 1.26.0.dev20260123__py3-none-any.whl → 1.26.0.dev20260126__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
@@ -17,6 +17,7 @@
17
17
 
18
18
  import hashlib
19
19
  import json
20
+ import re
20
21
  from collections.abc import Callable, Iterable, Iterator
21
22
  from contextlib import contextmanager
22
23
  from pathlib import Path
@@ -31,6 +32,8 @@ from flwr.cli.typing import SuperLinkConnection
31
32
  from flwr.common.constant import (
32
33
  ACCESS_TOKEN_KEY,
33
34
  AUTHN_TYPE_JSON_KEY,
35
+ FEDERATION_NOT_FOUND_MESSAGE,
36
+ FEDERATION_NOT_SPECIFIED_MESSAGE,
34
37
  NO_ACCOUNT_AUTH_MESSAGE,
35
38
  NO_ARTIFACT_PROVIDER_MESSAGE,
36
39
  NODE_NOT_FOUND_MESSAGE,
@@ -213,7 +216,7 @@ def load_cli_auth_plugin_from_connection(
213
216
 
214
217
  Raises
215
218
  ------
216
- typer.Exit
219
+ click.ClickException
217
220
  If the authentication type is unknown.
218
221
  """
219
222
  # Determine the auth type if not provided
@@ -227,22 +230,19 @@ def load_cli_auth_plugin_from_connection(
227
230
  auth_plugin_class = get_cli_plugin_class(authn_type)
228
231
  return auth_plugin_class(host)
229
232
  except ValueError:
230
- typer.echo(f"❌ Unknown account authentication type: {authn_type}")
231
- raise typer.Exit(code=1) from None
233
+ raise click.ClickException(
234
+ f"Unknown account authentication type: {authn_type}"
235
+ ) from None
232
236
 
233
237
 
234
238
  def require_superlink_address(connection: SuperLinkConnection) -> str:
235
239
  """Return the SuperLink address or exit if it is not configured."""
236
240
  if connection.address is None:
237
241
  cmd = click.get_current_context().command.name
238
- typer.secho(
239
- f"`flwr {cmd}` currently works with a SuperLink. Ensure that the "
240
- "correct SuperLink (Control API) address is provided in `pyproject.toml`.",
241
- fg=typer.colors.RED,
242
- bold=True,
243
- err=True,
242
+ raise click.ClickException(
243
+ f"`flwr {cmd}` currently works with a SuperLink. Ensure that the "
244
+ "correct SuperLink (Control API) address is provided in `pyproject.toml`."
244
245
  )
245
- raise typer.Exit(code=1)
246
246
  return connection.address
247
247
 
248
248
 
@@ -301,7 +301,7 @@ def flwr_cli_grpc_exc_handler() -> Iterator[None]: # pylint: disable=too-many-b
301
301
 
302
302
  Raises
303
303
  ------
304
- typer.Exit
304
+ click.ClickException
305
305
  On handled gRPC error statuses with appropriate exit code.
306
306
  grpc.RpcError
307
307
  For unhandled gRPC error statuses.
@@ -310,115 +310,71 @@ def flwr_cli_grpc_exc_handler() -> Iterator[None]: # pylint: disable=too-many-b
310
310
  yield
311
311
  except grpc.RpcError as e:
312
312
  if e.code() == grpc.StatusCode.UNAUTHENTICATED:
313
- typer.secho(
314
- "Authentication failed. Please run `flwr login`"
315
- " to authenticate and try again.",
316
- fg=typer.colors.RED,
317
- bold=True,
318
- err=True,
319
- )
320
- raise typer.Exit(code=1) from None
313
+ raise click.ClickException(
314
+ "Authentication failed. Please run `flwr login`"
315
+ " to authenticate and try again."
316
+ ) from None
321
317
  if e.code() == grpc.StatusCode.UNIMPLEMENTED:
322
318
  if e.details() == NO_ACCOUNT_AUTH_MESSAGE: # pylint: disable=E1101
323
- typer.secho(
324
- "Account authentication is not enabled on this SuperLink.",
325
- fg=typer.colors.RED,
326
- bold=True,
327
- err=True,
328
- )
329
- elif e.details() == NO_ARTIFACT_PROVIDER_MESSAGE: # pylint: disable=E1101
330
- typer.secho(
331
- "The SuperLink does not support `flwr pull` command.",
332
- fg=typer.colors.RED,
333
- bold=True,
334
- err=True,
335
- )
336
- else:
337
- typer.secho(
338
- "❌ The SuperLink cannot process this request. Please verify that "
339
- "you set the address to its Control API endpoint correctly in your "
340
- "`pyproject.toml`, and ensure that the Flower versions used by "
341
- "the CLI and SuperLink are compatible.",
342
- fg=typer.colors.RED,
343
- bold=True,
344
- err=True,
345
- )
346
- raise typer.Exit(code=1) from None
319
+ raise click.ClickException(
320
+ "Account authentication is not enabled on this SuperLink."
321
+ ) from None
322
+ if e.details() == NO_ARTIFACT_PROVIDER_MESSAGE: # pylint: disable=E1101
323
+ raise click.ClickException(
324
+ "The SuperLink does not support `flwr pull` command."
325
+ ) from None
326
+ raise click.ClickException(
327
+ "The SuperLink cannot process this request. Please verify that "
328
+ "you set the address to its Control API endpoint correctly in your "
329
+ "`pyproject.toml`, and ensure that the Flower versions used by "
330
+ "the CLI and SuperLink are compatible."
331
+ ) from None
347
332
  if e.code() == grpc.StatusCode.PERMISSION_DENIED:
348
- typer.secho(
349
- "❌ Permission denied.",
350
- fg=typer.colors.RED,
351
- bold=True,
352
- err=True,
353
- )
354
333
  # pylint: disable-next=E1101
355
- typer.secho(e.details(), fg=typer.colors.RED, bold=True)
356
- raise typer.Exit(code=1) from None
334
+ raise click.ClickException(f"Permission denied.\n{e.details()}") from None
357
335
  if e.code() == grpc.StatusCode.UNAVAILABLE:
358
- typer.secho(
336
+ raise click.ClickException(
359
337
  "Connection to the SuperLink is unavailable. Please check your network "
360
- "connection and 'address' in the federation configuration.",
361
- fg=typer.colors.RED,
362
- bold=True,
363
- err=True,
364
- )
365
- raise typer.Exit(code=1) from None
338
+ "connection and 'address' in the SuperLink connection configuration."
339
+ ) from None
366
340
  if e.code() == grpc.StatusCode.NOT_FOUND:
367
341
  if e.details() == RUN_ID_NOT_FOUND_MESSAGE: # pylint: disable=E1101
368
- typer.secho(
369
- "❌ Run ID not found.",
370
- fg=typer.colors.RED,
371
- bold=True,
372
- err=True,
373
- )
374
- raise typer.Exit(code=1) from None
342
+ raise click.ClickException("Run ID not found.") from None
375
343
  if e.details() == NODE_NOT_FOUND_MESSAGE: # pylint: disable=E1101
376
- typer.secho(
377
- "Node ID not found for this account.",
378
- fg=typer.colors.RED,
379
- bold=True,
380
- err=True,
381
- )
382
- raise typer.Exit(code=1) from None
344
+ raise click.ClickException(
345
+ "Node ID not found for this account."
346
+ ) from None
383
347
  if e.code() == grpc.StatusCode.FAILED_PRECONDITION:
384
348
  if e.details() == PULL_UNFINISHED_RUN_MESSAGE: # pylint: disable=E1101
385
- typer.secho(
386
- "Run is not finished yet. Artifacts can only be pulled after "
387
- "the run is finished. You can check the run status with `flwr ls`.",
388
- fg=typer.colors.RED,
389
- bold=True,
390
- err=True,
391
- )
392
- raise typer.Exit(code=1) from None
349
+ raise click.ClickException(
350
+ "Run is not finished yet. Artifacts can only be pulled after "
351
+ "the run is finished. You can check the run status with `flwr ls`."
352
+ ) from None
393
353
  if (
394
354
  e.details() == PUBLIC_KEY_ALREADY_IN_USE_MESSAGE
395
355
  ): # pylint: disable=E1101
396
- typer.secho(
397
- "The provided public key is already in use by another "
398
- "SuperNode.",
399
- fg=typer.colors.RED,
400
- bold=True,
401
- err=True,
402
- )
403
- raise typer.Exit(code=1) from None
356
+ raise click.ClickException(
357
+ "The provided public key is already in use by another SuperNode."
358
+ ) from None
404
359
  if e.details() == PUBLIC_KEY_NOT_VALID: # pylint: disable=E1101
405
- typer.secho(
406
- "The provided public key is invalid. Please provide a valid "
407
- "NIST EC public key.",
408
- fg=typer.colors.RED,
409
- bold=True,
410
- err=True,
411
- )
412
- raise typer.Exit(code=1) from None
360
+ raise click.ClickException(
361
+ "The provided public key is invalid. Please provide a valid "
362
+ "NIST EC public key."
363
+ ) from None
364
+ if e.details() == FEDERATION_NOT_SPECIFIED_MESSAGE: # pylint: disable=E1101
365
+ raise click.ClickException(
366
+ "No federation specified. "
367
+ "Please specify a federation and try again.",
368
+ ) from None
369
+ patten = re.compile(FEDERATION_NOT_FOUND_MESSAGE.replace("%s", "(.+)"))
370
+ if m := patten.match(e.details()): # pylint: disable=E1101
371
+ raise click.ClickException(
372
+ f"Federation '{m.group(1)}' does not exist. "
373
+ "Please verify the federation name and try again."
374
+ ) from None
413
375
 
414
376
  # Log details from grpc error directly
415
- typer.secho(
416
- f"❌ {e.details()}",
417
- fg=typer.colors.RED,
418
- bold=True,
419
- err=True,
420
- )
421
- raise typer.Exit(code=1) from None
377
+ raise click.ClickException(f"{e.details()}") from None
422
378
  raise
423
379
 
424
380
 
@@ -478,23 +434,17 @@ def validate_credentials_content(creds_path: Path) -> str:
478
434
  try:
479
435
  creds: dict[str, str] = json.loads(creds_path.read_text(encoding="utf-8"))
480
436
  except (OSError, json.JSONDecodeError) as err:
481
- typer.secho(
482
- f"Invalid credentials file at '{creds_path}': {err}",
483
- fg=typer.colors.RED,
484
- err=True,
485
- )
486
- raise typer.Exit(code=1) from err
437
+ raise click.ClickException(
438
+ f"Invalid credentials file at '{creds_path}': {err}"
439
+ ) from err
487
440
 
488
441
  required_keys = [AUTHN_TYPE_JSON_KEY, ACCESS_TOKEN_KEY, REFRESH_TOKEN_KEY]
489
442
  missing = [key for key in required_keys if key not in creds]
490
443
 
491
444
  if missing:
492
- typer.secho(
445
+ raise click.ClickException(
493
446
  f"Credentials file '{creds_path}' is missing "
494
- f"required key(s): {', '.join(missing)}. Please log in again.",
495
- fg=typer.colors.RED,
496
- err=True,
447
+ f"required key(s): {', '.join(missing)}. Please log in again."
497
448
  )
498
- raise typer.Exit(code=1)
499
449
 
500
450
  return creds[ACCESS_TOKEN_KEY]
flwr/common/config.py CHANGED
@@ -22,8 +22,8 @@ from io import BytesIO
22
22
  from pathlib import Path
23
23
  from typing import IO, Any, TypeVar, cast, get_args
24
24
 
25
+ import click
25
26
  import tomli
26
- import typer
27
27
 
28
28
  from flwr.app.user_config import UserConfig, UserConfigValue
29
29
  from flwr.common.constant import (
@@ -235,17 +235,13 @@ def parse_config_args(config: list[str] | None, flatten: bool = True) -> dict[st
235
235
  overrides.update(tomli.loads(toml_str))
236
236
  flat_overrides = flatten_dict(overrides) if flatten else overrides
237
237
  except tomli.TOMLDecodeError as err:
238
- typer.secho(
239
- "The provided configuration string is in an invalid format. "
238
+ raise click.ClickException(
239
+ "The provided configuration string is in an invalid format. "
240
240
  "The correct format should be, e.g., 'key1=123 key2=false "
241
241
  'key3="string"\', where values must be of type bool, int, '
242
242
  "string, or float. Ensure proper formatting with "
243
- "space-separated key-value pairs.",
244
- fg=typer.colors.RED,
245
- bold=True,
246
- err=True,
247
- )
248
- raise typer.Exit(code=1) from err
243
+ "space-separated key-value pairs."
244
+ ) from err
249
245
 
250
246
  return flat_overrides
251
247
 
flwr/common/constant.py CHANGED
@@ -180,6 +180,8 @@ SUPERNODE_NOT_CREATED_FROM_CLI_MESSAGE = "Invalid SuperNode credentials"
180
180
  PUBLIC_KEY_ALREADY_IN_USE_MESSAGE = "Public key already in use"
181
181
  PUBLIC_KEY_NOT_VALID = "The provided public key is not valid"
182
182
  NODE_NOT_FOUND_MESSAGE = "Node ID not found for account"
183
+ FEDERATION_NOT_SPECIFIED_MESSAGE = "No federation specified in the request"
184
+ FEDERATION_NOT_FOUND_MESSAGE = "Federation '%s' does not exist"
183
185
 
184
186
 
185
187
  class MessageTypeLegacy:
@@ -166,13 +166,13 @@ def pull_messages( # pylint: disable=too-many-locals
166
166
  response = PullMessagesResponse(messages_list=msg_proto, message_object_trees=trees)
167
167
 
168
168
  # Record incoming traffic size
169
- bytes_recv = len(request.SerializeToString())
169
+ bytes_recv = request.ByteSize()
170
170
 
171
171
  # Record traffic only if message was successfully processed
172
172
  # All messages in this request are assumed to belong to the same run
173
173
  if run_id_to_record is not None:
174
174
  # Record outgoing traffic size
175
- bytes_sent = len(response.SerializeToString())
175
+ bytes_sent = response.ByteSize()
176
176
  state.store_traffic(
177
177
  run_id_to_record, bytes_sent=bytes_sent, bytes_recv=bytes_recv
178
178
  )
@@ -191,7 +191,7 @@ def push_messages(
191
191
  run_id = msg.metadata.run_id
192
192
 
193
193
  # Record incoming traffic size
194
- bytes_recv = len(request.SerializeToString())
194
+ bytes_recv = request.ByteSize()
195
195
 
196
196
  # Abort if the run is not running
197
197
  abort_msg = check_abort(
@@ -218,7 +218,7 @@ def push_messages(
218
218
  )
219
219
 
220
220
  # Record outgoing traffic size
221
- bytes_sent = len(response.SerializeToString())
221
+ bytes_sent = response.ByteSize()
222
222
 
223
223
  # Record traffic only if message was successfully processed
224
224
  # Only one message is processed per request
@@ -165,20 +165,51 @@ class SqlLinkState(LinkState, SqlCoreState): # pylint: disable=R0904
165
165
 
166
166
  return message.metadata.message_id
167
167
 
168
+ # pylint: disable-next=too-many-locals
168
169
  def _check_stored_messages(self, message_ids: set[str]) -> None:
169
170
  """Check and delete the message if it's invalid."""
170
171
  if not message_ids:
171
172
  return
172
173
 
173
174
  with self.session():
175
+ # Batch fetch all messages in one query
176
+ placeholders = ",".join([f":mid_{i}" for i in range(len(message_ids))])
177
+ query = f"""
178
+ SELECT * FROM message_ins
179
+ WHERE message_id IN ({placeholders})
180
+ """
181
+ params = {f"mid_{i}": str(mid) for i, mid in enumerate(message_ids)}
182
+ message_rows = self.query(query, params)
183
+
184
+ if not message_rows:
185
+ return
186
+
187
+ # Build message lookup dict
188
+ message_dict: dict[str, dict[str, Any]] = {
189
+ row["message_id"]: row for row in message_rows
190
+ }
191
+
192
+ # Collect unique run_ids for batch federation lookup
193
+ run_ids = {row["run_id"] for row in message_rows}
194
+ placeholders = ",".join([f":rid_{i}" for i in range(len(run_ids))])
195
+ query = f"""
196
+ SELECT run_id, federation FROM run
197
+ WHERE run_id IN ({placeholders})
198
+ """
199
+ params = {f"rid_{i}": rid for i, rid in enumerate(run_ids)}
200
+ run_rows = self.query(query, params)
201
+
202
+ # Build run_id to federation mapping
203
+ run_id_to_federation: dict[int, str] = {
204
+ row["run_id"]: row["federation"] for row in run_rows
205
+ }
206
+
174
207
  invalid_msg_ids: set[str] = set()
175
208
  current_time = now().timestamp()
176
209
 
210
+ # Check each message for validity
177
211
  for msg_id in message_ids:
178
- # Check if message exists
179
- query = "SELECT * FROM message_ins WHERE message_id = :message_id"
180
- message_rows = self.query(query, {"message_id": msg_id})
181
- message_row = message_rows[0] if message_rows else None
212
+ message_row = message_dict.get(msg_id)
182
213
  if not message_row:
183
214
  continue
184
215
 
@@ -188,15 +219,12 @@ class SqlLinkState(LinkState, SqlCoreState): # pylint: disable=R0904
188
219
  invalid_msg_ids.add(msg_id)
189
220
  continue
190
221
 
191
- # Check if src_node_id and dst_node_id are in the federation
192
- # Get federation from run table
222
+ # Check if run exists and get federation
193
223
  run_id = message_row["run_id"]
194
- query = "SELECT federation FROM run WHERE run_id = :run_id"
195
- run_row = self.query(query, {"run_id": run_id})[0]
196
- if not run_row: # This should not happen
224
+ federation = run_id_to_federation.get(run_id)
225
+ if not federation:
197
226
  invalid_msg_ids.add(msg_id)
198
227
  continue
199
- federation = run_row["federation"]
200
228
 
201
229
  # Convert sint64 to uint64 for node IDs
202
230
  src_node_id = int64_to_uint64(message_row["src_node_id"])
@@ -29,6 +29,8 @@ from flwr.cli.config_utils import get_fab_metadata
29
29
  from flwr.common import Context, RecordDict, now
30
30
  from flwr.common.constant import (
31
31
  FAB_MAX_SIZE,
32
+ FEDERATION_NOT_FOUND_MESSAGE,
33
+ FEDERATION_NOT_SPECIFIED_MESSAGE,
32
34
  HEARTBEAT_DEFAULT_INTERVAL,
33
35
  LOG_STREAM_INTERVAL,
34
36
  NO_ACCOUNT_AUTH_MESSAGE,
@@ -80,7 +82,7 @@ from flwr.proto.control_pb2 import ( # pylint: disable=E0611
80
82
  from flwr.proto.federation_pb2 import Federation # pylint: disable=E0611
81
83
  from flwr.proto.node_pb2 import NodeInfo # pylint: disable=E0611
82
84
  from flwr.server.superlink.linkstate import LinkState, LinkStateFactory
83
- from flwr.supercore.constant import PLATFORM_API_URL
85
+ from flwr.supercore.constant import NOOP_FEDERATION, PLATFORM_API_URL
84
86
  from flwr.supercore.ffs import FfsFactory
85
87
  from flwr.supercore.object_store import ObjectStore, ObjectStoreFactory
86
88
  from flwr.supercore.primitives.asymmetric import bytes_to_public_key, uses_nist_ec_curve
@@ -149,10 +151,11 @@ class ControlServicer(control_pb2_grpc.ControlServicer):
149
151
  )
150
152
 
151
153
  # Check (1) federation exists and (2) the flwr_aid is a member
152
- federation = request.federation
153
-
154
+ federation = request.federation or NOOP_FEDERATION
154
155
  if not state.federation_manager.exists(federation):
155
- raise ValueError(f"Federation '{federation}' does not exist.")
156
+ if request.federation:
157
+ raise ValueError(FEDERATION_NOT_FOUND_MESSAGE % federation)
158
+ raise ValueError(FEDERATION_NOT_SPECIFIED_MESSAGE)
156
159
 
157
160
  if not state.federation_manager.has_member(flwr_aid, federation):
158
161
  raise ValueError(
@@ -170,7 +173,7 @@ class ControlServicer(control_pb2_grpc.ControlServicer):
170
173
  fab_hash = ffs.put(fab.content, fab.verifications)
171
174
 
172
175
  if fab_hash != fab.hash_str:
173
- raise RuntimeError(
176
+ raise ValueError(
174
177
  f"FAB ({fab.hash_str}) hash from request doesn't match contents"
175
178
  )
176
179
  fab_id, fab_version = get_fab_metadata(fab.content)
@@ -180,7 +183,7 @@ class ControlServicer(control_pb2_grpc.ControlServicer):
180
183
  fab_version,
181
184
  fab_hash,
182
185
  override_config,
183
- request.federation,
186
+ federation,
184
187
  federation_options,
185
188
  flwr_aid,
186
189
  )
@@ -206,13 +209,9 @@ class ControlServicer(control_pb2_grpc.ControlServicer):
206
209
  # Register the context at the LinkState
207
210
  state.set_serverapp_context(run_id=run_id, context=context)
208
211
 
209
- # pylint: disable-next=broad-except
210
- except Exception as e:
212
+ except ValueError as e:
211
213
  log(ERROR, "Could not start run: %s", str(e))
212
- context.abort(
213
- grpc.StatusCode.FAILED_PRECONDITION,
214
- str(e),
215
- )
214
+ context.abort(grpc.StatusCode.FAILED_PRECONDITION, str(e))
216
215
 
217
216
  log(INFO, "Created run %s", str(run_id))
218
217
  return StartRunResponse(run_id=run_id)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: flwr-nightly
3
- Version: 1.26.0.dev20260123
3
+ Version: 1.26.0.dev20260126
4
4
  Summary: Flower: A Friendly Federated AI Framework
5
5
  License: Apache-2.0
6
6
  Keywords: Artificial Intelligence,Federated AI,Federated Analytics,Federated Evaluation,Federated Learning,Flower,Machine Learning
@@ -8,41 +8,41 @@ flwr/app/user_config.py,sha256=7xsOVs-NYIvE710iE1qRFqxlA3LQNnmcoVXqcg_Ez2g,802
8
8
  flwr/cli/__init__.py,sha256=EfMGmHoobET6P2blBt_eOByXL8299MgFfB7XNdaPQ6I,720
9
9
  flwr/cli/app.py,sha256=62ELnHyEbgTp2GDzgsuk-mJ09_Gs8WHysbRceOnH-x8,3851
10
10
  flwr/cli/app_cmd/__init__.py,sha256=O_vTzS2u-n27fBYnDbjTMMKQQ2Bz80Y4JqGBHSAnK40,856
11
- flwr/cli/app_cmd/publish.py,sha256=fqCtlY0DGGAohKqlPDAiMQ6eFUAh90BmGRhCmOhibNY,8726
12
- flwr/cli/app_cmd/review.py,sha256=FNhWlHYu76Z6vXV6ShCTiDj8hs8CnULjU-svyBoNE9s,7642
11
+ flwr/cli/app_cmd/publish.py,sha256=DAFRu12EAO1NtzrGN9uYN_hW20gQZ2vCyf0HggzqaZ0,8006
12
+ flwr/cli/app_cmd/review.py,sha256=FPusshF36519z_KN36mU2fcvRtb5DCh0esinsts8WEs,7200
13
13
  flwr/cli/auth_plugin/__init__.py,sha256=qpebWV9uLpx72_J8yTVgT1DlH2Y9MK_RraDoTYEqv-w,1359
14
14
  flwr/cli/auth_plugin/auth_plugin.py,sha256=CKGsk0RvSmKPDfz5RsQIE_w1bWROBSOoVydbub4Z-I8,2813
15
15
  flwr/cli/auth_plugin/noop_auth_plugin.py,sha256=GKrZ97w7NoZGn2r6gzqtMvyeHXeIkNKCLTfT_NHaiwg,3209
16
- flwr/cli/auth_plugin/oidc_cli_plugin.py,sha256=JG5hrpm_xiRa5sgdqHzZmi1FkZVlDyRWPaQh6H-CfrI,6079
17
- flwr/cli/build.py,sha256=A9lzUNuGqLNId6PQppSWSlbMACl_LeW5Ispp9DuuX6k,10383
16
+ flwr/cli/auth_plugin/oidc_cli_plugin.py,sha256=1gN00FifSrhUA5s5uaE_GpQ3N7U8fQec4PXlSJr50RU,5975
17
+ flwr/cli/build.py,sha256=wjLrxWHGnwRFp7WxZFgm8J0cwcdQY9-QHxjFnEa2dII,10097
18
18
  flwr/cli/cli_account_auth_interceptor.py,sha256=mXgxThpZjU_2Xlae9xT8ewOw60GeE64comDd57asLIY,3680
19
19
  flwr/cli/config/__init__.py,sha256=46z6whA3hvKkl9APRs-UG7Ym3K9VOqKx_pYcgelRjtE,788
20
- flwr/cli/config/ls.py,sha256=ktRga1KWt4IDK5TQNT6ixfP66zcspkf-F2j3CkkpsGo,3665
20
+ flwr/cli/config/ls.py,sha256=llQiXC0kK7shT96Y3GD2uvVP3MjWWLpYTeExUH1rALo,3537
21
21
  flwr/cli/config_migration.py,sha256=UM3lZU34TOhGXkjBBChyGaE6r7uaVV2NpyP4TZhFPyY,10848
22
- flwr/cli/config_utils.py,sha256=FR24Q07mo97u8Yv2HlMc78GG1RgDo5CUr3865xetTBo,8174
22
+ flwr/cli/config_utils.py,sha256=t9GNUPnUH1nUNZQ3oGjx6Jd5VSO9SlnQXjz3-yro7Rs,7683
23
23
  flwr/cli/constant.py,sha256=Ihww6e-6V_Ocv7pRnIQeezdy72_RBL9dPYv87Yf4ppI,3612
24
24
  flwr/cli/example.py,sha256=SNTorkKPrx1rOryGREUyZu8TcOc1-vFv1zEddaysdY0,2216
25
25
  flwr/cli/federation/__init__.py,sha256=okxswL4fAjApI9gV_alU1lRkTUcQRbwlzvtUTLz61fE,793
26
- flwr/cli/federation/ls.py,sha256=QveAVH6nV5f5Ta8xHi_vlWa6d5cwsTIVeWmbZRep67U,10786
27
- flwr/cli/flower_config.py,sha256=RXYIkz3199iXu5eNodExM8KcXAQww4WhtaVOd6y4uZw,15782
28
- flwr/cli/install.py,sha256=yhgUWd_Psyc18DaoQHEQ5Ji45ZQ-3LclueM9uRxUEPw,10063
29
- flwr/cli/log.py,sha256=hZWCZX7gUsT29ZTe6BSe_U2Y2YHmFB8jdE9ds4MKtfQ,7364
26
+ flwr/cli/federation/ls.py,sha256=xjS3HHNwOXXsaNN-xrdWvClmV29R6yT8R2AA0SVzJas,10689
27
+ flwr/cli/flower_config.py,sha256=8XGB9-XjJrpR2xYOcFWjmvmqGZRS5_M-rPhuZQQASSs,15267
28
+ flwr/cli/install.py,sha256=gBYg1SczpvBh8MMrXJxi0q4DUdzXCdvapK3jC3CBlPk,9114
29
+ flwr/cli/log.py,sha256=BPA0dvGlXx5PrtURPua5fJyF7iVrb28K4fEY2Uth0EE,7317
30
30
  flwr/cli/login/__init__.py,sha256=B1SXKU3HCQhWfFDMJhlC7FOl8UsvH4mxysxeBnrfyUE,800
31
- flwr/cli/login/login.py,sha256=_8NwLF3BrTHnMsLc9GFeYYe8p5m1Jphai-0ynUcdCDk,4311
32
- flwr/cli/ls.py,sha256=5Gv4Myy6WwPYZUPdMWTtToWV7B0WuY1w6FAHsFVoofI,12890
31
+ flwr/cli/login/login.py,sha256=uUUrt6TNJjV_udwS3qJ5TXcRqqtI9nBySdXzwXItoVc,3999
32
+ flwr/cli/ls.py,sha256=ROSDyaQw5y9BjcBUtj57Vc3HgHTW_JbYX5NDIl-Yfhg,12793
33
33
  flwr/cli/new/__init__.py,sha256=QA1E2QtzPvFCjLTUHnFnJbufuFiGyT_0Y53Wpbvg1F0,790
34
- flwr/cli/new/new.py,sha256=VKrwkpd_voU4YwCVPIBPeFZjZiLW9OGpMPX_tpvPAE0,8315
35
- flwr/cli/pull.py,sha256=7XwyedyE7mi8CNut57JoJpSYnlcW9INooY87wnm26fE,3069
34
+ flwr/cli/new/new.py,sha256=15phs5dhEpo7ORs7uulGzHWtW9W5ZGn0EKFE_T5WXb8,7829
35
+ flwr/cli/pull.py,sha256=XzBvLrdYGrSCuky5OoCEU4V9UR9QlyZMT7Tj-W6wSw0,2946
36
36
  flwr/cli/run/__init__.py,sha256=RPyB7KbYTFl6YRiilCch6oezxrLQrl1kijV7BMGkLbA,790
37
- flwr/cli/run/run.py,sha256=J2vYLz2ypPlBXLtvwYHMEg3-cuLEkEFLKJTrd4p3hQI,9272
37
+ flwr/cli/run/run.py,sha256=6yrVljd1CqqALq-wqiv0TnZlveiN5ymiUI5iTjuvUJM,8954
38
38
  flwr/cli/run_utils.py,sha256=ZnlBOqFfRxVEPZKR_9zYrynNcohiCFY8QN6OFyOCrQs,5082
39
- flwr/cli/stop.py,sha256=PvhhSQNsV-OgNLMZjaR6Ev6f7b8EWpDwmGIa4WMVrEc,4978
39
+ flwr/cli/stop.py,sha256=w3frNt3TD5AukGmlGq4CbWo-3PC3B-YSLO6PjJeHjH4,4692
40
40
  flwr/cli/supernode/__init__.py,sha256=DBkjoPo2hS2Y-ghJxwLbrAbCQFBgD82_Itl2_892UBo,917
41
41
  flwr/cli/supernode/ls.py,sha256=x4ghJHpqcpDGuZx91ZehzSdmrUJ8ZuZvpY_UybnP63U,8224
42
- flwr/cli/supernode/register.py,sha256=b5tt6rPAA2t4cUBqnzcaCUJzy2uqKETSB43bGR5ltH0,5871
43
- flwr/cli/supernode/unregister.py,sha256=O72yiDuJaNrXx-5Pv6DKFxNYwxAHwEDBkAcqrlpwpC8,3949
42
+ flwr/cli/supernode/register.py,sha256=YPf28ZDvqPAQAt6c6OG73AJa9zZPONKgpxhnnb3NWQk,5498
43
+ flwr/cli/supernode/unregister.py,sha256=qWGg8G_KqF300ze4D1dYaSIRJZkl9zwM2ul8VLYjJMY,3719
44
44
  flwr/cli/typing.py,sha256=MaY3NAca2PgmNByogksDKSCoRQLQpXTgO8NO9nLP0yA,8008
45
- flwr/cli/utils.py,sha256=JfYmWbkalOzRHykHZvnD8TGn1R3Epk-F-dhEyXmZAYM,16394
45
+ flwr/cli/utils.py,sha256=jLhe-Voj0v8cK16MwRXW7qf34lEffOauRIukDyYX2II,15258
46
46
  flwr/client/__init__.py,sha256=xwkPJfdeWxIIfmiPE5vnmnY_JbTlErP0Qs9eBP6qRFg,1252
47
47
  flwr/client/client.py,sha256=3HAchxvknKG9jYbB7swNyDj-e5vUWDuMKoLvbT7jCVM,7895
48
48
  flwr/client/dpfedavg_numpy_client.py,sha256=ELDHyEJcTB-FlLhHC-JXy8HuB3ZFHfT0HL3g1VSWY5w,7451
@@ -76,8 +76,8 @@ flwr/clientapp/typing.py,sha256=Ld2rsD40SvIRD1Z_IdAGaYSbRtkgXZ5CPFIkJJ3Ao-A,862
76
76
  flwr/clientapp/utils.py,sha256=UEb3DFpAsAaG1ARU34D3L8njn4k1iPg-qpHl_Hyo8zA,4340
77
77
  flwr/common/__init__.py,sha256=7Rf7Ti78N7vUydpIZ2b-1im6ciWz0G5_w91N9YEPsLM,4195
78
78
  flwr/common/args.py,sha256=1ehgieKUQ9AtNcu2S5y501jB_mJ8mPA7GXiS3imGdgM,5799
79
- flwr/common/config.py,sha256=kXz0Lo4kqat45pnCyIVapHCHeNAZ42yeUc0SMLWKUik,13940
80
- flwr/common/constant.py,sha256=0_5p3Y0qOBfhecxG5-8di_2MpluXrQpqasTkQ59qXBQ,10013
79
+ flwr/common/config.py,sha256=Y9cmrKOZUge3Dxg9ddlkYRI_o1wLAkXwiMsDbtdQkFA,13807
80
+ flwr/common/constant.py,sha256=CJiJxxmrW2ixencNokEv9XXAbVOJdirBT3UUl4pwZyQ,10153
81
81
  flwr/common/context.py,sha256=pnFVcn-X0XKK1giw82I54meNodJJEoUwZ-NpkzT37zo,2421
82
82
  flwr/common/differential_privacy.py,sha256=HiW2qQa5mCQfE0oePapFp3q0uZzjoHKthp5UrkRFtY8,6143
83
83
  flwr/common/differential_privacy_constants.py,sha256=ruEjH4qF_S2bgxRI6brWCGWQPxFk-P7pviFguy9KvQ0,1074
@@ -260,7 +260,7 @@ flwr/server/superlink/fleet/grpc_rere/__init__.py,sha256=ahDJJ1e-lDxBpeBMgPk7YZt
260
260
  flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py,sha256=DtHuDP7fvgO-iamI48ACr0TQcD20eBYwMicHKIjhmXQ,12583
261
261
  flwr/server/superlink/fleet/grpc_rere/node_auth_server_interceptor.py,sha256=88e9yEapAbk8fOoqG4f4-jvXMLuJAZYQF9j6whczegc,5811
262
262
  flwr/server/superlink/fleet/message_handler/__init__.py,sha256=fHsRV0KvJ8HtgSA4_YBsEzuhJLjO8p6xx4aCY2oE1p4,731
263
- flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=9K88lwHADwq7o9XqzG3PPVzVz3cTUTBrQC8R6IVN1Rc,12165
263
+ flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=FO-CuOKfOwomjefmZsn_NGUM4m0ptPGwMOtfQTYfro0,12109
264
264
  flwr/server/superlink/fleet/rest_rere/__init__.py,sha256=Lzc93nA7tDqoy-zRUaPG316oqFiZX1HUCL5ELaXY_xw,735
265
265
  flwr/server/superlink/fleet/rest_rere/rest_api.py,sha256=cDWDQBf79F9tZ1mXOErc-nsnY4zFP9Tcv7Fs-bQIdiU,9616
266
266
  flwr/server/superlink/fleet/vce/__init__.py,sha256=XOKbAWOzlCqEOQ3M2cBYkH7HKA7PxlbCJMunt-ty-DY,784
@@ -272,7 +272,7 @@ flwr/server/superlink/linkstate/__init__.py,sha256=KSUCjOfJlW1g6GAjlqK3mTviqLvJL
272
272
  flwr/server/superlink/linkstate/in_memory_linkstate.py,sha256=1-aaSwad77SeYND3HEF2041KNG5ZA-8i1RcheYZMNq8,31689
273
273
  flwr/server/superlink/linkstate/linkstate.py,sha256=Zz2vBI0QFFnptCUIeNjqQCbpCvMMzfsZluprEMkkHio,16809
274
274
  flwr/server/superlink/linkstate/linkstate_factory.py,sha256=BTzPIqrWa797YKdOEHt0iu4ujxRcK4FNvUgjsOYQfMs,2859
275
- flwr/server/superlink/linkstate/sql_linkstate.py,sha256=EJHS1SC5acaxRQb1Nmpjen3elDK6L93s8pDUXNAE_Wk,47782
275
+ flwr/server/superlink/linkstate/sql_linkstate.py,sha256=ziZvpEQBVV9GSxjHiS0fAyaY1G7x4y6XKlNLH-c_4TQ,48727
276
276
  flwr/server/superlink/linkstate/utils.py,sha256=IA1mKKhGVBPoD61VXKFa8dZ_prnfuyWIuKAeeHPLmuE,16000
277
277
  flwr/server/superlink/serverappio/__init__.py,sha256=Fy4zJuoccZe5mZSEIpOmQvU6YeXFBa1M4eZuXXmJcn8,717
278
278
  flwr/server/superlink/serverappio/serverappio_grpc.py,sha256=2NFPynJMpYpT9C98Fr4n0QrTTjWBWbeUzlHcc6pg2kY,2279
@@ -387,7 +387,7 @@ flwr/superlink/servicer/control/control_account_auth_interceptor.py,sha256=AJs7G
387
387
  flwr/superlink/servicer/control/control_event_log_interceptor.py,sha256=r9LjF5VkrE1sZIcml-sO2uOPAwpvr6dj4tFchqoDcR4,5965
388
388
  flwr/superlink/servicer/control/control_grpc.py,sha256=AD7q2eo7RvXEhntcfVLgoKAR7AWfD_Z56Qw51wGLanY,4218
389
389
  flwr/superlink/servicer/control/control_license_interceptor.py,sha256=8d28soJ0mLLhpSGCpuY2YzgbX0vVO7Sqe2DcApEgILc,3336
390
- flwr/superlink/servicer/control/control_servicer.py,sha256=-fMk8HOmYIEtJL8Qmx3PkIZvfcuR9DM7MPFZeaTmMVk,25415
390
+ flwr/superlink/servicer/control/control_servicer.py,sha256=JUrnM2SrQeKM65_thKya_40_VoSdC1ml8zmxNhoXWb4,25529
391
391
  flwr/supernode/__init__.py,sha256=KgeCaVvXWrU3rptNR1y0oBp4YtXbAcrnCcJAiOoWkI4,707
392
392
  flwr/supernode/cli/__init__.py,sha256=JuEMr0-s9zv-PEWKuLB9tj1ocNfroSyNJ-oyv7ati9A,887
393
393
  flwr/supernode/cli/flower_supernode.py,sha256=1HdhlGaVo51_7w3AL1hE5zfIVJMow0Ngi_F3Js01djs,10815
@@ -402,7 +402,7 @@ flwr/supernode/servicer/__init__.py,sha256=lucTzre5WPK7G1YLCfaqg3rbFWdNSb7ZTt-ca
402
402
  flwr/supernode/servicer/clientappio/__init__.py,sha256=7Oy62Y_oijqF7Dxi6tpcUQyOpLc_QpIRZ83NvwmB0Yg,813
403
403
  flwr/supernode/servicer/clientappio/clientappio_servicer.py,sha256=rRL4CQ0L78jF_p0ct4-JMGREt6wWRy__wy4czF4f54Y,11639
404
404
  flwr/supernode/start_client_internal.py,sha256=BYk69UBQ2gQJaDQxXhccUgfOWrb7ShAstrbcMOCZIIs,26173
405
- flwr_nightly-1.26.0.dev20260123.dist-info/METADATA,sha256=6qgGCPCTOXXGCDUea3DHh770_NI9PSfIsF_sVY_ET-4,14398
406
- flwr_nightly-1.26.0.dev20260123.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
407
- flwr_nightly-1.26.0.dev20260123.dist-info/entry_points.txt,sha256=hxHD2ixb_vJFDOlZV-zB4Ao32_BQlL34ftsDh1GXv14,420
408
- flwr_nightly-1.26.0.dev20260123.dist-info/RECORD,,
405
+ flwr_nightly-1.26.0.dev20260126.dist-info/METADATA,sha256=tcxTPuQjyJ_6Uyt2AjjiDY18bTLl4a5awalqhBFiJkM,14398
406
+ flwr_nightly-1.26.0.dev20260126.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
407
+ flwr_nightly-1.26.0.dev20260126.dist-info/entry_points.txt,sha256=hxHD2ixb_vJFDOlZV-zB4Ao32_BQlL34ftsDh1GXv14,420
408
+ flwr_nightly-1.26.0.dev20260126.dist-info/RECORD,,