flwr-nightly 1.19.0.dev20250516__py3-none-any.whl → 1.19.0.dev20250520__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/app/__init__.py ADDED
@@ -0,0 +1,15 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Public Flower App APIs."""
flwr/app/error.py ADDED
@@ -0,0 +1,68 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Error."""
16
+
17
+
18
+ from __future__ import annotations
19
+
20
+ from typing import Optional, cast
21
+
22
+ DEFAULT_TTL = 43200 # This is 12 hours
23
+ MESSAGE_INIT_ERROR_MESSAGE = (
24
+ "Invalid arguments for Message. Expected one of the documented "
25
+ "signatures: Message(content: RecordDict, dst_node_id: int, message_type: str,"
26
+ " *, [ttl: float, group_id: str]) or Message(content: RecordDict | error: Error,"
27
+ " *, reply_to: Message, [ttl: float])."
28
+ )
29
+
30
+
31
+ class Error:
32
+ """The class storing information about an error that occurred.
33
+
34
+ Parameters
35
+ ----------
36
+ code : int
37
+ An identifier for the error.
38
+ reason : Optional[str]
39
+ A reason for why the error arose (e.g. an exception stack-trace)
40
+ """
41
+
42
+ def __init__(self, code: int, reason: str | None = None) -> None:
43
+ var_dict = {
44
+ "_code": code,
45
+ "_reason": reason,
46
+ }
47
+ self.__dict__.update(var_dict)
48
+
49
+ @property
50
+ def code(self) -> int:
51
+ """Error code."""
52
+ return cast(int, self.__dict__["_code"])
53
+
54
+ @property
55
+ def reason(self) -> str | None:
56
+ """Reason reported about the error."""
57
+ return cast(Optional[str], self.__dict__["_reason"])
58
+
59
+ def __repr__(self) -> str:
60
+ """Return a string representation of this instance."""
61
+ view = ", ".join([f"{k.lstrip('_')}={v!r}" for k, v in self.__dict__.items()])
62
+ return f"{self.__class__.__qualname__}({view})"
63
+
64
+ def __eq__(self, other: object) -> bool:
65
+ """Compare two instances of the class."""
66
+ if not isinstance(other, self.__class__):
67
+ raise NotImplementedError
68
+ return self.__dict__ == other.__dict__
flwr/app/metadata.py ADDED
@@ -0,0 +1,223 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Metadata."""
16
+
17
+
18
+ from __future__ import annotations
19
+
20
+ from typing import cast
21
+
22
+ from ..common.constant import MessageType, MessageTypeLegacy
23
+
24
+
25
+ class Metadata: # pylint: disable=too-many-instance-attributes
26
+ """The class representing metadata associated with the current message.
27
+
28
+ Parameters
29
+ ----------
30
+ run_id : int
31
+ An identifier for the current run.
32
+ message_id : str
33
+ An identifier for the current message.
34
+ src_node_id : int
35
+ An identifier for the node sending this message.
36
+ dst_node_id : int
37
+ An identifier for the node receiving this message.
38
+ reply_to_message_id : str
39
+ An identifier for the message to which this message is a reply.
40
+ group_id : str
41
+ An identifier for grouping messages. In some settings,
42
+ this is used as the FL round.
43
+ created_at : float
44
+ Unix timestamp when the message was created.
45
+ ttl : float
46
+ Time-to-live for this message in seconds.
47
+ message_type : str
48
+ A string that encodes the action to be executed on
49
+ the receiving end.
50
+ """
51
+
52
+ def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments
53
+ self,
54
+ run_id: int,
55
+ message_id: str,
56
+ src_node_id: int,
57
+ dst_node_id: int,
58
+ reply_to_message_id: str,
59
+ group_id: str,
60
+ created_at: float,
61
+ ttl: float,
62
+ message_type: str,
63
+ ) -> None:
64
+ var_dict = {
65
+ "_run_id": run_id,
66
+ "_message_id": message_id,
67
+ "_src_node_id": src_node_id,
68
+ "_dst_node_id": dst_node_id,
69
+ "_reply_to_message_id": reply_to_message_id,
70
+ "_group_id": group_id,
71
+ "_created_at": created_at,
72
+ "_ttl": ttl,
73
+ "_message_type": message_type,
74
+ }
75
+ self.__dict__.update(var_dict)
76
+ self.message_type = message_type # Trigger validation
77
+
78
+ @property
79
+ def run_id(self) -> int:
80
+ """An identifier for the current run."""
81
+ return cast(int, self.__dict__["_run_id"])
82
+
83
+ @property
84
+ def message_id(self) -> str:
85
+ """An identifier for the current message."""
86
+ return cast(str, self.__dict__["_message_id"])
87
+
88
+ @property
89
+ def src_node_id(self) -> int:
90
+ """An identifier for the node sending this message."""
91
+ return cast(int, self.__dict__["_src_node_id"])
92
+
93
+ @property
94
+ def reply_to_message_id(self) -> str:
95
+ """An identifier for the message to which this message is a reply."""
96
+ return cast(str, self.__dict__["_reply_to_message_id"])
97
+
98
+ @property
99
+ def dst_node_id(self) -> int:
100
+ """An identifier for the node receiving this message."""
101
+ return cast(int, self.__dict__["_dst_node_id"])
102
+
103
+ @dst_node_id.setter
104
+ def dst_node_id(self, value: int) -> None:
105
+ """Set dst_node_id."""
106
+ self.__dict__["_dst_node_id"] = value
107
+
108
+ @property
109
+ def group_id(self) -> str:
110
+ """An identifier for grouping messages."""
111
+ return cast(str, self.__dict__["_group_id"])
112
+
113
+ @group_id.setter
114
+ def group_id(self, value: str) -> None:
115
+ """Set group_id."""
116
+ self.__dict__["_group_id"] = value
117
+
118
+ @property
119
+ def created_at(self) -> float:
120
+ """Unix timestamp when the message was created."""
121
+ return cast(float, self.__dict__["_created_at"])
122
+
123
+ @created_at.setter
124
+ def created_at(self, value: float) -> None:
125
+ """Set creation timestamp of this message."""
126
+ self.__dict__["_created_at"] = value
127
+
128
+ @property
129
+ def delivered_at(self) -> str:
130
+ """Unix timestamp when the message was delivered."""
131
+ return cast(str, self.__dict__["_delivered_at"])
132
+
133
+ @delivered_at.setter
134
+ def delivered_at(self, value: str) -> None:
135
+ """Set delivery timestamp of this message."""
136
+ self.__dict__["_delivered_at"] = value
137
+
138
+ @property
139
+ def ttl(self) -> float:
140
+ """Time-to-live for this message."""
141
+ return cast(float, self.__dict__["_ttl"])
142
+
143
+ @ttl.setter
144
+ def ttl(self, value: float) -> None:
145
+ """Set ttl."""
146
+ self.__dict__["_ttl"] = value
147
+
148
+ @property
149
+ def message_type(self) -> str:
150
+ """A string that encodes the action to be executed on the receiving end."""
151
+ return cast(str, self.__dict__["_message_type"])
152
+
153
+ @message_type.setter
154
+ def message_type(self, value: str) -> None:
155
+ """Set message_type."""
156
+ # Validate message type
157
+ if validate_legacy_message_type(value):
158
+ pass # Backward compatibility for legacy message types
159
+ elif not validate_message_type(value):
160
+ raise ValueError(
161
+ f"Invalid message type: '{value}'. "
162
+ "Expected format: '<category>' or '<category>.<action>', "
163
+ "where <category> must be 'train', 'evaluate', or 'query', "
164
+ "and <action> must be a valid Python identifier."
165
+ )
166
+
167
+ self.__dict__["_message_type"] = value
168
+
169
+ def __repr__(self) -> str:
170
+ """Return a string representation of this instance."""
171
+ view = ", ".join([f"{k.lstrip('_')}={v!r}" for k, v in self.__dict__.items()])
172
+ return f"{self.__class__.__qualname__}({view})"
173
+
174
+ def __eq__(self, other: object) -> bool:
175
+ """Compare two instances of the class."""
176
+ if not isinstance(other, self.__class__):
177
+ raise NotImplementedError
178
+ return self.__dict__ == other.__dict__
179
+
180
+
181
+ def validate_message_type(message_type: str) -> bool:
182
+ """Validate if the message type is valid.
183
+
184
+ A valid message type format must be one of the following:
185
+
186
+ - "<category>"
187
+ - "<category>.<action>"
188
+
189
+ where `category` must be one of "train", "evaluate", or "query",
190
+ and `action` must be a valid Python identifier.
191
+ """
192
+ # Check if conforming to the format "<category>"
193
+ valid_types = {
194
+ MessageType.TRAIN,
195
+ MessageType.EVALUATE,
196
+ MessageType.QUERY,
197
+ MessageType.SYSTEM,
198
+ }
199
+ if message_type in valid_types:
200
+ return True
201
+
202
+ # Check if conforming to the format "<category>.<action>"
203
+ if message_type.count(".") != 1:
204
+ return False
205
+
206
+ category, action = message_type.split(".")
207
+ if category in valid_types and action.isidentifier():
208
+ return True
209
+
210
+ return False
211
+
212
+
213
+ def validate_legacy_message_type(message_type: str) -> bool:
214
+ """Validate if the legacy message type is valid."""
215
+ # Backward compatibility for legacy message types
216
+ if message_type in (
217
+ MessageTypeLegacy.GET_PARAMETERS,
218
+ MessageTypeLegacy.GET_PROPERTIES,
219
+ "reconnect",
220
+ ):
221
+ return True
222
+
223
+ return False
flwr/client/app.py CHANGED
@@ -30,6 +30,7 @@ import grpc
30
30
  from cryptography.hazmat.primitives.asymmetric import ec
31
31
  from grpc import RpcError
32
32
 
33
+ from flwr.app.error import Error
33
34
  from flwr.cli.config_utils import get_fab_metadata
34
35
  from flwr.cli.install import install_from_fab
35
36
  from flwr.client.client import Client
@@ -57,7 +58,6 @@ from flwr.common.constant import (
57
58
  from flwr.common.exit import ExitCode, flwr_exit
58
59
  from flwr.common.grpc import generic_create_grpc_server
59
60
  from flwr.common.logger import log, warn_deprecated_feature
60
- from flwr.common.message import Error
61
61
  from flwr.common.retry_invoker import RetryInvoker, RetryState, exponential
62
62
  from flwr.common.typing import Fab, Run, RunNotRunningException, UserConfig
63
63
  from flwr.proto.clientappio_pb2_grpc import add_ClientAppIoServicer_to_server
flwr/client/client_app.py CHANGED
@@ -20,6 +20,7 @@ from collections.abc import Iterator
20
20
  from contextlib import contextmanager
21
21
  from typing import Callable, Optional
22
22
 
23
+ from flwr.app.metadata import validate_message_type
23
24
  from flwr.client.client import Client
24
25
  from flwr.client.message_handler.message_handler import (
25
26
  handle_legacy_message_from_msgtype,
@@ -28,7 +29,6 @@ from flwr.client.mod.utils import make_ffn
28
29
  from flwr.client.typing import ClientFnExt, Mod
29
30
  from flwr.common import Context, Message, MessageType
30
31
  from flwr.common.logger import warn_deprecated_feature
31
- from flwr.common.message import validate_message_type
32
32
 
33
33
  from .typing import ClientAppCallable
34
34
 
@@ -23,6 +23,7 @@ from typing import Optional
23
23
 
24
24
  import grpc
25
25
 
26
+ from flwr.app.error import Error
26
27
  from flwr.cli.install import install_from_fab
27
28
  from flwr.client.client_app import ClientApp, LoadClientAppError
28
29
  from flwr.common import Context, Message
@@ -32,7 +33,6 @@ from flwr.common.constant import CLIENTAPPIO_API_DEFAULT_CLIENT_ADDRESS, ErrorCo
32
33
  from flwr.common.exit import ExitCode, flwr_exit
33
34
  from flwr.common.grpc import create_channel, on_channel_state_change
34
35
  from flwr.common.logger import log
35
- from flwr.common.message import Error
36
36
  from flwr.common.retry_invoker import _make_simple_grpc_retry_invoker, _wrap_stub
37
37
  from flwr.common.serde import (
38
38
  context_from_proto,
@@ -25,13 +25,14 @@ from typing import Callable, Optional, Union, cast
25
25
  import grpc
26
26
  from cryptography.hazmat.primitives.asymmetric import ec
27
27
 
28
+ from flwr.app.metadata import Metadata
28
29
  from flwr.client.message_handler.message_handler import validate_out_message
29
30
  from flwr.common import GRPC_MAX_MESSAGE_LENGTH
30
31
  from flwr.common.constant import HEARTBEAT_CALL_TIMEOUT, HEARTBEAT_DEFAULT_INTERVAL
31
32
  from flwr.common.grpc import create_channel, on_channel_state_change
32
33
  from flwr.common.heartbeat import HeartbeatSender
33
34
  from flwr.common.logger import log
34
- from flwr.common.message import Message, Metadata
35
+ from flwr.common.message import Message
35
36
  from flwr.common.retry_invoker import RetryInvoker
36
37
  from flwr.common.secure_aggregation.crypto.symmetric_encryption import (
37
38
  generate_key_pairs,
@@ -25,13 +25,14 @@ from cryptography.hazmat.primitives.asymmetric import ec
25
25
  from google.protobuf.message import Message as GrpcMessage
26
26
  from requests.exceptions import ConnectionError as RequestsConnectionError
27
27
 
28
+ from flwr.app.metadata import Metadata
28
29
  from flwr.client.message_handler.message_handler import validate_out_message
29
30
  from flwr.common import GRPC_MAX_MESSAGE_LENGTH
30
31
  from flwr.common.constant import HEARTBEAT_DEFAULT_INTERVAL
31
32
  from flwr.common.exit import ExitCode, flwr_exit
32
33
  from flwr.common.heartbeat import HeartbeatSender
33
34
  from flwr.common.logger import log
34
- from flwr.common.message import Message, Metadata
35
+ from flwr.common.message import Message
35
36
  from flwr.common.retry_invoker import RetryInvoker
36
37
  from flwr.common.serde import message_from_proto, message_to_proto, run_from_proto
37
38
  from flwr.common.typing import Fab, Run
@@ -0,0 +1,15 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Public Flower ClientApp APIs."""
flwr/common/__init__.py CHANGED
@@ -15,6 +15,8 @@
15
15
  """Common components shared between server and client."""
16
16
 
17
17
 
18
+ from ..app.error import Error as Error
19
+ from ..app.metadata import Metadata as Metadata
18
20
  from .constant import MessageType as MessageType
19
21
  from .constant import MessageTypeLegacy as MessageTypeLegacy
20
22
  from .context import Context as Context
@@ -23,9 +25,7 @@ from .grpc import GRPC_MAX_MESSAGE_LENGTH
23
25
  from .logger import configure as configure
24
26
  from .logger import log as log
25
27
  from .message import DEFAULT_TTL
26
- from .message import Error as Error
27
28
  from .message import Message as Message
28
- from .message import Metadata as Metadata
29
29
  from .parameter import bytes_to_ndarray as bytes_to_ndarray
30
30
  from .parameter import ndarray_to_bytes as ndarray_to_bytes
31
31
  from .parameter import ndarrays_to_parameters as ndarrays_to_parameters
@@ -0,0 +1,97 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """InflatableObject utils."""
16
+
17
+
18
+ from typing import Union
19
+
20
+ from flwr.proto.fleet_pb2_grpc import FleetStub # pylint: disable=E0611
21
+ from flwr.proto.message_pb2 import ( # pylint: disable=E0611
22
+ PullObjectRequest,
23
+ PullObjectResponse,
24
+ PushObjectRequest,
25
+ PushObjectResponse,
26
+ )
27
+ from flwr.proto.serverappio_pb2_grpc import ServerAppIoStub # pylint: disable=E0611
28
+
29
+ from .inflatable import (
30
+ InflatableObject,
31
+ get_object_head_values_from_object_content,
32
+ get_object_id,
33
+ )
34
+ from .record import Array, ArrayRecord, ConfigRecord, MetricRecord, RecordDict
35
+
36
+ # Helper registry that maps names of classes to their type
37
+ inflatable_class_registry: dict[str, type[InflatableObject]] = {
38
+ Array.__qualname__: Array,
39
+ ArrayRecord.__qualname__: ArrayRecord,
40
+ ConfigRecord.__qualname__: ConfigRecord,
41
+ MetricRecord.__qualname__: MetricRecord,
42
+ RecordDict.__qualname__: RecordDict,
43
+ }
44
+
45
+
46
+ def push_object_to_servicer(
47
+ obj: InflatableObject, stub: Union[FleetStub, ServerAppIoStub]
48
+ ) -> set[str]:
49
+ """Recursively deflate an object and push it to the servicer.
50
+
51
+ Objects with the same ID are not pushed twice. It returns the set of pushed object
52
+ IDs.
53
+ """
54
+ pushed_object_ids: set[str] = set()
55
+ # Push children if it has any
56
+ if children := obj.children:
57
+ for child in children.values():
58
+ pushed_object_ids |= push_object_to_servicer(child, stub)
59
+
60
+ # Deflate object and push
61
+ object_content = obj.deflate()
62
+ object_id = get_object_id(object_content)
63
+ _: PushObjectResponse = stub.PushObject(
64
+ PushObjectRequest(
65
+ object_id=object_id,
66
+ object_content=object_content,
67
+ )
68
+ )
69
+ pushed_object_ids.add(object_id)
70
+
71
+ return pushed_object_ids
72
+
73
+
74
+ def pull_object_from_servicer(
75
+ object_id: str, stub: Union[FleetStub, ServerAppIoStub]
76
+ ) -> InflatableObject:
77
+ """Recursively inflate an object by pulling it from the servicer."""
78
+ # Pull object
79
+ object_proto: PullObjectResponse = stub.PullObject(
80
+ PullObjectRequest(object_id=object_id)
81
+ )
82
+ object_content = object_proto.object_content
83
+
84
+ # Extract object class and object_ids of children
85
+ obj_type, children_obj_ids, _ = get_object_head_values_from_object_content(
86
+ object_content=object_content
87
+ )
88
+ # Resolve object class
89
+ cls_type = inflatable_class_registry[obj_type]
90
+
91
+ # Pull all children objects
92
+ children: dict[str, InflatableObject] = {}
93
+ for child_object_id in children_obj_ids:
94
+ children[child_object_id] = pull_object_from_servicer(child_object_id, stub)
95
+
96
+ # Inflate object passing its children
97
+ return cls_type.inflate(object_content, children=children)
flwr/common/message.py CHANGED
@@ -18,12 +18,14 @@
18
18
  from __future__ import annotations
19
19
 
20
20
  from logging import WARNING
21
- from typing import Any, Optional, cast, overload
21
+ from typing import Any, cast, overload
22
22
 
23
23
  from flwr.common.date import now
24
24
  from flwr.common.logger import warn_deprecated_feature
25
25
 
26
- from .constant import MESSAGE_TTL_TOLERANCE, MessageType, MessageTypeLegacy
26
+ from ..app.error import Error
27
+ from ..app.metadata import Metadata
28
+ from .constant import MESSAGE_TTL_TOLERANCE
27
29
  from .logger import log
28
30
  from .record import RecordDict
29
31
 
@@ -56,202 +58,6 @@ class MessageInitializationError(TypeError):
56
58
  super().__init__(message or MESSAGE_INIT_ERROR_MESSAGE)
57
59
 
58
60
 
59
- class Metadata: # pylint: disable=too-many-instance-attributes
60
- """The class representing metadata associated with the current message.
61
-
62
- Parameters
63
- ----------
64
- run_id : int
65
- An identifier for the current run.
66
- message_id : str
67
- An identifier for the current message.
68
- src_node_id : int
69
- An identifier for the node sending this message.
70
- dst_node_id : int
71
- An identifier for the node receiving this message.
72
- reply_to_message_id : str
73
- An identifier for the message to which this message is a reply.
74
- group_id : str
75
- An identifier for grouping messages. In some settings,
76
- this is used as the FL round.
77
- created_at : float
78
- Unix timestamp when the message was created.
79
- ttl : float
80
- Time-to-live for this message in seconds.
81
- message_type : str
82
- A string that encodes the action to be executed on
83
- the receiving end.
84
- """
85
-
86
- def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments
87
- self,
88
- run_id: int,
89
- message_id: str,
90
- src_node_id: int,
91
- dst_node_id: int,
92
- reply_to_message_id: str,
93
- group_id: str,
94
- created_at: float,
95
- ttl: float,
96
- message_type: str,
97
- ) -> None:
98
- var_dict = {
99
- "_run_id": run_id,
100
- "_message_id": message_id,
101
- "_src_node_id": src_node_id,
102
- "_dst_node_id": dst_node_id,
103
- "_reply_to_message_id": reply_to_message_id,
104
- "_group_id": group_id,
105
- "_created_at": created_at,
106
- "_ttl": ttl,
107
- "_message_type": message_type,
108
- }
109
- self.__dict__.update(var_dict)
110
- self.message_type = message_type # Trigger validation
111
-
112
- @property
113
- def run_id(self) -> int:
114
- """An identifier for the current run."""
115
- return cast(int, self.__dict__["_run_id"])
116
-
117
- @property
118
- def message_id(self) -> str:
119
- """An identifier for the current message."""
120
- return cast(str, self.__dict__["_message_id"])
121
-
122
- @property
123
- def src_node_id(self) -> int:
124
- """An identifier for the node sending this message."""
125
- return cast(int, self.__dict__["_src_node_id"])
126
-
127
- @property
128
- def reply_to_message_id(self) -> str:
129
- """An identifier for the message to which this message is a reply."""
130
- return cast(str, self.__dict__["_reply_to_message_id"])
131
-
132
- @property
133
- def dst_node_id(self) -> int:
134
- """An identifier for the node receiving this message."""
135
- return cast(int, self.__dict__["_dst_node_id"])
136
-
137
- @dst_node_id.setter
138
- def dst_node_id(self, value: int) -> None:
139
- """Set dst_node_id."""
140
- self.__dict__["_dst_node_id"] = value
141
-
142
- @property
143
- def group_id(self) -> str:
144
- """An identifier for grouping messages."""
145
- return cast(str, self.__dict__["_group_id"])
146
-
147
- @group_id.setter
148
- def group_id(self, value: str) -> None:
149
- """Set group_id."""
150
- self.__dict__["_group_id"] = value
151
-
152
- @property
153
- def created_at(self) -> float:
154
- """Unix timestamp when the message was created."""
155
- return cast(float, self.__dict__["_created_at"])
156
-
157
- @created_at.setter
158
- def created_at(self, value: float) -> None:
159
- """Set creation timestamp of this message."""
160
- self.__dict__["_created_at"] = value
161
-
162
- @property
163
- def delivered_at(self) -> str:
164
- """Unix timestamp when the message was delivered."""
165
- return cast(str, self.__dict__["_delivered_at"])
166
-
167
- @delivered_at.setter
168
- def delivered_at(self, value: str) -> None:
169
- """Set delivery timestamp of this message."""
170
- self.__dict__["_delivered_at"] = value
171
-
172
- @property
173
- def ttl(self) -> float:
174
- """Time-to-live for this message."""
175
- return cast(float, self.__dict__["_ttl"])
176
-
177
- @ttl.setter
178
- def ttl(self, value: float) -> None:
179
- """Set ttl."""
180
- self.__dict__["_ttl"] = value
181
-
182
- @property
183
- def message_type(self) -> str:
184
- """A string that encodes the action to be executed on the receiving end."""
185
- return cast(str, self.__dict__["_message_type"])
186
-
187
- @message_type.setter
188
- def message_type(self, value: str) -> None:
189
- """Set message_type."""
190
- # Validate message type
191
- if validate_legacy_message_type(value):
192
- pass # Backward compatibility for legacy message types
193
- elif not validate_message_type(value):
194
- raise ValueError(
195
- f"Invalid message type: '{value}'. "
196
- "Expected format: '<category>' or '<category>.<action>', "
197
- "where <category> must be 'train', 'evaluate', or 'query', "
198
- "and <action> must be a valid Python identifier."
199
- )
200
-
201
- self.__dict__["_message_type"] = value
202
-
203
- def __repr__(self) -> str:
204
- """Return a string representation of this instance."""
205
- view = ", ".join([f"{k.lstrip('_')}={v!r}" for k, v in self.__dict__.items()])
206
- return f"{self.__class__.__qualname__}({view})"
207
-
208
- def __eq__(self, other: object) -> bool:
209
- """Compare two instances of the class."""
210
- if not isinstance(other, self.__class__):
211
- raise NotImplementedError
212
- return self.__dict__ == other.__dict__
213
-
214
-
215
- class Error:
216
- """The class storing information about an error that occurred.
217
-
218
- Parameters
219
- ----------
220
- code : int
221
- An identifier for the error.
222
- reason : Optional[str]
223
- A reason for why the error arose (e.g. an exception stack-trace)
224
- """
225
-
226
- def __init__(self, code: int, reason: str | None = None) -> None:
227
- var_dict = {
228
- "_code": code,
229
- "_reason": reason,
230
- }
231
- self.__dict__.update(var_dict)
232
-
233
- @property
234
- def code(self) -> int:
235
- """Error code."""
236
- return cast(int, self.__dict__["_code"])
237
-
238
- @property
239
- def reason(self) -> str | None:
240
- """Reason reported about the error."""
241
- return cast(Optional[str], self.__dict__["_reason"])
242
-
243
- def __repr__(self) -> str:
244
- """Return a string representation of this instance."""
245
- view = ", ".join([f"{k.lstrip('_')}={v!r}" for k, v in self.__dict__.items()])
246
- return f"{self.__class__.__qualname__}({view})"
247
-
248
- def __eq__(self, other: object) -> bool:
249
- """Compare two instances of the class."""
250
- if not isinstance(other, self.__class__):
251
- raise NotImplementedError
252
- return self.__dict__ == other.__dict__
253
-
254
-
255
61
  class Message:
256
62
  """Represents a message exchanged between ClientApp and ServerApp.
257
63
 
@@ -614,48 +420,3 @@ def _check_arg_types( # pylint: disable=too-many-arguments, R0917
614
420
  ):
615
421
  return
616
422
  raise MessageInitializationError()
617
-
618
-
619
- def validate_message_type(message_type: str) -> bool:
620
- """Validate if the message type is valid.
621
-
622
- A valid message type format must be one of the following:
623
-
624
- - "<category>"
625
- - "<category>.<action>"
626
-
627
- where `category` must be one of "train", "evaluate", or "query",
628
- and `action` must be a valid Python identifier.
629
- """
630
- # Check if conforming to the format "<category>"
631
- valid_types = {
632
- MessageType.TRAIN,
633
- MessageType.EVALUATE,
634
- MessageType.QUERY,
635
- MessageType.SYSTEM,
636
- }
637
- if message_type in valid_types:
638
- return True
639
-
640
- # Check if conforming to the format "<category>.<action>"
641
- if message_type.count(".") != 1:
642
- return False
643
-
644
- category, action = message_type.split(".")
645
- if category in valid_types and action.isidentifier():
646
- return True
647
-
648
- return False
649
-
650
-
651
- def validate_legacy_message_type(message_type: str) -> bool:
652
- """Validate if the legacy message type is valid."""
653
- # Backward compatibility for legacy message types
654
- if message_type in (
655
- MessageTypeLegacy.GET_PARAMETERS,
656
- MessageTypeLegacy.GET_PROPERTIES,
657
- "reconnect",
658
- ):
659
- return True
660
-
661
- return False
@@ -284,7 +284,7 @@ class Array(InflatableObject):
284
284
  Array
285
285
  The inflated Array.
286
286
  """
287
- if children is not None:
287
+ if children:
288
288
  raise ValueError("`Array` objects do not have children.")
289
289
 
290
290
  obj_body = get_object_body(object_content, cls)
@@ -204,7 +204,7 @@ class ConfigRecord(TypedDict[str, ConfigRecordValues], InflatableObject):
204
204
  ConfigRecord
205
205
  The inflated ConfigRecord.
206
206
  """
207
- if children is not None:
207
+ if children:
208
208
  raise ValueError("`ConfigRecord` objects do not have children.")
209
209
 
210
210
  obj_body = get_object_body(object_content, cls)
flwr/common/serde.py CHANGED
@@ -44,6 +44,9 @@ from flwr.proto.transport_pb2 import (
44
44
  Status,
45
45
  )
46
46
 
47
+ from ..app.error import Error
48
+ from ..app.metadata import Metadata
49
+
47
50
  # pylint: enable=E0611
48
51
  from . import (
49
52
  Array,
@@ -55,7 +58,7 @@ from . import (
55
58
  typing,
56
59
  )
57
60
  from .constant import INT64_MAX_VALUE
58
- from .message import Error, Message, Metadata, make_message
61
+ from .message import Message, make_message
59
62
  from .serde_utils import record_value_dict_from_proto, record_value_dict_to_proto
60
63
 
61
64
  # === Parameters message ===
@@ -0,0 +1,15 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Compatibility package containing deprecated legacy components."""
@@ -0,0 +1,15 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Legacy components previously located in ``flwr.client``."""
@@ -0,0 +1,15 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Legacy components previously located in ``flwr.common``."""
@@ -0,0 +1,15 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Legacy components previously located in ``flwr.server``."""
@@ -0,0 +1,15 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Legacy components previously located in ``flwr.simulation``."""
@@ -26,6 +26,7 @@ from queue import Empty, Queue
26
26
  from time import sleep
27
27
  from typing import Callable, Optional
28
28
 
29
+ from flwr.app.error import Error
29
30
  from flwr.client.client_app import ClientApp, ClientAppException, LoadClientAppError
30
31
  from flwr.client.clientapp.utils import get_load_client_app_fn
31
32
  from flwr.client.run_info_store import DeprecatedRunInfoStore
@@ -37,7 +38,6 @@ from flwr.common.constant import (
37
38
  ErrorCode,
38
39
  )
39
40
  from flwr.common.logger import log
40
- from flwr.common.message import Error
41
41
  from flwr.common.typing import Run
42
42
  from flwr.server.superlink.linkstate import LinkState, LinkStateFactory
43
43
 
@@ -0,0 +1,15 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Public Flower ServerApp APIs."""
@@ -0,0 +1,15 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Infrastructure components shared between SuperLink and SuperNode."""
@@ -0,0 +1,15 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Flower SuperLink."""
@@ -0,0 +1,15 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Flower SuperNode."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: flwr-nightly
3
- Version: 1.19.0.dev20250516
3
+ Version: 1.19.0.dev20250520
4
4
  Summary: Flower: A Friendly Federated AI Framework
5
5
  License: Apache-2.0
6
6
  Keywords: Artificial Intelligence,Federated AI,Federated Analytics,Federated Evaluation,Federated Learning,Flower,Machine Learning
@@ -1,4 +1,7 @@
1
1
  flwr/__init__.py,sha256=5JdNd_I_ZxHJv2tbnM_Ug2_LQ4DkhZ2FiA7l23V13hU,937
2
+ flwr/app/__init__.py,sha256=VNahoTMYIbIQt8EMit-UvliLoJib7uSsvKANJJXUWzM,713
3
+ flwr/app/error.py,sha256=0PwA-E_CAs5P_nWAA0kksVO1A44t4CNLEf7u-Su-uJ0,2342
4
+ flwr/app/metadata.py,sha256=rdMBn0zhIOYmCvmGENQWSQqDwcxwsMJzCle4PQdlc_Y,7331
2
5
  flwr/cli/__init__.py,sha256=EfMGmHoobET6P2blBt_eOByXL8299MgFfB7XNdaPQ6I,720
3
6
  flwr/cli/app.py,sha256=AKCP45Dkbpvdil_4Ir9S93L3HP3iUOnHmcZjscoM8uU,1856
4
7
  flwr/cli/auth_plugin/__init__.py,sha256=FyaoqPzcxlBTFfJ2sBRC5USwQLmAhFr5KuBwfMO4bmo,1052
@@ -72,11 +75,11 @@ flwr/cli/run/run.py,sha256=mbyf46Tm3qrL8NW02JyDjs6BI49m9UMzXsGK8-Af1r4,8232
72
75
  flwr/cli/stop.py,sha256=iLbh1dq8XMdcIlh0Lh8ufG6h0VvrP1kyp_mGO-kimt0,4976
73
76
  flwr/cli/utils.py,sha256=FjRYfzTw75qh5YHmrg9XzBA6o73T6xWt9WQYIxq-iHY,11207
74
77
  flwr/client/__init__.py,sha256=FslaZOoCGPIzlK-NhL7bFMVVnmFDOh_PhW4AfGzno68,1192
75
- flwr/client/app.py,sha256=N4-LwxoHT_I-O3K1xfkNRh6fyloR-1YFYoWhOxjlRrM,34282
78
+ flwr/client/app.py,sha256=wTZHxy8FS_lcIP3uXc6IzsDpbeDg0arWJGckCy3Xcn4,34277
76
79
  flwr/client/client.py,sha256=3HAchxvknKG9jYbB7swNyDj-e5vUWDuMKoLvbT7jCVM,7895
77
- flwr/client/client_app.py,sha256=BDKks4ZN6PSHTRyWeiUsaB8in_nzjCLdHf66DMEVQ0g,16920
80
+ flwr/client/client_app.py,sha256=zVhi-l3chAb06ozFsKwix3hU_RpOLjST13Ha50AVIPE,16918
78
81
  flwr/client/clientapp/__init__.py,sha256=nPMoWEB1FhwexuW-vKdhwFkFr_4MW-2YMZExP9vfTGg,800
79
- flwr/client/clientapp/app.py,sha256=7zE2qKNalBVeI9w63ACfB60cDima9wtbjC3uLH0clHQ,9062
82
+ flwr/client/clientapp/app.py,sha256=N1nd4PnwWzzZc3kn1g01SULXVMriCstCnfDYV_KERqc,9057
80
83
  flwr/client/clientapp/clientappio_servicer.py,sha256=LmzkxtNQBn5vVrHc0Bhq2WqaK6-LM2v4kfLBN0PiNNM,8522
81
84
  flwr/client/clientapp/utils.py,sha256=LsiW1OL2VPcjom3xN29pgBQC0UrttQ-xWL_GF1fkKDo,4344
82
85
  flwr/client/dpfedavg_numpy_client.py,sha256=3hul067cT2E9jBhzp7bFnFAZ_D2nWcIUEdHYE05FpzU,7404
@@ -86,7 +89,7 @@ flwr/client/grpc_client/__init__.py,sha256=MDOckOODn-FJnkkFEfb2JO-2G97wrBr_TTqht
86
89
  flwr/client/grpc_client/connection.py,sha256=xAyvcTVr7bkwUfR5P3D_LKlZYiyySpt5sEwORA1h8Gc,9189
87
90
  flwr/client/grpc_rere_client/__init__.py,sha256=i7iS0Lt8B7q0E2L72e4F_YrKm6ClRKnd71PNA6PW2O0,752
88
91
  flwr/client/grpc_rere_client/client_interceptor.py,sha256=zFaVHw6AxeNO-7eCKKb-RxrPa7zbM5Z-2-1Efc4adQY,2451
89
- flwr/client/grpc_rere_client/connection.py,sha256=Ukvvf0VGwYfcYIESpD49cw_TpvPke0dp7bGHbsnbmd0,12035
92
+ flwr/client/grpc_rere_client/connection.py,sha256=MCUkpx2KGETTPOrBGZfp2rktMOHmuPR4x0eqcevZapo,12064
90
93
  flwr/client/grpc_rere_client/grpc_adapter.py,sha256=JvMZ7vCFTaTEo6AzKYh3zDmeQAU7VSjdysbC6t3ufWg,6351
91
94
  flwr/client/message_handler/__init__.py,sha256=0lyljDVqre3WljiZbPcwCCf8GiIaSVI_yo_ylEyPwSE,719
92
95
  flwr/client/message_handler/message_handler.py,sha256=-vZKGg2gP81182LFXDmiZtajLlIfZjV6FyMS43qQVwU,6532
@@ -104,12 +107,13 @@ flwr/client/nodestate/nodestate.py,sha256=-LAjZOnS7VyHC05ll3b31cYDjwAt6l4WmYt7du
104
107
  flwr/client/nodestate/nodestate_factory.py,sha256=UYTDCcwK_baHUmkzkJDxL0UEqvtTfOMlQRrROMCd0Xo,1430
105
108
  flwr/client/numpy_client.py,sha256=Qq6ghsIAop2slKqAfgiI5NiHJ4LIxGmrik3Ror4_XVc,9581
106
109
  flwr/client/rest_client/__init__.py,sha256=MBiuK62hj439m9rtwSwI184Hth6Tt5GbmpNMyl3zkZY,735
107
- flwr/client/rest_client/connection.py,sha256=s8dfD7T6ZR3X-AGUr6hM437HkLiddyVuaBlKUViIFWY,12777
110
+ flwr/client/rest_client/connection.py,sha256=Xlf1eEMXq17VVVELPGPT1pqJKw8l0iq4Jnvz13v95C8,12806
108
111
  flwr/client/run_info_store.py,sha256=MaJ3UQ-07hWtK67wnWu0zR29jrk0fsfgJX506dvEOfE,4042
109
112
  flwr/client/supernode/__init__.py,sha256=i3gFbV5ie_FGyRMpzOvqtZAi0Z0ChIEJ7I2Kr0ym0PM,793
110
113
  flwr/client/supernode/app.py,sha256=lURLjP8jiOWhlX3-uh-7t_l1o_JEUz_FmkuNY91xmUQ,8975
111
114
  flwr/client/typing.py,sha256=Jw3rawDzI_-ZDcRmEQcs5gZModY7oeQlEeltYsdOhlU,1048
112
- flwr/common/__init__.py,sha256=YhHy4JMhPamXxOSI4Atqwb0actwuR0JbkuNqwCePo4A,4162
115
+ flwr/clientapp/__init__.py,sha256=zGW4z49Ojzoi1hDiRC7kyhLjijUilc6fqHhtM_ATRVA,719
116
+ flwr/common/__init__.py,sha256=5GCLVk399Az_rTJHNticRlL0Sl_oPw_j5_LuFKfX7-M,4171
113
117
  flwr/common/address.py,sha256=9JucdTwlc-jpeJkRKeUboZoacUtErwSVtnDR9kAtLqE,4119
114
118
  flwr/common/args.py,sha256=-aX_jVnSaDrJR2KZ8Wq0Y3dQHII4R4MJtJOIXzVUA0c,5417
115
119
  flwr/common/auth_plugin/__init__.py,sha256=m271m9YjK2QfKDOuIIhcTvGmv1GWh1PL97QB05NTSHs,887
@@ -130,15 +134,16 @@ flwr/common/exit_handlers.py,sha256=MEk5_savTLphn-6lW57UQlos-XrFA39XEBn-OF1vXXg,
130
134
  flwr/common/grpc.py,sha256=manTaHaPiyYngUq1ErZvvV2B2GxlXUUUGRy3jc3TBIQ,9798
131
135
  flwr/common/heartbeat.py,sha256=SyEpNDnmJ0lni0cWO67rcoJVKasCLmkNHm3dKLeNrLU,5749
132
136
  flwr/common/inflatable.py,sha256=ZKW4L2GMAxInUlbNK_zDZs7uW4-CuQui9TnWVglpDic,5279
137
+ flwr/common/inflatable_grpc_utils.py,sha256=StkhGH8x9zR-p5MH52HdLG9MLzKv_rT8sPdbR9ZzNyE,3368
133
138
  flwr/common/logger.py,sha256=JbRf6E2vQxXzpDBq1T8IDUJo_usu3gjWEBPQ6uKcmdg,13049
134
- flwr/common/message.py,sha256=znr205Erq2hkxwFbvNNCsQTRS2UKv_Qsyu0sFNEhEAw,23721
139
+ flwr/common/message.py,sha256=4QPeMFP_BWPltgi0-0ARROhtL2k1b4BFflrgWCn3uJ0,16020
135
140
  flwr/common/object_ref.py,sha256=p3SfTeqo3Aj16SkB-vsnNn01zswOPdGNBitcbRnqmUk,9134
136
141
  flwr/common/parameter.py,sha256=UVw6sOgehEFhFs4uUCMl2kfVq1PD6ncmWgPLMsZPKPE,2095
137
142
  flwr/common/pyproject.py,sha256=2SU6yJW7059SbMXgzjOdK1GZRWO6AixDH7BmdxbMvHI,1386
138
143
  flwr/common/record/__init__.py,sha256=cNGccdDoxttqgnUgyKRIqLWULjW-NaSmOufVxtXq-sw,1197
139
- flwr/common/record/array.py,sha256=bomTFJViJjeQ649Fo9CREEJdSrqiYLDYRFWogpiBKCs,10850
144
+ flwr/common/record/array.py,sha256=XQAXLFXc_dXkwrbrPzXqqVPLW_O1JLIuyrOtAmbmIKY,10838
140
145
  flwr/common/record/arrayrecord.py,sha256=1DII6iloauHvBaWPzYtgaVAT9plNRBaaInGA6p8-j20,16787
141
- flwr/common/record/configrecord.py,sha256=SYpGR89JSDWTjdGT3jemuUW-EHATrkSDmPSgqzZ_H1M,9664
146
+ flwr/common/record/configrecord.py,sha256=nDoIc_-vh7XUx2BuojenpcqSgM2XxD4NyGFAYpmXabM,9652
142
147
  flwr/common/record/conversion_utils.py,sha256=wbNCzy7oAqaA3-arhls_EqRZYXRC4YrWIoE-Gy82fJ0,1191
143
148
  flwr/common/record/metricrecord.py,sha256=Gxl9TdVpMAHg6pNN2SxB-as8iPDnPx398KEhORU4n3A,8839
144
149
  flwr/common/record/recorddict.py,sha256=p7hBimFpKM1XKUe6OAkR_7pYGzGL_EwUJUvJ8odZEcY,14986
@@ -153,11 +158,16 @@ flwr/common/secure_aggregation/ndarrays_arithmetic.py,sha256=TrggOlizlny3V2KS7-3
153
158
  flwr/common/secure_aggregation/quantization.py,sha256=ssFZpiRyj9ltIh0Ai3vGkDqWFO4SoqgoD1mDU9XqMEM,2400
154
159
  flwr/common/secure_aggregation/secaggplus_constants.py,sha256=dGYhWOBMMDJcQH4_tQNC8-Efqm-ecEUNN9ANz59UnCk,2182
155
160
  flwr/common/secure_aggregation/secaggplus_utils.py,sha256=E_xU-Zd45daO1em7M6C2wOjFXVtJf-6tl7fp-7xq1wo,3214
156
- flwr/common/serde.py,sha256=B9PpDh_f3sO0okztebD_6bgX1dK-pJtDr6CNtZ-gJIQ,23910
161
+ flwr/common/serde.py,sha256=IMU32jIwcF_iPej7d8PXLxZ4xZxFrsy4XPdlDyXQ9bk,23960
157
162
  flwr/common/serde_utils.py,sha256=ofmrgVHRBfrE1MtQwLQk0x12JS9vL-u8wHXrgZE2ueg,3985
158
163
  flwr/common/telemetry.py,sha256=jF47v0SbnBd43XamHtl3wKxs3knFUY2p77cm_2lzZ8M,8762
159
164
  flwr/common/typing.py,sha256=97QRfRRS7sQnjkAI5FDZ01-38oQUSz4i1qqewQmBWRg,6886
160
165
  flwr/common/version.py,sha256=7GAGzPn73Mkh09qhrjbmjZQtcqVhBuzhFBaK4Mk4VRk,1325
166
+ flwr/compat/__init__.py,sha256=gbfDQKKKMZzi3GswyVRgyLdDlHiWj3wU6dg7y6m5O_s,752
167
+ flwr/compat/client/__init__.py,sha256=qpbo0lcxdNL4qy5KHqiGm8OLxSxkYgI_-dLh5rwhtcI,746
168
+ flwr/compat/common/__init__.py,sha256=OMnKw4ad0qYMSIA9LZRa2gOkhSOXwAZCpAHnBQE_hFc,746
169
+ flwr/compat/server/__init__.py,sha256=TGVSoOTuf5T5JHUVrK5wuorQF7L6Wvdem8B4uufvMJY,746
170
+ flwr/compat/simulation/__init__.py,sha256=MApGa-tysDDw34iSdxZ7TWOKtGJM-z3i8fIRJa0qbZ8,750
161
171
  flwr/proto/__init__.py,sha256=S3VbQzVwNC1P-3_9EdrXuwgptO-BVuuAe20Z_OUc1cQ,683
162
172
  flwr/proto/clientappio_pb2.py,sha256=aroQDv0D2GquQ5Ujqml7n7l6ObZoXqMvDa0XVO-_8Cc,3703
163
173
  flwr/proto/clientappio_pb2.pyi,sha256=iL6pOPmnot5wP3aXGiDfiUpp-eJIkysyju0ebPehS8Y,5670
@@ -291,7 +301,7 @@ flwr/server/superlink/fleet/vce/__init__.py,sha256=XOKbAWOzlCqEOQ3M2cBYkH7HKA7Px
291
301
  flwr/server/superlink/fleet/vce/backend/__init__.py,sha256=PPH89Yqd1XKm-sRJN6R0WQlKT_b4v54Kzl2yzHAFzM8,1437
292
302
  flwr/server/superlink/fleet/vce/backend/backend.py,sha256=-wDHjgAy5mrfEgXj0GxkJI7lhEbgSUyPwmNAf9ZcDzc,2193
293
303
  flwr/server/superlink/fleet/vce/backend/raybackend.py,sha256=Hx9hxL7lju1_VJoAwkhBOGerZ3628u0P1zgkPhGWRPY,7154
294
- flwr/server/superlink/fleet/vce/vce_api.py,sha256=m7WUiHRl-jTqzjH3cqNCj3RXe3ohT6V6I0JIR6zWZj8,12780
304
+ flwr/server/superlink/fleet/vce/vce_api.py,sha256=zwCK4dAtZrDEAI3OxmKa9mx4ZhFqMnz6G1x2JOKqZyM,12775
295
305
  flwr/server/superlink/linkstate/__init__.py,sha256=OtsgvDTnZLU3k0sUbkHbqoVwW6ql2FDmb6uT6DbNkZo,1064
296
306
  flwr/server/superlink/linkstate/in_memory_linkstate.py,sha256=vvoOWjYlmOlbakH7AzpMh0jB70Qxx7UTlAGqjcA8ctM,25926
297
307
  flwr/server/superlink/linkstate/linkstate.py,sha256=j6nW351t07VrBhFqjO34z8tf2PuKOE9aCX9SqpW96pQ,13100
@@ -315,6 +325,7 @@ flwr/server/workflow/default_workflows.py,sha256=RlD26dXbSksY-23f3ZspnN1YU1DOhDY
315
325
  flwr/server/workflow/secure_aggregation/__init__.py,sha256=vGkycLb65CxdaMkKsANxQE6AS4urfZKvwcS3r1Vln_c,880
316
326
  flwr/server/workflow/secure_aggregation/secagg_workflow.py,sha256=b_pKk7gmbahwyj0ftOOLXvu-AMtRHEc82N9PJTEO8dc,5839
317
327
  flwr/server/workflow/secure_aggregation/secaggplus_workflow.py,sha256=DkayCsnlAya6Y2PZsueLgoUCMRtV-GbnW08RfWx_SXM,29460
328
+ flwr/serverapp/__init__.py,sha256=HPvC_ZvMS7GCM7ALVrG_Wwm4bSDr4DZETeC561v3T9w,719
318
329
  flwr/simulation/__init__.py,sha256=Gg6OsP1Z-ixc3-xxzvl7j7rz2Fijy9rzyEPpxgAQCeM,1556
319
330
  flwr/simulation/app.py,sha256=Uy3lPwAvfZECkWPLcC0oDXTwY14e4ou8itIcBltjmWE,10437
320
331
  flwr/simulation/legacy_app.py,sha256=nMISQqW0otJL1-2Kfd94O6BLlGS2IEmEPKTM2WGKrIs,15861
@@ -324,6 +335,7 @@ flwr/simulation/ray_transport/ray_client_proxy.py,sha256=2kVUDrJe2ViOJEuB0v_Xb3X
324
335
  flwr/simulation/ray_transport/utils.py,sha256=KrexpWYCF-dAF3UHc9yDbPQWO-ahMT-BbD8nURLgiHk,2393
325
336
  flwr/simulation/run_simulation.py,sha256=Nvw_6hI71aE2nU95_tt1F9VSo3OJWrvA97e3XZuqE4k,20310
326
337
  flwr/simulation/simulationio_connection.py,sha256=mzS1C6EEREwQDPceDo30anAasmTDLb9qqV2tXlBhOUA,3494
338
+ flwr/supercore/__init__.py,sha256=pqkFoow_E6UhbBlhmoD1gmTH-33yJRhBsIZqxRPFZ7U,755
327
339
  flwr/superexec/__init__.py,sha256=YFqER0IJc1XEWfsX6AxZ9LSRq0sawPYrNYki-brvTIc,715
328
340
  flwr/superexec/app.py,sha256=U2jjOHb2LGWoU7vrl9_czTzre9O2mPxu3CPGUZ86sK4,1465
329
341
  flwr/superexec/deployment.py,sha256=2wBBZgdNAn1Ik1M3HGg4t23CV8oZqzDz1zkOBzHjZLE,6734
@@ -333,7 +345,9 @@ flwr/superexec/exec_servicer.py,sha256=Z0YYfs6eNPhqn8rY0x_R04XgR2mKFpggt07IH0EhU
333
345
  flwr/superexec/exec_user_auth_interceptor.py,sha256=iqygALkOMBUu_s_R9G0mFThZA7HTUzuXCLgxLCefiwI,4440
334
346
  flwr/superexec/executor.py,sha256=M5ucqSE53jfRtuCNf59WFLqQvA1Mln4741TySeZE7qQ,3112
335
347
  flwr/superexec/simulation.py,sha256=j6YwUvBN7EQ09ID7MYOCVZ70PGbuyBy8f9bXU0EszEM,4088
336
- flwr_nightly-1.19.0.dev20250516.dist-info/METADATA,sha256=UonPzdp9wmMEFyT7_6JpqX1De35aXAtDj1cUVzzcNkg,15910
337
- flwr_nightly-1.19.0.dev20250516.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
338
- flwr_nightly-1.19.0.dev20250516.dist-info/entry_points.txt,sha256=2-1L-GNKhwGw2_7_RoH55vHw2SIHjdAQy3HAVAWl9PY,374
339
- flwr_nightly-1.19.0.dev20250516.dist-info/RECORD,,
348
+ flwr/superlink/__init__.py,sha256=GNSuJ4-N6Z8wun2iZNlXqENt5beUyzC0Gi_tN396bbM,707
349
+ flwr/supernode/__init__.py,sha256=KgeCaVvXWrU3rptNR1y0oBp4YtXbAcrnCcJAiOoWkI4,707
350
+ flwr_nightly-1.19.0.dev20250520.dist-info/METADATA,sha256=HyqyQmw4kiBnhIKntjNtkH6kQb6qQ7szzRV19cj0IMA,15910
351
+ flwr_nightly-1.19.0.dev20250520.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
352
+ flwr_nightly-1.19.0.dev20250520.dist-info/entry_points.txt,sha256=2-1L-GNKhwGw2_7_RoH55vHw2SIHjdAQy3HAVAWl9PY,374
353
+ flwr_nightly-1.19.0.dev20250520.dist-info/RECORD,,