flwr-nightly 1.8.0.dev20240401__py3-none-any.whl → 1.9.0.dev20240403__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/new/templates/app/pyproject.pytorch.toml.tpl +1 -1
- flwr/cli/new/templates/app/requirements.pytorch.txt.tpl +1 -1
- flwr/client/app.py +24 -9
- flwr/client/client_app.py +9 -0
- flwr/client/grpc_rere_client/connection.py +1 -1
- flwr/client/rest_client/connection.py +1 -1
- flwr/common/constant.py +14 -0
- flwr/common/message.py +15 -0
- flwr/proto/fleet_pb2.py +26 -26
- flwr/proto/fleet_pb2.pyi +5 -0
- flwr/server/driver/driver.py +15 -5
- flwr/server/superlink/fleet/message_handler/message_handler.py +1 -1
- flwr/server/superlink/fleet/vce/vce_api.py +14 -4
- flwr/server/superlink/state/in_memory_state.py +25 -8
- flwr/server/superlink/state/sqlite_state.py +53 -5
- flwr/server/superlink/state/state.py +1 -1
- flwr/server/superlink/state/utils.py +56 -0
- flwr/server/workflow/default_workflows.py +1 -4
- flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +0 -5
- flwr/simulation/ray_transport/ray_actor.py +2 -22
- {flwr_nightly-1.8.0.dev20240401.dist-info → flwr_nightly-1.9.0.dev20240403.dist-info}/METADATA +1 -1
- {flwr_nightly-1.8.0.dev20240401.dist-info → flwr_nightly-1.9.0.dev20240403.dist-info}/RECORD +25 -24
- {flwr_nightly-1.8.0.dev20240401.dist-info → flwr_nightly-1.9.0.dev20240403.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.8.0.dev20240401.dist-info → flwr_nightly-1.9.0.dev20240403.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.8.0.dev20240401.dist-info → flwr_nightly-1.9.0.dev20240403.dist-info}/entry_points.txt +0 -0
|
@@ -15,7 +15,7 @@ readme = "README.md"
|
|
|
15
15
|
[tool.poetry.dependencies]
|
|
16
16
|
python = "^3.9"
|
|
17
17
|
# Mandatory dependencies
|
|
18
|
-
flwr
|
|
18
|
+
flwr = { version = "^1.8.0", extras = ["simulation"] }
|
|
19
19
|
flwr-datasets = { version = "0.0.2", extras = ["vision"] }
|
|
20
20
|
torch = "2.2.1"
|
|
21
21
|
torchvision = "0.17.1"
|
flwr/client/app.py
CHANGED
|
@@ -34,6 +34,7 @@ from flwr.common.constant import (
|
|
|
34
34
|
TRANSPORT_TYPE_GRPC_RERE,
|
|
35
35
|
TRANSPORT_TYPE_REST,
|
|
36
36
|
TRANSPORT_TYPES,
|
|
37
|
+
ErrorCode,
|
|
37
38
|
)
|
|
38
39
|
from flwr.common.exit_handlers import register_exit_handlers
|
|
39
40
|
from flwr.common.logger import log, warn_deprecated_feature
|
|
@@ -483,7 +484,7 @@ def _start_client_internal(
|
|
|
483
484
|
# Create an error reply message that will never be used to prevent
|
|
484
485
|
# the used-before-assignment linting error
|
|
485
486
|
reply_message = message.create_error_reply(
|
|
486
|
-
error=Error(code=
|
|
487
|
+
error=Error(code=ErrorCode.UNKNOWN, reason="Unknown")
|
|
487
488
|
)
|
|
488
489
|
|
|
489
490
|
# Handle app loading and task message
|
|
@@ -491,27 +492,41 @@ def _start_client_internal(
|
|
|
491
492
|
# Load ClientApp instance
|
|
492
493
|
client_app: ClientApp = load_client_app_fn()
|
|
493
494
|
|
|
495
|
+
# Execute ClientApp
|
|
494
496
|
reply_message = client_app(message=message, context=context)
|
|
495
|
-
# Update node state
|
|
496
|
-
node_state.update_context(
|
|
497
|
-
run_id=message.metadata.run_id,
|
|
498
|
-
context=context,
|
|
499
|
-
)
|
|
500
497
|
except Exception as ex: # pylint: disable=broad-exception-caught
|
|
501
|
-
log(ERROR, "ClientApp raised an exception", exc_info=ex)
|
|
502
498
|
|
|
503
499
|
# Legacy grpc-bidi
|
|
504
500
|
if transport in ["grpc-bidi", None]:
|
|
501
|
+
log(ERROR, "Client raised an exception.", exc_info=ex)
|
|
505
502
|
# Raise exception, crash process
|
|
506
503
|
raise ex
|
|
507
504
|
|
|
508
505
|
# Don't update/change NodeState
|
|
509
506
|
|
|
510
|
-
|
|
507
|
+
e_code = ErrorCode.CLIENT_APP_RAISED_EXCEPTION
|
|
511
508
|
# Reason example: "<class 'ZeroDivisionError'>:<'division by zero'>"
|
|
512
509
|
reason = str(type(ex)) + ":<'" + str(ex) + "'>"
|
|
510
|
+
exc_entity = "ClientApp"
|
|
511
|
+
if isinstance(ex, LoadClientAppError):
|
|
512
|
+
reason = (
|
|
513
|
+
"An exception was raised when attempting to load "
|
|
514
|
+
"`ClientApp`"
|
|
515
|
+
)
|
|
516
|
+
e_code = ErrorCode.LOAD_CLIENT_APP_EXCEPTION
|
|
517
|
+
exc_entity = "SuperNode"
|
|
518
|
+
|
|
519
|
+
log(ERROR, "%s raised an exception", exc_entity, exc_info=ex)
|
|
520
|
+
|
|
521
|
+
# Create error message
|
|
513
522
|
reply_message = message.create_error_reply(
|
|
514
|
-
error=Error(code=
|
|
523
|
+
error=Error(code=e_code, reason=reason)
|
|
524
|
+
)
|
|
525
|
+
else:
|
|
526
|
+
# No exception, update node state
|
|
527
|
+
node_state.update_context(
|
|
528
|
+
run_id=message.metadata.run_id,
|
|
529
|
+
context=context,
|
|
515
530
|
)
|
|
516
531
|
|
|
517
532
|
# Send
|
flwr/client/client_app.py
CHANGED
|
@@ -28,6 +28,15 @@ from flwr.common.logger import warn_preview_feature
|
|
|
28
28
|
from .typing import ClientAppCallable
|
|
29
29
|
|
|
30
30
|
|
|
31
|
+
class ClientAppException(Exception):
|
|
32
|
+
"""Exception raised when an exception is raised while executing a ClientApp."""
|
|
33
|
+
|
|
34
|
+
def __init__(self, message: str):
|
|
35
|
+
ex_name = self.__class__.__name__
|
|
36
|
+
self.message = f"\nException {ex_name} occurred. Message: " + message
|
|
37
|
+
super().__init__(self.message)
|
|
38
|
+
|
|
39
|
+
|
|
31
40
|
class ClientApp:
|
|
32
41
|
"""Flower ClientApp.
|
|
33
42
|
|
|
@@ -151,7 +151,7 @@ def grpc_request_response( # pylint: disable=R0914, R0915
|
|
|
151
151
|
def create_node() -> None:
|
|
152
152
|
"""Set create_node."""
|
|
153
153
|
# Call FleetAPI
|
|
154
|
-
create_node_request = CreateNodeRequest()
|
|
154
|
+
create_node_request = CreateNodeRequest(ping_interval=PING_DEFAULT_INTERVAL)
|
|
155
155
|
create_node_response = retry_invoker.invoke(
|
|
156
156
|
stub.CreateNode,
|
|
157
157
|
request=create_node_request,
|
|
@@ -201,7 +201,7 @@ def http_request_response( # pylint: disable=R0914, R0915
|
|
|
201
201
|
|
|
202
202
|
def create_node() -> None:
|
|
203
203
|
"""Set create_node."""
|
|
204
|
-
create_node_req_proto = CreateNodeRequest()
|
|
204
|
+
create_node_req_proto = CreateNodeRequest(ping_interval=PING_DEFAULT_INTERVAL)
|
|
205
205
|
create_node_req_bytes: bytes = create_node_req_proto.SerializeToString()
|
|
206
206
|
|
|
207
207
|
res = retry_invoker.invoke(
|
flwr/common/constant.py
CHANGED
|
@@ -41,6 +41,7 @@ PING_DEFAULT_INTERVAL = 30
|
|
|
41
41
|
PING_CALL_TIMEOUT = 5
|
|
42
42
|
PING_BASE_MULTIPLIER = 0.8
|
|
43
43
|
PING_RANDOM_RANGE = (-0.1, 0.1)
|
|
44
|
+
PING_MAX_INTERVAL = 1e300
|
|
44
45
|
|
|
45
46
|
|
|
46
47
|
class MessageType:
|
|
@@ -74,3 +75,16 @@ class SType:
|
|
|
74
75
|
def __new__(cls) -> SType:
|
|
75
76
|
"""Prevent instantiation."""
|
|
76
77
|
raise TypeError(f"{cls.__name__} cannot be instantiated.")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class ErrorCode:
|
|
81
|
+
"""Error codes for Message's Error."""
|
|
82
|
+
|
|
83
|
+
UNKNOWN = 0
|
|
84
|
+
LOAD_CLIENT_APP_EXCEPTION = 1
|
|
85
|
+
CLIENT_APP_RAISED_EXCEPTION = 2
|
|
86
|
+
NODE_UNAVAILABLE = 3
|
|
87
|
+
|
|
88
|
+
def __new__(cls) -> ErrorCode:
|
|
89
|
+
"""Prevent instantiation."""
|
|
90
|
+
raise TypeError(f"{cls.__name__} cannot be instantiated.")
|
flwr/common/message.py
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
19
|
import time
|
|
20
|
+
import warnings
|
|
20
21
|
from dataclasses import dataclass
|
|
21
22
|
|
|
22
23
|
from .record import RecordSet
|
|
@@ -311,6 +312,13 @@ class Message:
|
|
|
311
312
|
|
|
312
313
|
ttl = msg.meta.ttl - (reply.meta.created_at - msg.meta.created_at)
|
|
313
314
|
"""
|
|
315
|
+
if ttl:
|
|
316
|
+
warnings.warn(
|
|
317
|
+
"A custom TTL was set, but note that the SuperLink does not enforce "
|
|
318
|
+
"the TTL yet. The SuperLink will start enforcing the TTL in a future "
|
|
319
|
+
"version of Flower.",
|
|
320
|
+
stacklevel=2,
|
|
321
|
+
)
|
|
314
322
|
# If no TTL passed, use default for message creation (will update after
|
|
315
323
|
# message creation)
|
|
316
324
|
ttl_ = DEFAULT_TTL if ttl is None else ttl
|
|
@@ -349,6 +357,13 @@ class Message:
|
|
|
349
357
|
Message
|
|
350
358
|
A new `Message` instance representing the reply.
|
|
351
359
|
"""
|
|
360
|
+
if ttl:
|
|
361
|
+
warnings.warn(
|
|
362
|
+
"A custom TTL was set, but note that the SuperLink does not enforce "
|
|
363
|
+
"the TTL yet. The SuperLink will start enforcing the TTL in a future "
|
|
364
|
+
"version of Flower.",
|
|
365
|
+
stacklevel=2,
|
|
366
|
+
)
|
|
352
367
|
# If no TTL passed, use default for message creation (will update after
|
|
353
368
|
# message creation)
|
|
354
369
|
ttl_ = DEFAULT_TTL if ttl is None else ttl
|
flwr/proto/fleet_pb2.py
CHANGED
|
@@ -16,7 +16,7 @@ from flwr.proto import node_pb2 as flwr_dot_proto_dot_node__pb2
|
|
|
16
16
|
from flwr.proto import task_pb2 as flwr_dot_proto_dot_task__pb2
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66lwr/proto/fleet.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x15\x66lwr/proto/task.proto\"
|
|
19
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66lwr/proto/fleet.proto\x12\nflwr.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x15\x66lwr/proto/task.proto\"*\n\x11\x43reateNodeRequest\x12\x15\n\rping_interval\x18\x01 \x01(\x01\"4\n\x12\x43reateNodeResponse\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"3\n\x11\x44\x65leteNodeRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"\x14\n\x12\x44\x65leteNodeResponse\"D\n\x0bPingRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x15\n\rping_interval\x18\x02 \x01(\x01\"\x1f\n\x0cPingResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"F\n\x12PullTaskInsRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x10\n\x08task_ids\x18\x02 \x03(\t\"k\n\x13PullTaskInsResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rtask_ins_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.TaskIns\"@\n\x12PushTaskResRequest\x12*\n\rtask_res_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.TaskRes\"\xae\x01\n\x13PushTaskResResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12=\n\x07results\x18\x02 \x03(\x0b\x32,.flwr.proto.PushTaskResResponse.ResultsEntry\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x1e\n\tReconnect\x12\x11\n\treconnect\x18\x01 \x01(\x04\x32\x86\x03\n\x05\x46leet\x12M\n\nCreateNode\x12\x1d.flwr.proto.CreateNodeRequest\x1a\x1e.flwr.proto.CreateNodeResponse\"\x00\x12M\n\nDeleteNode\x12\x1d.flwr.proto.DeleteNodeRequest\x1a\x1e.flwr.proto.DeleteNodeResponse\"\x00\x12;\n\x04Ping\x12\x17.flwr.proto.PingRequest\x1a\x18.flwr.proto.PingResponse\"\x00\x12P\n\x0bPullTaskIns\x12\x1e.flwr.proto.PullTaskInsRequest\x1a\x1f.flwr.proto.PullTaskInsResponse\"\x00\x12P\n\x0bPushTaskRes\x12\x1e.flwr.proto.PushTaskResRequest\x1a\x1f.flwr.proto.PushTaskResResponse\"\x00\x62\x06proto3')
|
|
20
20
|
|
|
21
21
|
_globals = globals()
|
|
22
22
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
@@ -26,29 +26,29 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|
|
26
26
|
_globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._options = None
|
|
27
27
|
_globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._serialized_options = b'8\001'
|
|
28
28
|
_globals['_CREATENODEREQUEST']._serialized_start=84
|
|
29
|
-
_globals['_CREATENODEREQUEST']._serialized_end=
|
|
30
|
-
_globals['_CREATENODERESPONSE']._serialized_start=
|
|
31
|
-
_globals['_CREATENODERESPONSE']._serialized_end=
|
|
32
|
-
_globals['_DELETENODEREQUEST']._serialized_start=
|
|
33
|
-
_globals['_DELETENODEREQUEST']._serialized_end=
|
|
34
|
-
_globals['_DELETENODERESPONSE']._serialized_start=
|
|
35
|
-
_globals['_DELETENODERESPONSE']._serialized_end=
|
|
36
|
-
_globals['_PINGREQUEST']._serialized_start=
|
|
37
|
-
_globals['_PINGREQUEST']._serialized_end=
|
|
38
|
-
_globals['_PINGRESPONSE']._serialized_start=
|
|
39
|
-
_globals['_PINGRESPONSE']._serialized_end=
|
|
40
|
-
_globals['_PULLTASKINSREQUEST']._serialized_start=
|
|
41
|
-
_globals['_PULLTASKINSREQUEST']._serialized_end=
|
|
42
|
-
_globals['_PULLTASKINSRESPONSE']._serialized_start=
|
|
43
|
-
_globals['_PULLTASKINSRESPONSE']._serialized_end=
|
|
44
|
-
_globals['_PUSHTASKRESREQUEST']._serialized_start=
|
|
45
|
-
_globals['_PUSHTASKRESREQUEST']._serialized_end=
|
|
46
|
-
_globals['_PUSHTASKRESRESPONSE']._serialized_start=
|
|
47
|
-
_globals['_PUSHTASKRESRESPONSE']._serialized_end=
|
|
48
|
-
_globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._serialized_start=
|
|
49
|
-
_globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._serialized_end=
|
|
50
|
-
_globals['_RECONNECT']._serialized_start=
|
|
51
|
-
_globals['_RECONNECT']._serialized_end=
|
|
52
|
-
_globals['_FLEET']._serialized_start=
|
|
53
|
-
_globals['_FLEET']._serialized_end=
|
|
29
|
+
_globals['_CREATENODEREQUEST']._serialized_end=126
|
|
30
|
+
_globals['_CREATENODERESPONSE']._serialized_start=128
|
|
31
|
+
_globals['_CREATENODERESPONSE']._serialized_end=180
|
|
32
|
+
_globals['_DELETENODEREQUEST']._serialized_start=182
|
|
33
|
+
_globals['_DELETENODEREQUEST']._serialized_end=233
|
|
34
|
+
_globals['_DELETENODERESPONSE']._serialized_start=235
|
|
35
|
+
_globals['_DELETENODERESPONSE']._serialized_end=255
|
|
36
|
+
_globals['_PINGREQUEST']._serialized_start=257
|
|
37
|
+
_globals['_PINGREQUEST']._serialized_end=325
|
|
38
|
+
_globals['_PINGRESPONSE']._serialized_start=327
|
|
39
|
+
_globals['_PINGRESPONSE']._serialized_end=358
|
|
40
|
+
_globals['_PULLTASKINSREQUEST']._serialized_start=360
|
|
41
|
+
_globals['_PULLTASKINSREQUEST']._serialized_end=430
|
|
42
|
+
_globals['_PULLTASKINSRESPONSE']._serialized_start=432
|
|
43
|
+
_globals['_PULLTASKINSRESPONSE']._serialized_end=539
|
|
44
|
+
_globals['_PUSHTASKRESREQUEST']._serialized_start=541
|
|
45
|
+
_globals['_PUSHTASKRESREQUEST']._serialized_end=605
|
|
46
|
+
_globals['_PUSHTASKRESRESPONSE']._serialized_start=608
|
|
47
|
+
_globals['_PUSHTASKRESRESPONSE']._serialized_end=782
|
|
48
|
+
_globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._serialized_start=736
|
|
49
|
+
_globals['_PUSHTASKRESRESPONSE_RESULTSENTRY']._serialized_end=782
|
|
50
|
+
_globals['_RECONNECT']._serialized_start=784
|
|
51
|
+
_globals['_RECONNECT']._serialized_end=814
|
|
52
|
+
_globals['_FLEET']._serialized_start=817
|
|
53
|
+
_globals['_FLEET']._serialized_end=1207
|
|
54
54
|
# @@protoc_insertion_point(module_scope)
|
flwr/proto/fleet_pb2.pyi
CHANGED
|
@@ -16,8 +16,13 @@ DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
|
|
|
16
16
|
class CreateNodeRequest(google.protobuf.message.Message):
|
|
17
17
|
"""CreateNode messages"""
|
|
18
18
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
19
|
+
PING_INTERVAL_FIELD_NUMBER: builtins.int
|
|
20
|
+
ping_interval: builtins.float
|
|
19
21
|
def __init__(self,
|
|
22
|
+
*,
|
|
23
|
+
ping_interval: builtins.float = ...,
|
|
20
24
|
) -> None: ...
|
|
25
|
+
def ClearField(self, field_name: typing_extensions.Literal["ping_interval",b"ping_interval"]) -> None: ...
|
|
21
26
|
global___CreateNodeRequest = CreateNodeRequest
|
|
22
27
|
|
|
23
28
|
class CreateNodeResponse(google.protobuf.message.Message):
|
flwr/server/driver/driver.py
CHANGED
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
# ==============================================================================
|
|
15
15
|
"""Flower driver service client."""
|
|
16
16
|
|
|
17
|
-
|
|
18
17
|
import time
|
|
18
|
+
import warnings
|
|
19
19
|
from typing import Iterable, List, Optional, Tuple
|
|
20
20
|
|
|
21
21
|
from flwr.common import DEFAULT_TTL, Message, Metadata, RecordSet
|
|
@@ -91,7 +91,7 @@ class Driver:
|
|
|
91
91
|
message_type: str,
|
|
92
92
|
dst_node_id: int,
|
|
93
93
|
group_id: str,
|
|
94
|
-
ttl: float =
|
|
94
|
+
ttl: Optional[float] = None,
|
|
95
95
|
) -> Message:
|
|
96
96
|
"""Create a new message with specified parameters.
|
|
97
97
|
|
|
@@ -111,10 +111,11 @@ class Driver:
|
|
|
111
111
|
group_id : str
|
|
112
112
|
The ID of the group to which this message is associated. In some settings,
|
|
113
113
|
this is used as the FL round.
|
|
114
|
-
ttl : float (default:
|
|
114
|
+
ttl : Optional[float] (default: None)
|
|
115
115
|
Time-to-live for the round trip of this message, i.e., the time from sending
|
|
116
116
|
this message to receiving a reply. It specifies in seconds the duration for
|
|
117
|
-
which the message and its potential reply are considered valid.
|
|
117
|
+
which the message and its potential reply are considered valid. If unset,
|
|
118
|
+
the default TTL (i.e., `common.DEFAULT_TTL`) will be used.
|
|
118
119
|
|
|
119
120
|
Returns
|
|
120
121
|
-------
|
|
@@ -122,6 +123,15 @@ class Driver:
|
|
|
122
123
|
A new `Message` instance with the specified content and metadata.
|
|
123
124
|
"""
|
|
124
125
|
_, run_id = self._get_grpc_driver_and_run_id()
|
|
126
|
+
if ttl:
|
|
127
|
+
warnings.warn(
|
|
128
|
+
"A custom TTL was set, but note that the SuperLink does not enforce "
|
|
129
|
+
"the TTL yet. The SuperLink will start enforcing the TTL in a future "
|
|
130
|
+
"version of Flower.",
|
|
131
|
+
stacklevel=2,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
ttl_ = DEFAULT_TTL if ttl is None else ttl
|
|
125
135
|
metadata = Metadata(
|
|
126
136
|
run_id=run_id,
|
|
127
137
|
message_id="", # Will be set by the server
|
|
@@ -129,7 +139,7 @@ class Driver:
|
|
|
129
139
|
dst_node_id=dst_node_id,
|
|
130
140
|
reply_to_message="",
|
|
131
141
|
group_id=group_id,
|
|
132
|
-
ttl=
|
|
142
|
+
ttl=ttl_,
|
|
133
143
|
message_type=message_type,
|
|
134
144
|
)
|
|
135
145
|
return Message(metadata=metadata, content=content)
|
|
@@ -22,8 +22,9 @@ import traceback
|
|
|
22
22
|
from logging import DEBUG, ERROR, INFO, WARN
|
|
23
23
|
from typing import Callable, Dict, List, Optional
|
|
24
24
|
|
|
25
|
-
from flwr.client.client_app import ClientApp, LoadClientAppError
|
|
25
|
+
from flwr.client.client_app import ClientApp, ClientAppException, LoadClientAppError
|
|
26
26
|
from flwr.client.node_state import NodeState
|
|
27
|
+
from flwr.common.constant import PING_MAX_INTERVAL, ErrorCode
|
|
27
28
|
from flwr.common.logger import log
|
|
28
29
|
from flwr.common.message import Error
|
|
29
30
|
from flwr.common.object_ref import load_app
|
|
@@ -43,7 +44,7 @@ def _register_nodes(
|
|
|
43
44
|
nodes_mapping: NodeToPartitionMapping = {}
|
|
44
45
|
state = state_factory.state()
|
|
45
46
|
for i in range(num_nodes):
|
|
46
|
-
node_id = state.create_node()
|
|
47
|
+
node_id = state.create_node(ping_interval=PING_MAX_INTERVAL)
|
|
47
48
|
nodes_mapping[node_id] = i
|
|
48
49
|
log(INFO, "Registered %i nodes", len(nodes_mapping))
|
|
49
50
|
return nodes_mapping
|
|
@@ -93,9 +94,18 @@ async def worker(
|
|
|
93
94
|
except Exception as ex: # pylint: disable=broad-exception-caught
|
|
94
95
|
log(ERROR, ex)
|
|
95
96
|
log(ERROR, traceback.format_exc())
|
|
97
|
+
|
|
98
|
+
if isinstance(ex, ClientAppException):
|
|
99
|
+
e_code = ErrorCode.CLIENT_APP_RAISED_EXCEPTION
|
|
100
|
+
elif isinstance(ex, LoadClientAppError):
|
|
101
|
+
e_code = ErrorCode.LOAD_CLIENT_APP_EXCEPTION
|
|
102
|
+
else:
|
|
103
|
+
e_code = ErrorCode.UNKNOWN
|
|
104
|
+
|
|
96
105
|
reason = str(type(ex)) + ":<'" + str(ex) + "'>"
|
|
97
|
-
|
|
98
|
-
|
|
106
|
+
out_mssg = message.create_error_reply(
|
|
107
|
+
error=Error(code=e_code, reason=reason)
|
|
108
|
+
)
|
|
99
109
|
|
|
100
110
|
finally:
|
|
101
111
|
if out_mssg:
|
|
@@ -27,6 +27,8 @@ from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611
|
|
|
27
27
|
from flwr.server.superlink.state.state import State
|
|
28
28
|
from flwr.server.utils import validate_task_ins_or_res
|
|
29
29
|
|
|
30
|
+
from .utils import make_node_unavailable_taskres
|
|
31
|
+
|
|
30
32
|
|
|
31
33
|
class InMemoryState(State):
|
|
32
34
|
"""In-memory State implementation."""
|
|
@@ -129,15 +131,32 @@ class InMemoryState(State):
|
|
|
129
131
|
with self.lock:
|
|
130
132
|
# Find TaskRes that were not delivered yet
|
|
131
133
|
task_res_list: List[TaskRes] = []
|
|
134
|
+
replied_task_ids: Set[UUID] = set()
|
|
132
135
|
for _, task_res in self.task_res_store.items():
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
and task_res.task.delivered_at == ""
|
|
136
|
-
):
|
|
136
|
+
reply_to = UUID(task_res.task.ancestry[0])
|
|
137
|
+
if reply_to in task_ids and task_res.task.delivered_at == "":
|
|
137
138
|
task_res_list.append(task_res)
|
|
139
|
+
replied_task_ids.add(reply_to)
|
|
138
140
|
if limit and len(task_res_list) == limit:
|
|
139
141
|
break
|
|
140
142
|
|
|
143
|
+
# Check if the node is offline
|
|
144
|
+
for task_id in task_ids - replied_task_ids:
|
|
145
|
+
if limit and len(task_res_list) == limit:
|
|
146
|
+
break
|
|
147
|
+
task_ins = self.task_ins_store.get(task_id)
|
|
148
|
+
if task_ins is None:
|
|
149
|
+
continue
|
|
150
|
+
node_id = task_ins.task.consumer.node_id
|
|
151
|
+
online_until, _ = self.node_ids[node_id]
|
|
152
|
+
# Generate a TaskRes containing an error reply if the node is offline.
|
|
153
|
+
if online_until < time.time():
|
|
154
|
+
err_taskres = make_node_unavailable_taskres(
|
|
155
|
+
ref_taskins=task_ins,
|
|
156
|
+
)
|
|
157
|
+
self.task_res_store[UUID(err_taskres.task_id)] = err_taskres
|
|
158
|
+
task_res_list.append(err_taskres)
|
|
159
|
+
|
|
141
160
|
# Mark all of them as delivered
|
|
142
161
|
delivered_at = now().isoformat()
|
|
143
162
|
for task_res in task_res_list:
|
|
@@ -182,16 +201,14 @@ class InMemoryState(State):
|
|
|
182
201
|
"""
|
|
183
202
|
return len(self.task_res_store)
|
|
184
203
|
|
|
185
|
-
def create_node(self) -> int:
|
|
204
|
+
def create_node(self, ping_interval: float) -> int:
|
|
186
205
|
"""Create, store in state, and return `node_id`."""
|
|
187
206
|
# Sample a random int64 as node_id
|
|
188
207
|
node_id: int = int.from_bytes(os.urandom(8), "little", signed=True)
|
|
189
208
|
|
|
190
209
|
with self.lock:
|
|
191
210
|
if node_id not in self.node_ids:
|
|
192
|
-
|
|
193
|
-
# TODO: change 1e9 to 30s # pylint: disable=W0511
|
|
194
|
-
self.node_ids[node_id] = (time.time() + 1e9, 1e9)
|
|
211
|
+
self.node_ids[node_id] = (time.time() + ping_interval, ping_interval)
|
|
195
212
|
return node_id
|
|
196
213
|
log(ERROR, "Unexpected node registration failure.")
|
|
197
214
|
return 0
|
|
@@ -30,6 +30,7 @@ from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611
|
|
|
30
30
|
from flwr.server.utils.validator import validate_task_ins_or_res
|
|
31
31
|
|
|
32
32
|
from .state import State
|
|
33
|
+
from .utils import make_node_unavailable_taskres
|
|
33
34
|
|
|
34
35
|
SQL_CREATE_TABLE_NODE = """
|
|
35
36
|
CREATE TABLE IF NOT EXISTS node(
|
|
@@ -344,6 +345,7 @@ class SqliteState(State):
|
|
|
344
345
|
|
|
345
346
|
return task_id
|
|
346
347
|
|
|
348
|
+
# pylint: disable-next=R0914
|
|
347
349
|
def get_task_res(self, task_ids: Set[UUID], limit: Optional[int]) -> List[TaskRes]:
|
|
348
350
|
"""Get TaskRes for task_ids.
|
|
349
351
|
|
|
@@ -374,7 +376,7 @@ class SqliteState(State):
|
|
|
374
376
|
AND delivered_at = ""
|
|
375
377
|
"""
|
|
376
378
|
|
|
377
|
-
data: Dict[str, Union[str, int]] = {}
|
|
379
|
+
data: Dict[str, Union[str, float, int]] = {}
|
|
378
380
|
|
|
379
381
|
if limit is not None:
|
|
380
382
|
query += " LIMIT :limit"
|
|
@@ -408,6 +410,54 @@ class SqliteState(State):
|
|
|
408
410
|
rows = self.query(query, data)
|
|
409
411
|
|
|
410
412
|
result = [dict_to_task_res(row) for row in rows]
|
|
413
|
+
|
|
414
|
+
# 1. Query: Fetch consumer_node_id of remaining task_ids
|
|
415
|
+
# Assume the ancestry field only contains one element
|
|
416
|
+
data.clear()
|
|
417
|
+
replied_task_ids: Set[UUID] = {UUID(str(row["ancestry"])) for row in rows}
|
|
418
|
+
remaining_task_ids = task_ids - replied_task_ids
|
|
419
|
+
placeholders = ",".join([f":id_{i}" for i in range(len(remaining_task_ids))])
|
|
420
|
+
query = f"""
|
|
421
|
+
SELECT consumer_node_id
|
|
422
|
+
FROM task_ins
|
|
423
|
+
WHERE task_id IN ({placeholders});
|
|
424
|
+
"""
|
|
425
|
+
for index, task_id in enumerate(remaining_task_ids):
|
|
426
|
+
data[f"id_{index}"] = str(task_id)
|
|
427
|
+
node_ids = [int(row["consumer_node_id"]) for row in self.query(query, data)]
|
|
428
|
+
|
|
429
|
+
# 2. Query: Select offline nodes
|
|
430
|
+
placeholders = ",".join([f":id_{i}" for i in range(len(node_ids))])
|
|
431
|
+
query = f"""
|
|
432
|
+
SELECT node_id
|
|
433
|
+
FROM node
|
|
434
|
+
WHERE node_id IN ({placeholders})
|
|
435
|
+
AND online_until < :time;
|
|
436
|
+
"""
|
|
437
|
+
data = {f"id_{i}": str(node_id) for i, node_id in enumerate(node_ids)}
|
|
438
|
+
data["time"] = time.time()
|
|
439
|
+
offline_node_ids = [int(row["node_id"]) for row in self.query(query, data)]
|
|
440
|
+
|
|
441
|
+
# 3. Query: Select TaskIns for offline nodes
|
|
442
|
+
placeholders = ",".join([f":id_{i}" for i in range(len(offline_node_ids))])
|
|
443
|
+
query = f"""
|
|
444
|
+
SELECT *
|
|
445
|
+
FROM task_ins
|
|
446
|
+
WHERE consumer_node_id IN ({placeholders});
|
|
447
|
+
"""
|
|
448
|
+
data = {f"id_{i}": str(node_id) for i, node_id in enumerate(offline_node_ids)}
|
|
449
|
+
task_ins_rows = self.query(query, data)
|
|
450
|
+
|
|
451
|
+
# Make TaskRes containing node unavailabe error
|
|
452
|
+
for row in task_ins_rows:
|
|
453
|
+
if limit and len(result) == limit:
|
|
454
|
+
break
|
|
455
|
+
task_ins = dict_to_task_ins(row)
|
|
456
|
+
err_taskres = make_node_unavailable_taskres(
|
|
457
|
+
ref_taskins=task_ins,
|
|
458
|
+
)
|
|
459
|
+
result.append(err_taskres)
|
|
460
|
+
|
|
411
461
|
return result
|
|
412
462
|
|
|
413
463
|
def num_task_ins(self) -> int:
|
|
@@ -468,7 +518,7 @@ class SqliteState(State):
|
|
|
468
518
|
|
|
469
519
|
return None
|
|
470
520
|
|
|
471
|
-
def create_node(self) -> int:
|
|
521
|
+
def create_node(self, ping_interval: float) -> int:
|
|
472
522
|
"""Create, store in state, and return `node_id`."""
|
|
473
523
|
# Sample a random int64 as node_id
|
|
474
524
|
node_id: int = int.from_bytes(os.urandom(8), "little", signed=True)
|
|
@@ -478,9 +528,7 @@ class SqliteState(State):
|
|
|
478
528
|
)
|
|
479
529
|
|
|
480
530
|
try:
|
|
481
|
-
|
|
482
|
-
# TODO: change 1e9 to 30s # pylint: disable=W0511
|
|
483
|
-
self.query(query, (node_id, time.time() + 1e9, 1e9))
|
|
531
|
+
self.query(query, (node_id, time.time() + ping_interval, ping_interval))
|
|
484
532
|
except sqlite3.IntegrityError:
|
|
485
533
|
log(ERROR, "Unexpected node registration failure.")
|
|
486
534
|
return 0
|
|
@@ -132,7 +132,7 @@ class State(abc.ABC):
|
|
|
132
132
|
"""Delete all delivered TaskIns/TaskRes pairs."""
|
|
133
133
|
|
|
134
134
|
@abc.abstractmethod
|
|
135
|
-
def create_node(self) -> int:
|
|
135
|
+
def create_node(self, ping_interval: float) -> int:
|
|
136
136
|
"""Create, store in state, and return `node_id`."""
|
|
137
137
|
|
|
138
138
|
@abc.abstractmethod
|
|
@@ -0,0 +1,56 @@
|
|
|
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
|
+
"""Utility functions for State."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
import time
|
|
19
|
+
from logging import ERROR
|
|
20
|
+
from uuid import uuid4
|
|
21
|
+
|
|
22
|
+
from flwr.common import log
|
|
23
|
+
from flwr.common.constant import ErrorCode
|
|
24
|
+
from flwr.proto.error_pb2 import Error # pylint: disable=E0611
|
|
25
|
+
from flwr.proto.node_pb2 import Node # pylint: disable=E0611
|
|
26
|
+
from flwr.proto.task_pb2 import Task, TaskIns, TaskRes # pylint: disable=E0611
|
|
27
|
+
|
|
28
|
+
NODE_UNAVAILABLE_ERROR_REASON = (
|
|
29
|
+
"Error: Node Unavailable - The destination node is currently unavailable. "
|
|
30
|
+
"It exceeds the time limit specified in its last ping."
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def make_node_unavailable_taskres(ref_taskins: TaskIns) -> TaskRes:
|
|
35
|
+
"""Generate a TaskRes with a node unavailable error from a TaskIns."""
|
|
36
|
+
current_time = time.time()
|
|
37
|
+
ttl = ref_taskins.task.ttl - (current_time - ref_taskins.task.created_at)
|
|
38
|
+
if ttl < 0:
|
|
39
|
+
log(ERROR, "Creating TaskRes for TaskIns that exceeds its TTL.")
|
|
40
|
+
ttl = 0
|
|
41
|
+
return TaskRes(
|
|
42
|
+
task_id=str(uuid4()),
|
|
43
|
+
group_id=ref_taskins.group_id,
|
|
44
|
+
run_id=ref_taskins.run_id,
|
|
45
|
+
task=Task(
|
|
46
|
+
producer=Node(node_id=ref_taskins.task.consumer.node_id, anonymous=False),
|
|
47
|
+
consumer=Node(node_id=ref_taskins.task.producer.node_id, anonymous=False),
|
|
48
|
+
created_at=current_time,
|
|
49
|
+
ttl=ttl,
|
|
50
|
+
ancestry=[ref_taskins.task_id],
|
|
51
|
+
task_type=ref_taskins.task.task_type,
|
|
52
|
+
error=Error(
|
|
53
|
+
code=ErrorCode.NODE_UNAVAILABLE, reason=NODE_UNAVAILABLE_ERROR_REASON
|
|
54
|
+
),
|
|
55
|
+
),
|
|
56
|
+
)
|
|
@@ -21,7 +21,7 @@ from logging import INFO
|
|
|
21
21
|
from typing import Optional, cast
|
|
22
22
|
|
|
23
23
|
import flwr.common.recordset_compat as compat
|
|
24
|
-
from flwr.common import
|
|
24
|
+
from flwr.common import ConfigsRecord, Context, GetParametersIns, log
|
|
25
25
|
from flwr.common.constant import MessageType, MessageTypeLegacy
|
|
26
26
|
|
|
27
27
|
from ..compat.app_utils import start_update_client_manager_thread
|
|
@@ -127,7 +127,6 @@ def default_init_params_workflow(driver: Driver, context: Context) -> None:
|
|
|
127
127
|
message_type=MessageTypeLegacy.GET_PARAMETERS,
|
|
128
128
|
dst_node_id=random_client.node_id,
|
|
129
129
|
group_id="0",
|
|
130
|
-
ttl=DEFAULT_TTL,
|
|
131
130
|
)
|
|
132
131
|
]
|
|
133
132
|
)
|
|
@@ -226,7 +225,6 @@ def default_fit_workflow( # pylint: disable=R0914
|
|
|
226
225
|
message_type=MessageType.TRAIN,
|
|
227
226
|
dst_node_id=proxy.node_id,
|
|
228
227
|
group_id=str(current_round),
|
|
229
|
-
ttl=DEFAULT_TTL,
|
|
230
228
|
)
|
|
231
229
|
for proxy, fitins in client_instructions
|
|
232
230
|
]
|
|
@@ -306,7 +304,6 @@ def default_evaluate_workflow(driver: Driver, context: Context) -> None:
|
|
|
306
304
|
message_type=MessageType.EVALUATE,
|
|
307
305
|
dst_node_id=proxy.node_id,
|
|
308
306
|
group_id=str(current_round),
|
|
309
|
-
ttl=DEFAULT_TTL,
|
|
310
307
|
)
|
|
311
308
|
for proxy, evalins in client_instructions
|
|
312
309
|
]
|
|
@@ -22,7 +22,6 @@ from typing import Dict, List, Optional, Set, Tuple, Union, cast
|
|
|
22
22
|
|
|
23
23
|
import flwr.common.recordset_compat as compat
|
|
24
24
|
from flwr.common import (
|
|
25
|
-
DEFAULT_TTL,
|
|
26
25
|
ConfigsRecord,
|
|
27
26
|
Context,
|
|
28
27
|
FitRes,
|
|
@@ -374,7 +373,6 @@ class SecAggPlusWorkflow:
|
|
|
374
373
|
message_type=MessageType.TRAIN,
|
|
375
374
|
dst_node_id=nid,
|
|
376
375
|
group_id=str(cfg[WorkflowKey.CURRENT_ROUND]),
|
|
377
|
-
ttl=DEFAULT_TTL,
|
|
378
376
|
)
|
|
379
377
|
|
|
380
378
|
log(
|
|
@@ -422,7 +420,6 @@ class SecAggPlusWorkflow:
|
|
|
422
420
|
message_type=MessageType.TRAIN,
|
|
423
421
|
dst_node_id=nid,
|
|
424
422
|
group_id=str(cfg[WorkflowKey.CURRENT_ROUND]),
|
|
425
|
-
ttl=DEFAULT_TTL,
|
|
426
423
|
)
|
|
427
424
|
|
|
428
425
|
# Broadcast public keys to clients and receive secret key shares
|
|
@@ -493,7 +490,6 @@ class SecAggPlusWorkflow:
|
|
|
493
490
|
message_type=MessageType.TRAIN,
|
|
494
491
|
dst_node_id=nid,
|
|
495
492
|
group_id=str(cfg[WorkflowKey.CURRENT_ROUND]),
|
|
496
|
-
ttl=DEFAULT_TTL,
|
|
497
493
|
)
|
|
498
494
|
|
|
499
495
|
log(
|
|
@@ -564,7 +560,6 @@ class SecAggPlusWorkflow:
|
|
|
564
560
|
message_type=MessageType.TRAIN,
|
|
565
561
|
dst_node_id=nid,
|
|
566
562
|
group_id=str(current_round),
|
|
567
|
-
ttl=DEFAULT_TTL,
|
|
568
563
|
)
|
|
569
564
|
|
|
570
565
|
log(
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
|
|
17
17
|
import asyncio
|
|
18
18
|
import threading
|
|
19
|
-
import traceback
|
|
20
19
|
from abc import ABC
|
|
21
20
|
from logging import DEBUG, ERROR, WARNING
|
|
22
21
|
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, Union
|
|
@@ -25,22 +24,13 @@ import ray
|
|
|
25
24
|
from ray import ObjectRef
|
|
26
25
|
from ray.util.actor_pool import ActorPool
|
|
27
26
|
|
|
28
|
-
from flwr.client.client_app import ClientApp, LoadClientAppError
|
|
27
|
+
from flwr.client.client_app import ClientApp, ClientAppException, LoadClientAppError
|
|
29
28
|
from flwr.common import Context, Message
|
|
30
29
|
from flwr.common.logger import log
|
|
31
30
|
|
|
32
31
|
ClientAppFn = Callable[[], ClientApp]
|
|
33
32
|
|
|
34
33
|
|
|
35
|
-
class ClientException(Exception):
|
|
36
|
-
"""Raised when client side logic crashes with an exception."""
|
|
37
|
-
|
|
38
|
-
def __init__(self, message: str):
|
|
39
|
-
div = ">" * 7
|
|
40
|
-
self.message = "\n" + div + "A ClientException occurred." + message
|
|
41
|
-
super().__init__(self.message)
|
|
42
|
-
|
|
43
|
-
|
|
44
34
|
class VirtualClientEngineActor(ABC):
|
|
45
35
|
"""Abstract base class for VirtualClientEngine Actors."""
|
|
46
36
|
|
|
@@ -71,17 +61,7 @@ class VirtualClientEngineActor(ABC):
|
|
|
71
61
|
raise load_ex
|
|
72
62
|
|
|
73
63
|
except Exception as ex:
|
|
74
|
-
|
|
75
|
-
mssg = (
|
|
76
|
-
"\n\tSomething went wrong when running your client run."
|
|
77
|
-
"\n\tClient "
|
|
78
|
-
+ cid
|
|
79
|
-
+ " crashed when the "
|
|
80
|
-
+ self.__class__.__name__
|
|
81
|
-
+ " was running its run."
|
|
82
|
-
"\n\tException triggered on the client side: " + client_trace,
|
|
83
|
-
)
|
|
84
|
-
raise ClientException(str(mssg)) from ex
|
|
64
|
+
raise ClientAppException(str(ex)) from ex
|
|
85
65
|
|
|
86
66
|
return cid, out_message, context
|
|
87
67
|
|
{flwr_nightly-1.8.0.dev20240401.dist-info → flwr_nightly-1.9.0.dev20240403.dist-info}/RECORD
RENAMED
|
@@ -19,23 +19,23 @@ flwr/cli/new/templates/app/code/server.tensorflow.py.tpl,sha256=d6J5VM681d0j4hj1
|
|
|
19
19
|
flwr/cli/new/templates/app/code/task.pytorch.py.tpl,sha256=e3quQBKqC5-ZKbl7AKLvEs89SdzMk-k30rxeDx9I63c,3675
|
|
20
20
|
flwr/cli/new/templates/app/flower.toml.tpl,sha256=gJ5MZ7zaiaVvIEt5X_kkU-SU2NmeXkAZ9NXJS00-Axw,269
|
|
21
21
|
flwr/cli/new/templates/app/pyproject.numpy.toml.tpl,sha256=5kGEAPrHKHFfzxmKy1AvrHMcp46nZwnQb2z5zPX8XZY,408
|
|
22
|
-
flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl,sha256=
|
|
22
|
+
flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl,sha256=SUmoMyRodzYkxElKDF_rgP-Ftirw4hKUoOE8EcRpQb0,488
|
|
23
23
|
flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl,sha256=6odFG__2Wb8CHNUDJRjA0H3bOkZ8Z7iziTNJKX2_SOI,697
|
|
24
24
|
flwr/cli/new/templates/app/requirements.numpy.txt.tpl,sha256=YfJLjL-ONv0hnw5k4EfHv6uMpaqfLzOhkT_P4aWv5Fo,30
|
|
25
|
-
flwr/cli/new/templates/app/requirements.pytorch.txt.tpl,sha256=
|
|
25
|
+
flwr/cli/new/templates/app/requirements.pytorch.txt.tpl,sha256=3dvhiFgiOw3HAHCDmyiqvBSTF492wQm75KUKzVCOkUc,86
|
|
26
26
|
flwr/cli/new/templates/app/requirements.tensorflow.txt.tpl,sha256=MsiO0GbUe35h5giVMaE2YykKMAhtC5ccAc_4EcmJUNs,209
|
|
27
27
|
flwr/cli/run/__init__.py,sha256=oCd6HmQDx-sqver1gecgx-uMA38BLTSiiKpl7RGNceg,789
|
|
28
28
|
flwr/cli/run/run.py,sha256=C7Yh-Y0f64PEabb9733jBKIhhOUFpcRmCZJIDtv-NG8,2329
|
|
29
29
|
flwr/cli/utils.py,sha256=_V2BlFVNNG2naZrq227fZ8o4TxBN_hB-4fQsen9uQoo,2300
|
|
30
30
|
flwr/client/__init__.py,sha256=futk_IdY_N1h8BTve4Iru51bxm7H1gv58ZPIXWi5XUA,1187
|
|
31
|
-
flwr/client/app.py,sha256=
|
|
31
|
+
flwr/client/app.py,sha256=L8TJxRbo8j58Nr99CY3Gk_zDzWLwS0CQp60QbVMPKd4,26114
|
|
32
32
|
flwr/client/client.py,sha256=Vp9UkOkoHdNfn6iMYZsj_5m_GICiFfUlKEVaLad-YhM,8183
|
|
33
|
-
flwr/client/client_app.py,sha256
|
|
33
|
+
flwr/client/client_app.py,sha256=-Cs0084tLQUoBCeYZdG2KgU7cjp95_ZJ4MfjoaN4Fzk,8636
|
|
34
34
|
flwr/client/dpfedavg_numpy_client.py,sha256=9Tnig4iml2J88HBKNahegjXjbfvIQyBtaIQaqjbeqsA,7435
|
|
35
35
|
flwr/client/grpc_client/__init__.py,sha256=LsnbqXiJhgQcB0XzAlUQgPx011Uf7Y7yabIC1HxivJ8,735
|
|
36
36
|
flwr/client/grpc_client/connection.py,sha256=w3Lble9-eCzNOR7fBUsVedVCK4ui9QPhK7i7Ew_a5Vk,8717
|
|
37
37
|
flwr/client/grpc_rere_client/__init__.py,sha256=avn6W_vHEM_yZEB1S7hCZgnTbXb6ZujqRP_vAzyXu-0,752
|
|
38
|
-
flwr/client/grpc_rere_client/connection.py,sha256=
|
|
38
|
+
flwr/client/grpc_rere_client/connection.py,sha256=JaQIQYUJnmZHfqrGBxYZmEtyC-rUdCCaK1HrMcOXEig,8560
|
|
39
39
|
flwr/client/heartbeat.py,sha256=6Ix2Du9SDlXU_nre48WIDUXDy3AVoZsGKacSq2NqT5c,2377
|
|
40
40
|
flwr/client/message_handler/__init__.py,sha256=abHvBRJJiiaAMNgeILQbMOa6h8WqMK2BcnvxwQZFpic,719
|
|
41
41
|
flwr/client/message_handler/message_handler.py,sha256=ml_FlduAJ5pxO31n1tKRrWfQRSxkMgKLbwXXcRsNSos,6553
|
|
@@ -52,11 +52,11 @@ flwr/client/node_state.py,sha256=KTTs_l4I0jBM7IsSsbAGjhfL_yZC3QANbzyvyfZBRDM,177
|
|
|
52
52
|
flwr/client/node_state_tests.py,sha256=gPwz0zf2iuDSa11jedkur_u3Xm7lokIDG5ALD2MCvSw,2195
|
|
53
53
|
flwr/client/numpy_client.py,sha256=u76GWAdHmJM88Agm2EgLQSvO8Jnk225mJTk-_TmPjFE,10283
|
|
54
54
|
flwr/client/rest_client/__init__.py,sha256=ThwOnkMdzxo_UuyTI47Q7y9oSpuTgNT2OuFvJCfuDiw,735
|
|
55
|
-
flwr/client/rest_client/connection.py,sha256=
|
|
55
|
+
flwr/client/rest_client/connection.py,sha256=rDLQlymPOZYT4cqOaw8sejlMhmlzyqJL-UrZqyWHv8s,14482
|
|
56
56
|
flwr/client/typing.py,sha256=c9EvjlEjasxn1Wqx6bGl6Xg6vM1gMFfmXht-E2i5J-k,1006
|
|
57
57
|
flwr/common/__init__.py,sha256=dHOptgKxna78CEQLD5Yu0QIsoSgpIIw5AhIUZCHDWAU,3721
|
|
58
58
|
flwr/common/address.py,sha256=iTAN9jtmIGMrWFnx9XZQl45ZEtQJVZZLYPRBSNVARGI,1882
|
|
59
|
-
flwr/common/constant.py,sha256=
|
|
59
|
+
flwr/common/constant.py,sha256=GsixlCwohCBlQ6_mTk29HChuyRftgTELTCN06AxrOyc,2424
|
|
60
60
|
flwr/common/context.py,sha256=ounF-mWPPtXGwtae3sg5EhF58ScviOa3MVqxRpGVu-8,1313
|
|
61
61
|
flwr/common/date.py,sha256=UWhBZj49yX9LD4BmatS_ZFZu_-kweGh0KQJ1djyWWH4,891
|
|
62
62
|
flwr/common/differential_privacy.py,sha256=WZWrL7C9XaB9l9NDkLDI5PvM7jwcoTTFu08ZVG8-M5Q,6113
|
|
@@ -65,7 +65,7 @@ flwr/common/dp.py,sha256=Hc3lLHihjexbJaD_ft31gdv9XRcwOTgDBwJzICuok3A,2004
|
|
|
65
65
|
flwr/common/exit_handlers.py,sha256=2Nt0wLhc17KQQsLPFSRAjjhUiEFfJK6tNozdGiIY4Fs,2812
|
|
66
66
|
flwr/common/grpc.py,sha256=HimjpTtIY3Vfqtlq3u-CYWjqAl9rSn0uo3A8JjhUmwQ,2273
|
|
67
67
|
flwr/common/logger.py,sha256=3hfKun9YISWj4i_QhxgZdnaHJc4x-QvFJQJTKHZ2KHs,6096
|
|
68
|
-
flwr/common/message.py,sha256=
|
|
68
|
+
flwr/common/message.py,sha256=NvxiWT9YI8GmIt2r3EPVPFFAFQo3xhP09mvnAxjHivQ,12385
|
|
69
69
|
flwr/common/object_ref.py,sha256=ELoUCAFO-vbjJC41CGpa-WBG2SLYe3ErW-d9YCG3zqA,4961
|
|
70
70
|
flwr/common/parameter.py,sha256=-bFAUayToYDF50FZGrBC1hQYJCQDtB2bbr3ZuVLMtdE,2095
|
|
71
71
|
flwr/common/pyproject.py,sha256=EI_ovbCHGmhYrdPx0RSDi5EkFZFof-8m1PA54c0ZTjc,1385
|
|
@@ -99,8 +99,8 @@ flwr/proto/error_pb2.py,sha256=LarjKL90LbwkXKlhzNrDssgl4DXcvIPve8NVCXHpsKA,1084
|
|
|
99
99
|
flwr/proto/error_pb2.pyi,sha256=ZNH4HhJTU_KfMXlyCeg8FwU-fcUYxTqEmoJPtWtHikc,734
|
|
100
100
|
flwr/proto/error_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
|
101
101
|
flwr/proto/error_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
|
|
102
|
-
flwr/proto/fleet_pb2.py,sha256=
|
|
103
|
-
flwr/proto/fleet_pb2.pyi,sha256=
|
|
102
|
+
flwr/proto/fleet_pb2.py,sha256=0PSDvjWer5VDh10L7BckF8-WeNYZzXC2BQQF_E0EacQ,4356
|
|
103
|
+
flwr/proto/fleet_pb2.pyi,sha256=45kQ9YINv3VG0nxWSjCN4SppdepjKW8rRBlxKxz7ud4,7571
|
|
104
104
|
flwr/proto/fleet_pb2_grpc.py,sha256=U2UeEqWQ7VE58C1ngm_yVniiwBuXfnHmzITYPt6BEtA,9042
|
|
105
105
|
flwr/proto/fleet_pb2_grpc.pyi,sha256=Cd8oZqhK9ORMB7iKyW0NBvCeP8Bg1OZbnn_8GzDxEHU,2491
|
|
106
106
|
flwr/proto/node_pb2.py,sha256=1zfXEvgGObglIcaVb4SLFmOcHZvA8eHzEtMFM5A6FYY,1081
|
|
@@ -131,7 +131,7 @@ flwr/server/compat/driver_client_proxy.py,sha256=QWLl5YJwI6NVADwjQGQJqkLtCfPNT-a
|
|
|
131
131
|
flwr/server/compat/legacy_context.py,sha256=D2s7PvQoDnTexuRmf1uG9Von7GUj4Qqyr7qLklSlKAM,1766
|
|
132
132
|
flwr/server/criterion.py,sha256=ypbAexbztzGUxNen9RCHF91QeqiEQix4t4Ih3E-42MM,1061
|
|
133
133
|
flwr/server/driver/__init__.py,sha256=yYyVX1FcDiDFM6rw0-DSZpuRy0EoWRfG9puwlQUswFA,820
|
|
134
|
-
flwr/server/driver/driver.py,sha256=
|
|
134
|
+
flwr/server/driver/driver.py,sha256=AwAxgYRx-FI6NvI5ukmdGlEmQRyp5GZSElFnDZhelj8,10106
|
|
135
135
|
flwr/server/driver/grpc_driver.py,sha256=D2n3_Es_DHFgQsq_TjYVEz8RYJJJYoe24E1vozaTFiE,4586
|
|
136
136
|
flwr/server/history.py,sha256=hDsoBaA4kUa6d1yvDVXuLluBqOBKSm0_fVDtUtYJkmg,5121
|
|
137
137
|
flwr/server/run_serverapp.py,sha256=3hoXa57T4L1vOWVWPSSdZ_UyRO-uTwUIrhha6TJAXMg,5592
|
|
@@ -175,38 +175,39 @@ flwr/server/superlink/fleet/grpc_bidi/grpc_server.py,sha256=1QyBX5qcFPjMVlv7Trvn
|
|
|
175
175
|
flwr/server/superlink/fleet/grpc_rere/__init__.py,sha256=bEJOMWbSlqkw-y5ZHtEXczhoSlAxErcRYffmTMQAV8M,758
|
|
176
176
|
flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py,sha256=LC_ntiLZMIZkspwjtQ9_MZ4agzArebO4HIVJ3YOrFx8,3036
|
|
177
177
|
flwr/server/superlink/fleet/message_handler/__init__.py,sha256=hEY0l61ojH8Iz30_K1btm1HJ6J49iZJSFUsVYqUTw3A,731
|
|
178
|
-
flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=
|
|
178
|
+
flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=rVisujx0B0WZROlp4uwk1KjzgPR7Pit4rBnurF5xXUw,3273
|
|
179
179
|
flwr/server/superlink/fleet/rest_rere/__init__.py,sha256=VKDvDq5H8koOUztpmQacVzGJXPLEEkL1Vmolxt3mvnY,735
|
|
180
180
|
flwr/server/superlink/fleet/rest_rere/rest_api.py,sha256=_tGtARm4x957Fu1EWoDieqOzV9CQZTM4GgKe2GxIOvw,6734
|
|
181
181
|
flwr/server/superlink/fleet/vce/__init__.py,sha256=36MHKiefnJeyjwMQzVUK4m06Ojon3WDcwZGQsAcyVhQ,783
|
|
182
182
|
flwr/server/superlink/fleet/vce/backend/__init__.py,sha256=oBIzmnrSSRvH_H0vRGEGWhWzQQwqe3zn6e13RsNwlIY,1466
|
|
183
183
|
flwr/server/superlink/fleet/vce/backend/backend.py,sha256=LJsKl7oixVvptcG98Rd9ejJycNWcEVB0ODvSreLGp-A,2260
|
|
184
184
|
flwr/server/superlink/fleet/vce/backend/raybackend.py,sha256=TaT2EpbVEsIY0EDzF8obadyZaSXjD38TFGdDPI-ytD0,6375
|
|
185
|
-
flwr/server/superlink/fleet/vce/vce_api.py,sha256=
|
|
185
|
+
flwr/server/superlink/fleet/vce/vce_api.py,sha256=c2J2m6v1jDyuAhiBArdZNIk4cbiZNFJkpKlBJFEQq-c,12454
|
|
186
186
|
flwr/server/superlink/state/__init__.py,sha256=ij-7Ms-hyordQdRmGQxY1-nVa4OhixJ0jr7_YDkys0s,1003
|
|
187
|
-
flwr/server/superlink/state/in_memory_state.py,sha256=
|
|
188
|
-
flwr/server/superlink/state/sqlite_state.py,sha256=
|
|
189
|
-
flwr/server/superlink/state/state.py,sha256=
|
|
187
|
+
flwr/server/superlink/state/in_memory_state.py,sha256=lZPoAwyZE0LcKgef8rFa5dzekIhs2q_TPGv7iddJNKI,9586
|
|
188
|
+
flwr/server/superlink/state/sqlite_state.py,sha256=z2jF0UV0VMsVyVIpT_7v13ji6wuFJSmyNbYZhxwelbE,23985
|
|
189
|
+
flwr/server/superlink/state/state.py,sha256=1cboTXmRGu3r4ebdNby-Ht3qVwAfLgc563YF6awvPSw,6058
|
|
190
190
|
flwr/server/superlink/state/state_factory.py,sha256=91cSB-KOAFM37z7T098WxTkVeKNaAZ_mTI75snn2_tk,1654
|
|
191
|
+
flwr/server/superlink/state/utils.py,sha256=qhIjBu5_rqm9GLMB6QS5TIRrMDVs85lmY17BqZ1ccLk,2207
|
|
191
192
|
flwr/server/typing.py,sha256=2zSG-KuDAgwFPuzgVjTLDaEqJ8gXXGqFR2RD-qIk730,913
|
|
192
193
|
flwr/server/utils/__init__.py,sha256=RQVbo-bcsVtp_lJBf7dL5w01FbLrr7v3YedeGp5_YMs,908
|
|
193
194
|
flwr/server/utils/tensorboard.py,sha256=k0G6bqsLx7wfYbH2KtXsDYcOCfyIeE12-hefXA7lZdg,5485
|
|
194
195
|
flwr/server/utils/validator.py,sha256=pzyXoOEEPSoYC2UEzened8IKSFRI-kIqqI0QlwRK9jk,5301
|
|
195
196
|
flwr/server/workflow/__init__.py,sha256=SXY0XkwbkezFBxxrFB5hKUtmtAgnYISBkPouR1V71ss,902
|
|
196
197
|
flwr/server/workflow/constant.py,sha256=q4DLdR8Krlxuewq2AQjwTL75hphxE5ODNz4AhViHMXk,1082
|
|
197
|
-
flwr/server/workflow/default_workflows.py,sha256=
|
|
198
|
+
flwr/server/workflow/default_workflows.py,sha256=ROJNsY538jSGMaNyF7GHwXMtV7us1Vx8OKyUHWYeDcA,12547
|
|
198
199
|
flwr/server/workflow/secure_aggregation/__init__.py,sha256=3XlgDOjD_hcukTGl6Bc1B-8M_dPlVSJuTbvXIbiO-Ic,880
|
|
199
200
|
flwr/server/workflow/secure_aggregation/secagg_workflow.py,sha256=wpAkYPId0nfK6SgpUAtsCni4_MQLd-uqJ81tUKu3xlI,5838
|
|
200
|
-
flwr/server/workflow/secure_aggregation/secaggplus_workflow.py,sha256=
|
|
201
|
+
flwr/server/workflow/secure_aggregation/secaggplus_workflow.py,sha256=BRqhlnVe8CYNoUvb_KCfRXay02NTT6a-pCrMaOqAxGc,29038
|
|
201
202
|
flwr/simulation/__init__.py,sha256=hpoKzdovrH0_Cf8HIcXxQxyUUb3BiSk-WUNLf5STHcc,1400
|
|
202
203
|
flwr/simulation/app.py,sha256=WqJxdXTEuehwMW605p5NMmvBbKYx5tuqnV3Mp7jSWXM,13904
|
|
203
204
|
flwr/simulation/ray_transport/__init__.py,sha256=FsaAnzC4cw4DqoouBCix6496k29jACkfeIam55BvW9g,734
|
|
204
|
-
flwr/simulation/ray_transport/ray_actor.py,sha256=
|
|
205
|
+
flwr/simulation/ray_transport/ray_actor.py,sha256=_wv2eP7qxkCZ-6rMyYWnjLrGPBZRxjvTPjaVk8zIaQ4,19367
|
|
205
206
|
flwr/simulation/ray_transport/ray_client_proxy.py,sha256=oDu4sEPIOu39vrNi-fqDAe10xtNUXMO49bM2RWfRcyw,6738
|
|
206
207
|
flwr/simulation/ray_transport/utils.py,sha256=TYdtfg1P9VfTdLMOJlifInGpxWHYs9UfUqIv2wfkRLA,2392
|
|
207
208
|
flwr/simulation/run_simulation.py,sha256=HiIH6aa_v56NfKQN5ZBd94NyVfaZNyFs43_kItYsQXU,15685
|
|
208
|
-
flwr_nightly-1.
|
|
209
|
-
flwr_nightly-1.
|
|
210
|
-
flwr_nightly-1.
|
|
211
|
-
flwr_nightly-1.
|
|
212
|
-
flwr_nightly-1.
|
|
209
|
+
flwr_nightly-1.9.0.dev20240403.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
210
|
+
flwr_nightly-1.9.0.dev20240403.dist-info/METADATA,sha256=EInfcIsQaaOnqtDIPwen-CdLHM_ElURkwIxwA8MD5BQ,15257
|
|
211
|
+
flwr_nightly-1.9.0.dev20240403.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
212
|
+
flwr_nightly-1.9.0.dev20240403.dist-info/entry_points.txt,sha256=utu2wybGyYJSTtsB2ktY_gmy-XtMFo9EFZdishX0zR4,320
|
|
213
|
+
flwr_nightly-1.9.0.dev20240403.dist-info/RECORD,,
|
{flwr_nightly-1.8.0.dev20240401.dist-info → flwr_nightly-1.9.0.dev20240403.dist-info}/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|