flwr-nightly 1.15.0.dev20250130__py3-none-any.whl → 1.15.2.dev20250214__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.
Files changed (36) hide show
  1. flwr/cli/auth_plugin/oidc_cli_plugin.py +2 -2
  2. flwr/cli/ls.py +3 -2
  3. flwr/cli/new/templates/app/README.baseline.md.tpl +4 -4
  4. flwr/cli/new/templates/app/README.md.tpl +1 -1
  5. flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +1 -1
  6. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +1 -1
  7. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +1 -1
  8. flwr/cli/new/templates/app/pyproject.jax.toml.tpl +1 -1
  9. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +1 -1
  10. flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +1 -1
  11. flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +1 -1
  12. flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +1 -1
  13. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +1 -1
  14. flwr/cli/stop.py +3 -2
  15. flwr/cli/utils.py +2 -2
  16. flwr/client/supernode/app.py +4 -28
  17. flwr/common/args.py +25 -47
  18. flwr/common/config.py +15 -2
  19. flwr/common/constant.py +9 -7
  20. flwr/common/exit_handlers.py +17 -29
  21. flwr/common/object_ref.py +0 -14
  22. flwr/proto/task_pb2.py +6 -6
  23. flwr/proto/task_pb2.pyi +1 -4
  24. flwr/server/app.py +5 -9
  25. flwr/server/driver/inmemory_driver.py +0 -1
  26. flwr/server/superlink/driver/serverappio_servicer.py +1 -5
  27. flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +17 -4
  28. flwr/server/superlink/fleet/message_handler/message_handler.py +0 -4
  29. flwr/server/superlink/fleet/vce/vce_api.py +0 -1
  30. flwr/server/superlink/linkstate/sqlite_linkstate.py +0 -6
  31. flwr/server/utils/validator.py +0 -3
  32. {flwr_nightly-1.15.0.dev20250130.dist-info → flwr_nightly-1.15.2.dev20250214.dist-info}/METADATA +2 -2
  33. {flwr_nightly-1.15.0.dev20250130.dist-info → flwr_nightly-1.15.2.dev20250214.dist-info}/RECORD +36 -36
  34. {flwr_nightly-1.15.0.dev20250130.dist-info → flwr_nightly-1.15.2.dev20250214.dist-info}/LICENSE +0 -0
  35. {flwr_nightly-1.15.0.dev20250130.dist-info → flwr_nightly-1.15.2.dev20250214.dist-info}/WHEEL +0 -0
  36. {flwr_nightly-1.15.0.dev20250130.dist-info → flwr_nightly-1.15.2.dev20250214.dist-info}/entry_points.txt +0 -0
@@ -26,7 +26,7 @@ import typer
26
26
  from flwr.common.auth_plugin import CliAuthPlugin
27
27
  from flwr.common.constant import (
28
28
  ACCESS_TOKEN_KEY,
29
- AUTH_TYPE_KEY,
29
+ AUTH_TYPE_JSON_KEY,
30
30
  REFRESH_TOKEN_KEY,
31
31
  AuthType,
32
32
  )
@@ -97,7 +97,7 @@ class OidcCliPlugin(CliAuthPlugin):
97
97
  self.access_token = credentials.access_token
98
98
  self.refresh_token = credentials.refresh_token
99
99
  json_dict = {
100
- AUTH_TYPE_KEY: AuthType.OIDC,
100
+ AUTH_TYPE_JSON_KEY: AuthType.OIDC,
101
101
  ACCESS_TOKEN_KEY: credentials.access_token,
102
102
  REFRESH_TOKEN_KEY: credentials.refresh_token,
103
103
  }
flwr/cli/ls.py CHANGED
@@ -117,7 +117,7 @@ def ls( # pylint: disable=too-many-locals, too-many-branches, R0913, R0917
117
117
  federation, config, federation_config_overrides
118
118
  )
119
119
  exit_if_no_address(federation_config, "ls")
120
-
120
+ channel = None
121
121
  try:
122
122
  if runs and run_id is not None:
123
123
  raise ValueError(
@@ -148,7 +148,8 @@ def ls( # pylint: disable=too-many-locals, too-many-branches, R0913, R0917
148
148
  )
149
149
  raise typer.Exit(code=1) from err
150
150
  finally:
151
- channel.close()
151
+ if channel:
152
+ channel.close()
152
153
  except (typer.Exit, Exception) as err: # pylint: disable=broad-except
153
154
  if suppress_output:
154
155
  restore_output()
@@ -13,7 +13,7 @@ dataset: [dataset1, dataset2] # TODO: list of datasets you include in your basel
13
13
 
14
14
  > [!IMPORTANT]
15
15
  > To help having all baselines similarly formatted and structured, we have included two scripts in `baselines/dev` that when run will format your code and run some tests checking if it's formatted.
16
- > These checks use standard packages such as `isort`, `black`, `pylint` and others. You as a baseline creator will need to install additional pacakges. These are already specified in the `pyproject.toml` of
16
+ > These checks use standard packages such as `isort`, `black`, `pylint` and others. You as a baseline creator will need to install additional packages. These are already specified in the `pyproject.toml` of
17
17
  > your baseline. Follow these steps:
18
18
 
19
19
  ```bash
@@ -66,9 +66,9 @@ cd .. # so you are in the `flower/baselines` directory
66
66
 
67
67
  ## About this baseline
68
68
 
69
- **What’s implemented:** :warning: *_Concisely describe what experiment(s) (e.g. Figure 1, Table 2, etc) in the publication can be replicated by running the code. Please only use a few sentences. ”_*
69
+ **What’s implemented:** :warning: *_Concisely describe what experiment(s) (e.g. Figure 1, Table 2, etc.) in the publication can be replicated by running the code. Please only use a few sentences. ”_*
70
70
 
71
- **Datasets:** :warning: *_List the datasets you used (if you used a medium to large dataset, >10GB please also include the sizes of the dataset). We highly recommend using [FlowerDatasets](https://flower.ai/docs/datasets/index.html) to download and partition your dataset. If you have other ways to download the data, you can also use `FlowerDatasets` to partiion it._*
71
+ **Datasets:** :warning: *_List the datasets you used (if you used a medium to large dataset, >10GB please also include the sizes of the dataset). We highly recommend using [FlowerDatasets](https://flower.ai/docs/datasets/index.html) to download and partition your dataset. If you have other ways to download the data, you can also use `FlowerDatasets` to partition it._*
72
72
 
73
73
  **Hardware Setup:** :warning: *_Give some details about the hardware (e.g. a server with 8x V100 32GB and 256GB of RAM) you used to run the experiments for this baseline. Indicate how long it took to run the experiments. Someone out there might not have access to the same resources you have so, could you list the absolute minimum hardware needed to run the experiment in a reasonable amount of time ? (e.g. minimum is 1x 16GB GPU otherwise a client model can’t be trained with a sufficiently large batch size). Could you test this works too?_*
74
74
 
@@ -122,6 +122,6 @@ flwr run . --run-config learning-rate=0.1,coefficient=0.123
122
122
  flwr run . --run-config <my-big-experiment-config>.toml
123
123
  ```
124
124
 
125
- :warning: _It is preferable to show a single commmand (or multilple commands if they belong to the same experiment) and then a table/plot with the expected results, instead of showing all the commands first and then all the results/plots._
125
+ :warning: _It is preferable to show a single command (or multiple commands if they belong to the same experiment) and then a table/plot with the expected results, instead of showing all the commands first and then all the results/plots._
126
126
  :warning: _If you present plots or other figures, please include either a Jupyter notebook showing how to create them or include a utility function that can be called after the experiments finish running._
127
127
  :warning: If you include plots or figures, save them in `.png` format and place them in a new directory named `_static` at the same level as your `README.md`.
@@ -18,7 +18,7 @@ Refer to the [How to Run Simulations](https://flower.ai/docs/framework/how-to-ru
18
18
 
19
19
  ## Run with the Deployment Engine
20
20
 
21
- Follow this [how-to guide](https://flower.ai/docs/framework/how-to-run-flower-with-deployment-engine.html) to run the same app in this example but with Flower's Deployment Engine. After that, you might be intersted in setting up [secure TLS-enabled communications](https://flower.ai/docs/framework/how-to-enable-tls-connections.html) and [SuperNode authentication](https://flower.ai/docs/framework/how-to-authenticate-supernodes.html) in your federation.
21
+ Follow this [how-to guide](https://flower.ai/docs/framework/how-to-run-flower-with-deployment-engine.html) to run the same app in this example but with Flower's Deployment Engine. After that, you might be interested in setting up [secure TLS-enabled communications](https://flower.ai/docs/framework/how-to-enable-tls-connections.html) and [SuperNode authentication](https://flower.ai/docs/framework/how-to-authenticate-supernodes.html) in your federation.
22
22
 
23
23
  You can run Flower on Docker too! Check out the [Flower with Docker](https://flower.ai/docs/framework/docker/index.html) documentation.
24
24
 
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.0",
11
+ "flwr[simulation]>=1.15.2",
12
12
  "flwr-datasets[vision]>=0.5.0",
13
13
  "torch==2.5.1",
14
14
  "torchvision==0.20.1",
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.0",
11
+ "flwr[simulation]>=1.15.2",
12
12
  "flwr-datasets>=0.5.0",
13
13
  "torch==2.3.1",
14
14
  "trl==0.8.1",
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.0",
11
+ "flwr[simulation]>=1.15.2",
12
12
  "flwr-datasets>=0.5.0",
13
13
  "torch==2.5.1",
14
14
  "transformers>=4.30.0,<5.0",
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.0",
11
+ "flwr[simulation]>=1.15.2",
12
12
  "jax==0.4.30",
13
13
  "jaxlib==0.4.30",
14
14
  "scikit-learn==1.6.1",
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.0",
11
+ "flwr[simulation]>=1.15.2",
12
12
  "flwr-datasets[vision]>=0.5.0",
13
13
  "mlx==0.21.1",
14
14
  ]
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.0",
11
+ "flwr[simulation]>=1.15.2",
12
12
  "numpy>=2.0.2",
13
13
  ]
14
14
 
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.0",
11
+ "flwr[simulation]>=1.15.2",
12
12
  "flwr-datasets[vision]>=0.5.0",
13
13
  "torch==2.5.1",
14
14
  "torchvision==0.20.1",
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.0",
11
+ "flwr[simulation]>=1.15.2",
12
12
  "flwr-datasets[vision]>=0.5.0",
13
13
  "scikit-learn>=1.6.1",
14
14
  ]
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.0",
11
+ "flwr[simulation]>=1.15.2",
12
12
  "flwr-datasets[vision]>=0.5.0",
13
13
  "tensorflow>=2.11.1,<2.18.0",
14
14
  ]
flwr/cli/stop.py CHANGED
@@ -84,7 +84,7 @@ def stop( # pylint: disable=R0914
84
84
  federation, config, federation_config_overrides
85
85
  )
86
86
  exit_if_no_address(federation_config, "stop")
87
-
87
+ channel = None
88
88
  try:
89
89
  auth_plugin = try_obtain_cli_auth_plugin(app, federation, federation_config)
90
90
  channel = init_channel(app, federation_config, auth_plugin)
@@ -101,7 +101,8 @@ def stop( # pylint: disable=R0914
101
101
  )
102
102
  raise typer.Exit(code=1) from err
103
103
  finally:
104
- channel.close()
104
+ if channel:
105
+ channel.close()
105
106
  except (typer.Exit, Exception) as err: # pylint: disable=broad-except
106
107
  if suppress_output:
107
108
  restore_output()
flwr/cli/utils.py CHANGED
@@ -28,7 +28,7 @@ import typer
28
28
 
29
29
  from flwr.cli.cli_user_auth_interceptor import CliUserAuthInterceptor
30
30
  from flwr.common.auth_plugin import CliAuthPlugin
31
- from flwr.common.constant import AUTH_TYPE_KEY, CREDENTIALS_DIR, FLWR_DIR
31
+ from flwr.common.constant import AUTH_TYPE_JSON_KEY, CREDENTIALS_DIR, FLWR_DIR
32
32
  from flwr.common.grpc import (
33
33
  GRPC_MAX_MESSAGE_LENGTH,
34
34
  create_channel,
@@ -239,7 +239,7 @@ def try_obtain_cli_auth_plugin(
239
239
  try:
240
240
  with config_path.open("r", encoding="utf-8") as file:
241
241
  json_file = json.load(file)
242
- auth_type = json_file[AUTH_TYPE_KEY]
242
+ auth_type = json_file[AUTH_TYPE_JSON_KEY]
243
243
  except (FileNotFoundError, KeyError):
244
244
  typer.secho(
245
245
  "❌ Missing or invalid credentials for user authentication. "
@@ -41,7 +41,7 @@ from flwr.common.constant import (
41
41
  )
42
42
  from flwr.common.exit import ExitCode, flwr_exit
43
43
  from flwr.common.exit_handlers import register_exit_handlers
44
- from flwr.common.logger import log, warn_deprecated_feature
44
+ from flwr.common.logger import log
45
45
 
46
46
  from ..app import start_client_internal
47
47
  from ..clientapp.utils import get_load_client_app_fn
@@ -50,7 +50,6 @@ from ..clientapp.utils import get_load_client_app_fn
50
50
  def run_supernode() -> None:
51
51
  """Run Flower SuperNode."""
52
52
  args = _parse_args_run_supernode().parse_args()
53
- _warn_deprecated_server_arg(args)
54
53
 
55
54
  log(INFO, "Starting Flower SuperNode")
56
55
 
@@ -109,26 +108,6 @@ def run_client_app() -> None:
109
108
  register_exit_handlers(event_type=EventType.RUN_CLIENT_APP_LEAVE)
110
109
 
111
110
 
112
- def _warn_deprecated_server_arg(args: argparse.Namespace) -> None:
113
- """Warn about the deprecated argument `--server`."""
114
- if args.server != FLEET_API_GRPC_RERE_DEFAULT_ADDRESS:
115
- warn = "Passing flag --server is deprecated. Use --superlink instead."
116
- warn_deprecated_feature(warn)
117
-
118
- if args.superlink != FLEET_API_GRPC_RERE_DEFAULT_ADDRESS:
119
- # if `--superlink` also passed, then
120
- # warn user that this argument overrides what was passed with `--server`
121
- log(
122
- WARN,
123
- "Both `--server` and `--superlink` were passed. "
124
- "`--server` will be ignored. Connecting to the Superlink Fleet API "
125
- "at %s.",
126
- args.superlink,
127
- )
128
- else:
129
- args.superlink = args.server
130
-
131
-
132
111
  def _parse_args_run_supernode() -> argparse.ArgumentParser:
133
112
  """Parse flower-supernode command line arguments."""
134
113
  parser = argparse.ArgumentParser(
@@ -206,15 +185,12 @@ def _parse_args_common(parser: argparse.ArgumentParser) -> None:
206
185
  help="Specifies the path to the PEM-encoded root certificate file for "
207
186
  "establishing secure HTTPS connections.",
208
187
  )
209
- parser.add_argument(
210
- "--server",
211
- default=FLEET_API_GRPC_RERE_DEFAULT_ADDRESS,
212
- help="Server address",
213
- )
214
188
  parser.add_argument(
215
189
  "--superlink",
216
190
  default=FLEET_API_GRPC_RERE_DEFAULT_ADDRESS,
217
- help="SuperLink Fleet API (gRPC-rere) address (IPv4, IPv6, or a domain name)",
191
+ help="SuperLink Fleet API address (IPv4, IPv6, or a domain name). If using the "
192
+ "REST (experimental) transport, ensure your address is in the form "
193
+ "`http://...` or `https://...` when TLS is enabled.",
218
194
  )
219
195
  parser.add_argument(
220
196
  "--max-retries",
flwr/common/args.py CHANGED
@@ -20,13 +20,9 @@ import sys
20
20
  from logging import DEBUG, ERROR, WARN
21
21
  from os.path import isfile
22
22
  from pathlib import Path
23
- from typing import Optional
23
+ from typing import Optional, Union
24
24
 
25
- from flwr.common.constant import (
26
- TRANSPORT_TYPE_GRPC_ADAPTER,
27
- TRANSPORT_TYPE_GRPC_RERE,
28
- TRANSPORT_TYPE_REST,
29
- )
25
+ from flwr.common.constant import TRANSPORT_TYPE_REST
30
26
  from flwr.common.logger import log
31
27
 
32
28
 
@@ -55,9 +51,9 @@ def add_args_flwr_app_common(parser: argparse.ArgumentParser) -> None:
55
51
  def try_obtain_root_certificates(
56
52
  args: argparse.Namespace,
57
53
  grpc_server_address: str,
58
- ) -> Optional[bytes]:
54
+ ) -> Optional[Union[bytes, str]]:
59
55
  """Validate and return the root certificates."""
60
- root_cert_path = args.root_certificates
56
+ root_cert_path: Optional[str] = args.root_certificates
61
57
  if args.insecure:
62
58
  if root_cert_path is not None:
63
59
  sys.exit(
@@ -93,56 +89,38 @@ def try_obtain_root_certificates(
93
89
  grpc_server_address,
94
90
  root_cert_path,
95
91
  )
92
+ if args.transport == TRANSPORT_TYPE_REST:
93
+ return root_cert_path
96
94
  return root_certificates
97
95
 
98
96
 
99
97
  def try_obtain_server_certificates(
100
98
  args: argparse.Namespace,
101
- transport_type: str,
102
99
  ) -> Optional[tuple[bytes, bytes, bytes]]:
103
100
  """Validate and return the CA cert, server cert, and server private key."""
104
101
  if args.insecure:
105
102
  log(WARN, "Option `--insecure` was set. Starting insecure HTTP server.")
106
103
  return None
107
104
  # Check if certificates are provided
108
- if transport_type in [TRANSPORT_TYPE_GRPC_RERE, TRANSPORT_TYPE_GRPC_ADAPTER]:
109
- if args.ssl_certfile and args.ssl_keyfile and args.ssl_ca_certfile:
110
- if not isfile(args.ssl_ca_certfile):
111
- sys.exit("Path argument `--ssl-ca-certfile` does not point to a file.")
112
- if not isfile(args.ssl_certfile):
113
- sys.exit("Path argument `--ssl-certfile` does not point to a file.")
114
- if not isfile(args.ssl_keyfile):
115
- sys.exit("Path argument `--ssl-keyfile` does not point to a file.")
116
- certificates = (
117
- Path(args.ssl_ca_certfile).read_bytes(), # CA certificate
118
- Path(args.ssl_certfile).read_bytes(), # server certificate
119
- Path(args.ssl_keyfile).read_bytes(), # server private key
120
- )
121
- return certificates
122
- if args.ssl_certfile or args.ssl_keyfile or args.ssl_ca_certfile:
123
- sys.exit(
124
- "You need to provide valid file paths to `--ssl-certfile`, "
125
- "`--ssl-keyfile`, and `—-ssl-ca-certfile` to create a secure "
126
- "connection in Fleet API server (gRPC-rere)."
127
- )
128
- if transport_type == TRANSPORT_TYPE_REST:
129
- if args.ssl_certfile and args.ssl_keyfile:
130
- if not isfile(args.ssl_certfile):
131
- sys.exit("Path argument `--ssl-certfile` does not point to a file.")
132
- if not isfile(args.ssl_keyfile):
133
- sys.exit("Path argument `--ssl-keyfile` does not point to a file.")
134
- certificates = (
135
- b"",
136
- Path(args.ssl_certfile).read_bytes(), # server certificate
137
- Path(args.ssl_keyfile).read_bytes(), # server private key
138
- )
139
- return certificates
140
- if args.ssl_certfile or args.ssl_keyfile:
141
- sys.exit(
142
- "You need to provide valid file paths to `--ssl-certfile` "
143
- "and `--ssl-keyfile` to create a secure connection "
144
- "in Fleet API server (REST, experimental)."
145
- )
105
+ if args.ssl_certfile and args.ssl_keyfile and args.ssl_ca_certfile:
106
+ if not isfile(args.ssl_ca_certfile):
107
+ sys.exit("Path argument `--ssl-ca-certfile` does not point to a file.")
108
+ if not isfile(args.ssl_certfile):
109
+ sys.exit("Path argument `--ssl-certfile` does not point to a file.")
110
+ if not isfile(args.ssl_keyfile):
111
+ sys.exit("Path argument `--ssl-keyfile` does not point to a file.")
112
+ certificates = (
113
+ Path(args.ssl_ca_certfile).read_bytes(), # CA certificate
114
+ Path(args.ssl_certfile).read_bytes(), # server certificate
115
+ Path(args.ssl_keyfile).read_bytes(), # server private key
116
+ )
117
+ return certificates
118
+ if args.ssl_certfile or args.ssl_keyfile or args.ssl_ca_certfile:
119
+ sys.exit(
120
+ "You need to provide valid file paths to `--ssl-certfile`, "
121
+ "`--ssl-keyfile`, and `—-ssl-ca-certfile` to create a secure "
122
+ "connection in Fleet API server (gRPC-rere)."
123
+ )
146
124
  log(
147
125
  ERROR,
148
126
  "Certificates are required unless running in insecure mode. "
flwr/common/config.py CHANGED
@@ -23,6 +23,7 @@ from pathlib import Path
23
23
  from typing import IO, Any, Optional, TypeVar, Union, cast, get_args
24
24
 
25
25
  import tomli
26
+ import typer
26
27
 
27
28
  from flwr.common.constant import (
28
29
  APP_DIR,
@@ -233,8 +234,20 @@ def parse_config_args(
233
234
 
234
235
  matches = pattern.findall(config_line)
235
236
  toml_str = "\n".join(f"{k} = {v}" for k, v in matches)
236
- overrides.update(tomli.loads(toml_str))
237
- flat_overrides = flatten_dict(overrides) if flatten else overrides
237
+ try:
238
+ overrides.update(tomli.loads(toml_str))
239
+ flat_overrides = flatten_dict(overrides) if flatten else overrides
240
+ except tomli.TOMLDecodeError as err:
241
+ typer.secho(
242
+ "❌ The provided configuration string is in an invalid format. "
243
+ "The correct format should be, e.g., 'key1=123 key2=false "
244
+ 'key3="string"\', where values must be of type bool, int, '
245
+ "string, or float. Ensure proper formatting with "
246
+ "space-separated key-value pairs.",
247
+ fg=typer.colors.RED,
248
+ bold=True,
249
+ )
250
+ raise typer.Exit(code=1) from err
238
251
 
239
252
  return flat_overrides
240
253
 
flwr/common/constant.py CHANGED
@@ -108,15 +108,17 @@ MAX_RETRY_DELAY = 20 # Maximum delay duration between two consecutive retries.
108
108
 
109
109
  # Constants for user authentication
110
110
  CREDENTIALS_DIR = ".credentials"
111
- AUTH_TYPE_KEY = "auth_type"
112
- ACCESS_TOKEN_KEY = "access_token"
113
- REFRESH_TOKEN_KEY = "refresh_token"
111
+ AUTH_TYPE_JSON_KEY = "auth-type" # For key name in JSON file
112
+ AUTH_TYPE_YAML_KEY = "auth_type" # For key name in YAML file
113
+ ACCESS_TOKEN_KEY = "flwr-oidc-access-token"
114
+ REFRESH_TOKEN_KEY = "flwr-oidc-refresh-token"
114
115
 
115
116
  # Constants for node authentication
116
- PUBLIC_KEY_HEADER = "public-key-bin" # Must end with "-bin" for binary data
117
- SIGNATURE_HEADER = "signature-bin" # Must end with "-bin" for binary data
118
- TIMESTAMP_HEADER = "timestamp"
119
- TIMESTAMP_TOLERANCE = 10 # Tolerance for timestamp verification
117
+ PUBLIC_KEY_HEADER = "flwr-public-key-bin" # Must end with "-bin" for binary data
118
+ SIGNATURE_HEADER = "flwr-signature-bin" # Must end with "-bin" for binary data
119
+ TIMESTAMP_HEADER = "flwr-timestamp"
120
+ TIMESTAMP_TOLERANCE = 10 # General tolerance for timestamp verification
121
+ SYSTEM_TIME_TOLERANCE = 5 # Allowance for system time drift
120
122
 
121
123
 
122
124
  class MessageType:
@@ -15,10 +15,10 @@
15
15
  """Common function to register exit handlers for server and client."""
16
16
 
17
17
 
18
- from signal import SIGINT, SIGQUIT, SIGTERM, signal
18
+ import signal
19
19
  from threading import Thread
20
20
  from types import FrameType
21
- from typing import Optional
21
+ from typing import Callable, Optional
22
22
 
23
23
  from grpc import Server
24
24
 
@@ -26,12 +26,15 @@ from flwr.common.telemetry import EventType
26
26
 
27
27
  from .exit import ExitCode, flwr_exit
28
28
 
29
- SIGNAL_TO_EXIT_CODE = {
30
- SIGINT: ExitCode.GRACEFUL_EXIT_SIGINT,
31
- SIGQUIT: ExitCode.GRACEFUL_EXIT_SIGQUIT,
32
- SIGTERM: ExitCode.GRACEFUL_EXIT_SIGTERM,
29
+ SIGNAL_TO_EXIT_CODE: dict[int, int] = {
30
+ signal.SIGINT: ExitCode.GRACEFUL_EXIT_SIGINT,
31
+ signal.SIGTERM: ExitCode.GRACEFUL_EXIT_SIGTERM,
33
32
  }
34
33
 
34
+ # SIGQUIT is not available on Windows
35
+ if hasattr(signal, "SIGQUIT"):
36
+ SIGNAL_TO_EXIT_CODE[signal.SIGQUIT] = ExitCode.GRACEFUL_EXIT_SIGQUIT
37
+
35
38
 
36
39
  def register_exit_handlers(
37
40
  event_type: EventType,
@@ -54,23 +57,16 @@ def register_exit_handlers(
54
57
  An optional list of threads that need to be gracefully
55
58
  terminated before exiting.
56
59
  """
57
- default_handlers = {
58
- SIGINT: None,
59
- SIGQUIT: None,
60
- SIGTERM: None,
61
- }
62
-
63
- def graceful_exit_handler( # type: ignore
64
- signalnum,
65
- frame: FrameType, # pylint: disable=unused-argument
66
- ) -> None:
60
+ default_handlers: dict[int, Callable[[int, FrameType], None]] = {}
61
+
62
+ def graceful_exit_handler(signalnum: int, _frame: FrameType) -> None:
67
63
  """Exit handler to be registered with `signal.signal`.
68
64
 
69
65
  When called will reset signal handler to original signal handler from
70
66
  default_handlers.
71
67
  """
72
68
  # Reset to default handler
73
- signal(signalnum, default_handlers[signalnum])
69
+ signal.signal(signalnum, default_handlers[signalnum]) # type: ignore
74
70
 
75
71
  if grpc_servers is not None:
76
72
  for grpc_server in grpc_servers:
@@ -87,15 +83,7 @@ def register_exit_handlers(
87
83
  event_type=event_type,
88
84
  )
89
85
 
90
- default_handlers[SIGINT] = signal( # type: ignore
91
- SIGINT,
92
- graceful_exit_handler, # type: ignore
93
- )
94
- default_handlers[SIGQUIT] = signal( # type: ignore
95
- SIGQUIT,
96
- graceful_exit_handler, # type: ignore
97
- )
98
- default_handlers[SIGTERM] = signal( # type: ignore
99
- SIGTERM,
100
- graceful_exit_handler, # type: ignore
101
- )
86
+ # Register signal handlers
87
+ for sig in SIGNAL_TO_EXIT_CODE:
88
+ default_handler = signal.signal(sig, graceful_exit_handler) # type: ignore
89
+ default_handlers[sig] = default_handler # type: ignore
flwr/common/object_ref.py CHANGED
@@ -19,13 +19,10 @@ import ast
19
19
  import importlib
20
20
  import sys
21
21
  from importlib.util import find_spec
22
- from logging import WARN
23
22
  from pathlib import Path
24
23
  from threading import Lock
25
24
  from typing import Any, Optional, Union
26
25
 
27
- from .logger import log
28
-
29
26
  OBJECT_REF_HELP_STR = """
30
27
  \n\nThe object reference string should have the form <module>:<attribute>. Valid
31
28
  examples include `client:app` and `project.package.module:wrapper.app`. It must
@@ -171,17 +168,6 @@ def load_app( # pylint: disable= too-many-branches
171
168
  # Import the module
172
169
  if module_str not in sys.modules:
173
170
  module = importlib.import_module(module_str)
174
- # Hack: `tabnet` does not work with `importlib.reload`
175
- elif "tabnet" in sys.modules:
176
- log(
177
- WARN,
178
- "Cannot reload module `%s` from disk due to compatibility issues "
179
- "with the `tabnet` library. The module will be loaded from the "
180
- "cache instead. If you experience issues, consider restarting "
181
- "the application.",
182
- module_str,
183
- )
184
- module = sys.modules[module_str]
185
171
  else:
186
172
  module = sys.modules[module_str]
187
173
  _reload_modules(project_dir)
flwr/proto/task_pb2.py CHANGED
@@ -17,7 +17,7 @@ from flwr.proto import recordset_pb2 as flwr_dot_proto_dot_recordset__pb2
17
17
  from flwr.proto import error_pb2 as flwr_dot_proto_dot_error__pb2
18
18
 
19
19
 
20
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/task.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x16\x66lwr/proto/error.proto\"\x89\x02\n\x04Task\x12\"\n\x08producer\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\"\n\x08\x63onsumer\x18\x02 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x12\n\ncreated_at\x18\x03 \x01(\x01\x12\x14\n\x0c\x64\x65livered_at\x18\x04 \x01(\t\x12\x11\n\tpushed_at\x18\x05 \x01(\x01\x12\x0b\n\x03ttl\x18\x06 \x01(\x01\x12\x10\n\x08\x61ncestry\x18\x07 \x03(\t\x12\x11\n\ttask_type\x18\x08 \x01(\t\x12(\n\trecordset\x18\t \x01(\x0b\x32\x15.flwr.proto.RecordSet\x12 \n\x05\x65rror\x18\n \x01(\x0b\x32\x11.flwr.proto.Error\"\\\n\x07TaskIns\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x04\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\\\n\x07TaskRes\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x04\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Taskb\x06proto3')
20
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/task.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x16\x66lwr/proto/error.proto\"\xf6\x01\n\x04Task\x12\"\n\x08producer\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\"\n\x08\x63onsumer\x18\x02 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x12\n\ncreated_at\x18\x03 \x01(\x01\x12\x14\n\x0c\x64\x65livered_at\x18\x04 \x01(\t\x12\x0b\n\x03ttl\x18\x06 \x01(\x01\x12\x10\n\x08\x61ncestry\x18\x07 \x03(\t\x12\x11\n\ttask_type\x18\x08 \x01(\t\x12(\n\trecordset\x18\t \x01(\x0b\x32\x15.flwr.proto.RecordSet\x12 \n\x05\x65rror\x18\n \x01(\x0b\x32\x11.flwr.proto.Error\"\\\n\x07TaskIns\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x04\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Task\"\\\n\x07TaskRes\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x10\n\x08group_id\x18\x02 \x01(\t\x12\x0e\n\x06run_id\x18\x03 \x01(\x04\x12\x1e\n\x04task\x18\x04 \x01(\x0b\x32\x10.flwr.proto.Taskb\x06proto3')
21
21
 
22
22
  _globals = globals()
23
23
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -25,9 +25,9 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.task_pb2', _glob
25
25
  if _descriptor._USE_C_DESCRIPTORS == False:
26
26
  DESCRIPTOR._options = None
27
27
  _globals['_TASK']._serialized_start=113
28
- _globals['_TASK']._serialized_end=378
29
- _globals['_TASKINS']._serialized_start=380
30
- _globals['_TASKINS']._serialized_end=472
31
- _globals['_TASKRES']._serialized_start=474
32
- _globals['_TASKRES']._serialized_end=566
28
+ _globals['_TASK']._serialized_end=359
29
+ _globals['_TASKINS']._serialized_start=361
30
+ _globals['_TASKINS']._serialized_end=453
31
+ _globals['_TASKRES']._serialized_start=455
32
+ _globals['_TASKRES']._serialized_end=547
33
33
  # @@protoc_insertion_point(module_scope)
flwr/proto/task_pb2.pyi CHANGED
@@ -20,7 +20,6 @@ class Task(google.protobuf.message.Message):
20
20
  CONSUMER_FIELD_NUMBER: builtins.int
21
21
  CREATED_AT_FIELD_NUMBER: builtins.int
22
22
  DELIVERED_AT_FIELD_NUMBER: builtins.int
23
- PUSHED_AT_FIELD_NUMBER: builtins.int
24
23
  TTL_FIELD_NUMBER: builtins.int
25
24
  ANCESTRY_FIELD_NUMBER: builtins.int
26
25
  TASK_TYPE_FIELD_NUMBER: builtins.int
@@ -32,7 +31,6 @@ class Task(google.protobuf.message.Message):
32
31
  def consumer(self) -> flwr.proto.node_pb2.Node: ...
33
32
  created_at: builtins.float
34
33
  delivered_at: typing.Text
35
- pushed_at: builtins.float
36
34
  ttl: builtins.float
37
35
  @property
38
36
  def ancestry(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: ...
@@ -47,7 +45,6 @@ class Task(google.protobuf.message.Message):
47
45
  consumer: typing.Optional[flwr.proto.node_pb2.Node] = ...,
48
46
  created_at: builtins.float = ...,
49
47
  delivered_at: typing.Text = ...,
50
- pushed_at: builtins.float = ...,
51
48
  ttl: builtins.float = ...,
52
49
  ancestry: typing.Optional[typing.Iterable[typing.Text]] = ...,
53
50
  task_type: typing.Text = ...,
@@ -55,7 +52,7 @@ class Task(google.protobuf.message.Message):
55
52
  error: typing.Optional[flwr.proto.error_pb2.Error] = ...,
56
53
  ) -> None: ...
57
54
  def HasField(self, field_name: typing_extensions.Literal["consumer",b"consumer","error",b"error","producer",b"producer","recordset",b"recordset"]) -> builtins.bool: ...
58
- def ClearField(self, field_name: typing_extensions.Literal["ancestry",b"ancestry","consumer",b"consumer","created_at",b"created_at","delivered_at",b"delivered_at","error",b"error","producer",b"producer","pushed_at",b"pushed_at","recordset",b"recordset","task_type",b"task_type","ttl",b"ttl"]) -> None: ...
55
+ def ClearField(self, field_name: typing_extensions.Literal["ancestry",b"ancestry","consumer",b"consumer","created_at",b"created_at","delivered_at",b"delivered_at","error",b"error","producer",b"producer","recordset",b"recordset","task_type",b"task_type","ttl",b"ttl"]) -> None: ...
59
56
  global___Task = Task
60
57
 
61
58
  class TaskIns(google.protobuf.message.Message):
flwr/server/app.py CHANGED
@@ -40,7 +40,7 @@ from flwr.common.args import try_obtain_server_certificates
40
40
  from flwr.common.auth_plugin import ExecAuthPlugin
41
41
  from flwr.common.config import get_flwr_dir, parse_config_args
42
42
  from flwr.common.constant import (
43
- AUTH_TYPE_KEY,
43
+ AUTH_TYPE_YAML_KEY,
44
44
  CLIENT_OCTET,
45
45
  EXEC_API_DEFAULT_SERVER_ADDRESS,
46
46
  FLEET_API_GRPC_BIDI_DEFAULT_ADDRESS,
@@ -265,7 +265,7 @@ def run_superlink() -> None:
265
265
  simulationio_address, _, _ = _format_address(args.simulationio_api_address)
266
266
 
267
267
  # Obtain certificates
268
- certificates = try_obtain_server_certificates(args, args.fleet_api_type)
268
+ certificates = try_obtain_server_certificates(args)
269
269
 
270
270
  # Disable the user auth TLS check if args.disable_oidc_tls_cert_verification is
271
271
  # provided
@@ -353,17 +353,13 @@ def run_superlink() -> None:
353
353
  ) is None:
354
354
  flwr_exit(ExitCode.COMMON_MISSING_EXTRA_REST)
355
355
 
356
- _, ssl_certfile, ssl_keyfile = (
357
- certificates if certificates is not None else (None, None, None)
358
- )
359
-
360
356
  fleet_thread = threading.Thread(
361
357
  target=_run_fleet_api_rest,
362
358
  args=(
363
359
  host,
364
360
  port,
365
- ssl_keyfile,
366
- ssl_certfile,
361
+ args.ssl_keyfile,
362
+ args.ssl_certfile,
367
363
  state_factory,
368
364
  ffs_factory,
369
365
  num_workers,
@@ -582,7 +578,7 @@ def _try_obtain_exec_auth_plugin(
582
578
 
583
579
  # Load authentication configuration
584
580
  auth_config: dict[str, Any] = config.get("authentication", {})
585
- auth_type: str = auth_config.get(AUTH_TYPE_KEY, "")
581
+ auth_type: str = auth_config.get(AUTH_TYPE_YAML_KEY, "")
586
582
 
587
583
  # Load authentication plugin
588
584
  try:
@@ -126,7 +126,6 @@ class InMemoryDriver(Driver):
126
126
  # Convert Message to TaskIns
127
127
  taskins = message_to_taskins(msg)
128
128
  # Store in state
129
- taskins.task.pushed_at = time.time()
130
129
  task_id = self.state.store_task_ins(taskins)
131
130
  if task_id:
132
131
  task_ids.append(str(task_id))
@@ -22,7 +22,7 @@ from uuid import UUID
22
22
 
23
23
  import grpc
24
24
 
25
- from flwr.common import ConfigsRecord, now
25
+ from flwr.common import ConfigsRecord
26
26
  from flwr.common.constant import Status
27
27
  from flwr.common.logger import log
28
28
  from flwr.common.serde import (
@@ -151,9 +151,6 @@ class ServerAppIoServicer(serverappio_pb2_grpc.ServerAppIoServicer):
151
151
  context,
152
152
  )
153
153
 
154
- # Set pushed_at (timestamp in seconds)
155
- pushed_at = now().timestamp()
156
-
157
154
  # Validate request and insert in State
158
155
  _raise_if(
159
156
  validation_error=len(request.messages_list) == 0,
@@ -165,7 +162,6 @@ class ServerAppIoServicer(serverappio_pb2_grpc.ServerAppIoServicer):
165
162
  message_proto = request.messages_list.pop(0)
166
163
  message = message_from_proto(message_proto=message_proto)
167
164
  task_ins = message_to_taskins(message=message)
168
- task_ins.task.pushed_at = pushed_at
169
165
  validation_errors = validate_task_ins_or_res(task_ins)
170
166
  _raise_if(
171
167
  validation_error=bool(validation_errors),
@@ -25,6 +25,7 @@ from flwr.common import now
25
25
  from flwr.common.constant import (
26
26
  PUBLIC_KEY_HEADER,
27
27
  SIGNATURE_HEADER,
28
+ SYSTEM_TIME_TOLERANCE,
28
29
  TIMESTAMP_HEADER,
29
30
  TIMESTAMP_TOLERANCE,
30
31
  )
@@ -38,10 +39,15 @@ from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
38
39
  )
39
40
  from flwr.server.superlink.linkstate import LinkStateFactory
40
41
 
42
+ MIN_TIMESTAMP_DIFF = -SYSTEM_TIME_TOLERANCE
43
+ MAX_TIMESTAMP_DIFF = TIMESTAMP_TOLERANCE + SYSTEM_TIME_TOLERANCE
41
44
 
42
- def _unary_unary_rpc_terminator(message: str) -> grpc.RpcMethodHandler:
45
+
46
+ def _unary_unary_rpc_terminator(
47
+ message: str, code: Any = grpc.StatusCode.UNAUTHENTICATED
48
+ ) -> grpc.RpcMethodHandler:
43
49
  def terminate(_request: GrpcMessage, context: grpc.ServicerContext) -> GrpcMessage:
44
- context.abort(grpc.StatusCode.UNAUTHENTICATED, message)
50
+ context.abort(code, message)
45
51
  raise RuntimeError("Should not reach this point") # Make mypy happy
46
52
 
47
53
  return grpc.unary_unary_rpc_method_handler(terminate)
@@ -64,7 +70,7 @@ class AuthenticateServerInterceptor(grpc.ServerInterceptor): # type: ignore
64
70
  self.state_factory = state_factory
65
71
  self.auto_auth = auto_auth
66
72
 
67
- def intercept_service(
73
+ def intercept_service( # pylint: disable=too-many-return-statements
68
74
  self,
69
75
  continuation: Callable[[Any], Any],
70
76
  handler_call_details: grpc.HandlerCallDetails,
@@ -75,6 +81,13 @@ class AuthenticateServerInterceptor(grpc.ServerInterceptor): # type: ignore
75
81
  metadata sent by the node. Continue RPC call if node is authenticated, else,
76
82
  terminate RPC call by setting context to abort.
77
83
  """
84
+ # Filter out non-Fleet service calls
85
+ if not handler_call_details.method.startswith("/flwr.proto.Fleet/"):
86
+ return _unary_unary_rpc_terminator(
87
+ "This request should be sent to a different service.",
88
+ grpc.StatusCode.FAILED_PRECONDITION,
89
+ )
90
+
78
91
  state = self.state_factory.state()
79
92
  metadata_dict = dict(handler_call_details.invocation_metadata)
80
93
 
@@ -100,7 +113,7 @@ class AuthenticateServerInterceptor(grpc.ServerInterceptor): # type: ignore
100
113
  current = now()
101
114
  time_diff = current - datetime.datetime.fromisoformat(timestamp_iso)
102
115
  # Abort the RPC call if the timestamp is too old or in the future
103
- if not 0 < time_diff.total_seconds() < TIMESTAMP_TOLERANCE:
116
+ if not MIN_TIMESTAMP_DIFF < time_diff.total_seconds() < MAX_TIMESTAMP_DIFF:
104
117
  return _unary_unary_rpc_terminator("Invalid timestamp")
105
118
 
106
119
  # Continue the RPC call
@@ -15,7 +15,6 @@
15
15
  """Fleet API message handlers."""
16
16
 
17
17
 
18
- import time
19
18
  from typing import Optional
20
19
  from uuid import UUID
21
20
 
@@ -122,9 +121,6 @@ def push_messages(
122
121
  if abort_msg:
123
122
  raise InvalidRunStatusException(abort_msg)
124
123
 
125
- # Set pushed_at (timestamp in seconds)
126
- task_res.task.pushed_at = time.time()
127
-
128
124
  # Store TaskRes in State
129
125
  message_id: Optional[UUID] = state.store_task_res(task_res=task_res)
130
126
 
@@ -140,7 +140,6 @@ def worker(
140
140
  # Convert to TaskRes
141
141
  task_res = message_to_taskres(out_mssg)
142
142
  # Store TaskRes in state
143
- task_res.task.pushed_at = time.time()
144
143
  taskres_queue.put(task_res)
145
144
 
146
145
 
@@ -126,7 +126,6 @@ CREATE TABLE IF NOT EXISTS task_ins(
126
126
  consumer_node_id INTEGER,
127
127
  created_at REAL,
128
128
  delivered_at TEXT,
129
- pushed_at REAL,
130
129
  ttl REAL,
131
130
  ancestry TEXT,
132
131
  task_type TEXT,
@@ -144,7 +143,6 @@ CREATE TABLE IF NOT EXISTS task_res(
144
143
  consumer_node_id INTEGER,
145
144
  created_at REAL,
146
145
  delivered_at TEXT,
147
- pushed_at REAL,
148
146
  ttl REAL,
149
147
  ancestry TEXT,
150
148
  task_type TEXT,
@@ -1053,7 +1051,6 @@ def task_ins_to_dict(task_msg: TaskIns) -> dict[str, Any]:
1053
1051
  "consumer_node_id": task_msg.task.consumer.node_id,
1054
1052
  "created_at": task_msg.task.created_at,
1055
1053
  "delivered_at": task_msg.task.delivered_at,
1056
- "pushed_at": task_msg.task.pushed_at,
1057
1054
  "ttl": task_msg.task.ttl,
1058
1055
  "ancestry": ",".join(task_msg.task.ancestry),
1059
1056
  "task_type": task_msg.task.task_type,
@@ -1072,7 +1069,6 @@ def task_res_to_dict(task_msg: TaskRes) -> dict[str, Any]:
1072
1069
  "consumer_node_id": task_msg.task.consumer.node_id,
1073
1070
  "created_at": task_msg.task.created_at,
1074
1071
  "delivered_at": task_msg.task.delivered_at,
1075
- "pushed_at": task_msg.task.pushed_at,
1076
1072
  "ttl": task_msg.task.ttl,
1077
1073
  "ancestry": ",".join(task_msg.task.ancestry),
1078
1074
  "task_type": task_msg.task.task_type,
@@ -1099,7 +1095,6 @@ def dict_to_task_ins(task_dict: dict[str, Any]) -> TaskIns:
1099
1095
  ),
1100
1096
  created_at=task_dict["created_at"],
1101
1097
  delivered_at=task_dict["delivered_at"],
1102
- pushed_at=task_dict["pushed_at"],
1103
1098
  ttl=task_dict["ttl"],
1104
1099
  ancestry=task_dict["ancestry"].split(","),
1105
1100
  task_type=task_dict["task_type"],
@@ -1127,7 +1122,6 @@ def dict_to_task_res(task_dict: dict[str, Any]) -> TaskRes:
1127
1122
  ),
1128
1123
  created_at=task_dict["created_at"],
1129
1124
  delivered_at=task_dict["delivered_at"],
1130
- pushed_at=task_dict["pushed_at"],
1131
1125
  ttl=task_dict["ttl"],
1132
1126
  ancestry=task_dict["ancestry"].split(","),
1133
1127
  task_type=task_dict["task_type"],
@@ -45,9 +45,6 @@ def validate_task_ins_or_res(tasks_ins_res: Union[TaskIns, TaskRes]) -> list[str
45
45
  validation_errors.append("`delivered_at` must be an empty str")
46
46
  if tasks_ins_res.task.ttl <= 0:
47
47
  validation_errors.append("`ttl` must be higher than zero")
48
- if tasks_ins_res.task.pushed_at < 1711497600.0:
49
- # unix timestamp of 27 March 2024 00h:00m:00s UTC
50
- validation_errors.append("`pushed_at` is not a recent timestamp")
51
48
 
52
49
  # Verify TTL and created_at time
53
50
  current_time = time.time()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flwr-nightly
3
- Version: 1.15.0.dev20250130
3
+ Version: 1.15.2.dev20250214
4
4
  Summary: Flower: A Friendly Federated AI Framework
5
5
  Home-page: https://flower.ai
6
6
  License: Apache-2.0
@@ -40,7 +40,7 @@ Requires-Dist: pathspec (>=0.12.1,<0.13.0)
40
40
  Requires-Dist: protobuf (>=4.21.6,<5.0.0)
41
41
  Requires-Dist: pycryptodome (>=3.18.0,<4.0.0)
42
42
  Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
43
- Requires-Dist: ray (==2.10.0) ; (python_version >= "3.9" and python_version < "3.12") and (extra == "simulation")
43
+ Requires-Dist: ray (==2.31.0) ; (python_version >= "3.9" and python_version < "3.13") and (extra == "simulation")
44
44
  Requires-Dist: requests (>=2.31.0,<3.0.0)
45
45
  Requires-Dist: rich (>=13.5.0,<14.0.0)
46
46
  Requires-Dist: starlette (>=0.45.2,<0.46.0) ; extra == "rest"
@@ -2,7 +2,7 @@ flwr/__init__.py,sha256=VmBWedrCxqmt4QvUHBLqyVEH6p7zaFMD_oCHerXHSVw,937
2
2
  flwr/cli/__init__.py,sha256=cZJVgozlkC6Ni2Hd_FAIrqefrkCGOV18fikToq-6iLw,720
3
3
  flwr/cli/app.py,sha256=UeXrW5gxrUnFViDjAMIxGNZZKwu3a1oAj83v53IWIWM,1382
4
4
  flwr/cli/auth_plugin/__init__.py,sha256=FyaoqPzcxlBTFfJ2sBRC5USwQLmAhFr5KuBwfMO4bmo,1052
5
- flwr/cli/auth_plugin/oidc_cli_plugin.py,sha256=nooDDWO_3bWYqi_KBrsO3YteDIIuvTZD30XymbvRPlA,5374
5
+ flwr/cli/auth_plugin/oidc_cli_plugin.py,sha256=gIhW6Jg9QAo-jL43LYPpw_kn7pdUZZae0s0H8dEgjLM,5384
6
6
  flwr/cli/build.py,sha256=4P70i_FnUs0P21aTwjTXtFQSAfY-C04hUDF-2npfJdo,6345
7
7
  flwr/cli/cli_user_auth_interceptor.py,sha256=aZepPA298s-HjGmkJGMvI_uZe72O5aLC3jri-ilG53o,3126
8
8
  flwr/cli/config_utils.py,sha256=LelRR960I36n1IPw7BIu79fKoOh0JePA58kAtoXSTH0,7518
@@ -12,15 +12,15 @@ flwr/cli/install.py,sha256=-RnrYGejN_zyXXp_CoddSQwoQfRTWWyt9WYlxphJzyU,8180
12
12
  flwr/cli/log.py,sha256=vcO-r5EIc127mOQ26uxKVITX-w_Zib7AxSVuuN70_JY,6671
13
13
  flwr/cli/login/__init__.py,sha256=6_9zOzbPOAH72K2wX3-9dXTAbS7Mjpa5sEn2lA6eHHI,800
14
14
  flwr/cli/login/login.py,sha256=iNnNF1bvV0n8Z-vNc89azFNA73JqKZlO1s5OF2atsTc,3917
15
- flwr/cli/ls.py,sha256=5KCHdctN5f5GkCAkbZSC1OuKdhmLzobINpltsdtDtQU,11383
15
+ flwr/cli/ls.py,sha256=cm3NuY1sFq51xVRhUG0MbAfVTrRSjJ1HMIubde80LuY,11433
16
16
  flwr/cli/new/__init__.py,sha256=pOQtPT9W4kCIttcKne5m-FtJbvTqdjTVJxzQ9AUYK8I,790
17
17
  flwr/cli/new/new.py,sha256=scyyKt8mzkc3El1bypgkHjKwVQEc2-q4I50PxriPFdI,9922
18
18
  flwr/cli/new/templates/__init__.py,sha256=4luU8RL-CK8JJCstQ_ON809W9bNTkY1l9zSaPKBkgwY,725
19
19
  flwr/cli/new/templates/app/.gitignore.tpl,sha256=HZJcGQoxp7aUzaPg8Uqch3kNrIESwr9yjimDxJYgXVY,3104
20
20
  flwr/cli/new/templates/app/LICENSE.tpl,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
21
- flwr/cli/new/templates/app/README.baseline.md.tpl,sha256=4dg2aBS-NIleVyDlxsG8m65Af6LIJ-pZA5ICjGFU5XA,9641
21
+ flwr/cli/new/templates/app/README.baseline.md.tpl,sha256=oClo5eR0iLuPzBT7uS3ikhNRAnySz_lhkHFElixKyJM,9640
22
22
  flwr/cli/new/templates/app/README.flowertune.md.tpl,sha256=QSG51uifue2KVZz2ZNw8kmOStS7svC2AQ2gTa5E7Bhs,3326
23
- flwr/cli/new/templates/app/README.md.tpl,sha256=XOtDKeo3sVapPtuUAnlQwr6Fj1lA9y1fJCpS8xnaPfw,1392
23
+ flwr/cli/new/templates/app/README.md.tpl,sha256=qZ6XHeCdSoDwtJqgcyi-ChgOCLMwQ3E42rcY-9qhlUY,1392
24
24
  flwr/cli/new/templates/app/__init__.py,sha256=DU7QMY7IhMQyuwm_tja66xU0KXTWQFqzfTqwg-_NJdE,729
25
25
  flwr/cli/new/templates/app/code/__init__.baseline.py.tpl,sha256=YkHAgppUeD2BnBoGfVB6dEvBfjuIPGsU1gw4CiUi3qA,40
26
26
  flwr/cli/new/templates/app/code/__init__.py,sha256=EM6vfvgAILKPaPn7H1wMV1Wi01WyZCP_Eg6NxD6oWg8,736
@@ -58,19 +58,19 @@ flwr/cli/new/templates/app/code/task.pytorch.py.tpl,sha256=XlJqA4Ix_PloO_zJLhjiN
58
58
  flwr/cli/new/templates/app/code/task.sklearn.py.tpl,sha256=SeIIo0rr_6ffn4Qx2xELD18jYXCkcW__NWtYEDXCICM,1843
59
59
  flwr/cli/new/templates/app/code/task.tensorflow.py.tpl,sha256=SKXAZdgBnPpbAbJ90Rb7oQ5ilnopBx_j_JNFoUDeEAI,1732
60
60
  flwr/cli/new/templates/app/code/utils.baseline.py.tpl,sha256=YkHAgppUeD2BnBoGfVB6dEvBfjuIPGsU1gw4CiUi3qA,40
61
- flwr/cli/new/templates/app/pyproject.baseline.toml.tpl,sha256=O4BIe8wKupf0r_xqgKuT8DbUUKvbG8bhEmv8x0cdRBo,2666
62
- flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl,sha256=j1SG4rIeoSil6EG0SF8PdeBsuLch0Zc-uh_qjmin260,1873
63
- flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl,sha256=f5GpZjHDeJvy0yXBq9T4O2TK-T-e4-JQZ2gbCOkH698,1143
64
- flwr/cli/new/templates/app/pyproject.jax.toml.tpl,sha256=7NScYo-h9BUIwDsMUrmVfOKgdVDKUDSf7mj7yEMHC2M,673
65
- flwr/cli/new/templates/app/pyproject.mlx.toml.tpl,sha256=FfcqHuKmq6uHMEQthhiVDmuv0KzheLqrG8oBfk54hns,744
66
- flwr/cli/new/templates/app/pyproject.numpy.toml.tpl,sha256=roGj5SIPgZhWNwLRiDAxkmc7hO9Nsm94KADs3TdfQ6I,611
67
- flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl,sha256=fdj7M8fSaOZVsoIpryHdzYcgL5I0nVWqnZQurj02xLs,710
68
- flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl,sha256=35EisD-7h4MmWyRVC6NMqKDO-pS9nUBTNQD8Ax1AmGY,686
69
- flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl,sha256=1X_IlLswBnU65nIj7CgpPbhqWCPQRXp5o5SG-kIrX5w,710
61
+ flwr/cli/new/templates/app/pyproject.baseline.toml.tpl,sha256=KaRdKS6Um_7_BwaC2JyPVssvO0XoqugXr3uScQW_gmQ,2666
62
+ flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl,sha256=V0ARllDsjHQU7PkgsPk2wQKmcWkbiTYNnDzrQaH8PX8,1873
63
+ flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl,sha256=-br1AywMPM2TdOKwooz_jotI4iUoqLMmDkdVIV5txYM,1143
64
+ flwr/cli/new/templates/app/pyproject.jax.toml.tpl,sha256=p8v65ymJtY50uh8kSyzAOYN34mvf2oQti2yN8d4T_gM,673
65
+ flwr/cli/new/templates/app/pyproject.mlx.toml.tpl,sha256=faz_lde3WU4HAJK_3h2SDR8Kejsv9P1jUHQQKyKdyZM,744
66
+ flwr/cli/new/templates/app/pyproject.numpy.toml.tpl,sha256=xP-U8w8_qim3BS5pTa9QYj38H2DfdcY24mKOdZRqkus,611
67
+ flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl,sha256=wLYfJlglT6k3Q5t3PGC43H5eVNouDnEqwK19KHUEj8o,710
68
+ flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl,sha256=9p0NzvIHoM0ZvlDUpa1lBMwIY_kpigmNCM7-5r3xWcg,686
69
+ flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl,sha256=C_kmVlZ-kqzcBJfMzsimE0voz1UbJMQqO_hfZQjMmg0,710
70
70
  flwr/cli/run/__init__.py,sha256=cCsKVB0SFzh2b3QmGba6BHckB85xlhjh3mh4pBpACtY,790
71
71
  flwr/cli/run/run.py,sha256=kEOYKin9qPJy8SODxcAvIWk-OskKPsxvcbvhDhf2VD4,8299
72
- flwr/cli/stop.py,sha256=DBCKg9AhB1WcJsyqfkHKR1_V_yT7D32zqa9QhmX9IAU,4926
73
- flwr/cli/utils.py,sha256=hd6XUqu4Ty3m0mEtulQb1f_JV-W65fV_1SGAYCe5Vxs,11226
72
+ flwr/cli/stop.py,sha256=E4TGynmYQss5iWJ_fjSdYIW8nrNta2KOiK4sfvHKO_g,4976
73
+ flwr/cli/utils.py,sha256=D9XcpxzwkGPNdwX16o0kI-sYnRDMlWYyKNIpz6npRhQ,11236
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
@@ -109,15 +109,15 @@ flwr/client/rest_client/__init__.py,sha256=5KGlp7pjc1dhNRkKlaNtUfQmg8wrRFh9lS3P3
109
109
  flwr/client/rest_client/connection.py,sha256=9_JDGHkmaiPgk6CmcQId56Ia1ucQfrqcpNOUObdZaZU,13008
110
110
  flwr/client/run_info_store.py,sha256=ZN2Phi4DSLbSyzg8RmzJcVYh1g6eurHOmWRCT7GMtw4,4040
111
111
  flwr/client/supernode/__init__.py,sha256=SUhWOzcgXRNXk1V9UgB5-FaWukqqrOEajVUHEcPkwyQ,865
112
- flwr/client/supernode/app.py,sha256=q-hOZUpvxN64Eo4uBe_Om7uMneIE_ux5fyNp7siINxY,10142
112
+ flwr/client/supernode/app.py,sha256=oBbggh56HoieksBkTdDHAJC8VUFbrmGOP0-D9wdcZek,9265
113
113
  flwr/client/typing.py,sha256=dxoTBnTMfqXr5J7G3y-uNjqxYCddvxhu89spfj4Lm2U,1048
114
114
  flwr/common/__init__.py,sha256=TVaoFEJE158aui1TPZQiJCDZX4RNHRyI8I55VC80HhI,3901
115
115
  flwr/common/address.py,sha256=9KNYE69WW_QVcyumsux3Qn1wmn4J7f13Y9nHASpvzbA,3018
116
- flwr/common/args.py,sha256=bCvtG0hhh_hVjl9NoWsY_g7kLMIN3jCN7B883HvZ7hg,6223
116
+ flwr/common/args.py,sha256=MgkTUXACuySHyNdxrb7-pK0_R-S2Q7W5MnE3onYUf5I,5183
117
117
  flwr/common/auth_plugin/__init__.py,sha256=1Y8Oj3iB49IHDu9tvDih1J74Ygu7k85V9s2A4WORPyA,887
118
118
  flwr/common/auth_plugin/auth_plugin.py,sha256=wgDorBUB4IkK6twQ8vNawRVz7BDPmKdXZBNLqhU9RSs,3871
119
- flwr/common/config.py,sha256=n6T5Vi6BUFul37GUpKp9Doqnz35phJqSud_G3ySWlIQ,13336
120
- flwr/common/constant.py,sha256=mw2H-rTFI5Lwv8EK2dlW5RDAynQWeSawcwup2p0vLN4,6419
119
+ flwr/common/config.py,sha256=SAkG3BztnA6iupXxF3GAIpGmWVVCH0ptyMpC9yjr_14,13965
120
+ flwr/common/constant.py,sha256=AdNCrHi4sgMCecdX7hHWxMFz3y9pWsjSGU25mA4OJyE,6619
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
123
  flwr/common/differential_privacy.py,sha256=YA01NqjddKNAEVmf7hXmOVxOjhekgzvJudk3mBGq-2k,6148
@@ -126,11 +126,11 @@ 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
- flwr/common/exit_handlers.py,sha256=Dke87CC6d6b6kqkC2mF0I4JsP4mHhlQTFxkS4sKKgyw,3308
129
+ flwr/common/exit_handlers.py,sha256=yclujry30954o0lI7vtknTajskPCvK8TXw2V3RdldXU,3174
130
130
  flwr/common/grpc.py,sha256=K60AIvIqH0CvkkiqBfw5HoxQfbFOL2DrhKPjbZ8raIE,9786
131
131
  flwr/common/logger.py,sha256=Hund1C6bEhMw3GemlzuFK22tXZ27YeHLrFB0b4LP5f8,13041
132
132
  flwr/common/message.py,sha256=Zv4ID2BLQsbff0F03DI_MeFoHbSqVZAdDD9NcKYv6Zo,13832
133
- flwr/common/object_ref.py,sha256=fIXf8aP5mG6Nuni7dvcKK5Di3zRfRWGs4ljvqIXplds,10115
133
+ flwr/common/object_ref.py,sha256=Mv8OE6f9wmLs_KQWt8aPV5aw-g6fgWDfj28L2b8Jl-Y,9514
134
134
  flwr/common/parameter.py,sha256=-bFAUayToYDF50FZGrBC1hQYJCQDtB2bbr3ZuVLMtdE,2095
135
135
  flwr/common/pyproject.py,sha256=vEAxl800XiJ1JNJDui8vuVV-08msnB6hLt7o95viZl0,1386
136
136
  flwr/common/record/__init__.py,sha256=LUixpq0Z-lMJwCIu1-4u5HfvRPjRMRgoAc6YJQ6UEOs,1055
@@ -207,8 +207,8 @@ flwr/proto/simulationio_pb2.py,sha256=GOOmivAJPLQ6mPXrfKS8CyYeE6Kk-Q5mInLz5pyZSs
207
207
  flwr/proto/simulationio_pb2.pyi,sha256=oXx8_FLBe5B54wduZj-f89kub73XxNtQbThuW8YfPAs,2660
208
208
  flwr/proto/simulationio_pb2_grpc.py,sha256=9I3yAfJaeMuG-qH_5Ge45eFOftsIOmL9b8E_xHmcvKw,11232
209
209
  flwr/proto/simulationio_pb2_grpc.pyi,sha256=YHvKtyo7UdbBgdhoN0ndzZeB5vIC3JuR5PAJLrl-OKM,3206
210
- flwr/proto/task_pb2.py,sha256=LbKBPk0iy4I_HvxRI1xMqE-vW_CZmAiaCgKt0wI_zy4,2361
211
- flwr/proto/task_pb2.pyi,sha256=KJVsLm-THY5QjHreHDm_-OS1tyZyD61mx6BzOpoeMjw,4320
210
+ flwr/proto/task_pb2.py,sha256=pFKpq2QSvmFQOEpv2bgCG9jPAVauIHXQ9p5ASW-Z6lE,2322
211
+ flwr/proto/task_pb2.pyi,sha256=PZXt-QkD-hFzTlgNVVx6SGvgbTCweBfisivEi_HfDWc,4183
212
212
  flwr/proto/task_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
213
213
  flwr/proto/task_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
214
214
  flwr/proto/transport_pb2.py,sha256=P-jX_tUyk_8xFe-vIUUSfZlHGtk2Ou3A8eXdBKkp5AY,9824
@@ -217,7 +217,7 @@ flwr/proto/transport_pb2_grpc.py,sha256=vLN3EHtx2aEEMCO4f1Upu-l27BPzd3-5pV-u8wPc
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=_WxQwMtaiihPcoZ27b4upnv1zAQN_NT9VMXARuYNFfU,30687
220
+ flwr/server/app.py,sha256=CVj7lDAYJ4GYnBvAIa0R3A8JV5Dt-ATxDOrLxafLFV8,30545
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
@@ -229,7 +229,7 @@ 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
231
  flwr/server/driver/grpc_driver.py,sha256=3mSws0l83fWD4aq9-MmHFnIfyf4REoAXUkWfyJDHros,9864
232
- flwr/server/driver/inmemory_driver.py,sha256=b1U1PrB_Vpn--vav8SX-sn0THD9BTlV9UFIpuWTWLro,6665
232
+ flwr/server/driver/inmemory_driver.py,sha256=7ZtWDDJa8xupPAHNaDdCE2DOIOIYgrffmJMdKjs3wdA,6616
233
233
  flwr/server/history.py,sha256=qSb5_pPTrwofpSYGsZWzMPkl_4uJ4mJFWesxXDrEvDU,5026
234
234
  flwr/server/run_serverapp.py,sha256=vIPhvJx0i5sEZO4IKM6ruCXmx4ncat76rh0B4KhdhhM,2446
235
235
  flwr/server/server.py,sha256=1ZsFEptmAV-L2vP2etNC9Ed5CLSxpuKzUFkAPQ4l5Xc,17893
@@ -265,7 +265,7 @@ flwr/server/strategy/strategy.py,sha256=cXapkD5uDrt5C-RbmWDn9FLoap3Q41i7GKvbmfbC
265
265
  flwr/server/superlink/__init__.py,sha256=8tHYCfodUlRD8PCP9fHgvu8cz5N31A2QoRVL0jDJ15E,707
266
266
  flwr/server/superlink/driver/__init__.py,sha256=5soEK5QSvxNjmJQ-CGTWROc4alSAeU0e9Ad9RDhsd3E,717
267
267
  flwr/server/superlink/driver/serverappio_grpc.py,sha256=UzHwo6qYZMeOhr7nn1iZbcyDSmwvnq_kpYH0mEAndW0,2173
268
- flwr/server/superlink/driver/serverappio_servicer.py,sha256=xbmjm5A6PclNqzkJf3VNBCULY7mnj6ij4rWDqAM-G0A,13255
268
+ flwr/server/superlink/driver/serverappio_servicer.py,sha256=Ld_d4ygbvJ7YmsIA8O9oD3E4tBKDY7MlpQzBjDUyvi0,13116
269
269
  flwr/server/superlink/ffs/__init__.py,sha256=FAY-zShcfPmOxosok2QyT6hTNMNctG8cH9s_nIl8jkI,840
270
270
  flwr/server/superlink/ffs/disk_ffs.py,sha256=n_Ah0sQwXGVQ9wj5965nLjdkQQbpoHCljjXKFnwftsU,3297
271
271
  flwr/server/superlink/ffs/ffs.py,sha256=qLI1UfosJugu2BKOJWqHIhafTm-YiuKqGf3OGWPH0NM,2395
@@ -280,21 +280,21 @@ flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py,sha256=h3EhqgelegVC4E
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
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
283
+ flwr/server/superlink/fleet/grpc_rere/server_interceptor.py,sha256=KPgAcnYsKPPI7_iYNSnqGbyv4tsqZuBqrTiREwVBJiM,6984
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=DM53K4yLOmzXikTe6i6KJ0v8IvlJKDifvFEV09GFKhI,5510
285
+ flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=QpLo3E-viPQ1Ia4isRM21htCfU3QH0P4wqMfXAtX8Hk,5412
286
286
  flwr/server/superlink/fleet/rest_rere/__init__.py,sha256=5jbYbAn75sGv-gBwOPDySE0kz96F6dTYLeMrGqNi4lM,735
287
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
291
291
  flwr/server/superlink/fleet/vce/backend/raybackend.py,sha256=jsUkFEVQTnrucK1jNQ_cUM8YwL7W4MQNA1GAf8ibRdg,7156
292
- flwr/server/superlink/fleet/vce/vce_api.py,sha256=WTnUILr1OHS8LfjXQUA3FyWJYdJgdqpFAybyJUD-1Xo,13025
292
+ flwr/server/superlink/fleet/vce/vce_api.py,sha256=iXNSAJ7f8Sg1hOrVuRTGRkLdSWeFIpNWbusoOTc4I8I,12971
293
293
  flwr/server/superlink/linkstate/__init__.py,sha256=v-2JyJlCB3qyhMNwMjmcNVOq4rkooqFU0LHH8Zo1jls,1064
294
294
  flwr/server/superlink/linkstate/in_memory_linkstate.py,sha256=4ahMj7TLe-GO2ctyeZ2BBRkviGv27s6x1NS_ETRJHP8,20514
295
295
  flwr/server/superlink/linkstate/linkstate.py,sha256=LWA5zRwN829GDAeSo5kmkzsMu0SkXa9qg4aG_0QN0uk,12159
296
296
  flwr/server/superlink/linkstate/linkstate_factory.py,sha256=ISSMjDlwuN7swxjOeYlTNpI_kuZ8PGkMcJnf1dbhUSE,2069
297
- flwr/server/superlink/linkstate/sqlite_linkstate.py,sha256=E07w0_eCoOnZOBbdh3I3PN5k5tqt4LrEnYAuiMOF0I0,40398
297
+ flwr/server/superlink/linkstate/sqlite_linkstate.py,sha256=YEXk_3avSF9T9sk5xxYwNeljLZ-qzg1zIAJOlkkmsX0,40146
298
298
  flwr/server/superlink/linkstate/utils.py,sha256=EpRehwI4NeEW3oINICPWP9STK49N0aszd5s5jtle7DQ,13602
299
299
  flwr/server/superlink/simulation/__init__.py,sha256=mg-oapC9dkzEfjXPQFior5lpWj4g9kwbLovptyYM_g0,718
300
300
  flwr/server/superlink/simulation/simulationio_grpc.py,sha256=8aUrZZLdvprKUfLLqFID4aItus9beU6m1qLQYIPB7k0,2224
@@ -303,7 +303,7 @@ flwr/server/superlink/utils.py,sha256=KVb3K_g2vYfu9TnftcN0ewmev133WZcjuEePMm8d7G
303
303
  flwr/server/typing.py,sha256=5kaRLZuxTEse9A0g7aVna2VhYxU3wTq1f3d3mtw7kXs,1019
304
304
  flwr/server/utils/__init__.py,sha256=pltsPHJoXmUIr3utjwwYxu7_ZAGy5u4MVHzv9iA5Un8,908
305
305
  flwr/server/utils/tensorboard.py,sha256=gEBD8w_5uaIfp5aw5RYH66lYZpd_SfkObHQ7eDd9MUk,5466
306
- flwr/server/utils/validator.py,sha256=SpoKWDlVfFI5aJr2jXWfwJjBc5OZUMMacQbOxj6wPdI,4603
306
+ flwr/server/utils/validator.py,sha256=BQ56tDrrOOG52q3RVeeCODz-oEBxu4L19wbfkBPdCqw,4419
307
307
  flwr/server/workflow/__init__.py,sha256=SXY0XkwbkezFBxxrFB5hKUtmtAgnYISBkPouR1V71ss,902
308
308
  flwr/server/workflow/constant.py,sha256=q4DLdR8Krlxuewq2AQjwTL75hphxE5ODNz4AhViHMXk,1082
309
309
  flwr/server/workflow/default_workflows.py,sha256=UMC9JgdomKwxql5G0OV4AeRXWI-bMClaLAOn5OrZMnw,14073
@@ -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.dev20250130.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
331
- flwr_nightly-1.15.0.dev20250130.dist-info/METADATA,sha256=dbjtqlBMS612vZE-bOQsxhq7gtEDGtyPWAxDiMqS_LM,15873
332
- flwr_nightly-1.15.0.dev20250130.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
333
- flwr_nightly-1.15.0.dev20250130.dist-info/entry_points.txt,sha256=JlNxX3qhaV18_2yj5a3kJW1ESxm31cal9iS_N_pf1Rk,538
334
- flwr_nightly-1.15.0.dev20250130.dist-info/RECORD,,
330
+ flwr_nightly-1.15.2.dev20250214.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
331
+ flwr_nightly-1.15.2.dev20250214.dist-info/METADATA,sha256=wzTSnImyVoIq3yRELxxOkJoOzNAAIt1v9sqfR0Os_7k,15873
332
+ flwr_nightly-1.15.2.dev20250214.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
333
+ flwr_nightly-1.15.2.dev20250214.dist-info/entry_points.txt,sha256=JlNxX3qhaV18_2yj5a3kJW1ESxm31cal9iS_N_pf1Rk,538
334
+ flwr_nightly-1.15.2.dev20250214.dist-info/RECORD,,