flwr 1.23.0__py3-none-any.whl → 1.24.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.
- flwr/__init__.py +16 -5
- flwr/app/error.py +2 -2
- flwr/app/exception.py +3 -3
- flwr/cli/app.py +19 -0
- flwr/cli/app_cmd/__init__.py +23 -0
- flwr/cli/app_cmd/publish.py +285 -0
- flwr/cli/app_cmd/review.py +252 -0
- flwr/cli/auth_plugin/auth_plugin.py +4 -5
- flwr/cli/auth_plugin/noop_auth_plugin.py +54 -11
- flwr/cli/auth_plugin/oidc_cli_plugin.py +32 -9
- flwr/cli/build.py +60 -18
- flwr/cli/cli_account_auth_interceptor.py +24 -7
- flwr/cli/config_utils.py +101 -13
- flwr/cli/federation/__init__.py +24 -0
- flwr/cli/federation/ls.py +140 -0
- flwr/cli/federation/show.py +317 -0
- flwr/cli/install.py +91 -13
- flwr/cli/log.py +52 -9
- flwr/cli/login/login.py +7 -4
- flwr/cli/ls.py +170 -130
- flwr/cli/new/new.py +33 -50
- flwr/cli/new/templates/app/code/task.pytorch.py.tpl +1 -0
- flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.jax.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +3 -3
- flwr/cli/new/templates/app/pyproject.pytorch_legacy_api.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +2 -2
- flwr/cli/new/templates/app/pyproject.xgboost.toml.tpl +1 -1
- flwr/cli/pull.py +10 -5
- flwr/cli/run/run.py +77 -30
- flwr/cli/run_utils.py +130 -0
- flwr/cli/stop.py +25 -7
- flwr/cli/supernode/ls.py +16 -8
- flwr/cli/supernode/register.py +9 -4
- flwr/cli/supernode/unregister.py +5 -3
- flwr/cli/utils.py +376 -16
- flwr/client/__init__.py +1 -1
- flwr/client/dpfedavg_numpy_client.py +4 -1
- flwr/client/grpc_adapter_client/connection.py +6 -7
- flwr/client/grpc_rere_client/connection.py +10 -11
- flwr/client/grpc_rere_client/grpc_adapter.py +6 -2
- flwr/client/grpc_rere_client/node_auth_client_interceptor.py +2 -1
- flwr/client/message_handler/message_handler.py +2 -2
- flwr/client/mod/secure_aggregation/secaggplus_mod.py +3 -3
- flwr/client/numpy_client.py +1 -1
- flwr/client/rest_client/connection.py +12 -14
- flwr/client/run_info_store.py +4 -5
- flwr/client/typing.py +1 -1
- flwr/clientapp/client_app.py +9 -10
- flwr/clientapp/mod/centraldp_mods.py +16 -17
- flwr/clientapp/mod/localdp_mod.py +8 -9
- flwr/clientapp/typing.py +1 -1
- flwr/clientapp/utils.py +3 -3
- flwr/common/address.py +1 -2
- flwr/common/args.py +3 -4
- flwr/common/config.py +13 -16
- flwr/common/constant.py +5 -2
- flwr/common/differential_privacy.py +3 -4
- flwr/common/event_log_plugin/event_log_plugin.py +3 -4
- flwr/common/exit/exit.py +15 -2
- flwr/common/exit/exit_code.py +19 -0
- flwr/common/exit/exit_handler.py +6 -2
- flwr/common/exit/signal_handler.py +5 -5
- flwr/common/grpc.py +6 -6
- flwr/common/inflatable_protobuf_utils.py +1 -1
- flwr/common/inflatable_utils.py +38 -21
- flwr/common/logger.py +19 -19
- flwr/common/message.py +4 -4
- flwr/common/object_ref.py +7 -7
- flwr/common/record/array.py +3 -3
- flwr/common/record/arrayrecord.py +18 -30
- flwr/common/record/configrecord.py +3 -3
- flwr/common/record/recorddict.py +5 -5
- flwr/common/record/typeddict.py +9 -2
- flwr/common/recorddict_compat.py +7 -10
- flwr/common/retry_invoker.py +20 -20
- flwr/common/secure_aggregation/ndarrays_arithmetic.py +3 -3
- flwr/common/serde.py +5 -4
- flwr/common/serde_utils.py +2 -2
- flwr/common/telemetry.py +9 -5
- flwr/common/typing.py +52 -37
- flwr/compat/client/app.py +38 -37
- flwr/compat/client/grpc_client/connection.py +11 -11
- flwr/compat/server/app.py +5 -6
- flwr/proto/appio_pb2.py +13 -3
- flwr/proto/appio_pb2.pyi +134 -65
- flwr/proto/appio_pb2_grpc.py +20 -0
- flwr/proto/appio_pb2_grpc.pyi +27 -0
- flwr/proto/clientappio_pb2.py +17 -7
- flwr/proto/clientappio_pb2.pyi +15 -0
- flwr/proto/clientappio_pb2_grpc.py +206 -40
- flwr/proto/clientappio_pb2_grpc.pyi +168 -53
- flwr/proto/control_pb2.py +71 -52
- flwr/proto/control_pb2.pyi +277 -111
- flwr/proto/control_pb2_grpc.py +249 -40
- flwr/proto/control_pb2_grpc.pyi +185 -52
- flwr/proto/error_pb2.py +13 -3
- flwr/proto/error_pb2.pyi +24 -6
- flwr/proto/error_pb2_grpc.py +20 -0
- flwr/proto/error_pb2_grpc.pyi +27 -0
- flwr/proto/fab_pb2.py +14 -4
- flwr/proto/fab_pb2.pyi +59 -31
- flwr/proto/fab_pb2_grpc.py +20 -0
- flwr/proto/fab_pb2_grpc.pyi +27 -0
- flwr/proto/federation_pb2.py +38 -0
- flwr/proto/federation_pb2.pyi +56 -0
- flwr/proto/federation_pb2_grpc.py +24 -0
- flwr/proto/federation_pb2_grpc.pyi +31 -0
- flwr/proto/fleet_pb2.py +14 -4
- flwr/proto/fleet_pb2.pyi +137 -61
- flwr/proto/fleet_pb2_grpc.py +189 -48
- flwr/proto/fleet_pb2_grpc.pyi +175 -61
- flwr/proto/grpcadapter_pb2.py +14 -4
- flwr/proto/grpcadapter_pb2.pyi +38 -16
- flwr/proto/grpcadapter_pb2_grpc.py +35 -4
- flwr/proto/grpcadapter_pb2_grpc.pyi +38 -7
- flwr/proto/heartbeat_pb2.py +17 -7
- flwr/proto/heartbeat_pb2.pyi +51 -22
- flwr/proto/heartbeat_pb2_grpc.py +20 -0
- flwr/proto/heartbeat_pb2_grpc.pyi +27 -0
- flwr/proto/log_pb2.py +13 -3
- flwr/proto/log_pb2.pyi +34 -11
- flwr/proto/log_pb2_grpc.py +20 -0
- flwr/proto/log_pb2_grpc.pyi +27 -0
- flwr/proto/message_pb2.py +15 -5
- flwr/proto/message_pb2.pyi +154 -86
- flwr/proto/message_pb2_grpc.py +20 -0
- flwr/proto/message_pb2_grpc.pyi +27 -0
- flwr/proto/node_pb2.py +15 -5
- flwr/proto/node_pb2.pyi +50 -25
- flwr/proto/node_pb2_grpc.py +20 -0
- flwr/proto/node_pb2_grpc.pyi +27 -0
- flwr/proto/recorddict_pb2.py +13 -3
- flwr/proto/recorddict_pb2.pyi +184 -107
- flwr/proto/recorddict_pb2_grpc.py +20 -0
- flwr/proto/recorddict_pb2_grpc.pyi +27 -0
- flwr/proto/run_pb2.py +40 -31
- flwr/proto/run_pb2.pyi +149 -84
- flwr/proto/run_pb2_grpc.py +20 -0
- flwr/proto/run_pb2_grpc.pyi +27 -0
- flwr/proto/serverappio_pb2.py +13 -3
- flwr/proto/serverappio_pb2.pyi +32 -8
- flwr/proto/serverappio_pb2_grpc.py +246 -65
- flwr/proto/serverappio_pb2_grpc.pyi +221 -85
- flwr/proto/simulationio_pb2.py +16 -8
- flwr/proto/simulationio_pb2.pyi +15 -0
- flwr/proto/simulationio_pb2_grpc.py +162 -41
- flwr/proto/simulationio_pb2_grpc.pyi +149 -55
- flwr/proto/transport_pb2.py +20 -10
- flwr/proto/transport_pb2.pyi +249 -160
- flwr/proto/transport_pb2_grpc.py +35 -4
- flwr/proto/transport_pb2_grpc.pyi +38 -8
- flwr/server/app.py +38 -17
- flwr/server/client_manager.py +4 -5
- flwr/server/client_proxy.py +10 -11
- flwr/server/compat/app.py +4 -5
- flwr/server/compat/app_utils.py +2 -1
- flwr/server/compat/grid_client_proxy.py +10 -12
- flwr/server/compat/legacy_context.py +3 -4
- flwr/server/fleet_event_log_interceptor.py +2 -1
- flwr/server/grid/grid.py +2 -3
- flwr/server/grid/grpc_grid.py +10 -8
- flwr/server/grid/inmemory_grid.py +4 -4
- flwr/server/run_serverapp.py +2 -3
- flwr/server/server.py +34 -39
- flwr/server/server_app.py +7 -8
- flwr/server/server_config.py +1 -2
- flwr/server/serverapp/app.py +34 -28
- flwr/server/serverapp_components.py +4 -5
- flwr/server/strategy/aggregate.py +9 -8
- flwr/server/strategy/bulyan.py +13 -11
- flwr/server/strategy/dp_adaptive_clipping.py +16 -20
- flwr/server/strategy/dp_fixed_clipping.py +12 -17
- flwr/server/strategy/dpfedavg_adaptive.py +3 -4
- flwr/server/strategy/dpfedavg_fixed.py +6 -10
- flwr/server/strategy/fault_tolerant_fedavg.py +14 -13
- flwr/server/strategy/fedadagrad.py +18 -14
- flwr/server/strategy/fedadam.py +16 -14
- flwr/server/strategy/fedavg.py +16 -17
- flwr/server/strategy/fedavg_android.py +15 -15
- flwr/server/strategy/fedavgm.py +21 -18
- flwr/server/strategy/fedmedian.py +2 -3
- flwr/server/strategy/fedopt.py +11 -10
- flwr/server/strategy/fedprox.py +10 -9
- flwr/server/strategy/fedtrimmedavg.py +12 -11
- flwr/server/strategy/fedxgb_bagging.py +13 -11
- flwr/server/strategy/fedxgb_cyclic.py +6 -6
- flwr/server/strategy/fedxgb_nn_avg.py +4 -4
- flwr/server/strategy/fedyogi.py +16 -14
- flwr/server/strategy/krum.py +12 -11
- flwr/server/strategy/qfedavg.py +16 -15
- flwr/server/strategy/strategy.py +6 -9
- flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +2 -1
- flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +1 -2
- flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +3 -4
- flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +10 -12
- flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +1 -3
- flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +4 -4
- flwr/server/superlink/fleet/grpc_rere/node_auth_server_interceptor.py +3 -2
- flwr/server/superlink/fleet/message_handler/message_handler.py +34 -28
- flwr/server/superlink/fleet/rest_rere/rest_api.py +2 -2
- flwr/server/superlink/fleet/vce/backend/backend.py +1 -1
- flwr/server/superlink/fleet/vce/backend/raybackend.py +5 -5
- flwr/server/superlink/fleet/vce/vce_api.py +15 -9
- flwr/server/superlink/linkstate/in_memory_linkstate.py +115 -150
- flwr/server/superlink/linkstate/linkstate.py +59 -43
- flwr/server/superlink/linkstate/linkstate_factory.py +22 -5
- flwr/server/superlink/linkstate/sqlite_linkstate.py +447 -438
- flwr/server/superlink/linkstate/utils.py +6 -6
- flwr/server/superlink/serverappio/serverappio_grpc.py +1 -2
- flwr/server/superlink/serverappio/serverappio_servicer.py +26 -21
- flwr/server/superlink/simulation/simulationio_grpc.py +1 -2
- flwr/server/superlink/simulation/simulationio_servicer.py +18 -13
- flwr/server/superlink/utils.py +4 -6
- flwr/server/typing.py +1 -1
- flwr/server/utils/tensorboard.py +15 -8
- flwr/server/workflow/default_workflows.py +5 -5
- flwr/server/workflow/secure_aggregation/secagg_workflow.py +2 -4
- flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +8 -8
- flwr/serverapp/strategy/bulyan.py +16 -15
- flwr/serverapp/strategy/dp_adaptive_clipping.py +12 -11
- flwr/serverapp/strategy/dp_fixed_clipping.py +11 -14
- flwr/serverapp/strategy/fedadagrad.py +10 -11
- flwr/serverapp/strategy/fedadam.py +10 -11
- flwr/serverapp/strategy/fedavg.py +9 -10
- flwr/serverapp/strategy/fedavgm.py +17 -16
- flwr/serverapp/strategy/fedmedian.py +2 -2
- flwr/serverapp/strategy/fedopt.py +10 -11
- flwr/serverapp/strategy/fedprox.py +7 -8
- flwr/serverapp/strategy/fedtrimmedavg.py +9 -9
- flwr/serverapp/strategy/fedxgb_bagging.py +3 -3
- flwr/serverapp/strategy/fedxgb_cyclic.py +9 -9
- flwr/serverapp/strategy/fedyogi.py +9 -11
- flwr/serverapp/strategy/krum.py +7 -7
- flwr/serverapp/strategy/multikrum.py +9 -9
- flwr/serverapp/strategy/qfedavg.py +17 -16
- flwr/serverapp/strategy/strategy.py +6 -9
- flwr/serverapp/strategy/strategy_utils.py +7 -8
- flwr/simulation/app.py +46 -42
- flwr/simulation/legacy_app.py +12 -12
- flwr/simulation/ray_transport/ray_actor.py +10 -11
- flwr/simulation/ray_transport/ray_client_proxy.py +11 -12
- flwr/simulation/run_simulation.py +43 -43
- flwr/simulation/simulationio_connection.py +4 -4
- flwr/supercore/cli/flower_superexec.py +3 -4
- flwr/supercore/constant.py +31 -1
- flwr/supercore/corestate/corestate.py +24 -3
- flwr/supercore/corestate/in_memory_corestate.py +138 -0
- flwr/supercore/corestate/sqlite_corestate.py +157 -0
- flwr/supercore/ffs/disk_ffs.py +1 -2
- flwr/supercore/ffs/ffs.py +1 -2
- flwr/supercore/ffs/ffs_factory.py +1 -2
- flwr/{common → supercore}/heartbeat.py +20 -25
- flwr/supercore/object_store/in_memory_object_store.py +1 -2
- flwr/supercore/object_store/object_store.py +1 -2
- flwr/supercore/object_store/object_store_factory.py +1 -2
- flwr/supercore/object_store/sqlite_object_store.py +8 -7
- flwr/supercore/primitives/asymmetric.py +1 -1
- flwr/supercore/primitives/asymmetric_ed25519.py +11 -1
- flwr/supercore/sqlite_mixin.py +37 -34
- flwr/supercore/superexec/plugin/base_exec_plugin.py +1 -2
- flwr/supercore/superexec/plugin/exec_plugin.py +3 -3
- flwr/supercore/superexec/run_superexec.py +9 -13
- flwr/superlink/artifact_provider/artifact_provider.py +1 -2
- flwr/superlink/auth_plugin/auth_plugin.py +6 -9
- flwr/superlink/auth_plugin/noop_auth_plugin.py +6 -9
- flwr/superlink/federation/__init__.py +24 -0
- flwr/superlink/federation/federation_manager.py +64 -0
- flwr/superlink/federation/noop_federation_manager.py +71 -0
- flwr/superlink/servicer/control/control_account_auth_interceptor.py +22 -13
- flwr/superlink/servicer/control/control_event_log_interceptor.py +7 -7
- flwr/superlink/servicer/control/control_grpc.py +5 -6
- flwr/superlink/servicer/control/control_license_interceptor.py +3 -3
- flwr/superlink/servicer/control/control_servicer.py +102 -18
- flwr/supernode/cli/flower_supernode.py +58 -3
- flwr/supernode/nodestate/in_memory_nodestate.py +60 -49
- flwr/supernode/nodestate/nodestate.py +7 -8
- flwr/supernode/nodestate/nodestate_factory.py +7 -4
- flwr/supernode/runtime/run_clientapp.py +41 -22
- flwr/supernode/servicer/clientappio/clientappio_servicer.py +40 -10
- flwr/supernode/start_client_internal.py +158 -42
- {flwr-1.23.0.dist-info → flwr-1.24.0.dist-info}/METADATA +8 -8
- flwr-1.24.0.dist-info/RECORD +454 -0
- flwr/supercore/object_store/utils.py +0 -43
- flwr-1.23.0.dist-info/RECORD +0 -439
- {flwr-1.23.0.dist-info → flwr-1.24.0.dist-info}/WHEEL +0 -0
- {flwr-1.23.0.dist-info → flwr-1.24.0.dist-info}/entry_points.txt +0 -0
|
@@ -63,7 +63,7 @@ class ArrayRecord(TypedDict[str, Array], InflatableObject):
|
|
|
63
63
|
|
|
64
64
|
A typed dictionary (``str`` to :class:`Array`) that can store named arrays,
|
|
65
65
|
including model parameters, gradients, embeddings or non-parameter arrays.
|
|
66
|
-
Internally, this behaves similarly to an ``
|
|
66
|
+
Internally, this behaves similarly to an ``dict[str, Array]``.
|
|
67
67
|
An ``ArrayRecord`` can be viewed as an equivalent to PyTorch's ``state_dict``,
|
|
68
68
|
but it holds arrays in a serialized form.
|
|
69
69
|
|
|
@@ -80,13 +80,13 @@ class ArrayRecord(TypedDict[str, Array], InflatableObject):
|
|
|
80
80
|
|
|
81
81
|
Parameters
|
|
82
82
|
----------
|
|
83
|
-
array_dict : Optional[
|
|
83
|
+
array_dict : Optional[dict[str, Array]] (default: None)
|
|
84
84
|
An existing dictionary containing named :class:`Array` instances. If
|
|
85
85
|
provided, these entries will be used directly to populate the record.
|
|
86
86
|
numpy_ndarrays : Optional[list[NDArray]] (default: None)
|
|
87
87
|
A list of NumPy arrays. Each array will be automatically converted
|
|
88
88
|
into an :class:`Array` and stored in this record with generated keys.
|
|
89
|
-
torch_state_dict : Optional[
|
|
89
|
+
torch_state_dict : Optional[dict[str, torch.Tensor]] (default: None)
|
|
90
90
|
A PyTorch ``state_dict`` (``str`` keys to ``torch.Tensor`` values). Each
|
|
91
91
|
tensor will be converted into an :class:`Array` and stored in this record.
|
|
92
92
|
keep_input : bool (default: True)
|
|
@@ -127,31 +127,23 @@ class ArrayRecord(TypedDict[str, Array], InflatableObject):
|
|
|
127
127
|
"""
|
|
128
128
|
|
|
129
129
|
@overload
|
|
130
|
-
def __init__(self) -> None: ...
|
|
130
|
+
def __init__(self) -> None: ...
|
|
131
131
|
|
|
132
132
|
@overload
|
|
133
|
-
def __init__(
|
|
134
|
-
self, array_dict:
|
|
133
|
+
def __init__(
|
|
134
|
+
self, array_dict: dict[str, Array], *, keep_input: bool = True
|
|
135
135
|
) -> None: ...
|
|
136
136
|
|
|
137
137
|
@overload
|
|
138
|
-
def __init__(
|
|
138
|
+
def __init__(
|
|
139
139
|
self, numpy_ndarrays: list[NDArray], *, keep_input: bool = True
|
|
140
140
|
) -> None: ...
|
|
141
141
|
|
|
142
142
|
@overload
|
|
143
|
-
def __init__(
|
|
143
|
+
def __init__(
|
|
144
144
|
self,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
keep_input: bool = True,
|
|
148
|
-
) -> None: ...
|
|
149
|
-
|
|
150
|
-
# This is also required for PyTorch state dict because they are not strongly typed
|
|
151
|
-
@overload
|
|
152
|
-
def __init__( # noqa: E704
|
|
153
|
-
self,
|
|
154
|
-
torch_state_dict: dict[str, Any],
|
|
145
|
+
# `Any` is required for PyTorch state dict because they are not strongly typed
|
|
146
|
+
torch_state_dict: dict[str, torch.Tensor] | dict[str, Any],
|
|
155
147
|
*,
|
|
156
148
|
keep_input: bool = True,
|
|
157
149
|
) -> None: ...
|
|
@@ -160,15 +152,15 @@ class ArrayRecord(TypedDict[str, Array], InflatableObject):
|
|
|
160
152
|
self,
|
|
161
153
|
*args: Any,
|
|
162
154
|
numpy_ndarrays: list[NDArray] | None = None,
|
|
163
|
-
torch_state_dict:
|
|
164
|
-
array_dict:
|
|
155
|
+
torch_state_dict: dict[str, torch.Tensor] | dict[str, Any] | None = None,
|
|
156
|
+
array_dict: dict[str, Array] | None = None,
|
|
165
157
|
keep_input: bool = True,
|
|
166
158
|
) -> None:
|
|
167
159
|
super().__init__(_check_key, _check_value)
|
|
168
160
|
|
|
169
161
|
# Determine the initialization method and validates input arguments.
|
|
170
162
|
# Support the following initialization formats:
|
|
171
|
-
# 1. cls(array_dict:
|
|
163
|
+
# 1. cls(array_dict: dict[str, Array], keep_input: bool)
|
|
172
164
|
# 2. cls(numpy_ndarrays: list[NDArray], keep_input: bool)
|
|
173
165
|
# 3. cls(torch_state_dict: dict[str, torch.Tensor], keep_input: bool)
|
|
174
166
|
|
|
@@ -213,7 +205,7 @@ class ArrayRecord(TypedDict[str, Array], InflatableObject):
|
|
|
213
205
|
and all(isinstance(k, str) for k in arg.keys())
|
|
214
206
|
and all(isinstance(v, Array) for v in arg.values())
|
|
215
207
|
):
|
|
216
|
-
array_dict = cast(
|
|
208
|
+
array_dict = cast(dict[str, Array], arg)
|
|
217
209
|
converted = self.from_array_dict(array_dict, keep_input=keep_input)
|
|
218
210
|
self.__dict__.update(converted.__dict__)
|
|
219
211
|
return
|
|
@@ -239,9 +231,7 @@ class ArrayRecord(TypedDict[str, Array], InflatableObject):
|
|
|
239
231
|
and all(isinstance(k, str) for k in arg.keys())
|
|
240
232
|
and all(isinstance(v, torch.Tensor) for v in arg.values())
|
|
241
233
|
):
|
|
242
|
-
torch_state_dict = cast(
|
|
243
|
-
OrderedDict[str, torch.Tensor], arg # type: ignore
|
|
244
|
-
)
|
|
234
|
+
torch_state_dict = cast(dict[str, torch.Tensor], arg) # type: ignore
|
|
245
235
|
converted = self.from_torch_state_dict(
|
|
246
236
|
torch_state_dict, keep_input=keep_input
|
|
247
237
|
)
|
|
@@ -253,7 +243,7 @@ class ArrayRecord(TypedDict[str, Array], InflatableObject):
|
|
|
253
243
|
@classmethod
|
|
254
244
|
def from_array_dict(
|
|
255
245
|
cls,
|
|
256
|
-
array_dict:
|
|
246
|
+
array_dict: dict[str, Array],
|
|
257
247
|
*,
|
|
258
248
|
keep_input: bool = True,
|
|
259
249
|
) -> ArrayRecord:
|
|
@@ -300,7 +290,7 @@ class ArrayRecord(TypedDict[str, Array], InflatableObject):
|
|
|
300
290
|
@classmethod
|
|
301
291
|
def from_torch_state_dict(
|
|
302
292
|
cls,
|
|
303
|
-
state_dict:
|
|
293
|
+
state_dict: dict[str, torch.Tensor],
|
|
304
294
|
*,
|
|
305
295
|
keep_input: bool = True,
|
|
306
296
|
) -> ArrayRecord:
|
|
@@ -433,9 +423,7 @@ class ArrayRecord(TypedDict[str, Array], InflatableObject):
|
|
|
433
423
|
|
|
434
424
|
# Instantiate new ArrayRecord
|
|
435
425
|
return ArrayRecord(
|
|
436
|
-
|
|
437
|
-
{name: children[object_id] for name, object_id in array_refs.items()}
|
|
438
|
-
)
|
|
426
|
+
{name: children[object_id] for name, object_id in array_refs.items()}
|
|
439
427
|
)
|
|
440
428
|
|
|
441
429
|
@property
|
|
@@ -142,11 +142,11 @@ class ConfigRecord(TypedDict[str, ConfigRecordValues], InflatableObject):
|
|
|
142
142
|
var_bytes = 0
|
|
143
143
|
if isinstance(value, bool):
|
|
144
144
|
var_bytes = 1
|
|
145
|
-
elif isinstance(value, (int
|
|
145
|
+
elif isinstance(value, (int | float)):
|
|
146
146
|
var_bytes = (
|
|
147
147
|
8 # the profobufing represents int/floats in ConfigRecords as 64bit
|
|
148
148
|
)
|
|
149
|
-
if isinstance(value, (str
|
|
149
|
+
if isinstance(value, (str | bytes)):
|
|
150
150
|
var_bytes = len(value)
|
|
151
151
|
if var_bytes == 0:
|
|
152
152
|
raise ValueError(
|
|
@@ -159,7 +159,7 @@ class ConfigRecord(TypedDict[str, ConfigRecordValues], InflatableObject):
|
|
|
159
159
|
|
|
160
160
|
for k, v in self.items():
|
|
161
161
|
if isinstance(v, list):
|
|
162
|
-
if isinstance(v[0], (bytes
|
|
162
|
+
if isinstance(v[0], (bytes | str)):
|
|
163
163
|
# not all str are of equal length necessarily
|
|
164
164
|
# for both the footprint of each element is 1 Byte
|
|
165
165
|
num_bytes += int(sum(len(s) for s in v)) # type: ignore
|
flwr/common/record/recorddict.py
CHANGED
|
@@ -20,7 +20,7 @@ from __future__ import annotations
|
|
|
20
20
|
import json
|
|
21
21
|
from logging import WARN
|
|
22
22
|
from textwrap import indent
|
|
23
|
-
from typing import TypeVar,
|
|
23
|
+
from typing import TypeVar, cast
|
|
24
24
|
|
|
25
25
|
from ..inflatable import InflatableObject, add_header_to_object_body, get_object_body
|
|
26
26
|
from ..logger import log
|
|
@@ -29,7 +29,7 @@ from .configrecord import ConfigRecord
|
|
|
29
29
|
from .metricrecord import MetricRecord
|
|
30
30
|
from .typeddict import TypedDict
|
|
31
31
|
|
|
32
|
-
RecordType =
|
|
32
|
+
RecordType = ArrayRecord | MetricRecord | ConfigRecord
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
class _WarningTracker:
|
|
@@ -59,7 +59,7 @@ def _check_key(key: str) -> None:
|
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
def _check_value(value: RecordType) -> None:
|
|
62
|
-
if not isinstance(value, (ArrayRecord
|
|
62
|
+
if not isinstance(value, (ArrayRecord | MetricRecord | ConfigRecord)):
|
|
63
63
|
raise TypeError(
|
|
64
64
|
f"Expected `{ArrayRecord.__name__}`, `{MetricRecord.__name__}`, "
|
|
65
65
|
f"or `{ConfigRecord.__name__}` but received "
|
|
@@ -76,7 +76,7 @@ class _SyncedDict(TypedDict[str, T]):
|
|
|
76
76
|
"""
|
|
77
77
|
|
|
78
78
|
def __init__(self, ref_recorddict: RecordDict, allowed_type: type[T]) -> None:
|
|
79
|
-
if not issubclass(allowed_type, (ArrayRecord
|
|
79
|
+
if not issubclass(allowed_type, (ArrayRecord | MetricRecord | ConfigRecord)):
|
|
80
80
|
raise TypeError(f"{allowed_type} is not a valid type.")
|
|
81
81
|
super().__init__(_check_key, self.check_value)
|
|
82
82
|
self.recorddict = ref_recorddict
|
|
@@ -341,7 +341,7 @@ class RecordDict(TypedDict[str, RecordType], InflatableObject):
|
|
|
341
341
|
|
|
342
342
|
# Ensure children are one of the *Record objects exepecte in a RecordDict
|
|
343
343
|
if not all(
|
|
344
|
-
isinstance(ch, (ArrayRecord
|
|
344
|
+
isinstance(ch, (ArrayRecord | ConfigRecord | MetricRecord))
|
|
345
345
|
for ch in children.values()
|
|
346
346
|
):
|
|
347
347
|
raise ValueError(
|
flwr/common/record/typeddict.py
CHANGED
|
@@ -15,8 +15,15 @@
|
|
|
15
15
|
"""Typed dict base class for *Records."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from collections.abc import
|
|
19
|
-
|
|
18
|
+
from collections.abc import (
|
|
19
|
+
Callable,
|
|
20
|
+
ItemsView,
|
|
21
|
+
Iterator,
|
|
22
|
+
KeysView,
|
|
23
|
+
MutableMapping,
|
|
24
|
+
ValuesView,
|
|
25
|
+
)
|
|
26
|
+
from typing import Generic, TypeVar, cast
|
|
20
27
|
|
|
21
28
|
from typing_extensions import Self
|
|
22
29
|
|
flwr/common/recorddict_compat.py
CHANGED
|
@@ -15,9 +15,8 @@
|
|
|
15
15
|
"""RecordDict utilities."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from collections import OrderedDict
|
|
19
18
|
from collections.abc import Mapping
|
|
20
|
-
from typing import
|
|
19
|
+
from typing import cast, get_args
|
|
21
20
|
|
|
22
21
|
from . import Array, ArrayRecord, ConfigRecord, MetricRecord, RecordDict
|
|
23
22
|
from .typing import (
|
|
@@ -104,25 +103,23 @@ def parameters_to_arrayrecord(parameters: Parameters, keep_input: bool) -> Array
|
|
|
104
103
|
tensor_type = parameters.tensor_type
|
|
105
104
|
|
|
106
105
|
num_arrays = len(parameters.tensors)
|
|
107
|
-
|
|
106
|
+
array_dict = {}
|
|
108
107
|
for idx in range(num_arrays):
|
|
109
108
|
if keep_input:
|
|
110
109
|
tensor = parameters.tensors[idx]
|
|
111
110
|
else:
|
|
112
111
|
tensor = parameters.tensors.pop(0)
|
|
113
|
-
|
|
114
|
-
data=tensor, dtype="", stype=tensor_type, shape=()
|
|
115
|
-
)
|
|
112
|
+
array_dict[str(idx)] = Array(data=tensor, dtype="", stype=tensor_type, shape=())
|
|
116
113
|
|
|
117
114
|
if num_arrays == 0:
|
|
118
|
-
|
|
115
|
+
array_dict[EMPTY_TENSOR_KEY] = Array(
|
|
119
116
|
data=b"", dtype="", stype=tensor_type, shape=()
|
|
120
117
|
)
|
|
121
|
-
return ArrayRecord(
|
|
118
|
+
return ArrayRecord(array_dict, keep_input=keep_input)
|
|
122
119
|
|
|
123
120
|
|
|
124
121
|
def _check_mapping_from_recordscalartype_to_scalar(
|
|
125
|
-
record_data: Mapping[str,
|
|
122
|
+
record_data: Mapping[str, ConfigRecordValues | MetricRecordValues],
|
|
126
123
|
) -> dict[str, Scalar]:
|
|
127
124
|
"""Check mapping `common.*RecordValues` into `common.Scalar` is possible."""
|
|
128
125
|
for value in record_data.values():
|
|
@@ -157,7 +154,7 @@ def _recorddict_to_fit_or_evaluate_ins_components(
|
|
|
157
154
|
|
|
158
155
|
|
|
159
156
|
def _fit_or_evaluate_ins_to_recorddict(
|
|
160
|
-
ins:
|
|
157
|
+
ins: FitIns | EvaluateIns, keep_input: bool
|
|
161
158
|
) -> RecordDict:
|
|
162
159
|
recorddict = RecordDict()
|
|
163
160
|
|
flwr/common/retry_invoker.py
CHANGED
|
@@ -19,10 +19,10 @@ import itertools
|
|
|
19
19
|
import random
|
|
20
20
|
import threading
|
|
21
21
|
import time
|
|
22
|
-
from collections.abc import Generator, Iterable
|
|
22
|
+
from collections.abc import Callable, Generator, Iterable
|
|
23
23
|
from dataclasses import dataclass
|
|
24
24
|
from logging import INFO, WARN
|
|
25
|
-
from typing import Any,
|
|
25
|
+
from typing import Any, cast
|
|
26
26
|
|
|
27
27
|
import grpc
|
|
28
28
|
|
|
@@ -39,7 +39,7 @@ from flwr.proto.simulationio_pb2_grpc import SimulationIoStub
|
|
|
39
39
|
def exponential(
|
|
40
40
|
base_delay: float = 1,
|
|
41
41
|
multiplier: float = 2,
|
|
42
|
-
max_delay:
|
|
42
|
+
max_delay: int | None = None,
|
|
43
43
|
) -> Generator[float, None, None]:
|
|
44
44
|
"""Wait time generator for exponential backoff strategy.
|
|
45
45
|
|
|
@@ -66,7 +66,7 @@ def exponential(
|
|
|
66
66
|
|
|
67
67
|
|
|
68
68
|
def constant(
|
|
69
|
-
interval:
|
|
69
|
+
interval: float | Iterable[float] = 1,
|
|
70
70
|
) -> Generator[float, None, None]:
|
|
71
71
|
"""Wait time generator for specified intervals.
|
|
72
72
|
|
|
@@ -114,8 +114,8 @@ class RetryState:
|
|
|
114
114
|
kwargs: dict[str, Any]
|
|
115
115
|
tries: int
|
|
116
116
|
elapsed_time: float
|
|
117
|
-
exception:
|
|
118
|
-
actual_wait:
|
|
117
|
+
exception: Exception | None = None
|
|
118
|
+
actual_wait: float | None = None
|
|
119
119
|
|
|
120
120
|
|
|
121
121
|
# pylint: disable-next=too-many-instance-attributes
|
|
@@ -184,16 +184,16 @@ class RetryInvoker:
|
|
|
184
184
|
def __init__(
|
|
185
185
|
self,
|
|
186
186
|
wait_gen_factory: Callable[[], Generator[float, None, None]],
|
|
187
|
-
recoverable_exceptions:
|
|
188
|
-
max_tries:
|
|
189
|
-
max_time:
|
|
187
|
+
recoverable_exceptions: type[Exception] | tuple[type[Exception], ...],
|
|
188
|
+
max_tries: int | None,
|
|
189
|
+
max_time: float | None,
|
|
190
190
|
*,
|
|
191
|
-
on_success:
|
|
192
|
-
on_backoff:
|
|
193
|
-
on_giveup:
|
|
194
|
-
jitter:
|
|
195
|
-
should_giveup:
|
|
196
|
-
wait_function:
|
|
191
|
+
on_success: Callable[[RetryState], None] | None = None,
|
|
192
|
+
on_backoff: Callable[[RetryState], None] | None = None,
|
|
193
|
+
on_giveup: Callable[[RetryState], None] | None = None,
|
|
194
|
+
jitter: Callable[[float], float] | None = full_jitter,
|
|
195
|
+
should_giveup: Callable[[Exception], bool] | None = None,
|
|
196
|
+
wait_function: Callable[[float], None] | None = None,
|
|
197
197
|
) -> None:
|
|
198
198
|
self.wait_gen_factory = wait_gen_factory
|
|
199
199
|
self.recoverable_exceptions = recoverable_exceptions
|
|
@@ -253,7 +253,7 @@ class RetryInvoker:
|
|
|
253
253
|
"""
|
|
254
254
|
|
|
255
255
|
def try_call_event_handler(
|
|
256
|
-
handler:
|
|
256
|
+
handler: Callable[[RetryState], None] | None,
|
|
257
257
|
) -> None:
|
|
258
258
|
if handler is not None:
|
|
259
259
|
handler(cast(RetryState, ref_state[0]))
|
|
@@ -261,7 +261,7 @@ class RetryInvoker:
|
|
|
261
261
|
try_cnt = 0
|
|
262
262
|
wait_generator = self.wait_gen_factory()
|
|
263
263
|
start = time.monotonic()
|
|
264
|
-
ref_state: list[
|
|
264
|
+
ref_state: list[RetryState | None] = [None]
|
|
265
265
|
|
|
266
266
|
while True:
|
|
267
267
|
try_cnt += 1
|
|
@@ -387,9 +387,9 @@ def _make_simple_grpc_retry_invoker() -> RetryInvoker:
|
|
|
387
387
|
|
|
388
388
|
|
|
389
389
|
def _wrap_stub(
|
|
390
|
-
stub:
|
|
391
|
-
ServerAppIoStub
|
|
392
|
-
|
|
390
|
+
stub: (
|
|
391
|
+
ServerAppIoStub | ClientAppIoStub | SimulationIoStub | FleetStub | GrpcAdapter
|
|
392
|
+
),
|
|
393
393
|
retry_invoker: RetryInvoker,
|
|
394
394
|
) -> None:
|
|
395
395
|
"""Wrap a gRPC stub with a retry invoker."""
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"""Utility functions for performing operations on Numpy NDArrays."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from typing import Any
|
|
18
|
+
from typing import Any
|
|
19
19
|
|
|
20
20
|
import numpy as np
|
|
21
21
|
from numpy.typing import DTypeLike, NDArray
|
|
@@ -68,14 +68,14 @@ def parameters_mod(parameters: list[NDArray[Any]], divisor: int) -> list[NDArray
|
|
|
68
68
|
|
|
69
69
|
|
|
70
70
|
def parameters_multiply(
|
|
71
|
-
parameters: list[NDArray[Any]], multiplier:
|
|
71
|
+
parameters: list[NDArray[Any]], multiplier: int | float
|
|
72
72
|
) -> list[NDArray[Any]]:
|
|
73
73
|
"""Multiply parameters by an integer/float multiplier."""
|
|
74
74
|
return [parameters[idx] * multiplier for idx in range(len(parameters))]
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
def parameters_divide(
|
|
78
|
-
parameters: list[NDArray[Any]], divisor:
|
|
78
|
+
parameters: list[NDArray[Any]], divisor: int | float
|
|
79
79
|
) -> list[NDArray[Any]]:
|
|
80
80
|
"""Divide weight by an integer/float divisor."""
|
|
81
81
|
return [parameters[idx] / divisor for idx in range(len(parameters))]
|
flwr/common/serde.py
CHANGED
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
"""ProtoBuf serialization and deserialization."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from collections import OrderedDict
|
|
19
18
|
from typing import Any, cast
|
|
20
19
|
|
|
21
20
|
# pylint: disable=E0611
|
|
@@ -410,9 +409,9 @@ def array_record_from_proto(
|
|
|
410
409
|
) -> ArrayRecord:
|
|
411
410
|
"""Deserialize ArrayRecord from ProtoBuf."""
|
|
412
411
|
return ArrayRecord(
|
|
413
|
-
array_dict=
|
|
414
|
-
|
|
415
|
-
|
|
412
|
+
array_dict={
|
|
413
|
+
item.key: array_from_proto(item.value) for item in record_proto.items
|
|
414
|
+
},
|
|
416
415
|
keep_input=False,
|
|
417
416
|
)
|
|
418
417
|
|
|
@@ -632,6 +631,7 @@ def run_to_proto(run: typing.Run) -> ProtoRun:
|
|
|
632
631
|
finished_at=run.finished_at,
|
|
633
632
|
status=run_status_to_proto(run.status),
|
|
634
633
|
flwr_aid=run.flwr_aid,
|
|
634
|
+
federation=run.federation,
|
|
635
635
|
)
|
|
636
636
|
return proto
|
|
637
637
|
|
|
@@ -650,6 +650,7 @@ def run_from_proto(run_proto: ProtoRun) -> typing.Run:
|
|
|
650
650
|
finished_at=run_proto.finished_at,
|
|
651
651
|
status=run_status_from_proto(run_proto.status),
|
|
652
652
|
flwr_aid=run_proto.flwr_aid,
|
|
653
|
+
federation=run_proto.federation,
|
|
653
654
|
)
|
|
654
655
|
return run
|
|
655
656
|
|
flwr/common/serde_utils.py
CHANGED
|
@@ -114,7 +114,7 @@ def record_value_dict_to_proto(
|
|
|
114
114
|
Note: `bool` MUST be put in the front of allowd_types if it exists.
|
|
115
115
|
"""
|
|
116
116
|
# Move bool to the front
|
|
117
|
-
if bool in allowed_types and allowed_types[0]
|
|
117
|
+
if bool in allowed_types and allowed_types[0] is not bool:
|
|
118
118
|
allowed_types.remove(bool)
|
|
119
119
|
allowed_types.insert(0, bool)
|
|
120
120
|
|
|
@@ -125,7 +125,7 @@ def record_value_dict_to_proto(
|
|
|
125
125
|
|
|
126
126
|
|
|
127
127
|
def record_value_dict_from_proto(
|
|
128
|
-
value_dict_proto: MutableMapping[str, Any]
|
|
128
|
+
value_dict_proto: MutableMapping[str, Any],
|
|
129
129
|
) -> dict[str, Any]:
|
|
130
130
|
"""Deserialize the record value dict from ProtoBuf."""
|
|
131
131
|
return {k: _record_value_from_proto(v) for k, v in value_dict_proto.items()}
|
flwr/common/telemetry.py
CHANGED
|
@@ -25,7 +25,7 @@ import uuid
|
|
|
25
25
|
from concurrent.futures import Future, ThreadPoolExecutor
|
|
26
26
|
from enum import Enum, auto
|
|
27
27
|
from pathlib import Path
|
|
28
|
-
from typing import Any,
|
|
28
|
+
from typing import Any, cast
|
|
29
29
|
|
|
30
30
|
from flwr.common.constant import FLWR_DIR
|
|
31
31
|
from flwr.common.version import package_name, package_version
|
|
@@ -56,7 +56,7 @@ def _configure_logger(log_level: int) -> None:
|
|
|
56
56
|
_configure_logger(LOGGER_LEVEL)
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
def log(msg:
|
|
59
|
+
def log(msg: str | Exception) -> None:
|
|
60
60
|
"""Log message using logger at DEBUG level."""
|
|
61
61
|
logging.getLogger(LOGGER_NAME).log(LOGGER_LEVEL, msg)
|
|
62
62
|
|
|
@@ -161,6 +161,10 @@ class EventType(str, Enum):
|
|
|
161
161
|
FLWR_SERVERAPP_RUN_ENTER = auto()
|
|
162
162
|
FLWR_SERVERAPP_RUN_LEAVE = auto()
|
|
163
163
|
|
|
164
|
+
# CLI: flwr-clientapp
|
|
165
|
+
FLWR_CLIENTAPP_RUN_ENTER = auto()
|
|
166
|
+
FLWR_CLIENTAPP_RUN_LEAVE = auto()
|
|
167
|
+
|
|
164
168
|
# --- Simulation Engine ------------------------------------------------------------
|
|
165
169
|
|
|
166
170
|
# CLI: flower-simulation
|
|
@@ -188,7 +192,7 @@ class EventType(str, Enum):
|
|
|
188
192
|
|
|
189
193
|
# Use the ThreadPoolExecutor with max_workers=1 to have a queue
|
|
190
194
|
# and also ensure that telemetry calls are not blocking.
|
|
191
|
-
state: dict[str,
|
|
195
|
+
state: dict[str, str | None | ThreadPoolExecutor | None] = {
|
|
192
196
|
# Will be assigned ThreadPoolExecutor(max_workers=1)
|
|
193
197
|
# in event() the first time it's required
|
|
194
198
|
"executor": None,
|
|
@@ -200,7 +204,7 @@ state: dict[str, Union[Optional[str], Optional[ThreadPoolExecutor]]] = {
|
|
|
200
204
|
|
|
201
205
|
def event(
|
|
202
206
|
event_type: EventType,
|
|
203
|
-
event_details:
|
|
207
|
+
event_details: dict[str, Any] | None = None,
|
|
204
208
|
) -> Future: # type: ignore
|
|
205
209
|
"""Submit create_event to ThreadPoolExecutor to avoid blocking."""
|
|
206
210
|
if state["executor"] is None:
|
|
@@ -212,7 +216,7 @@ def event(
|
|
|
212
216
|
return result
|
|
213
217
|
|
|
214
218
|
|
|
215
|
-
def create_event(event_type: EventType, event_details:
|
|
219
|
+
def create_event(event_type: EventType, event_details: dict[str, Any] | None) -> str:
|
|
216
220
|
"""Create telemetry event."""
|
|
217
221
|
if state["source"] is None:
|
|
218
222
|
state["source"] = _get_source_id()
|
flwr/common/typing.py
CHANGED
|
@@ -15,13 +15,16 @@
|
|
|
15
15
|
"""Flower type definitions."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
from collections.abc import Callable
|
|
18
19
|
from dataclasses import dataclass
|
|
19
20
|
from enum import Enum
|
|
20
|
-
from typing import Any
|
|
21
|
+
from typing import Any
|
|
21
22
|
|
|
22
23
|
import numpy as np
|
|
23
24
|
import numpy.typing as npt
|
|
24
25
|
|
|
26
|
+
from flwr.proto.node_pb2 import NodeInfo # pylint: disable=E0611
|
|
27
|
+
|
|
25
28
|
NDArray = npt.NDArray[Any]
|
|
26
29
|
NDArrayInt = npt.NDArray[np.int_]
|
|
27
30
|
NDArrayFloat = npt.NDArray[np.float64]
|
|
@@ -31,29 +34,29 @@ NDArrays = list[NDArray]
|
|
|
31
34
|
# ProtoBuf considers to be "Scalar Value Types", even though some of them arguably do
|
|
32
35
|
# not conform to other definitions of what a scalar is. Source:
|
|
33
36
|
# https://developers.google.com/protocol-buffers/docs/overview#scalar
|
|
34
|
-
Scalar =
|
|
35
|
-
Value =
|
|
36
|
-
bool
|
|
37
|
-
bytes
|
|
38
|
-
float
|
|
39
|
-
int
|
|
40
|
-
str
|
|
41
|
-
list[bool]
|
|
42
|
-
list[bytes]
|
|
43
|
-
list[float]
|
|
44
|
-
list[int]
|
|
45
|
-
list[str]
|
|
46
|
-
|
|
37
|
+
Scalar = bool | bytes | float | int | str
|
|
38
|
+
Value = (
|
|
39
|
+
bool
|
|
40
|
+
| bytes
|
|
41
|
+
| float
|
|
42
|
+
| int
|
|
43
|
+
| str
|
|
44
|
+
| list[bool]
|
|
45
|
+
| list[bytes]
|
|
46
|
+
| list[float]
|
|
47
|
+
| list[int]
|
|
48
|
+
| list[str]
|
|
49
|
+
)
|
|
50
|
+
|
|
47
51
|
|
|
48
52
|
# Value types for common.MetricRecord
|
|
49
|
-
MetricScalar =
|
|
50
|
-
MetricScalarList =
|
|
51
|
-
MetricRecordValues =
|
|
53
|
+
MetricScalar = int | float
|
|
54
|
+
MetricScalarList = list[int] | list[float]
|
|
55
|
+
MetricRecordValues = MetricScalar | MetricScalarList
|
|
52
56
|
# Value types for common.ConfigRecord
|
|
53
|
-
ConfigScalar =
|
|
54
|
-
ConfigScalarList =
|
|
55
|
-
ConfigRecordValues =
|
|
56
|
-
|
|
57
|
+
ConfigScalar = MetricScalar | str | bytes | bool
|
|
58
|
+
ConfigScalarList = MetricScalarList | list[str] | list[bytes] | list[bool]
|
|
59
|
+
ConfigRecordValues = ConfigScalar | ConfigScalarList
|
|
57
60
|
Metrics = dict[str, Scalar]
|
|
58
61
|
MetricsAggregationFn = Callable[[list[tuple[int, Metrics]]], Metrics]
|
|
59
62
|
|
|
@@ -61,7 +64,7 @@ Config = dict[str, Scalar]
|
|
|
61
64
|
Properties = dict[str, Scalar]
|
|
62
65
|
|
|
63
66
|
# Value type for user configs
|
|
64
|
-
UserConfigValue =
|
|
67
|
+
UserConfigValue = bool | float | int | str
|
|
65
68
|
UserConfig = dict[str, UserConfigValue]
|
|
66
69
|
|
|
67
70
|
|
|
@@ -177,7 +180,7 @@ class GetPropertiesRes:
|
|
|
177
180
|
class ReconnectIns:
|
|
178
181
|
"""ReconnectIns message from server to client."""
|
|
179
182
|
|
|
180
|
-
seconds:
|
|
183
|
+
seconds: int | None
|
|
181
184
|
|
|
182
185
|
|
|
183
186
|
@dataclass
|
|
@@ -191,20 +194,20 @@ class DisconnectRes:
|
|
|
191
194
|
class ServerMessage:
|
|
192
195
|
"""ServerMessage is a container used to hold one instruction message."""
|
|
193
196
|
|
|
194
|
-
get_properties_ins:
|
|
195
|
-
get_parameters_ins:
|
|
196
|
-
fit_ins:
|
|
197
|
-
evaluate_ins:
|
|
197
|
+
get_properties_ins: GetPropertiesIns | None = None
|
|
198
|
+
get_parameters_ins: GetParametersIns | None = None
|
|
199
|
+
fit_ins: FitIns | None = None
|
|
200
|
+
evaluate_ins: EvaluateIns | None = None
|
|
198
201
|
|
|
199
202
|
|
|
200
203
|
@dataclass
|
|
201
204
|
class ClientMessage:
|
|
202
205
|
"""ClientMessage is a container used to hold one result message."""
|
|
203
206
|
|
|
204
|
-
get_properties_res:
|
|
205
|
-
get_parameters_res:
|
|
206
|
-
fit_res:
|
|
207
|
-
evaluate_res:
|
|
207
|
+
get_properties_res: GetPropertiesRes | None = None
|
|
208
|
+
get_parameters_res: GetParametersRes | None = None
|
|
209
|
+
fit_res: FitRes | None = None
|
|
210
|
+
evaluate_res: EvaluateRes | None = None
|
|
208
211
|
|
|
209
212
|
|
|
210
213
|
@dataclass
|
|
@@ -231,6 +234,7 @@ class Run: # pylint: disable=too-many-instance-attributes
|
|
|
231
234
|
finished_at: str
|
|
232
235
|
status: RunStatus
|
|
233
236
|
flwr_aid: str
|
|
237
|
+
federation: str
|
|
234
238
|
|
|
235
239
|
@classmethod
|
|
236
240
|
def create_empty(cls, run_id: int) -> "Run":
|
|
@@ -247,6 +251,7 @@ class Run: # pylint: disable=too-many-instance-attributes
|
|
|
247
251
|
finished_at="",
|
|
248
252
|
status=RunStatus(status="", sub_status="", details=""),
|
|
249
253
|
flwr_aid="",
|
|
254
|
+
federation="",
|
|
250
255
|
)
|
|
251
256
|
|
|
252
257
|
|
|
@@ -295,16 +300,16 @@ class AccountAuthCredentials:
|
|
|
295
300
|
class AccountInfo:
|
|
296
301
|
"""User information for event log."""
|
|
297
302
|
|
|
298
|
-
flwr_aid:
|
|
299
|
-
account_name:
|
|
303
|
+
flwr_aid: str | None
|
|
304
|
+
account_name: str | None
|
|
300
305
|
|
|
301
306
|
|
|
302
307
|
@dataclass
|
|
303
308
|
class Actor:
|
|
304
309
|
"""Event log actor."""
|
|
305
310
|
|
|
306
|
-
actor_id:
|
|
307
|
-
description:
|
|
311
|
+
actor_id: str | None
|
|
312
|
+
description: str | None
|
|
308
313
|
ip_address: str
|
|
309
314
|
|
|
310
315
|
|
|
@@ -313,8 +318,8 @@ class Event:
|
|
|
313
318
|
"""Event log description."""
|
|
314
319
|
|
|
315
320
|
action: str
|
|
316
|
-
run_id:
|
|
317
|
-
fab_hash:
|
|
321
|
+
run_id: int | None
|
|
322
|
+
fab_hash: str | None
|
|
318
323
|
|
|
319
324
|
|
|
320
325
|
@dataclass
|
|
@@ -325,3 +330,13 @@ class LogEntry:
|
|
|
325
330
|
actor: Actor
|
|
326
331
|
event: Event
|
|
327
332
|
status: str
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
@dataclass
|
|
336
|
+
class Federation:
|
|
337
|
+
"""Federation details."""
|
|
338
|
+
|
|
339
|
+
name: str
|
|
340
|
+
member_aids: list[str]
|
|
341
|
+
nodes: list[NodeInfo]
|
|
342
|
+
runs: list[Run]
|