flwr 1.21.0__py3-none-any.whl → 1.22.0__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 (97) hide show
  1. flwr/cli/app.py +2 -0
  2. flwr/cli/new/new.py +9 -7
  3. flwr/cli/new/templates/app/README.flowertune.md.tpl +1 -1
  4. flwr/cli/new/templates/app/code/client.baseline.py.tpl +64 -47
  5. flwr/cli/new/templates/app/code/client.huggingface.py.tpl +68 -30
  6. flwr/cli/new/templates/app/code/client.jax.py.tpl +63 -42
  7. flwr/cli/new/templates/app/code/client.mlx.py.tpl +80 -51
  8. flwr/cli/new/templates/app/code/client.numpy.py.tpl +36 -13
  9. flwr/cli/new/templates/app/code/client.pytorch.py.tpl +71 -46
  10. flwr/cli/new/templates/app/code/client.pytorch_legacy_api.py.tpl +55 -0
  11. flwr/cli/new/templates/app/code/client.sklearn.py.tpl +75 -30
  12. flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +69 -44
  13. flwr/cli/new/templates/app/code/client.xgboost.py.tpl +110 -0
  14. flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +56 -90
  15. flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +1 -23
  16. flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +37 -58
  17. flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +39 -44
  18. flwr/cli/new/templates/app/code/model.baseline.py.tpl +0 -14
  19. flwr/cli/new/templates/app/code/server.baseline.py.tpl +27 -29
  20. flwr/cli/new/templates/app/code/server.huggingface.py.tpl +23 -19
  21. flwr/cli/new/templates/app/code/server.jax.py.tpl +27 -14
  22. flwr/cli/new/templates/app/code/server.mlx.py.tpl +29 -19
  23. flwr/cli/new/templates/app/code/server.numpy.py.tpl +30 -17
  24. flwr/cli/new/templates/app/code/server.pytorch.py.tpl +36 -26
  25. flwr/cli/new/templates/app/code/server.pytorch_legacy_api.py.tpl +31 -0
  26. flwr/cli/new/templates/app/code/server.sklearn.py.tpl +29 -21
  27. flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +28 -19
  28. flwr/cli/new/templates/app/code/server.xgboost.py.tpl +56 -0
  29. flwr/cli/new/templates/app/code/task.huggingface.py.tpl +16 -20
  30. flwr/cli/new/templates/app/code/task.jax.py.tpl +1 -1
  31. flwr/cli/new/templates/app/code/task.numpy.py.tpl +1 -1
  32. flwr/cli/new/templates/app/code/task.pytorch.py.tpl +14 -27
  33. flwr/cli/new/templates/app/code/{task.pytorch_msg_api.py.tpl → task.pytorch_legacy_api.py.tpl} +27 -14
  34. flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +1 -2
  35. flwr/cli/new/templates/app/code/task.xgboost.py.tpl +67 -0
  36. flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +4 -4
  37. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +2 -2
  38. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +4 -4
  39. flwr/cli/new/templates/app/pyproject.jax.toml.tpl +1 -1
  40. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +2 -2
  41. flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +1 -1
  42. flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +3 -3
  43. flwr/cli/new/templates/app/{pyproject.pytorch_msg_api.toml.tpl → pyproject.pytorch_legacy_api.toml.tpl} +3 -3
  44. flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +1 -1
  45. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +1 -1
  46. flwr/cli/new/templates/app/pyproject.xgboost.toml.tpl +61 -0
  47. flwr/cli/pull.py +100 -0
  48. flwr/cli/utils.py +17 -0
  49. flwr/clientapp/mod/__init__.py +4 -1
  50. flwr/clientapp/mod/centraldp_mods.py +156 -40
  51. flwr/clientapp/mod/localdp_mod.py +169 -0
  52. flwr/clientapp/typing.py +22 -0
  53. flwr/common/constant.py +3 -0
  54. flwr/common/exit/exit_code.py +4 -0
  55. flwr/common/record/typeddict.py +12 -0
  56. flwr/proto/control_pb2.py +7 -3
  57. flwr/proto/control_pb2.pyi +24 -0
  58. flwr/proto/control_pb2_grpc.py +34 -0
  59. flwr/proto/control_pb2_grpc.pyi +13 -0
  60. flwr/server/app.py +13 -0
  61. flwr/serverapp/strategy/__init__.py +26 -0
  62. flwr/serverapp/strategy/bulyan.py +238 -0
  63. flwr/serverapp/strategy/dp_adaptive_clipping.py +335 -0
  64. flwr/serverapp/strategy/dp_fixed_clipping.py +71 -49
  65. flwr/serverapp/strategy/fedadagrad.py +0 -3
  66. flwr/serverapp/strategy/fedadam.py +0 -3
  67. flwr/serverapp/strategy/fedavg.py +89 -64
  68. flwr/serverapp/strategy/fedavgm.py +198 -0
  69. flwr/serverapp/strategy/fedmedian.py +105 -0
  70. flwr/serverapp/strategy/fedprox.py +174 -0
  71. flwr/serverapp/strategy/fedtrimmedavg.py +176 -0
  72. flwr/serverapp/strategy/fedxgb_bagging.py +117 -0
  73. flwr/serverapp/strategy/fedxgb_cyclic.py +220 -0
  74. flwr/serverapp/strategy/fedyogi.py +0 -3
  75. flwr/serverapp/strategy/krum.py +112 -0
  76. flwr/serverapp/strategy/multikrum.py +247 -0
  77. flwr/serverapp/strategy/qfedavg.py +252 -0
  78. flwr/serverapp/strategy/strategy_utils.py +48 -0
  79. flwr/simulation/app.py +1 -1
  80. flwr/simulation/run_simulation.py +25 -30
  81. flwr/supercore/cli/flower_superexec.py +26 -1
  82. flwr/supercore/constant.py +19 -0
  83. flwr/supercore/superexec/plugin/exec_plugin.py +11 -1
  84. flwr/supercore/superexec/run_superexec.py +16 -2
  85. flwr/superlink/artifact_provider/__init__.py +22 -0
  86. flwr/superlink/artifact_provider/artifact_provider.py +37 -0
  87. flwr/superlink/servicer/control/control_grpc.py +3 -0
  88. flwr/superlink/servicer/control/control_servicer.py +59 -2
  89. {flwr-1.21.0.dist-info → flwr-1.22.0.dist-info}/METADATA +6 -16
  90. {flwr-1.21.0.dist-info → flwr-1.22.0.dist-info}/RECORD +93 -74
  91. flwr/cli/new/templates/app/code/client.pytorch_msg_api.py.tpl +0 -80
  92. flwr/cli/new/templates/app/code/server.pytorch_msg_api.py.tpl +0 -41
  93. flwr/serverapp/dp_fixed_clipping.py +0 -352
  94. flwr/serverapp/strategy/strategy_utils_tests.py +0 -304
  95. /flwr/cli/new/templates/app/code/{__init__.pytorch_msg_api.py.tpl → __init__.pytorch_legacy_api.py.tpl} +0 -0
  96. {flwr-1.21.0.dist-info → flwr-1.22.0.dist-info}/WHEEL +0 -0
  97. {flwr-1.21.0.dist-info → flwr-1.22.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,67 @@
1
+ """$project_name: A Flower / $framework_str app."""
2
+
3
+ import xgboost as xgb
4
+ from flwr_datasets import FederatedDataset
5
+ from flwr_datasets.partitioner import IidPartitioner
6
+
7
+
8
+ def train_test_split(partition, test_fraction, seed):
9
+ """Split the data into train and validation set given split rate."""
10
+ train_test = partition.train_test_split(test_size=test_fraction, seed=seed)
11
+ partition_train = train_test["train"]
12
+ partition_test = train_test["test"]
13
+
14
+ num_train = len(partition_train)
15
+ num_test = len(partition_test)
16
+
17
+ return partition_train, partition_test, num_train, num_test
18
+
19
+
20
+ def transform_dataset_to_dmatrix(data):
21
+ """Transform dataset to DMatrix format for xgboost."""
22
+ x = data["inputs"]
23
+ y = data["label"]
24
+ new_data = xgb.DMatrix(x, label=y)
25
+ return new_data
26
+
27
+
28
+ fds = None # Cache FederatedDataset
29
+
30
+
31
+ def load_data(partition_id, num_clients):
32
+ """Load partition HIGGS data."""
33
+ # Only initialize `FederatedDataset` once
34
+ global fds
35
+ if fds is None:
36
+ partitioner = IidPartitioner(num_partitions=num_clients)
37
+ fds = FederatedDataset(
38
+ dataset="jxie/higgs",
39
+ partitioners={"train": partitioner},
40
+ )
41
+
42
+ # Load the partition for this `partition_id`
43
+ partition = fds.load_partition(partition_id, split="train")
44
+ partition.set_format("numpy")
45
+
46
+ # Train/test splitting
47
+ train_data, valid_data, num_train, num_val = train_test_split(
48
+ partition, test_fraction=0.2, seed=42
49
+ )
50
+
51
+ # Reformat data to DMatrix for xgboost
52
+ train_dmatrix = transform_dataset_to_dmatrix(train_data)
53
+ valid_dmatrix = transform_dataset_to_dmatrix(valid_data)
54
+
55
+ return train_dmatrix, valid_dmatrix, num_train, num_val
56
+
57
+
58
+ def replace_keys(input_dict, match="-", target="_"):
59
+ """Recursively replace match string with target string in dictionary keys."""
60
+ new_dict = {}
61
+ for key, value in input_dict.items():
62
+ new_key = key.replace(match, target)
63
+ if isinstance(value, dict):
64
+ new_dict[new_key] = replace_keys(value, match, target)
65
+ else:
66
+ new_dict[new_key] = value
67
+ return new_dict
@@ -14,10 +14,10 @@ description = ""
14
14
  license = "Apache-2.0"
15
15
  # Dependencies for your Flower App
16
16
  dependencies = [
17
- "flwr[simulation]>=1.21.0",
17
+ "flwr[simulation]>=1.22.0",
18
18
  "flwr-datasets[vision]>=0.5.0",
19
- "torch==2.7.1",
20
- "torchvision==0.22.1",
19
+ "torch==2.8.0",
20
+ "torchvision==0.23.0",
21
21
  ]
22
22
 
23
23
  [tool.hatch.metadata]
@@ -132,7 +132,7 @@ clientapp = "$import_name.client_app:app"
132
132
  # Custom config values accessible via `context.run_config`
133
133
  [tool.flwr.app.config]
134
134
  num-server-rounds = 3
135
- fraction-fit = 0.5
135
+ fraction-train = 0.5
136
136
  local-epochs = 1
137
137
 
138
138
  # Default federation to use when running the app
@@ -14,7 +14,7 @@ description = ""
14
14
  license = "Apache-2.0"
15
15
  # Dependencies for your Flower App
16
16
  dependencies = [
17
- "flwr[simulation]>=1.21.0",
17
+ "flwr[simulation]>=1.22.0",
18
18
  "flwr-datasets>=0.5.0",
19
19
  "torch==2.4.0",
20
20
  "trl==0.8.1",
@@ -61,7 +61,7 @@ train.training-arguments.save-steps = 1000
61
61
  train.training-arguments.save-total-limit = 10
62
62
  train.training-arguments.gradient-checkpointing = true
63
63
  train.training-arguments.lr-scheduler-type = "constant"
64
- strategy.fraction-fit = $fraction_fit
64
+ strategy.fraction-train = $fraction_train
65
65
  strategy.fraction-evaluate = 0.0
66
66
  num-server-rounds = 200
67
67
 
@@ -14,9 +14,9 @@ description = ""
14
14
  license = "Apache-2.0"
15
15
  # Dependencies for your Flower App
16
16
  dependencies = [
17
- "flwr[simulation]>=1.21.0",
17
+ "flwr[simulation]>=1.22.0",
18
18
  "flwr-datasets>=0.5.0",
19
- "torch==2.7.1",
19
+ "torch>=2.7.1",
20
20
  "transformers>=4.30.0,<5.0",
21
21
  "evaluate>=0.4.0,<1.0",
22
22
  "datasets>=2.0.0, <3.0",
@@ -38,8 +38,8 @@ clientapp = "$import_name.client_app:app"
38
38
  # Custom config values accessible via `context.run_config`
39
39
  [tool.flwr.app.config]
40
40
  num-server-rounds = 3
41
- fraction-fit = 0.5
42
- local-epochs = 1
41
+ fraction-train = 0.5
42
+ local-steps = 5
43
43
  model-name = "prajjwal1/bert-tiny" # Set a larger model if you have access to more GPU resources
44
44
  num-labels = 2
45
45
 
@@ -14,7 +14,7 @@ description = ""
14
14
  license = "Apache-2.0"
15
15
  # Dependencies for your Flower App
16
16
  dependencies = [
17
- "flwr[simulation]>=1.21.0",
17
+ "flwr[simulation]>=1.22.0",
18
18
  "jax==0.4.30",
19
19
  "jaxlib==0.4.30",
20
20
  "scikit-learn==1.6.1",
@@ -14,9 +14,9 @@ description = ""
14
14
  license = "Apache-2.0"
15
15
  # Dependencies for your Flower App
16
16
  dependencies = [
17
- "flwr[simulation]>=1.21.0",
17
+ "flwr[simulation]>=1.22.0",
18
18
  "flwr-datasets[vision]>=0.5.0",
19
- "mlx==0.26.5",
19
+ "mlx==0.29.0",
20
20
  ]
21
21
 
22
22
  [tool.hatch.build.targets.wheel]
@@ -14,7 +14,7 @@ description = ""
14
14
  license = "Apache-2.0"
15
15
  # Dependencies for your Flower App
16
16
  dependencies = [
17
- "flwr[simulation]>=1.21.0",
17
+ "flwr[simulation]>=1.22.0",
18
18
  "numpy>=2.0.2",
19
19
  ]
20
20
 
@@ -14,7 +14,7 @@ description = ""
14
14
  license = "Apache-2.0"
15
15
  # Dependencies for your Flower App
16
16
  dependencies = [
17
- "flwr[simulation]>=1.21.0",
17
+ "flwr[simulation]>=1.22.0",
18
18
  "flwr-datasets[vision]>=0.5.0",
19
19
  "torch==2.7.1",
20
20
  "torchvision==0.22.1",
@@ -27,7 +27,6 @@ packages = ["."]
27
27
  publisher = "$username"
28
28
 
29
29
  # Point to your ServerApp and ClientApp objects
30
- # Format: "<module>:<object>"
31
30
  [tool.flwr.app.components]
32
31
  serverapp = "$import_name.server_app:app"
33
32
  clientapp = "$import_name.client_app:app"
@@ -35,8 +34,9 @@ clientapp = "$import_name.client_app:app"
35
34
  # Custom config values accessible via `context.run_config`
36
35
  [tool.flwr.app.config]
37
36
  num-server-rounds = 3
38
- fraction-fit = 0.5
37
+ fraction-train = 0.5
39
38
  local-epochs = 1
39
+ lr = 0.01
40
40
 
41
41
  # Default federation to use when running the app
42
42
  [tool.flwr.federations]
@@ -14,7 +14,7 @@ description = ""
14
14
  license = "Apache-2.0"
15
15
  # Dependencies for your Flower App
16
16
  dependencies = [
17
- "flwr[simulation]>=1.21.0",
17
+ "flwr[simulation]>=1.22.0",
18
18
  "flwr-datasets[vision]>=0.5.0",
19
19
  "torch==2.7.1",
20
20
  "torchvision==0.22.1",
@@ -27,6 +27,7 @@ packages = ["."]
27
27
  publisher = "$username"
28
28
 
29
29
  # Point to your ServerApp and ClientApp objects
30
+ # Format: "<module>:<object>"
30
31
  [tool.flwr.app.components]
31
32
  serverapp = "$import_name.server_app:app"
32
33
  clientapp = "$import_name.client_app:app"
@@ -34,9 +35,8 @@ clientapp = "$import_name.client_app:app"
34
35
  # Custom config values accessible via `context.run_config`
35
36
  [tool.flwr.app.config]
36
37
  num-server-rounds = 3
37
- fraction-train = 0.5
38
+ fraction-fit = 0.5
38
39
  local-epochs = 1
39
- lr = 0.01
40
40
 
41
41
  # Default federation to use when running the app
42
42
  [tool.flwr.federations]
@@ -14,7 +14,7 @@ description = ""
14
14
  license = "Apache-2.0"
15
15
  # Dependencies for your Flower App
16
16
  dependencies = [
17
- "flwr[simulation]>=1.21.0",
17
+ "flwr[simulation]>=1.22.0",
18
18
  "flwr-datasets[vision]>=0.5.0",
19
19
  "scikit-learn>=1.6.1",
20
20
  ]
@@ -14,7 +14,7 @@ description = ""
14
14
  license = "Apache-2.0"
15
15
  # Dependencies for your Flower App
16
16
  dependencies = [
17
- "flwr[simulation]>=1.21.0",
17
+ "flwr[simulation]>=1.22.0",
18
18
  "flwr-datasets[vision]>=0.5.0",
19
19
  "tensorflow>=2.11.1,<2.18.0",
20
20
  ]
@@ -0,0 +1,61 @@
1
+ # =====================================================================
2
+ # For a full TOML configuration guide, check the Flower docs:
3
+ # https://flower.ai/docs/framework/how-to-configure-pyproject-toml.html
4
+ # =====================================================================
5
+
6
+ [build-system]
7
+ requires = ["hatchling"]
8
+ build-backend = "hatchling.build"
9
+
10
+ [project]
11
+ name = "$package_name"
12
+ version = "1.0.0"
13
+ description = ""
14
+ license = "Apache-2.0"
15
+ # Dependencies for your Flower App
16
+ dependencies = [
17
+ "flwr[simulation]>=1.22.0",
18
+ "flwr-datasets>=0.5.0",
19
+ "xgboost>=2.0.0",
20
+ ]
21
+
22
+ [tool.hatch.build.targets.wheel]
23
+ packages = ["."]
24
+
25
+ [tool.flwr.app]
26
+ publisher = "$username"
27
+
28
+ [tool.flwr.app.components]
29
+ serverapp = "$import_name.server_app:app"
30
+ clientapp = "$import_name.client_app:app"
31
+
32
+ # Custom config values accessible via `context.run_config`
33
+ [tool.flwr.app.config]
34
+ num-server-rounds = 3
35
+ fraction-train = 0.1
36
+ fraction-evaluate = 0.1
37
+ local-epochs = 1
38
+
39
+ # XGBoost parameters
40
+ params.objective = "binary:logistic"
41
+ params.eta = 0.1 # Learning rate
42
+ params.max-depth = 8
43
+ params.eval-metric = "auc"
44
+ params.nthread = 16
45
+ params.num-parallel-tree = 1
46
+ params.subsample = 1
47
+ params.tree-method = "hist"
48
+
49
+ # Default federation to use when running the app
50
+ [tool.flwr.federations]
51
+ default = "local-simulation"
52
+
53
+ # Local simulation federation with 10 virtual SuperNodes
54
+ [tool.flwr.federations.local-simulation]
55
+ options.num-supernodes = 10
56
+
57
+ # Remote federation example for use with SuperLink
58
+ [tool.flwr.federations.remote-federation]
59
+ address = "<SUPERLINK-ADDRESS>:<PORT>"
60
+ insecure = true # Remove this line to enable TLS
61
+ # root-certificates = "<PATH/TO/ca.crt>" # For TLS setup
flwr/cli/pull.py ADDED
@@ -0,0 +1,100 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Flower command line interface `pull` command."""
16
+
17
+
18
+ from pathlib import Path
19
+ from typing import Annotated, Optional
20
+
21
+ import typer
22
+
23
+ from flwr.cli.config_utils import (
24
+ exit_if_no_address,
25
+ load_and_validate,
26
+ process_loaded_project_config,
27
+ validate_federation_in_project_config,
28
+ )
29
+ from flwr.cli.constant import FEDERATION_CONFIG_HELP_MESSAGE
30
+ from flwr.common.constant import FAB_CONFIG_FILE
31
+ from flwr.proto.control_pb2 import ( # pylint: disable=E0611
32
+ PullArtifactsRequest,
33
+ PullArtifactsResponse,
34
+ )
35
+ from flwr.proto.control_pb2_grpc import ControlStub
36
+
37
+ from .utils import flwr_cli_grpc_exc_handler, init_channel, try_obtain_cli_auth_plugin
38
+
39
+
40
+ def pull( # pylint: disable=R0914
41
+ run_id: Annotated[
42
+ int,
43
+ typer.Option(
44
+ "--run-id",
45
+ help="Run ID to pull artifacts from.",
46
+ ),
47
+ ],
48
+ app: Annotated[
49
+ Path,
50
+ typer.Argument(help="Path of the Flower App to run."),
51
+ ] = Path("."),
52
+ federation: Annotated[
53
+ Optional[str],
54
+ typer.Argument(help="Name of the federation."),
55
+ ] = None,
56
+ federation_config_overrides: Annotated[
57
+ Optional[list[str]],
58
+ typer.Option(
59
+ "--federation-config",
60
+ help=FEDERATION_CONFIG_HELP_MESSAGE,
61
+ ),
62
+ ] = None,
63
+ ) -> None:
64
+ """Pull artifacts from a Flower run."""
65
+ typer.secho("Loading project configuration... ", fg=typer.colors.BLUE)
66
+
67
+ pyproject_path = app / FAB_CONFIG_FILE if app else None
68
+ config, errors, warnings = load_and_validate(path=pyproject_path)
69
+ config = process_loaded_project_config(config, errors, warnings)
70
+ federation, federation_config = validate_federation_in_project_config(
71
+ federation, config, federation_config_overrides
72
+ )
73
+ exit_if_no_address(federation_config, "pull")
74
+ channel = None
75
+ try:
76
+
77
+ auth_plugin = try_obtain_cli_auth_plugin(app, federation, federation_config)
78
+ channel = init_channel(app, federation_config, auth_plugin)
79
+ stub = ControlStub(channel)
80
+ with flwr_cli_grpc_exc_handler():
81
+ res: PullArtifactsResponse = stub.PullArtifacts(
82
+ PullArtifactsRequest(run_id=run_id)
83
+ )
84
+
85
+ if not res.url:
86
+ typer.secho(
87
+ f"❌ A download URL for artifacts from run {run_id} couldn't be "
88
+ "obtained.",
89
+ fg=typer.colors.RED,
90
+ bold=True,
91
+ )
92
+ raise typer.Exit(code=1)
93
+
94
+ typer.secho(
95
+ f"✅ Artifacts for run {run_id} can be downloaded from: {res.url}",
96
+ fg=typer.colors.GREEN,
97
+ )
98
+ finally:
99
+ if channel:
100
+ channel.close()
flwr/cli/utils.py CHANGED
@@ -32,7 +32,9 @@ from flwr.common.constant import (
32
32
  AUTH_TYPE_JSON_KEY,
33
33
  CREDENTIALS_DIR,
34
34
  FLWR_DIR,
35
+ NO_ARTIFACT_PROVIDER_MESSAGE,
35
36
  NO_USER_AUTH_MESSAGE,
37
+ PULL_UNFINISHED_RUN_MESSAGE,
36
38
  RUN_ID_NOT_FOUND_MESSAGE,
37
39
  )
38
40
  from flwr.common.grpc import (
@@ -319,6 +321,12 @@ def flwr_cli_grpc_exc_handler() -> Iterator[None]:
319
321
  fg=typer.colors.RED,
320
322
  bold=True,
321
323
  )
324
+ elif e.details() == NO_ARTIFACT_PROVIDER_MESSAGE: # pylint: disable=E1101
325
+ typer.secho(
326
+ "❌ The SuperLink does not support `flwr pull` command.",
327
+ fg=typer.colors.RED,
328
+ bold=True,
329
+ )
322
330
  else:
323
331
  typer.secho(
324
332
  "❌ The SuperLink cannot process this request. Please verify that "
@@ -356,4 +364,13 @@ def flwr_cli_grpc_exc_handler() -> Iterator[None]:
356
364
  bold=True,
357
365
  )
358
366
  raise typer.Exit(code=1) from None
367
+ if e.code() == grpc.StatusCode.FAILED_PRECONDITION:
368
+ if e.details() == PULL_UNFINISHED_RUN_MESSAGE: # pylint: disable=E1101
369
+ typer.secho(
370
+ "❌ Run is not finished yet. Artifacts can only be pulled after "
371
+ "the run is finished. You can check the run status with `flwr ls`.",
372
+ fg=typer.colors.RED,
373
+ bold=True,
374
+ )
375
+ raise typer.Exit(code=1) from None
359
376
  raise
@@ -17,9 +17,12 @@
17
17
 
18
18
  from flwr.client.mod.comms_mods import arrays_size_mod, message_size_mod
19
19
 
20
- from .centraldp_mods import fixedclipping_mod
20
+ from .centraldp_mods import adaptiveclipping_mod, fixedclipping_mod
21
+ from .localdp_mod import LocalDpMod
21
22
 
22
23
  __all__ = [
24
+ "LocalDpMod",
25
+ "adaptiveclipping_mod",
23
26
  "arrays_size_mod",
24
27
  "fixedclipping_mod",
25
28
  "message_size_mod",