flwr-nightly 1.11.0.dev20240813__py3-none-any.whl → 1.11.0.dev20240815__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.
Potentially problematic release.
This version of flwr-nightly might be problematic. Click here for more details.
- flwr/cli/run/run.py +6 -2
- flwr/client/app.py +1 -1
- flwr/client/grpc_rere_client/connection.py +1 -0
- flwr/client/process/__init__.py +15 -0
- flwr/client/process/clientappio_servicer.py +145 -0
- flwr/client/rest_client/connection.py +2 -1
- flwr/common/config.py +7 -2
- flwr/common/record/recordset.py +9 -7
- flwr/common/record/typeddict.py +20 -58
- flwr/common/recordset_compat.py +6 -6
- flwr/common/serde.py +24 -2
- flwr/common/typing.py +1 -0
- flwr/proto/exec_pb2.py +16 -15
- flwr/proto/exec_pb2.pyi +7 -4
- flwr/proto/message_pb2.py +2 -2
- flwr/proto/message_pb2.pyi +4 -1
- flwr/server/app.py +12 -0
- flwr/server/driver/grpc_driver.py +1 -0
- flwr/server/superlink/driver/driver_grpc.py +3 -0
- flwr/server/superlink/driver/driver_servicer.py +14 -1
- flwr/server/superlink/ffs/ffs_factory.py +47 -0
- flwr/server/superlink/state/in_memory_state.py +7 -5
- flwr/server/superlink/state/sqlite_state.py +17 -7
- flwr/server/superlink/state/state.py +4 -3
- flwr/simulation/run_simulation.py +4 -1
- flwr/superexec/exec_servicer.py +1 -1
- {flwr_nightly-1.11.0.dev20240813.dist-info → flwr_nightly-1.11.0.dev20240815.dist-info}/METADATA +1 -1
- {flwr_nightly-1.11.0.dev20240813.dist-info → flwr_nightly-1.11.0.dev20240815.dist-info}/RECORD +31 -28
- {flwr_nightly-1.11.0.dev20240813.dist-info → flwr_nightly-1.11.0.dev20240815.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.11.0.dev20240813.dist-info → flwr_nightly-1.11.0.dev20240815.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.11.0.dev20240813.dist-info → flwr_nightly-1.11.0.dev20240815.dist-info}/entry_points.txt +0 -0
flwr/cli/run/run.py
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
# ==============================================================================
|
|
15
15
|
"""Flower command line interface `run` command."""
|
|
16
16
|
|
|
17
|
+
import hashlib
|
|
17
18
|
import subprocess
|
|
18
19
|
import sys
|
|
19
20
|
from logging import DEBUG
|
|
@@ -28,7 +29,8 @@ from flwr.cli.config_utils import load_and_validate
|
|
|
28
29
|
from flwr.common.config import flatten_dict, parse_config_args
|
|
29
30
|
from flwr.common.grpc import GRPC_MAX_MESSAGE_LENGTH, create_channel
|
|
30
31
|
from flwr.common.logger import log
|
|
31
|
-
from flwr.common.serde import user_config_to_proto
|
|
32
|
+
from flwr.common.serde import fab_to_proto, user_config_to_proto
|
|
33
|
+
from flwr.common.typing import Fab
|
|
32
34
|
from flwr.proto.exec_pb2 import StartRunRequest # pylint: disable=E0611
|
|
33
35
|
from flwr.proto.exec_pb2_grpc import ExecStub
|
|
34
36
|
|
|
@@ -163,9 +165,11 @@ def _run_with_superexec(
|
|
|
163
165
|
stub = ExecStub(channel)
|
|
164
166
|
|
|
165
167
|
fab_path = Path(build(app))
|
|
168
|
+
content = fab_path.read_bytes()
|
|
169
|
+
fab = Fab(hashlib.sha256(content).hexdigest(), content)
|
|
166
170
|
|
|
167
171
|
req = StartRunRequest(
|
|
168
|
-
|
|
172
|
+
fab=fab_to_proto(fab),
|
|
169
173
|
override_config=user_config_to_proto(
|
|
170
174
|
parse_config_args(config_overrides, separator=",")
|
|
171
175
|
),
|
flwr/client/app.py
CHANGED
|
@@ -398,7 +398,7 @@ def _start_client_internal(
|
|
|
398
398
|
runs[run_id] = get_run(run_id)
|
|
399
399
|
# If get_run is None, i.e., in grpc-bidi mode
|
|
400
400
|
else:
|
|
401
|
-
runs[run_id] = Run(run_id, "", "", {})
|
|
401
|
+
runs[run_id] = Run(run_id, "", "", "", {})
|
|
402
402
|
|
|
403
403
|
# Register context for this run
|
|
404
404
|
node_state.register_context(
|
|
@@ -286,6 +286,7 @@ def grpc_request_response( # pylint: disable=R0913, R0914, R0915
|
|
|
286
286
|
run_id,
|
|
287
287
|
get_run_response.run.fab_id,
|
|
288
288
|
get_run_response.run.fab_version,
|
|
289
|
+
get_run_response.run.fab_hash,
|
|
289
290
|
user_config_from_proto(get_run_response.run.override_config),
|
|
290
291
|
)
|
|
291
292
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Copyright 2024 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 AppIO service."""
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
"""ClientAppIo API servicer."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
from dataclasses import dataclass
|
|
19
|
+
from logging import DEBUG, ERROR
|
|
20
|
+
from typing import Optional
|
|
21
|
+
|
|
22
|
+
import grpc
|
|
23
|
+
|
|
24
|
+
from flwr.common import Context, Message, typing
|
|
25
|
+
from flwr.common.logger import log
|
|
26
|
+
from flwr.common.serde import (
|
|
27
|
+
clientappstatus_to_proto,
|
|
28
|
+
context_from_proto,
|
|
29
|
+
context_to_proto,
|
|
30
|
+
message_from_proto,
|
|
31
|
+
message_to_proto,
|
|
32
|
+
run_to_proto,
|
|
33
|
+
)
|
|
34
|
+
from flwr.common.typing import Run
|
|
35
|
+
|
|
36
|
+
# pylint: disable=E0611
|
|
37
|
+
from flwr.proto import clientappio_pb2_grpc
|
|
38
|
+
from flwr.proto.clientappio_pb2 import ( # pylint: disable=E0401
|
|
39
|
+
PullClientAppInputsRequest,
|
|
40
|
+
PullClientAppInputsResponse,
|
|
41
|
+
PushClientAppOutputsRequest,
|
|
42
|
+
PushClientAppOutputsResponse,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class ClientAppIoInputs:
|
|
48
|
+
"""Specify the inputs to the ClientApp."""
|
|
49
|
+
|
|
50
|
+
message: Message
|
|
51
|
+
context: Context
|
|
52
|
+
run: Run
|
|
53
|
+
token: int
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass
|
|
57
|
+
class ClientAppIoOutputs:
|
|
58
|
+
"""Specify the outputs from the ClientApp."""
|
|
59
|
+
|
|
60
|
+
message: Message
|
|
61
|
+
context: Context
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# pylint: disable=C0103,W0613,W0201
|
|
65
|
+
class ClientAppIoServicer(clientappio_pb2_grpc.ClientAppIoServicer):
|
|
66
|
+
"""ClientAppIo API servicer."""
|
|
67
|
+
|
|
68
|
+
def __init__(self) -> None:
|
|
69
|
+
self.clientapp_input: Optional[ClientAppIoInputs] = None
|
|
70
|
+
self.clientapp_output: Optional[ClientAppIoOutputs] = None
|
|
71
|
+
|
|
72
|
+
def PullClientAppInputs(
|
|
73
|
+
self, request: PullClientAppInputsRequest, context: grpc.ServicerContext
|
|
74
|
+
) -> PullClientAppInputsResponse:
|
|
75
|
+
"""Pull Message, Context, and Run."""
|
|
76
|
+
log(DEBUG, "ClientAppIo.PullClientAppInputs")
|
|
77
|
+
if self.clientapp_input is None:
|
|
78
|
+
raise ValueError(
|
|
79
|
+
"ClientAppIoInputs not set before calling `PullClientAppInputs`."
|
|
80
|
+
)
|
|
81
|
+
if request.token != self.clientapp_input.token:
|
|
82
|
+
context.abort(
|
|
83
|
+
grpc.StatusCode.INVALID_ARGUMENT,
|
|
84
|
+
"Mismatch between ClientApp and SuperNode token",
|
|
85
|
+
)
|
|
86
|
+
return PullClientAppInputsResponse(
|
|
87
|
+
message=message_to_proto(self.clientapp_input.message),
|
|
88
|
+
context=context_to_proto(self.clientapp_input.context),
|
|
89
|
+
run=run_to_proto(self.clientapp_input.run),
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def PushClientAppOutputs(
|
|
93
|
+
self, request: PushClientAppOutputsRequest, context: grpc.ServicerContext
|
|
94
|
+
) -> PushClientAppOutputsResponse:
|
|
95
|
+
"""Push Message and Context."""
|
|
96
|
+
log(DEBUG, "ClientAppIo.PushClientAppOutputs")
|
|
97
|
+
if self.clientapp_output is None:
|
|
98
|
+
raise ValueError(
|
|
99
|
+
"ClientAppIoOutputs not set before calling `PushClientAppOutputs`."
|
|
100
|
+
)
|
|
101
|
+
if self.clientapp_input is None:
|
|
102
|
+
raise ValueError(
|
|
103
|
+
"ClientAppIoInputs not set before calling `PushClientAppOutputs`."
|
|
104
|
+
)
|
|
105
|
+
if request.token != self.clientapp_input.token:
|
|
106
|
+
context.abort(
|
|
107
|
+
grpc.StatusCode.INVALID_ARGUMENT,
|
|
108
|
+
"Mismatch between ClientApp and SuperNode token",
|
|
109
|
+
)
|
|
110
|
+
try:
|
|
111
|
+
# Update Message and Context
|
|
112
|
+
self.clientapp_output.message = message_from_proto(request.message)
|
|
113
|
+
self.clientapp_output.context = context_from_proto(request.context)
|
|
114
|
+
# Set status
|
|
115
|
+
code = typing.ClientAppOutputCode.SUCCESS
|
|
116
|
+
status = typing.ClientAppOutputStatus(code=code, message="Success")
|
|
117
|
+
proto_status = clientappstatus_to_proto(status=status)
|
|
118
|
+
return PushClientAppOutputsResponse(status=proto_status)
|
|
119
|
+
except Exception as e: # pylint: disable=broad-exception-caught
|
|
120
|
+
log(ERROR, "ClientApp failed to push message to SuperNode, %s", e)
|
|
121
|
+
code = typing.ClientAppOutputCode.UNKNOWN_ERROR
|
|
122
|
+
status = typing.ClientAppOutputStatus(code=code, message="Push failed")
|
|
123
|
+
proto_status = clientappstatus_to_proto(status=status)
|
|
124
|
+
return PushClientAppOutputsResponse(status=proto_status)
|
|
125
|
+
|
|
126
|
+
def set_inputs(self, clientapp_input: ClientAppIoInputs) -> None:
|
|
127
|
+
"""Set ClientApp inputs."""
|
|
128
|
+
log(DEBUG, "ClientAppIo.SetInputs")
|
|
129
|
+
if self.clientapp_input is not None or self.clientapp_output is not None:
|
|
130
|
+
raise ValueError(
|
|
131
|
+
"ClientAppIoInputs and ClientAppIoOutputs must not be set before "
|
|
132
|
+
"calling `set_inputs`."
|
|
133
|
+
)
|
|
134
|
+
self.clientapp_input = clientapp_input
|
|
135
|
+
|
|
136
|
+
def get_outputs(self) -> ClientAppIoOutputs:
|
|
137
|
+
"""Get ClientApp outputs."""
|
|
138
|
+
log(DEBUG, "ClientAppIo.GetOutputs")
|
|
139
|
+
if self.clientapp_output is None:
|
|
140
|
+
raise ValueError("ClientAppIoOutputs not set before calling `get_outputs`.")
|
|
141
|
+
# Set outputs to a local variable and clear self.clientapp_output
|
|
142
|
+
output: ClientAppIoOutputs = self.clientapp_output
|
|
143
|
+
self.clientapp_input = None
|
|
144
|
+
self.clientapp_output = None
|
|
145
|
+
return output
|
|
@@ -358,12 +358,13 @@ def http_request_response( # pylint: disable=,R0913, R0914, R0915
|
|
|
358
358
|
# Send the request
|
|
359
359
|
res = _request(req, GetRunResponse, PATH_GET_RUN)
|
|
360
360
|
if res is None:
|
|
361
|
-
return Run(run_id, "", "", {})
|
|
361
|
+
return Run(run_id, "", "", "", {})
|
|
362
362
|
|
|
363
363
|
return Run(
|
|
364
364
|
run_id,
|
|
365
365
|
res.run.fab_id,
|
|
366
366
|
res.run.fab_version,
|
|
367
|
+
res.run.fab_hash,
|
|
367
368
|
user_config_from_proto(res.run.override_config),
|
|
368
369
|
)
|
|
369
370
|
|
flwr/common/config.py
CHANGED
|
@@ -74,10 +74,15 @@ def get_project_config(project_dir: Union[str, Path]) -> Dict[str, Any]:
|
|
|
74
74
|
return config
|
|
75
75
|
|
|
76
76
|
|
|
77
|
-
def
|
|
77
|
+
def fuse_dicts(
|
|
78
78
|
main_dict: UserConfig,
|
|
79
79
|
override_dict: UserConfig,
|
|
80
80
|
) -> UserConfig:
|
|
81
|
+
"""Merge a config with the overrides.
|
|
82
|
+
|
|
83
|
+
Remove the nesting by adding the nested keys as prefixes separated by dots, and fuse
|
|
84
|
+
it with the override dict.
|
|
85
|
+
"""
|
|
81
86
|
fused_dict = main_dict.copy()
|
|
82
87
|
|
|
83
88
|
for key, value in override_dict.items():
|
|
@@ -96,7 +101,7 @@ def get_fused_config_from_dir(
|
|
|
96
101
|
)
|
|
97
102
|
flat_default_config = flatten_dict(default_config)
|
|
98
103
|
|
|
99
|
-
return
|
|
104
|
+
return fuse_dicts(flat_default_config, override_config)
|
|
100
105
|
|
|
101
106
|
|
|
102
107
|
def get_fused_config(run: Run, flwr_dir: Optional[Path]) -> UserConfig:
|
flwr/common/record/recordset.py
CHANGED
|
@@ -15,8 +15,10 @@
|
|
|
15
15
|
"""RecordSet."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
18
20
|
from dataclasses import dataclass
|
|
19
|
-
from typing import
|
|
21
|
+
from typing import cast
|
|
20
22
|
|
|
21
23
|
from .configsrecord import ConfigsRecord
|
|
22
24
|
from .metricsrecord import MetricsRecord
|
|
@@ -34,9 +36,9 @@ class RecordSetData:
|
|
|
34
36
|
|
|
35
37
|
def __init__(
|
|
36
38
|
self,
|
|
37
|
-
parameters_records:
|
|
38
|
-
metrics_records:
|
|
39
|
-
configs_records:
|
|
39
|
+
parameters_records: dict[str, ParametersRecord] | None = None,
|
|
40
|
+
metrics_records: dict[str, MetricsRecord] | None = None,
|
|
41
|
+
configs_records: dict[str, ConfigsRecord] | None = None,
|
|
40
42
|
) -> None:
|
|
41
43
|
self.parameters_records = TypedDict[str, ParametersRecord](
|
|
42
44
|
self._check_fn_str, self._check_fn_params
|
|
@@ -88,9 +90,9 @@ class RecordSet:
|
|
|
88
90
|
|
|
89
91
|
def __init__(
|
|
90
92
|
self,
|
|
91
|
-
parameters_records:
|
|
92
|
-
metrics_records:
|
|
93
|
-
configs_records:
|
|
93
|
+
parameters_records: dict[str, ParametersRecord] | None = None,
|
|
94
|
+
metrics_records: dict[str, MetricsRecord] | None = None,
|
|
95
|
+
configs_records: dict[str, ConfigsRecord] | None = None,
|
|
94
96
|
) -> None:
|
|
95
97
|
data = RecordSetData(
|
|
96
98
|
parameters_records=parameters_records,
|
flwr/common/record/typeddict.py
CHANGED
|
@@ -15,99 +15,61 @@
|
|
|
15
15
|
"""Typed dict base class for *Records."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from typing import
|
|
18
|
+
from typing import Callable, Dict, Generic, Iterator, MutableMapping, TypeVar, cast
|
|
19
19
|
|
|
20
20
|
K = TypeVar("K") # Key type
|
|
21
21
|
V = TypeVar("V") # Value type
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
class TypedDict(Generic[K, V]):
|
|
24
|
+
class TypedDict(MutableMapping[K, V], Generic[K, V]):
|
|
25
25
|
"""Typed dictionary."""
|
|
26
26
|
|
|
27
27
|
def __init__(
|
|
28
28
|
self, check_key_fn: Callable[[K], None], check_value_fn: Callable[[V], None]
|
|
29
29
|
):
|
|
30
|
-
self.
|
|
31
|
-
self.
|
|
32
|
-
self.
|
|
30
|
+
self.__dict__["_check_key_fn"] = check_key_fn
|
|
31
|
+
self.__dict__["_check_value_fn"] = check_value_fn
|
|
32
|
+
self.__dict__["_data"] = {}
|
|
33
33
|
|
|
34
34
|
def __setitem__(self, key: K, value: V) -> None:
|
|
35
35
|
"""Set the given key to the given value after type checking."""
|
|
36
36
|
# Check the types of key and value
|
|
37
|
-
self._check_key_fn(key)
|
|
38
|
-
self._check_value_fn(value)
|
|
37
|
+
cast(Callable[[K], None], self.__dict__["_check_key_fn"])(key)
|
|
38
|
+
cast(Callable[[V], None], self.__dict__["_check_value_fn"])(value)
|
|
39
|
+
|
|
39
40
|
# Set key-value pair
|
|
40
|
-
self._data[key] = value
|
|
41
|
+
cast(Dict[K, V], self.__dict__["_data"])[key] = value
|
|
41
42
|
|
|
42
43
|
def __delitem__(self, key: K) -> None:
|
|
43
44
|
"""Remove the item with the specified key."""
|
|
44
|
-
del self._data[key]
|
|
45
|
+
del cast(Dict[K, V], self.__dict__["_data"])[key]
|
|
45
46
|
|
|
46
47
|
def __getitem__(self, item: K) -> V:
|
|
47
48
|
"""Return the value for the specified key."""
|
|
48
|
-
return self._data[item]
|
|
49
|
+
return cast(Dict[K, V], self.__dict__["_data"])[item]
|
|
49
50
|
|
|
50
51
|
def __iter__(self) -> Iterator[K]:
|
|
51
52
|
"""Yield an iterator over the keys of the dictionary."""
|
|
52
|
-
return iter(self._data)
|
|
53
|
+
return iter(cast(Dict[K, V], self.__dict__["_data"]))
|
|
53
54
|
|
|
54
55
|
def __repr__(self) -> str:
|
|
55
56
|
"""Return a string representation of the dictionary."""
|
|
56
|
-
return self._data.__repr__()
|
|
57
|
+
return cast(Dict[K, V], self.__dict__["_data"]).__repr__()
|
|
57
58
|
|
|
58
59
|
def __len__(self) -> int:
|
|
59
60
|
"""Return the number of items in the dictionary."""
|
|
60
|
-
return len(self._data)
|
|
61
|
+
return len(cast(Dict[K, V], self.__dict__["_data"]))
|
|
61
62
|
|
|
62
|
-
def __contains__(self, key:
|
|
63
|
+
def __contains__(self, key: object) -> bool:
|
|
63
64
|
"""Check if the dictionary contains the specified key."""
|
|
64
|
-
return key in self._data
|
|
65
|
+
return key in cast(Dict[K, V], self.__dict__["_data"])
|
|
65
66
|
|
|
66
67
|
def __eq__(self, other: object) -> bool:
|
|
67
68
|
"""Compare this instance to another dictionary or TypedDict."""
|
|
69
|
+
data = cast(Dict[K, V], self.__dict__["_data"])
|
|
68
70
|
if isinstance(other, TypedDict):
|
|
69
|
-
|
|
71
|
+
other_data = cast(Dict[K, V], other.__dict__["_data"])
|
|
72
|
+
return data == other_data
|
|
70
73
|
if isinstance(other, dict):
|
|
71
|
-
return
|
|
74
|
+
return data == other
|
|
72
75
|
return NotImplemented
|
|
73
|
-
|
|
74
|
-
def items(self) -> Iterator[Tuple[K, V]]:
|
|
75
|
-
"""R.items() -> a set-like object providing a view on R's items."""
|
|
76
|
-
return cast(Iterator[Tuple[K, V]], self._data.items())
|
|
77
|
-
|
|
78
|
-
def keys(self) -> Iterator[K]:
|
|
79
|
-
"""R.keys() -> a set-like object providing a view on R's keys."""
|
|
80
|
-
return cast(Iterator[K], self._data.keys())
|
|
81
|
-
|
|
82
|
-
def values(self) -> Iterator[V]:
|
|
83
|
-
"""R.values() -> an object providing a view on R's values."""
|
|
84
|
-
return cast(Iterator[V], self._data.values())
|
|
85
|
-
|
|
86
|
-
def update(self, *args: Any, **kwargs: Any) -> None:
|
|
87
|
-
"""R.update([E, ]**F) -> None.
|
|
88
|
-
|
|
89
|
-
Update R from dict/iterable E and F.
|
|
90
|
-
"""
|
|
91
|
-
for key, value in dict(*args, **kwargs).items():
|
|
92
|
-
self[key] = value
|
|
93
|
-
|
|
94
|
-
def pop(self, key: K) -> V:
|
|
95
|
-
"""R.pop(k[,d]) -> v, remove specified key and return the corresponding value.
|
|
96
|
-
|
|
97
|
-
If key is not found, d is returned if given, otherwise KeyError is raised.
|
|
98
|
-
"""
|
|
99
|
-
return self._data.pop(key)
|
|
100
|
-
|
|
101
|
-
def get(self, key: K, default: V) -> V:
|
|
102
|
-
"""R.get(k[,d]) -> R[k] if k in R, else d.
|
|
103
|
-
|
|
104
|
-
d defaults to None.
|
|
105
|
-
"""
|
|
106
|
-
return self._data.get(key, default)
|
|
107
|
-
|
|
108
|
-
def clear(self) -> None:
|
|
109
|
-
"""R.clear() -> None.
|
|
110
|
-
|
|
111
|
-
Remove all items from R.
|
|
112
|
-
"""
|
|
113
|
-
self._data.clear()
|
flwr/common/recordset_compat.py
CHANGED
|
@@ -145,7 +145,7 @@ def _recordset_to_fit_or_evaluate_ins_components(
|
|
|
145
145
|
# get config dict
|
|
146
146
|
config_record = recordset.configs_records[f"{ins_str}.config"]
|
|
147
147
|
# pylint: disable-next=protected-access
|
|
148
|
-
config_dict = _check_mapping_from_recordscalartype_to_scalar(config_record
|
|
148
|
+
config_dict = _check_mapping_from_recordscalartype_to_scalar(config_record)
|
|
149
149
|
|
|
150
150
|
return parameters, config_dict
|
|
151
151
|
|
|
@@ -213,7 +213,7 @@ def recordset_to_fitres(recordset: RecordSet, keep_input: bool) -> FitRes:
|
|
|
213
213
|
)
|
|
214
214
|
configs_record = recordset.configs_records[f"{ins_str}.metrics"]
|
|
215
215
|
# pylint: disable-next=protected-access
|
|
216
|
-
metrics = _check_mapping_from_recordscalartype_to_scalar(configs_record
|
|
216
|
+
metrics = _check_mapping_from_recordscalartype_to_scalar(configs_record)
|
|
217
217
|
status = _extract_status_from_recordset(ins_str, recordset)
|
|
218
218
|
|
|
219
219
|
return FitRes(
|
|
@@ -274,7 +274,7 @@ def recordset_to_evaluateres(recordset: RecordSet) -> EvaluateRes:
|
|
|
274
274
|
configs_record = recordset.configs_records[f"{ins_str}.metrics"]
|
|
275
275
|
|
|
276
276
|
# pylint: disable-next=protected-access
|
|
277
|
-
metrics = _check_mapping_from_recordscalartype_to_scalar(configs_record
|
|
277
|
+
metrics = _check_mapping_from_recordscalartype_to_scalar(configs_record)
|
|
278
278
|
status = _extract_status_from_recordset(ins_str, recordset)
|
|
279
279
|
|
|
280
280
|
return EvaluateRes(
|
|
@@ -314,7 +314,7 @@ def recordset_to_getparametersins(recordset: RecordSet) -> GetParametersIns:
|
|
|
314
314
|
"""Derive GetParametersIns from a RecordSet object."""
|
|
315
315
|
config_record = recordset.configs_records["getparametersins.config"]
|
|
316
316
|
# pylint: disable-next=protected-access
|
|
317
|
-
config_dict = _check_mapping_from_recordscalartype_to_scalar(config_record
|
|
317
|
+
config_dict = _check_mapping_from_recordscalartype_to_scalar(config_record)
|
|
318
318
|
|
|
319
319
|
return GetParametersIns(config=config_dict)
|
|
320
320
|
|
|
@@ -365,7 +365,7 @@ def recordset_to_getpropertiesins(recordset: RecordSet) -> GetPropertiesIns:
|
|
|
365
365
|
"""Derive GetPropertiesIns from a RecordSet object."""
|
|
366
366
|
config_record = recordset.configs_records["getpropertiesins.config"]
|
|
367
367
|
# pylint: disable-next=protected-access
|
|
368
|
-
config_dict = _check_mapping_from_recordscalartype_to_scalar(config_record
|
|
368
|
+
config_dict = _check_mapping_from_recordscalartype_to_scalar(config_record)
|
|
369
369
|
|
|
370
370
|
return GetPropertiesIns(config=config_dict)
|
|
371
371
|
|
|
@@ -384,7 +384,7 @@ def recordset_to_getpropertiesres(recordset: RecordSet) -> GetPropertiesRes:
|
|
|
384
384
|
res_str = "getpropertiesres"
|
|
385
385
|
config_record = recordset.configs_records[f"{res_str}.properties"]
|
|
386
386
|
# pylint: disable-next=protected-access
|
|
387
|
-
properties = _check_mapping_from_recordscalartype_to_scalar(config_record
|
|
387
|
+
properties = _check_mapping_from_recordscalartype_to_scalar(config_record)
|
|
388
388
|
|
|
389
389
|
status = _extract_status_from_recordset(res_str, recordset=recordset)
|
|
390
390
|
|
flwr/common/serde.py
CHANGED
|
@@ -22,6 +22,7 @@ from google.protobuf.message import Message as GrpcMessage
|
|
|
22
22
|
# pylint: disable=E0611
|
|
23
23
|
from flwr.proto.clientappio_pb2 import ClientAppOutputCode, ClientAppOutputStatus
|
|
24
24
|
from flwr.proto.error_pb2 import Error as ProtoError
|
|
25
|
+
from flwr.proto.fab_pb2 import Fab as ProtoFab
|
|
25
26
|
from flwr.proto.message_pb2 import Context as ProtoContext
|
|
26
27
|
from flwr.proto.message_pb2 import Message as ProtoMessage
|
|
27
28
|
from flwr.proto.message_pb2 import Metadata as ProtoMetadata
|
|
@@ -686,6 +687,19 @@ def message_from_taskres(taskres: TaskRes) -> Message:
|
|
|
686
687
|
return message
|
|
687
688
|
|
|
688
689
|
|
|
690
|
+
# === FAB ===
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
def fab_to_proto(fab: typing.Fab) -> ProtoFab:
|
|
694
|
+
"""Create a proto Fab object from a Python Fab."""
|
|
695
|
+
return ProtoFab(hash_str=fab.hash_str, content=fab.content)
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
def fab_from_proto(fab: ProtoFab) -> typing.Fab:
|
|
699
|
+
"""Create a Python Fab object from a proto Fab."""
|
|
700
|
+
return typing.Fab(fab.hash_str, fab.content)
|
|
701
|
+
|
|
702
|
+
|
|
689
703
|
# === User configs ===
|
|
690
704
|
|
|
691
705
|
|
|
@@ -745,6 +759,7 @@ def metadata_to_proto(metadata: Metadata) -> ProtoMetadata:
|
|
|
745
759
|
group_id=metadata.group_id,
|
|
746
760
|
ttl=metadata.ttl,
|
|
747
761
|
message_type=metadata.message_type,
|
|
762
|
+
created_at=metadata.created_at,
|
|
748
763
|
)
|
|
749
764
|
return proto
|
|
750
765
|
|
|
@@ -771,7 +786,9 @@ def message_to_proto(message: Message) -> ProtoMessage:
|
|
|
771
786
|
"""Serialize `Message` to ProtoBuf."""
|
|
772
787
|
proto = ProtoMessage(
|
|
773
788
|
metadata=metadata_to_proto(message.metadata),
|
|
774
|
-
content=
|
|
789
|
+
content=(
|
|
790
|
+
recordset_to_proto(message.content) if message.has_content() else None
|
|
791
|
+
),
|
|
775
792
|
error=error_to_proto(message.error) if message.has_error() else None,
|
|
776
793
|
)
|
|
777
794
|
return proto
|
|
@@ -779,6 +796,7 @@ def message_to_proto(message: Message) -> ProtoMessage:
|
|
|
779
796
|
|
|
780
797
|
def message_from_proto(message_proto: ProtoMessage) -> Message:
|
|
781
798
|
"""Deserialize `Message` from ProtoBuf."""
|
|
799
|
+
created_at = message_proto.metadata.created_at
|
|
782
800
|
message = Message(
|
|
783
801
|
metadata=metadata_from_proto(message_proto.metadata),
|
|
784
802
|
content=(
|
|
@@ -792,6 +810,9 @@ def message_from_proto(message_proto: ProtoMessage) -> Message:
|
|
|
792
810
|
else None
|
|
793
811
|
),
|
|
794
812
|
)
|
|
813
|
+
# `.created_at` is set upon Message object construction
|
|
814
|
+
# we need to manually set it to the original value
|
|
815
|
+
message.metadata.created_at = created_at
|
|
795
816
|
return message
|
|
796
817
|
|
|
797
818
|
|
|
@@ -829,8 +850,8 @@ def run_to_proto(run: typing.Run) -> ProtoRun:
|
|
|
829
850
|
run_id=run.run_id,
|
|
830
851
|
fab_id=run.fab_id,
|
|
831
852
|
fab_version=run.fab_version,
|
|
853
|
+
fab_hash=run.fab_hash,
|
|
832
854
|
override_config=user_config_to_proto(run.override_config),
|
|
833
|
-
fab_hash="",
|
|
834
855
|
)
|
|
835
856
|
return proto
|
|
836
857
|
|
|
@@ -841,6 +862,7 @@ def run_from_proto(run_proto: ProtoRun) -> typing.Run:
|
|
|
841
862
|
run_id=run_proto.run_id,
|
|
842
863
|
fab_id=run_proto.fab_id,
|
|
843
864
|
fab_version=run_proto.fab_version,
|
|
865
|
+
fab_hash=run_proto.fab_hash,
|
|
844
866
|
override_config=user_config_from_proto(run_proto.override_config),
|
|
845
867
|
)
|
|
846
868
|
return run
|
flwr/common/typing.py
CHANGED
flwr/proto/exec_pb2.py
CHANGED
|
@@ -12,10 +12,11 @@ from google.protobuf.internal import builder as _builder
|
|
|
12
12
|
_sym_db = _symbol_database.Default()
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
|
|
15
16
|
from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/exec.proto\x12\nflwr.proto\x1a\x1a\x66lwr/proto/transport.proto\"\
|
|
19
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/exec.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x1a\x66lwr/proto/transport.proto\"\xdf\x02\n\x0fStartRunRequest\x12\x1c\n\x03\x66\x61\x62\x18\x01 \x01(\x0b\x32\x0f.flwr.proto.Fab\x12H\n\x0foverride_config\x18\x02 \x03(\x0b\x32/.flwr.proto.StartRunRequest.OverrideConfigEntry\x12L\n\x11\x66\x65\x64\x65ration_config\x18\x03 \x03(\x0b\x32\x31.flwr.proto.StartRunRequest.FederationConfigEntry\x1aI\n\x13OverrideConfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\x1aK\n\x15\x46\x65\x64\x65rationConfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\"\"\n\x10StartRunResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\x12\"#\n\x11StreamLogsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x12\"(\n\x12StreamLogsResponse\x12\x12\n\nlog_output\x18\x01 \x01(\t2\xa0\x01\n\x04\x45xec\x12G\n\x08StartRun\x12\x1b.flwr.proto.StartRunRequest\x1a\x1c.flwr.proto.StartRunResponse\"\x00\x12O\n\nStreamLogs\x12\x1d.flwr.proto.StreamLogsRequest\x1a\x1e.flwr.proto.StreamLogsResponse\"\x00\x30\x01\x62\x06proto3')
|
|
19
20
|
|
|
20
21
|
_globals = globals()
|
|
21
22
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
@@ -26,18 +27,18 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|
|
26
27
|
_globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_options = b'8\001'
|
|
27
28
|
_globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._options = None
|
|
28
29
|
_globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._serialized_options = b'8\001'
|
|
29
|
-
_globals['_STARTRUNREQUEST']._serialized_start=
|
|
30
|
-
_globals['_STARTRUNREQUEST']._serialized_end=
|
|
31
|
-
_globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_start=
|
|
32
|
-
_globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_end=
|
|
33
|
-
_globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._serialized_start=
|
|
34
|
-
_globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._serialized_end=
|
|
35
|
-
_globals['_STARTRUNRESPONSE']._serialized_start=
|
|
36
|
-
_globals['_STARTRUNRESPONSE']._serialized_end=
|
|
37
|
-
_globals['_STREAMLOGSREQUEST']._serialized_start=
|
|
38
|
-
_globals['_STREAMLOGSREQUEST']._serialized_end=
|
|
39
|
-
_globals['_STREAMLOGSRESPONSE']._serialized_start=
|
|
40
|
-
_globals['_STREAMLOGSRESPONSE']._serialized_end=
|
|
41
|
-
_globals['_EXEC']._serialized_start=
|
|
42
|
-
_globals['_EXEC']._serialized_end=
|
|
30
|
+
_globals['_STARTRUNREQUEST']._serialized_start=88
|
|
31
|
+
_globals['_STARTRUNREQUEST']._serialized_end=439
|
|
32
|
+
_globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_start=289
|
|
33
|
+
_globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_end=362
|
|
34
|
+
_globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._serialized_start=364
|
|
35
|
+
_globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._serialized_end=439
|
|
36
|
+
_globals['_STARTRUNRESPONSE']._serialized_start=441
|
|
37
|
+
_globals['_STARTRUNRESPONSE']._serialized_end=475
|
|
38
|
+
_globals['_STREAMLOGSREQUEST']._serialized_start=477
|
|
39
|
+
_globals['_STREAMLOGSREQUEST']._serialized_end=512
|
|
40
|
+
_globals['_STREAMLOGSRESPONSE']._serialized_start=514
|
|
41
|
+
_globals['_STREAMLOGSRESPONSE']._serialized_end=554
|
|
42
|
+
_globals['_EXEC']._serialized_start=557
|
|
43
|
+
_globals['_EXEC']._serialized_end=717
|
|
43
44
|
# @@protoc_insertion_point(module_scope)
|
flwr/proto/exec_pb2.pyi
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
isort:skip_file
|
|
4
4
|
"""
|
|
5
5
|
import builtins
|
|
6
|
+
import flwr.proto.fab_pb2
|
|
6
7
|
import flwr.proto.transport_pb2
|
|
7
8
|
import google.protobuf.descriptor
|
|
8
9
|
import google.protobuf.internal.containers
|
|
@@ -44,21 +45,23 @@ class StartRunRequest(google.protobuf.message.Message):
|
|
|
44
45
|
def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ...
|
|
45
46
|
def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
FAB_FIELD_NUMBER: builtins.int
|
|
48
49
|
OVERRIDE_CONFIG_FIELD_NUMBER: builtins.int
|
|
49
50
|
FEDERATION_CONFIG_FIELD_NUMBER: builtins.int
|
|
50
|
-
|
|
51
|
+
@property
|
|
52
|
+
def fab(self) -> flwr.proto.fab_pb2.Fab: ...
|
|
51
53
|
@property
|
|
52
54
|
def override_config(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.transport_pb2.Scalar]: ...
|
|
53
55
|
@property
|
|
54
56
|
def federation_config(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.transport_pb2.Scalar]: ...
|
|
55
57
|
def __init__(self,
|
|
56
58
|
*,
|
|
57
|
-
|
|
59
|
+
fab: typing.Optional[flwr.proto.fab_pb2.Fab] = ...,
|
|
58
60
|
override_config: typing.Optional[typing.Mapping[typing.Text, flwr.proto.transport_pb2.Scalar]] = ...,
|
|
59
61
|
federation_config: typing.Optional[typing.Mapping[typing.Text, flwr.proto.transport_pb2.Scalar]] = ...,
|
|
60
62
|
) -> None: ...
|
|
61
|
-
def
|
|
63
|
+
def HasField(self, field_name: typing_extensions.Literal["fab",b"fab"]) -> builtins.bool: ...
|
|
64
|
+
def ClearField(self, field_name: typing_extensions.Literal["fab",b"fab","federation_config",b"federation_config","override_config",b"override_config"]) -> None: ...
|
|
62
65
|
global___StartRunRequest = StartRunRequest
|
|
63
66
|
|
|
64
67
|
class StartRunResponse(google.protobuf.message.Message):
|
flwr/proto/message_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 transport_pb2 as flwr_dot_proto_dot_transport__pb2
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x66lwr/proto/message.proto\x12\nflwr.proto\x1a\x16\x66lwr/proto/error.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x1a\x66lwr/proto/transport.proto\"{\n\x07Message\x12&\n\x08metadata\x18\x01 \x01(\x0b\x32\x14.flwr.proto.Metadata\x12&\n\x07\x63ontent\x18\x02 \x01(\x0b\x32\x15.flwr.proto.RecordSet\x12 \n\x05\x65rror\x18\x03 \x01(\x0b\x32\x11.flwr.proto.Error\"\xbf\x02\n\x07\x43ontext\x12\x0f\n\x07node_id\x18\x01 \x01(\x12\x12\x38\n\x0bnode_config\x18\x02 \x03(\x0b\x32#.flwr.proto.Context.NodeConfigEntry\x12$\n\x05state\x18\x03 \x01(\x0b\x32\x15.flwr.proto.RecordSet\x12\x36\n\nrun_config\x18\x04 \x03(\x0b\x32\".flwr.proto.Context.RunConfigEntry\x1a\x45\n\x0fNodeConfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\x1a\x44\n\x0eRunConfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\"\
|
|
20
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x66lwr/proto/message.proto\x12\nflwr.proto\x1a\x16\x66lwr/proto/error.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x1a\x66lwr/proto/transport.proto\"{\n\x07Message\x12&\n\x08metadata\x18\x01 \x01(\x0b\x32\x14.flwr.proto.Metadata\x12&\n\x07\x63ontent\x18\x02 \x01(\x0b\x32\x15.flwr.proto.RecordSet\x12 \n\x05\x65rror\x18\x03 \x01(\x0b\x32\x11.flwr.proto.Error\"\xbf\x02\n\x07\x43ontext\x12\x0f\n\x07node_id\x18\x01 \x01(\x12\x12\x38\n\x0bnode_config\x18\x02 \x03(\x0b\x32#.flwr.proto.Context.NodeConfigEntry\x12$\n\x05state\x18\x03 \x01(\x0b\x32\x15.flwr.proto.RecordSet\x12\x36\n\nrun_config\x18\x04 \x03(\x0b\x32\".flwr.proto.Context.RunConfigEntry\x1a\x45\n\x0fNodeConfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\x1a\x44\n\x0eRunConfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\"\xbb\x01\n\x08Metadata\x12\x0e\n\x06run_id\x18\x01 \x01(\x12\x12\x12\n\nmessage_id\x18\x02 \x01(\t\x12\x13\n\x0bsrc_node_id\x18\x03 \x01(\x12\x12\x13\n\x0b\x64st_node_id\x18\x04 \x01(\x12\x12\x18\n\x10reply_to_message\x18\x05 \x01(\t\x12\x10\n\x08group_id\x18\x06 \x01(\t\x12\x0b\n\x03ttl\x18\x07 \x01(\x01\x12\x14\n\x0cmessage_type\x18\x08 \x01(\t\x12\x12\n\ncreated_at\x18\t \x01(\x01\x62\x06proto3')
|
|
21
21
|
|
|
22
22
|
_globals = globals()
|
|
23
23
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
@@ -37,5 +37,5 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|
|
37
37
|
_globals['_CONTEXT_RUNCONFIGENTRY']._serialized_start=497
|
|
38
38
|
_globals['_CONTEXT_RUNCONFIGENTRY']._serialized_end=565
|
|
39
39
|
_globals['_METADATA']._serialized_start=568
|
|
40
|
-
_globals['_METADATA']._serialized_end=
|
|
40
|
+
_globals['_METADATA']._serialized_end=755
|
|
41
41
|
# @@protoc_insertion_point(module_scope)
|
flwr/proto/message_pb2.pyi
CHANGED
|
@@ -99,6 +99,7 @@ class Metadata(google.protobuf.message.Message):
|
|
|
99
99
|
GROUP_ID_FIELD_NUMBER: builtins.int
|
|
100
100
|
TTL_FIELD_NUMBER: builtins.int
|
|
101
101
|
MESSAGE_TYPE_FIELD_NUMBER: builtins.int
|
|
102
|
+
CREATED_AT_FIELD_NUMBER: builtins.int
|
|
102
103
|
run_id: builtins.int
|
|
103
104
|
message_id: typing.Text
|
|
104
105
|
src_node_id: builtins.int
|
|
@@ -107,6 +108,7 @@ class Metadata(google.protobuf.message.Message):
|
|
|
107
108
|
group_id: typing.Text
|
|
108
109
|
ttl: builtins.float
|
|
109
110
|
message_type: typing.Text
|
|
111
|
+
created_at: builtins.float
|
|
110
112
|
def __init__(self,
|
|
111
113
|
*,
|
|
112
114
|
run_id: builtins.int = ...,
|
|
@@ -117,6 +119,7 @@ class Metadata(google.protobuf.message.Message):
|
|
|
117
119
|
group_id: typing.Text = ...,
|
|
118
120
|
ttl: builtins.float = ...,
|
|
119
121
|
message_type: typing.Text = ...,
|
|
122
|
+
created_at: builtins.float = ...,
|
|
120
123
|
) -> None: ...
|
|
121
|
-
def ClearField(self, field_name: typing_extensions.Literal["dst_node_id",b"dst_node_id","group_id",b"group_id","message_id",b"message_id","message_type",b"message_type","reply_to_message",b"reply_to_message","run_id",b"run_id","src_node_id",b"src_node_id","ttl",b"ttl"]) -> None: ...
|
|
124
|
+
def ClearField(self, field_name: typing_extensions.Literal["created_at",b"created_at","dst_node_id",b"dst_node_id","group_id",b"group_id","message_id",b"message_id","message_type",b"message_type","reply_to_message",b"reply_to_message","run_id",b"run_id","src_node_id",b"src_node_id","ttl",b"ttl"]) -> None: ...
|
|
122
125
|
global___Metadata = Metadata
|
flwr/server/app.py
CHANGED
|
@@ -34,6 +34,7 @@ from cryptography.hazmat.primitives.serialization import (
|
|
|
34
34
|
|
|
35
35
|
from flwr.common import GRPC_MAX_MESSAGE_LENGTH, EventType, event
|
|
36
36
|
from flwr.common.address import parse_address
|
|
37
|
+
from flwr.common.config import get_flwr_dir
|
|
37
38
|
from flwr.common.constant import (
|
|
38
39
|
MISSING_EXTRA_REST,
|
|
39
40
|
TRANSPORT_TYPE_GRPC_ADAPTER,
|
|
@@ -57,6 +58,7 @@ from .server import Server, init_defaults, run_fl
|
|
|
57
58
|
from .server_config import ServerConfig
|
|
58
59
|
from .strategy import Strategy
|
|
59
60
|
from .superlink.driver.driver_grpc import run_driver_api_grpc
|
|
61
|
+
from .superlink.ffs.ffs_factory import FfsFactory
|
|
60
62
|
from .superlink.fleet.grpc_adapter.grpc_adapter_servicer import GrpcAdapterServicer
|
|
61
63
|
from .superlink.fleet.grpc_bidi.grpc_server import (
|
|
62
64
|
generic_create_grpc_server,
|
|
@@ -72,6 +74,7 @@ ADDRESS_FLEET_API_GRPC_BIDI = "[::]:8080" # IPv6 to keep start_server compatibl
|
|
|
72
74
|
ADDRESS_FLEET_API_REST = "0.0.0.0:9093"
|
|
73
75
|
|
|
74
76
|
DATABASE = ":flwr-in-memory-state:"
|
|
77
|
+
BASE_DIR = get_flwr_dir() / "superlink" / "ffs"
|
|
75
78
|
|
|
76
79
|
|
|
77
80
|
def start_server( # pylint: disable=too-many-arguments,too-many-locals
|
|
@@ -211,10 +214,14 @@ def run_superlink() -> None:
|
|
|
211
214
|
# Initialize StateFactory
|
|
212
215
|
state_factory = StateFactory(args.database)
|
|
213
216
|
|
|
217
|
+
# Initialize FfsFactory
|
|
218
|
+
ffs_factory = FfsFactory(args.storage_dir)
|
|
219
|
+
|
|
214
220
|
# Start Driver API
|
|
215
221
|
driver_server: grpc.Server = run_driver_api_grpc(
|
|
216
222
|
address=driver_address,
|
|
217
223
|
state_factory=state_factory,
|
|
224
|
+
ffs_factory=ffs_factory,
|
|
218
225
|
certificates=certificates,
|
|
219
226
|
)
|
|
220
227
|
|
|
@@ -610,6 +617,11 @@ def _add_args_common(parser: argparse.ArgumentParser) -> None:
|
|
|
610
617
|
"Flower will just create a state in memory.",
|
|
611
618
|
default=DATABASE,
|
|
612
619
|
)
|
|
620
|
+
parser.add_argument(
|
|
621
|
+
"--storage-dir",
|
|
622
|
+
help="The base directory to store the objects for the Flower File System.",
|
|
623
|
+
default=BASE_DIR,
|
|
624
|
+
)
|
|
613
625
|
parser.add_argument(
|
|
614
626
|
"--auth-list-public-keys",
|
|
615
627
|
type=str,
|
|
@@ -24,6 +24,7 @@ from flwr.common.logger import log
|
|
|
24
24
|
from flwr.proto.driver_pb2_grpc import ( # pylint: disable=E0611
|
|
25
25
|
add_DriverServicer_to_server,
|
|
26
26
|
)
|
|
27
|
+
from flwr.server.superlink.ffs.ffs_factory import FfsFactory
|
|
27
28
|
from flwr.server.superlink.state import StateFactory
|
|
28
29
|
|
|
29
30
|
from ..fleet.grpc_bidi.grpc_server import generic_create_grpc_server
|
|
@@ -33,12 +34,14 @@ from .driver_servicer import DriverServicer
|
|
|
33
34
|
def run_driver_api_grpc(
|
|
34
35
|
address: str,
|
|
35
36
|
state_factory: StateFactory,
|
|
37
|
+
ffs_factory: FfsFactory,
|
|
36
38
|
certificates: Optional[Tuple[bytes, bytes, bytes]],
|
|
37
39
|
) -> grpc.Server:
|
|
38
40
|
"""Run Driver API (gRPC, request-response)."""
|
|
39
41
|
# Create Driver API gRPC server
|
|
40
42
|
driver_servicer: grpc.Server = DriverServicer(
|
|
41
43
|
state_factory=state_factory,
|
|
44
|
+
ffs_factory=ffs_factory,
|
|
42
45
|
)
|
|
43
46
|
driver_add_servicer_to_server_fn = add_DriverServicer_to_server
|
|
44
47
|
driver_grpc_server = generic_create_grpc_server(
|
|
@@ -43,6 +43,8 @@ from flwr.proto.run_pb2 import ( # pylint: disable=E0611
|
|
|
43
43
|
Run,
|
|
44
44
|
)
|
|
45
45
|
from flwr.proto.task_pb2 import TaskRes # pylint: disable=E0611
|
|
46
|
+
from flwr.server.superlink.ffs import Ffs
|
|
47
|
+
from flwr.server.superlink.ffs.ffs_factory import FfsFactory
|
|
46
48
|
from flwr.server.superlink.state import State, StateFactory
|
|
47
49
|
from flwr.server.utils.validator import validate_task_ins_or_res
|
|
48
50
|
|
|
@@ -50,8 +52,9 @@ from flwr.server.utils.validator import validate_task_ins_or_res
|
|
|
50
52
|
class DriverServicer(driver_pb2_grpc.DriverServicer):
|
|
51
53
|
"""Driver API servicer."""
|
|
52
54
|
|
|
53
|
-
def __init__(self, state_factory: StateFactory) -> None:
|
|
55
|
+
def __init__(self, state_factory: StateFactory, ffs_factory: FfsFactory) -> None:
|
|
54
56
|
self.state_factory = state_factory
|
|
57
|
+
self.ffs_factory = ffs_factory
|
|
55
58
|
|
|
56
59
|
def GetNodes(
|
|
57
60
|
self, request: GetNodesRequest, context: grpc.ServicerContext
|
|
@@ -71,9 +74,19 @@ class DriverServicer(driver_pb2_grpc.DriverServicer):
|
|
|
71
74
|
"""Create run ID."""
|
|
72
75
|
log(DEBUG, "DriverServicer.CreateRun")
|
|
73
76
|
state: State = self.state_factory.state()
|
|
77
|
+
if request.HasField("fab") and request.fab.HasField("content"):
|
|
78
|
+
ffs: Ffs = self.ffs_factory.ffs()
|
|
79
|
+
fab_hash = ffs.put(request.fab.content, {})
|
|
80
|
+
_raise_if(
|
|
81
|
+
fab_hash != request.fab.hash_str,
|
|
82
|
+
f"FAB ({request.fab}) hash from request doesn't match contents",
|
|
83
|
+
)
|
|
84
|
+
else:
|
|
85
|
+
fab_hash = ""
|
|
74
86
|
run_id = state.create_run(
|
|
75
87
|
request.fab_id,
|
|
76
88
|
request.fab_version,
|
|
89
|
+
fab_hash,
|
|
77
90
|
user_config_from_proto(request.override_config),
|
|
78
91
|
)
|
|
79
92
|
return CreateRunResponse(run_id=run_id)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
"""Factory class that creates Ffs instances."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
from logging import DEBUG
|
|
19
|
+
from typing import Optional
|
|
20
|
+
|
|
21
|
+
from flwr.common.logger import log
|
|
22
|
+
|
|
23
|
+
from .disk_ffs import DiskFfs
|
|
24
|
+
from .ffs import Ffs
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class FfsFactory:
|
|
28
|
+
"""Factory class that creates Ffs instances.
|
|
29
|
+
|
|
30
|
+
Parameters
|
|
31
|
+
----------
|
|
32
|
+
base_dir : str
|
|
33
|
+
The base directory used by DiskFfs to store objects.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, base_dir: str) -> None:
|
|
37
|
+
self.base_dir = base_dir
|
|
38
|
+
self.ffs_instance: Optional[Ffs] = None
|
|
39
|
+
|
|
40
|
+
def ffs(self) -> Ffs:
|
|
41
|
+
"""Return a Ffs instance and create it, if necessary."""
|
|
42
|
+
if not self.ffs_instance:
|
|
43
|
+
log(DEBUG, "Initializing DiskFfs")
|
|
44
|
+
self.ffs_instance = DiskFfs(self.base_dir)
|
|
45
|
+
|
|
46
|
+
log(DEBUG, "Using DiskFfs")
|
|
47
|
+
return self.ffs_instance
|
|
@@ -277,11 +277,12 @@ class InMemoryState(State): # pylint: disable=R0902,R0904
|
|
|
277
277
|
|
|
278
278
|
def create_run(
|
|
279
279
|
self,
|
|
280
|
-
fab_id: str,
|
|
281
|
-
fab_version: str,
|
|
280
|
+
fab_id: Optional[str],
|
|
281
|
+
fab_version: Optional[str],
|
|
282
|
+
fab_hash: Optional[str],
|
|
282
283
|
override_config: UserConfig,
|
|
283
284
|
) -> int:
|
|
284
|
-
"""Create a new run for the specified `
|
|
285
|
+
"""Create a new run for the specified `fab_hash`."""
|
|
285
286
|
# Sample a random int64 as run_id
|
|
286
287
|
with self.lock:
|
|
287
288
|
run_id = generate_rand_int_from_bytes(RUN_ID_NUM_BYTES)
|
|
@@ -289,8 +290,9 @@ class InMemoryState(State): # pylint: disable=R0902,R0904
|
|
|
289
290
|
if run_id not in self.run_ids:
|
|
290
291
|
self.run_ids[run_id] = Run(
|
|
291
292
|
run_id=run_id,
|
|
292
|
-
fab_id=fab_id,
|
|
293
|
-
fab_version=fab_version,
|
|
293
|
+
fab_id=fab_id if fab_id else "",
|
|
294
|
+
fab_version=fab_version if fab_version else "",
|
|
295
|
+
fab_hash=fab_hash if fab_hash else "",
|
|
294
296
|
override_config=override_config,
|
|
295
297
|
)
|
|
296
298
|
return run_id
|
|
@@ -65,6 +65,7 @@ CREATE TABLE IF NOT EXISTS run(
|
|
|
65
65
|
run_id INTEGER UNIQUE,
|
|
66
66
|
fab_id TEXT,
|
|
67
67
|
fab_version TEXT,
|
|
68
|
+
fab_hash TEXT,
|
|
68
69
|
override_config TEXT
|
|
69
70
|
);
|
|
70
71
|
"""
|
|
@@ -617,8 +618,9 @@ class SqliteState(State): # pylint: disable=R0904
|
|
|
617
618
|
|
|
618
619
|
def create_run(
|
|
619
620
|
self,
|
|
620
|
-
fab_id: str,
|
|
621
|
-
fab_version: str,
|
|
621
|
+
fab_id: Optional[str],
|
|
622
|
+
fab_version: Optional[str],
|
|
623
|
+
fab_hash: Optional[str],
|
|
622
624
|
override_config: UserConfig,
|
|
623
625
|
) -> int:
|
|
624
626
|
"""Create a new run for the specified `fab_id` and `fab_version`."""
|
|
@@ -630,12 +632,19 @@ class SqliteState(State): # pylint: disable=R0904
|
|
|
630
632
|
# If run_id does not exist
|
|
631
633
|
if self.query(query, (run_id,))[0]["COUNT(*)"] == 0:
|
|
632
634
|
query = (
|
|
633
|
-
"INSERT INTO run
|
|
634
|
-
"
|
|
635
|
-
|
|
636
|
-
self.query(
|
|
637
|
-
query, (run_id, fab_id, fab_version, json.dumps(override_config))
|
|
635
|
+
"INSERT INTO run "
|
|
636
|
+
"(run_id, fab_id, fab_version, fab_hash, override_config)"
|
|
637
|
+
"VALUES (?, ?, ?, ?, ?);"
|
|
638
638
|
)
|
|
639
|
+
if fab_hash:
|
|
640
|
+
self.query(
|
|
641
|
+
query, (run_id, "", "", fab_hash, json.dumps(override_config))
|
|
642
|
+
)
|
|
643
|
+
else:
|
|
644
|
+
self.query(
|
|
645
|
+
query,
|
|
646
|
+
(run_id, fab_id, fab_version, "", json.dumps(override_config)),
|
|
647
|
+
)
|
|
639
648
|
return run_id
|
|
640
649
|
log(ERROR, "Unexpected run creation failure.")
|
|
641
650
|
return 0
|
|
@@ -702,6 +711,7 @@ class SqliteState(State): # pylint: disable=R0904
|
|
|
702
711
|
run_id=run_id,
|
|
703
712
|
fab_id=row["fab_id"],
|
|
704
713
|
fab_version=row["fab_version"],
|
|
714
|
+
fab_hash=row["fab_hash"],
|
|
705
715
|
override_config=json.loads(row["override_config"]),
|
|
706
716
|
)
|
|
707
717
|
except sqlite3.IntegrityError:
|
|
@@ -159,11 +159,12 @@ class State(abc.ABC): # pylint: disable=R0904
|
|
|
159
159
|
@abc.abstractmethod
|
|
160
160
|
def create_run(
|
|
161
161
|
self,
|
|
162
|
-
fab_id: str,
|
|
163
|
-
fab_version: str,
|
|
162
|
+
fab_id: Optional[str],
|
|
163
|
+
fab_version: Optional[str],
|
|
164
|
+
fab_hash: Optional[str],
|
|
164
165
|
override_config: UserConfig,
|
|
165
166
|
) -> int:
|
|
166
|
-
"""Create a new run for the specified `
|
|
167
|
+
"""Create a new run for the specified `fab_hash`."""
|
|
167
168
|
|
|
168
169
|
@abc.abstractmethod
|
|
169
170
|
def get_run(self, run_id: int) -> Optional[Run]:
|
|
@@ -163,6 +163,7 @@ def run_simulation_from_cli() -> None:
|
|
|
163
163
|
run_id=run_id,
|
|
164
164
|
fab_id="",
|
|
165
165
|
fab_version="",
|
|
166
|
+
fab_hash="",
|
|
166
167
|
override_config=override_config,
|
|
167
168
|
)
|
|
168
169
|
|
|
@@ -529,7 +530,9 @@ def _run_simulation(
|
|
|
529
530
|
# If no `Run` object is set, create one
|
|
530
531
|
if run is None:
|
|
531
532
|
run_id = generate_rand_int_from_bytes(RUN_ID_NUM_BYTES)
|
|
532
|
-
run = Run(
|
|
533
|
+
run = Run(
|
|
534
|
+
run_id=run_id, fab_id="", fab_version="", fab_hash="", override_config={}
|
|
535
|
+
)
|
|
533
536
|
|
|
534
537
|
args = (
|
|
535
538
|
num_supernodes,
|
flwr/superexec/exec_servicer.py
CHANGED
|
@@ -47,7 +47,7 @@ class ExecServicer(exec_pb2_grpc.ExecServicer):
|
|
|
47
47
|
log(INFO, "ExecServicer.StartRun")
|
|
48
48
|
|
|
49
49
|
run = self.executor.start_run(
|
|
50
|
-
request.
|
|
50
|
+
request.fab.content,
|
|
51
51
|
user_config_from_proto(request.override_config),
|
|
52
52
|
user_config_from_proto(request.federation_config),
|
|
53
53
|
)
|
{flwr_nightly-1.11.0.dev20240813.dist-info → flwr_nightly-1.11.0.dev20240815.dist-info}/RECORD
RENAMED
|
@@ -50,10 +50,10 @@ flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl,sha256=vIO1ArukTC76ogYLNmJ
|
|
|
50
50
|
flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl,sha256=jk_5teoyOVM9QdBea8J-nk10S6TKw81QZiiKB54ATF0,654
|
|
51
51
|
flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl,sha256=bRIvPCPvTTI4Eo5b61Rmw8WdDw3sjcohciTXgULN5l8,702
|
|
52
52
|
flwr/cli/run/__init__.py,sha256=oCd6HmQDx-sqver1gecgx-uMA38BLTSiiKpl7RGNceg,789
|
|
53
|
-
flwr/cli/run/run.py,sha256=
|
|
53
|
+
flwr/cli/run/run.py,sha256=Au7v9imSRRETacU16CJScbp5lr-jcduHen_ZFCeO6eY,7672
|
|
54
54
|
flwr/cli/utils.py,sha256=l65Ul0YsSBPuypk0uorAtEDmLEYiUrzpCXi6zCg9mJ4,4506
|
|
55
55
|
flwr/client/__init__.py,sha256=wzJZsYJIHf_8-PMzvfbinyzzjgh1UP1vLrAw2_yEbKI,1345
|
|
56
|
-
flwr/client/app.py,sha256=
|
|
56
|
+
flwr/client/app.py,sha256=4Phq-PQ56kXRZ_hqUhet72JO28To0lgwYLuwYhCa4Eo,26170
|
|
57
57
|
flwr/client/client.py,sha256=Vp9UkOkoHdNfn6iMYZsj_5m_GICiFfUlKEVaLad-YhM,8183
|
|
58
58
|
flwr/client/client_app.py,sha256=WcO4r6wrdfaus__3s22D2sYjfcptdgmVujUAYdNE6HU,10393
|
|
59
59
|
flwr/client/dpfedavg_numpy_client.py,sha256=ylZ-LpBIKmL1HCiS8kq4pkp2QGalc8rYEzDHdRG3VRQ,7435
|
|
@@ -63,7 +63,7 @@ flwr/client/grpc_client/__init__.py,sha256=LsnbqXiJhgQcB0XzAlUQgPx011Uf7Y7yabIC1
|
|
|
63
63
|
flwr/client/grpc_client/connection.py,sha256=czhRm23fwTgjN24Vf5nyNQ3hcb5Fo_5k-o9yZnelQCs,9362
|
|
64
64
|
flwr/client/grpc_rere_client/__init__.py,sha256=MK-oSoV3kwUEQnIwl0GN4OpiHR7eLOrMA8ikunET130,752
|
|
65
65
|
flwr/client/grpc_rere_client/client_interceptor.py,sha256=sYPEznuQPdy2BPDlvM9FK0ZRRucb4NfwUee1Z_mN82E,4954
|
|
66
|
-
flwr/client/grpc_rere_client/connection.py,sha256
|
|
66
|
+
flwr/client/grpc_rere_client/connection.py,sha256=-1hVwuVNKo3R5ZcEqKbAQT6I4L6P5fIKsQxHcwf0QNk,10584
|
|
67
67
|
flwr/client/grpc_rere_client/grpc_adapter.py,sha256=Pw7Toi4wCUIEdBMyv4yKirjgW6814gFhhAmsTYmV4IM,5005
|
|
68
68
|
flwr/client/heartbeat.py,sha256=cx37mJBH8LyoIN4Lks85wtqT1mnU5GulQnr4pGCvAq0,2404
|
|
69
69
|
flwr/client/message_handler/__init__.py,sha256=QxxQuBNpFPTHx3KiUNvQSlqMKlEnbRR1kFfc1KVje08,719
|
|
@@ -80,14 +80,16 @@ flwr/client/mod/utils.py,sha256=UAJXiB0wwVyLkCkpW_i5BXikdBR65p8sNFr7VNHm2nk,1226
|
|
|
80
80
|
flwr/client/node_state.py,sha256=Z0ZUPL5BWde9nfAPwR7cSV9YiNQeiEHbuMKDxqpy6-M,3492
|
|
81
81
|
flwr/client/node_state_tests.py,sha256=-4fVsn7y-z9NYBuhq-cjepgxgVuPqqQgDOL4SofrdIo,2239
|
|
82
82
|
flwr/client/numpy_client.py,sha256=u76GWAdHmJM88Agm2EgLQSvO8Jnk225mJTk-_TmPjFE,10283
|
|
83
|
+
flwr/client/process/__init__.py,sha256=s3hTr2dOWHkSnwivaL7YbXur38bEDgSPKKvwFLa1204,711
|
|
84
|
+
flwr/client/process/clientappio_servicer.py,sha256=ygh6wFC_q7fHV5L9G_W3Ftkn5la_BJixtOW-QzwxqyY,5536
|
|
83
85
|
flwr/client/rest_client/__init__.py,sha256=5KGlp7pjc1dhNRkKlaNtUfQmg8wrRFh9lS3P3uRS-7Q,735
|
|
84
|
-
flwr/client/rest_client/connection.py,sha256=
|
|
86
|
+
flwr/client/rest_client/connection.py,sha256=YOE2cfgRtkpNveeg88GZTTjUscgGN8XF2RAJ-M_TQ_U,12384
|
|
85
87
|
flwr/client/supernode/__init__.py,sha256=8JuFMx5B06SymNWZ9ndvUimD0mopq0Yp2RdQaUANsw8,937
|
|
86
88
|
flwr/client/supernode/app.py,sha256=mbSs612GCpRsv6xIi_TD_V2Gi7aYBdpo_e4nKs8kAvI,15910
|
|
87
89
|
flwr/client/typing.py,sha256=dxoTBnTMfqXr5J7G3y-uNjqxYCddvxhu89spfj4Lm2U,1048
|
|
88
90
|
flwr/common/__init__.py,sha256=4cBLNNnNTwHDnL_HCxhU5ILCSZ6fYh3A_aMBtlvHTVw,3721
|
|
89
91
|
flwr/common/address.py,sha256=wRu1Luezx1PWadwV9OA_KNko01oVvbRnPqfzaDn8QOk,1882
|
|
90
|
-
flwr/common/config.py,sha256
|
|
92
|
+
flwr/common/config.py,sha256=-aRW4UPv4T215gjwmDNQ1p9S-9T92_DlQ9SY39roDDU,6717
|
|
91
93
|
flwr/common/constant.py,sha256=1XxuRezsr9fl3xvQNPR2kyFkwNeG_f5vZayv0PFh0kY,3012
|
|
92
94
|
flwr/common/context.py,sha256=5Bd9RCrhLkYZOVR7vr97OVhzVBHQkS1fUsYiIKTwpxU,2239
|
|
93
95
|
flwr/common/date.py,sha256=OcQuwpb2HxcblTqYm6H223ufop5UZw5N_fzalbpOVzY,891
|
|
@@ -106,9 +108,9 @@ flwr/common/record/configsrecord.py,sha256=VKeFEYa6cneyStqQlUOaKj12by5ZI_NXYR25L
|
|
|
106
108
|
flwr/common/record/conversion_utils.py,sha256=n3I3SI2P6hUjyxbWNc0QAch-SEhfMK6Hm-UUaplAlUc,1393
|
|
107
109
|
flwr/common/record/metricsrecord.py,sha256=Yv99oRa3LzFgSfwl903S8sB8rAgr3Sv6i6ovW7pdHsA,3923
|
|
108
110
|
flwr/common/record/parametersrecord.py,sha256=2sgjxsolFBUfnYYstIciOir0HAs95lqWY3pdcsYvsso,4838
|
|
109
|
-
flwr/common/record/recordset.py,sha256=
|
|
110
|
-
flwr/common/record/typeddict.py,sha256=
|
|
111
|
-
flwr/common/recordset_compat.py,sha256=
|
|
111
|
+
flwr/common/record/recordset.py,sha256=CKEfjk-mTIlg_aFpTfDyXme1UAXhqz2Ei-h55xxzRiY,5058
|
|
112
|
+
flwr/common/record/typeddict.py,sha256=M9zU1vjuPmKRxA0uiP2v752TB3D2VfrJzKNWx-EFviw,3016
|
|
113
|
+
flwr/common/recordset_compat.py,sha256=5prvfx8mT4ZWIEU4Gmz2wzCbO4yPjQ3ONr20uKt3UM0,13973
|
|
112
114
|
flwr/common/retry_invoker.py,sha256=dQY5fPIKhy9OiFswZhLxA9fB455u-DYCvDVcFJmrPDk,11707
|
|
113
115
|
flwr/common/secure_aggregation/__init__.py,sha256=erPnTWdOfMH0K0HQTmj5foDJ6t3iYcExy2aACy8iZNQ,731
|
|
114
116
|
flwr/common/secure_aggregation/crypto/__init__.py,sha256=nlHesCWy8xxE5s6qHWnauCtyClcMQ2K0CEXAHakY5n0,738
|
|
@@ -118,9 +120,9 @@ flwr/common/secure_aggregation/ndarrays_arithmetic.py,sha256=7Y0WnWcYi8UWZEKnUb4
|
|
|
118
120
|
flwr/common/secure_aggregation/quantization.py,sha256=1obYr9qneaI8r-A0F_pghrPNG9FcAwM5svSLbzMw6C4,2310
|
|
119
121
|
flwr/common/secure_aggregation/secaggplus_constants.py,sha256=9MF-oQh62uD7rt9VeNB-rHf2gBLd5GL3S9OejCxmILY,2183
|
|
120
122
|
flwr/common/secure_aggregation/secaggplus_utils.py,sha256=3VssKgYF7HQIkSpROnEUoYWVt47p12PE_Rj4nYqqg04,3221
|
|
121
|
-
flwr/common/serde.py,sha256=
|
|
123
|
+
flwr/common/serde.py,sha256=SIKZa-TNCSWVtqx8L3aUkylN6gxK-IwXlgoukiYwYyc,29209
|
|
122
124
|
flwr/common/telemetry.py,sha256=nSjJHDitPhzB2qUl6LeSMT9Zld5lIk9uW98RpxQwiZw,8366
|
|
123
|
-
flwr/common/typing.py,sha256=
|
|
125
|
+
flwr/common/typing.py,sha256=rGabiSkjFvGIHwmhDqtuu-LBvz7LVSj1vyMlNtA7VA0,5004
|
|
124
126
|
flwr/common/version.py,sha256=W1ntylR04xkCP6zeSet6sRtBn7P1cje2lOqBJgYBjJY,1349
|
|
125
127
|
flwr/proto/__init__.py,sha256=hbY7JYakwZwCkYgCNlmHdc8rtvfoJbAZLalMdc--CGc,683
|
|
126
128
|
flwr/proto/clientappio_pb2.py,sha256=018Lj2HBXmEeq6KsmqFVVx2DGO2nDQqTA6YHEPjCTbc,3242
|
|
@@ -139,8 +141,8 @@ flwr/proto/error_pb2.py,sha256=LarjKL90LbwkXKlhzNrDssgl4DXcvIPve8NVCXHpsKA,1084
|
|
|
139
141
|
flwr/proto/error_pb2.pyi,sha256=ZNH4HhJTU_KfMXlyCeg8FwU-fcUYxTqEmoJPtWtHikc,734
|
|
140
142
|
flwr/proto/error_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
|
141
143
|
flwr/proto/error_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
|
|
142
|
-
flwr/proto/exec_pb2.py,sha256=
|
|
143
|
-
flwr/proto/exec_pb2.pyi,sha256=
|
|
144
|
+
flwr/proto/exec_pb2.py,sha256=iqAvJ03atrueo5duiRHD_peegJiLsrWuNnVU8lA2PXw,3231
|
|
145
|
+
flwr/proto/exec_pb2.pyi,sha256=5y6L3xFkAuCfLTn2pVIHQAlXp17YcTTq8WVDS7_MPl4,4273
|
|
144
146
|
flwr/proto/exec_pb2_grpc.py,sha256=faAN19XEMP8GTKrcIU6jvlWkN44n2KiUsZh_OG0sYcg,4072
|
|
145
147
|
flwr/proto/exec_pb2_grpc.pyi,sha256=VrFhT1Um3Nb8UC2YqnR9GIiM-Yyx0FqaxVOWljh-G_w,1208
|
|
146
148
|
flwr/proto/fab_pb2.py,sha256=ztC3HnD5e-bYpp7lxrlxkdc30haAlBHswTnt4X5G1eg,1432
|
|
@@ -155,8 +157,8 @@ flwr/proto/grpcadapter_pb2.py,sha256=bb8mW09XzNCpMdr1KuYQkefPFWR8lc8y1uL6Uk0TtsM
|
|
|
155
157
|
flwr/proto/grpcadapter_pb2.pyi,sha256=AR77gDsF6f8zqSIQp3877DUd7S8lP95lFak5Ir_WPkw,1716
|
|
156
158
|
flwr/proto/grpcadapter_pb2_grpc.py,sha256=rRNuNES5nBugUZWfeA8oAy8dMHgzqU_PF1srTseo3b8,2634
|
|
157
159
|
flwr/proto/grpcadapter_pb2_grpc.pyi,sha256=AgA9Qo_lnANb9SNuPzbZGAxupau-xcqYawZz6vqf-24,735
|
|
158
|
-
flwr/proto/message_pb2.py,sha256=
|
|
159
|
-
flwr/proto/message_pb2.pyi,sha256=
|
|
160
|
+
flwr/proto/message_pb2.py,sha256=6fiapmq94u3T9wqW7tGsWVuyLanW31VAg0-rD2Hfk8U,3151
|
|
161
|
+
flwr/proto/message_pb2.pyi,sha256=_J9NjZa7Pr-kSO7-GGOL5EvIXQx5mQD04iVIvnVHBMU,5617
|
|
160
162
|
flwr/proto/message_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
|
161
163
|
flwr/proto/message_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
|
|
162
164
|
flwr/proto/node_pb2.py,sha256=1zfXEvgGObglIcaVb4SLFmOcHZvA8eHzEtMFM5A6FYY,1081
|
|
@@ -181,7 +183,7 @@ flwr/proto/transport_pb2_grpc.py,sha256=vLN3EHtx2aEEMCO4f1Upu-l27BPzd3-5pV-u8wPc
|
|
|
181
183
|
flwr/proto/transport_pb2_grpc.pyi,sha256=AGXf8RiIiW2J5IKMlm_3qT3AzcDa4F3P5IqUjve_esA,766
|
|
182
184
|
flwr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
183
185
|
flwr/server/__init__.py,sha256=BxzPhvouvWFGi7CFpI5b4EeVR9XDqbK7Ndqg24EL_Rw,1679
|
|
184
|
-
flwr/server/app.py,sha256=
|
|
186
|
+
flwr/server/app.py,sha256=haNCyIL0v6jCwZemjzok_LB8zWxL_T9J4dOZ7AY2x78,24153
|
|
185
187
|
flwr/server/client_manager.py,sha256=T8UDSRJBVD3fyIDI7NTAA-NA7GPrMNNgH2OAF54RRxE,6127
|
|
186
188
|
flwr/server/client_proxy.py,sha256=4G-oTwhb45sfWLx2uZdcXD98IZwdTS6F88xe3akCdUg,2399
|
|
187
189
|
flwr/server/compat/__init__.py,sha256=VxnJtJyOjNFQXMNi9hIuzNlZM5n0Hj1p3aq_Pm2udw4,892
|
|
@@ -192,7 +194,7 @@ flwr/server/compat/legacy_context.py,sha256=wBzBcfV6YO6IQGriM_FdJ5XZfiBBEEJdS_Od
|
|
|
192
194
|
flwr/server/criterion.py,sha256=ypbAexbztzGUxNen9RCHF91QeqiEQix4t4Ih3E-42MM,1061
|
|
193
195
|
flwr/server/driver/__init__.py,sha256=bikRv6CjTwSvYh7tf10gziU5o2YotOWhhftz2tr3KDc,886
|
|
194
196
|
flwr/server/driver/driver.py,sha256=NT_yaeit7_kZEIsCEqOWPID1GrVD3ywH4xZ2wtIh5lM,5217
|
|
195
|
-
flwr/server/driver/grpc_driver.py,sha256=
|
|
197
|
+
flwr/server/driver/grpc_driver.py,sha256=EbnOtrTR4cmu2ZhmPqKEmOHAhNQD1fd0hAd_xN1MePQ,9749
|
|
196
198
|
flwr/server/driver/inmemory_driver.py,sha256=RcK94_NtjGZ4aZDIscnU7A3Uv1u8jGx29-xcbjQvZTM,6444
|
|
197
199
|
flwr/server/history.py,sha256=bBOHKyX1eQONIsUx4EUU-UnAk1i0EbEl8ioyMq_UWQ8,5063
|
|
198
200
|
flwr/server/run_serverapp.py,sha256=8HCGSVaNYd2cnd_j-JpVTRH7Cg8_U7ATZUejiMmJe0o,8894
|
|
@@ -226,11 +228,12 @@ flwr/server/strategy/qfedavg.py,sha256=LZ-zVHRFPVMeeROgDHfMshHaAKaq9Hu9Ev9blREQm
|
|
|
226
228
|
flwr/server/strategy/strategy.py,sha256=g6VoIFogEviRub6G4QsKdIp6M_Ek6GhBhqcdNx5ueUk,7543
|
|
227
229
|
flwr/server/superlink/__init__.py,sha256=8tHYCfodUlRD8PCP9fHgvu8cz5N31A2QoRVL0jDJ15E,707
|
|
228
230
|
flwr/server/superlink/driver/__init__.py,sha256=_JaRW-FdyikHc7souUrnk3mwTGViraEJCeUBY_M_ocs,712
|
|
229
|
-
flwr/server/superlink/driver/driver_grpc.py,sha256=
|
|
230
|
-
flwr/server/superlink/driver/driver_servicer.py,sha256=
|
|
231
|
+
flwr/server/superlink/driver/driver_grpc.py,sha256=XZ8veSfKStieUgkRntvOw10F0fmHytw_lr7CDtgzLpY,2055
|
|
232
|
+
flwr/server/superlink/driver/driver_servicer.py,sha256=k_3IuteN0zRDz-xsM7RImHn7JODXrcvTRQdobVH7rCw,6581
|
|
231
233
|
flwr/server/superlink/ffs/__init__.py,sha256=FAY-zShcfPmOxosok2QyT6hTNMNctG8cH9s_nIl8jkI,840
|
|
232
234
|
flwr/server/superlink/ffs/disk_ffs.py,sha256=ZsBCQVpuScm5QNul_XWlXU65XEaOGbH9ULIls6h7p1A,3213
|
|
233
235
|
flwr/server/superlink/ffs/ffs.py,sha256=AVl1AM7ZfVTPOIEQJuMR-aXUUd2foSkRe49NWoPecL8,2384
|
|
236
|
+
flwr/server/superlink/ffs/ffs_factory.py,sha256=N_eMuUZggotdGiDQ5r_Tf21xsu_ob0e3jyM6ag7d3kk,1490
|
|
234
237
|
flwr/server/superlink/fleet/__init__.py,sha256=76od-HhYjOUoZFLFDFCFnNHI4JLAmaXQEAyp7LWlQpc,711
|
|
235
238
|
flwr/server/superlink/fleet/grpc_adapter/__init__.py,sha256=spBQQJeYz8zPOBOfyMLv87kqWPASGB73AymcLXdFaYA,742
|
|
236
239
|
flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py,sha256=K4LkOsVzIdsR7Py_9cfo6CR-bDocpP15ktHTc2UnJ9k,4957
|
|
@@ -252,9 +255,9 @@ flwr/server/superlink/fleet/vce/backend/backend.py,sha256=KL0eHScWr_YfP2eY3VP8_O
|
|
|
252
255
|
flwr/server/superlink/fleet/vce/backend/raybackend.py,sha256=6-CjUTv1cFnAb53cZzEYCuVLrVu60tPczTo8meqeqbk,6289
|
|
253
256
|
flwr/server/superlink/fleet/vce/vce_api.py,sha256=AeJBEZIC3V54Wg4bzBJa0aO4IXUNiRzRDRv-EKhqtpQ,12750
|
|
254
257
|
flwr/server/superlink/state/__init__.py,sha256=Gj2OTFLXvA-mAjBvwuKDM3rDrVaQPcIoybSa2uskMTE,1003
|
|
255
|
-
flwr/server/superlink/state/in_memory_state.py,sha256=
|
|
256
|
-
flwr/server/superlink/state/sqlite_state.py,sha256=
|
|
257
|
-
flwr/server/superlink/state/state.py,sha256=
|
|
258
|
+
flwr/server/superlink/state/in_memory_state.py,sha256=XMcT5WvKPOrFOuKcByr5BRFacX4aR2n9bRkABUuPg-M,13206
|
|
259
|
+
flwr/server/superlink/state/sqlite_state.py,sha256=N8eOLZUveJOzdzL31-hXRYOMqV_-w75S1InyDenaDWU,29420
|
|
260
|
+
flwr/server/superlink/state/state.py,sha256=peHACUjhUF4gfZ5icMsBGjQNa6A6rvku9a_mziRJW40,8154
|
|
258
261
|
flwr/server/superlink/state/state_factory.py,sha256=Fo8pBQ1WWrVJK5TOEPZ_zgJE69_mfTGjTO6czh6571o,2021
|
|
259
262
|
flwr/server/superlink/state/utils.py,sha256=155ngcaSePy7nD8X4LHgpuVok6fcH5_CPNRiFAbLWDA,2407
|
|
260
263
|
flwr/server/typing.py,sha256=5kaRLZuxTEse9A0g7aVna2VhYxU3wTq1f3d3mtw7kXs,1019
|
|
@@ -273,16 +276,16 @@ flwr/simulation/ray_transport/__init__.py,sha256=wzcEEwUUlulnXsg6raCA1nGpP3LlAQD
|
|
|
273
276
|
flwr/simulation/ray_transport/ray_actor.py,sha256=3j0HgzjrlYjnzdTRy8aA4Nf6VoUvxi1hGRQkGSU5z6c,19020
|
|
274
277
|
flwr/simulation/ray_transport/ray_client_proxy.py,sha256=0abIsU0VBk9rNJZOKHIyzYGy3ZnWBgqYocX_oct1EP0,7307
|
|
275
278
|
flwr/simulation/ray_transport/utils.py,sha256=TYdtfg1P9VfTdLMOJlifInGpxWHYs9UfUqIv2wfkRLA,2392
|
|
276
|
-
flwr/simulation/run_simulation.py,sha256=
|
|
279
|
+
flwr/simulation/run_simulation.py,sha256=pKkyrAWzxf05j8AoXh2eYyYeV6PbAXtq1egv2l5JM3I,23447
|
|
277
280
|
flwr/superexec/__init__.py,sha256=9h94ogLxi6eJ3bUuJYq3E3pApThSabTPiSmPAGlTkHE,800
|
|
278
281
|
flwr/superexec/app.py,sha256=bmYl8zABnWka9WhRQxX4p1YAI76cYG655dP09ro-V0o,6485
|
|
279
282
|
flwr/superexec/deployment.py,sha256=B--96bAvyotQX-c4-umXIe50uCw4HVjD79rXCQtSUH4,6357
|
|
280
283
|
flwr/superexec/exec_grpc.py,sha256=PhqGoZEpTMxSQmUSV8Wgtzb1Za_pHJ-adZqo5RYnDyE,1942
|
|
281
|
-
flwr/superexec/exec_servicer.py,sha256=
|
|
284
|
+
flwr/superexec/exec_servicer.py,sha256=jl0aKVjm0PLQABcTL5c3jdSIzb0Z6hpVOtrAn4Ob7ts,2323
|
|
282
285
|
flwr/superexec/executor.py,sha256=k_adivto6R2U82DADOHNvdtobehBYreRek1gOEBIQnQ,2318
|
|
283
286
|
flwr/superexec/simulation.py,sha256=lfdClQYSAIMHe43aJ0Pk-kBw_xoV09LsIMfHo2eo-Ck,6775
|
|
284
|
-
flwr_nightly-1.11.0.
|
|
285
|
-
flwr_nightly-1.11.0.
|
|
286
|
-
flwr_nightly-1.11.0.
|
|
287
|
-
flwr_nightly-1.11.0.
|
|
288
|
-
flwr_nightly-1.11.0.
|
|
287
|
+
flwr_nightly-1.11.0.dev20240815.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
288
|
+
flwr_nightly-1.11.0.dev20240815.dist-info/METADATA,sha256=3zvVGv43ZwKbuaVf2LIn5jvzKs0k-30AY2WBWRLrFWA,15690
|
|
289
|
+
flwr_nightly-1.11.0.dev20240815.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
290
|
+
flwr_nightly-1.11.0.dev20240815.dist-info/entry_points.txt,sha256=KqQQGNjnr-2IT-bheOkO9yM4Gv5BtjaBgYKRkp-NhVg,388
|
|
291
|
+
flwr_nightly-1.11.0.dev20240815.dist-info/RECORD,,
|
{flwr_nightly-1.11.0.dev20240813.dist-info → flwr_nightly-1.11.0.dev20240815.dist-info}/LICENSE
RENAMED
|
File without changes
|
{flwr_nightly-1.11.0.dev20240813.dist-info → flwr_nightly-1.11.0.dev20240815.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|