flwr-nightly 1.15.0.dev20250114__py3-none-any.whl → 1.15.0.dev20250116__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/common/constant.py +3 -0
- flwr/common/logger.py +1 -1
- flwr/common/serde.py +6 -4
- flwr/proto/node_pb2.py +2 -2
- flwr/proto/node_pb2.pyi +1 -4
- flwr/server/compat/app_utils.py +0 -1
- flwr/server/compat/driver_client_proxy.py +1 -2
- flwr/server/driver/grpc_driver.py +5 -2
- flwr/server/driver/inmemory_driver.py +2 -1
- flwr/server/superlink/driver/serverappio_servicer.py +1 -3
- flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +2 -2
- flwr/server/superlink/fleet/message_handler/message_handler.py +4 -5
- flwr/server/superlink/linkstate/in_memory_linkstate.py +14 -26
- flwr/server/superlink/linkstate/linkstate.py +5 -18
- flwr/server/superlink/linkstate/sqlite_linkstate.py +30 -70
- flwr/server/superlink/linkstate/utils.py +18 -8
- flwr/server/utils/validator.py +9 -34
- flwr/simulation/legacy_app.py +4 -2
- {flwr_nightly-1.15.0.dev20250114.dist-info → flwr_nightly-1.15.0.dev20250116.dist-info}/METADATA +1 -1
- {flwr_nightly-1.15.0.dev20250114.dist-info → flwr_nightly-1.15.0.dev20250116.dist-info}/RECORD +23 -23
- {flwr_nightly-1.15.0.dev20250114.dist-info → flwr_nightly-1.15.0.dev20250116.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.15.0.dev20250114.dist-info → flwr_nightly-1.15.0.dev20250116.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.15.0.dev20250114.dist-info → flwr_nightly-1.15.0.dev20250116.dist-info}/entry_points.txt +0 -0
flwr/common/constant.py
CHANGED
@@ -83,6 +83,9 @@ FAB_HASH_TRUNCATION = 8
|
|
83
83
|
FLWR_DIR = ".flwr" # The default Flower directory: ~/.flwr/
|
84
84
|
FLWR_HOME = "FLWR_HOME" # If set, override the default Flower directory
|
85
85
|
|
86
|
+
# Constant for SuperLink
|
87
|
+
SUPERLINK_NODE_ID = 1
|
88
|
+
|
86
89
|
# Constants entries in Node config for Simulation
|
87
90
|
PARTITION_ID_KEY = "partition-id"
|
88
91
|
NUM_PARTITIONS_KEY = "num-partitions"
|
flwr/common/logger.py
CHANGED
@@ -320,7 +320,7 @@ def _log_uploader(
|
|
320
320
|
) -> None:
|
321
321
|
"""Upload logs to the SuperLink."""
|
322
322
|
exit_flag = False
|
323
|
-
node = Node(node_id=node_id
|
323
|
+
node = Node(node_id=node_id)
|
324
324
|
msgs: list[str] = []
|
325
325
|
while True:
|
326
326
|
# Fetch all messages from the queue
|
flwr/common/serde.py
CHANGED
@@ -21,6 +21,8 @@ from typing import Any, TypeVar, cast
|
|
21
21
|
|
22
22
|
from google.protobuf.message import Message as GrpcMessage
|
23
23
|
|
24
|
+
from flwr.common.constant import SUPERLINK_NODE_ID
|
25
|
+
|
24
26
|
# pylint: disable=E0611
|
25
27
|
from flwr.proto.clientappio_pb2 import ClientAppOutputCode, ClientAppOutputStatus
|
26
28
|
from flwr.proto.error_pb2 import Error as ProtoError
|
@@ -605,8 +607,8 @@ def message_to_taskins(message: Message) -> TaskIns:
|
|
605
607
|
group_id=md.group_id,
|
606
608
|
run_id=md.run_id,
|
607
609
|
task=Task(
|
608
|
-
producer=Node(node_id=
|
609
|
-
consumer=Node(node_id=md.dst_node_id
|
610
|
+
producer=Node(node_id=SUPERLINK_NODE_ID), # Assume driver node
|
611
|
+
consumer=Node(node_id=md.dst_node_id),
|
610
612
|
created_at=md.created_at,
|
611
613
|
ttl=md.ttl,
|
612
614
|
ancestry=[md.reply_to_message] if md.reply_to_message != "" else [],
|
@@ -659,8 +661,8 @@ def message_to_taskres(message: Message) -> TaskRes:
|
|
659
661
|
group_id=md.group_id,
|
660
662
|
run_id=md.run_id,
|
661
663
|
task=Task(
|
662
|
-
producer=Node(node_id=md.src_node_id
|
663
|
-
consumer=Node(node_id=
|
664
|
+
producer=Node(node_id=md.src_node_id),
|
665
|
+
consumer=Node(node_id=SUPERLINK_NODE_ID), # Assume driver node
|
664
666
|
created_at=md.created_at,
|
665
667
|
ttl=md.ttl,
|
666
668
|
ancestry=[md.reply_to_message] if md.reply_to_message != "" else [],
|
flwr/proto/node_pb2.py
CHANGED
@@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
|
|
14
14
|
|
15
15
|
|
16
16
|
|
17
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/node.proto\x12\nflwr.proto\"
|
17
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/node.proto\x12\nflwr.proto\"\x17\n\x04Node\x12\x0f\n\x07node_id\x18\x01 \x01(\x04\x62\x06proto3')
|
18
18
|
|
19
19
|
_globals = globals()
|
20
20
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
@@ -22,5 +22,5 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.node_pb2', _glob
|
|
22
22
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
23
23
|
DESCRIPTOR._options = None
|
24
24
|
_globals['_NODE']._serialized_start=37
|
25
|
-
_globals['_NODE']._serialized_end=
|
25
|
+
_globals['_NODE']._serialized_end=60
|
26
26
|
# @@protoc_insertion_point(module_scope)
|
flwr/proto/node_pb2.pyi
CHANGED
@@ -12,13 +12,10 @@ DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
|
|
12
12
|
class Node(google.protobuf.message.Message):
|
13
13
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
14
14
|
NODE_ID_FIELD_NUMBER: builtins.int
|
15
|
-
ANONYMOUS_FIELD_NUMBER: builtins.int
|
16
15
|
node_id: builtins.int
|
17
|
-
anonymous: builtins.bool
|
18
16
|
def __init__(self,
|
19
17
|
*,
|
20
18
|
node_id: builtins.int = ...,
|
21
|
-
anonymous: builtins.bool = ...,
|
22
19
|
) -> None: ...
|
23
|
-
def ClearField(self, field_name: typing_extensions.Literal["
|
20
|
+
def ClearField(self, field_name: typing_extensions.Literal["node_id",b"node_id"]) -> None: ...
|
24
21
|
global___Node = Node
|
flwr/server/compat/app_utils.py
CHANGED
@@ -28,12 +28,11 @@ from ..driver.driver import Driver
|
|
28
28
|
class DriverClientProxy(ClientProxy):
|
29
29
|
"""Flower client proxy which delegates work using the Driver API."""
|
30
30
|
|
31
|
-
def __init__(self, node_id: int, driver: Driver,
|
31
|
+
def __init__(self, node_id: int, driver: Driver, run_id: int):
|
32
32
|
super().__init__(str(node_id))
|
33
33
|
self.node_id = node_id
|
34
34
|
self.driver = driver
|
35
35
|
self.run_id = run_id
|
36
|
-
self.anonymous = anonymous
|
37
36
|
|
38
37
|
def get_properties(
|
39
38
|
self,
|
@@ -24,7 +24,10 @@ from typing import Optional, cast
|
|
24
24
|
import grpc
|
25
25
|
|
26
26
|
from flwr.common import DEFAULT_TTL, Message, Metadata, RecordSet
|
27
|
-
from flwr.common.constant import
|
27
|
+
from flwr.common.constant import (
|
28
|
+
SERVERAPPIO_API_DEFAULT_CLIENT_ADDRESS,
|
29
|
+
SUPERLINK_NODE_ID,
|
30
|
+
)
|
28
31
|
from flwr.common.grpc import create_channel
|
29
32
|
from flwr.common.logger import log
|
30
33
|
from flwr.common.retry_invoker import _make_simple_grpc_retry_invoker, _wrap_stub
|
@@ -76,7 +79,7 @@ class GrpcDriver(Driver):
|
|
76
79
|
self._run: Optional[Run] = None
|
77
80
|
self._grpc_stub: Optional[ServerAppIoStub] = None
|
78
81
|
self._channel: Optional[grpc.Channel] = None
|
79
|
-
self.node = Node(node_id=
|
82
|
+
self.node = Node(node_id=SUPERLINK_NODE_ID)
|
80
83
|
self._retry_invoker = _make_simple_grpc_retry_invoker()
|
81
84
|
|
82
85
|
@property
|
@@ -22,6 +22,7 @@ from typing import Optional, cast
|
|
22
22
|
from uuid import UUID
|
23
23
|
|
24
24
|
from flwr.common import DEFAULT_TTL, Message, Metadata, RecordSet
|
25
|
+
from flwr.common.constant import SUPERLINK_NODE_ID
|
25
26
|
from flwr.common.serde import message_from_taskres, message_to_taskins
|
26
27
|
from flwr.common.typing import Run
|
27
28
|
from flwr.proto.node_pb2 import Node # pylint: disable=E0611
|
@@ -49,7 +50,7 @@ class InMemoryDriver(Driver):
|
|
49
50
|
self._run: Optional[Run] = None
|
50
51
|
self.state = state_factory.state()
|
51
52
|
self.pull_interval = pull_interval
|
52
|
-
self.node = Node(node_id=
|
53
|
+
self.node = Node(node_id=SUPERLINK_NODE_ID)
|
53
54
|
|
54
55
|
def _check_message(self, message: Message) -> None:
|
55
56
|
# Check if the message is valid
|
@@ -102,9 +102,7 @@ class ServerAppIoServicer(serverappio_pb2_grpc.ServerAppIoServicer):
|
|
102
102
|
)
|
103
103
|
|
104
104
|
all_ids: set[int] = state.get_nodes(request.run_id)
|
105
|
-
nodes: list[Node] = [
|
106
|
-
Node(node_id=node_id, anonymous=False) for node_id in all_ids
|
107
|
-
]
|
105
|
+
nodes: list[Node] = [Node(node_id=node_id) for node_id in all_ids]
|
108
106
|
return GetNodesResponse(nodes=nodes)
|
109
107
|
|
110
108
|
def CreateRun(
|
@@ -218,11 +218,11 @@ class AuthenticateServerInterceptor(grpc.ServerInterceptor): # type: ignore
|
|
218
218
|
# Return previously assigned `node_id` for the provided `public_key`
|
219
219
|
if node_id is not None:
|
220
220
|
state.acknowledge_ping(node_id, request.ping_interval)
|
221
|
-
return CreateNodeResponse(node=Node(node_id=node_id
|
221
|
+
return CreateNodeResponse(node=Node(node_id=node_id))
|
222
222
|
|
223
223
|
# No `node_id` exists for the provided `public_key`
|
224
224
|
# Handle `CreateNode` here instead of calling the default method handler
|
225
225
|
# Note: the innermost `CreateNode` method will never be called
|
226
226
|
node_id = state.create_node(request.ping_interval)
|
227
227
|
state.set_node_public_key(node_id, public_key_bytes)
|
228
|
-
return CreateNodeResponse(node=Node(node_id=node_id
|
228
|
+
return CreateNodeResponse(node=Node(node_id=node_id))
|
@@ -66,13 +66,13 @@ def create_node(
|
|
66
66
|
"""."""
|
67
67
|
# Create node
|
68
68
|
node_id = state.create_node(ping_interval=request.ping_interval)
|
69
|
-
return CreateNodeResponse(node=Node(node_id=node_id
|
69
|
+
return CreateNodeResponse(node=Node(node_id=node_id))
|
70
70
|
|
71
71
|
|
72
72
|
def delete_node(request: DeleteNodeRequest, state: LinkState) -> DeleteNodeResponse:
|
73
73
|
"""."""
|
74
74
|
# Validate node_id
|
75
|
-
if request.node.
|
75
|
+
if request.node.node_id == 0: # i.e. unset `node_id`
|
76
76
|
return DeleteNodeResponse()
|
77
77
|
|
78
78
|
# Update state
|
@@ -91,9 +91,8 @@ def ping(
|
|
91
91
|
|
92
92
|
def pull_task_ins(request: PullTaskInsRequest, state: LinkState) -> PullTaskInsResponse:
|
93
93
|
"""Pull TaskIns handler."""
|
94
|
-
# Get node_id if client node is not anonymous
|
95
94
|
node = request.node # pylint: disable=no-member
|
96
|
-
node_id:
|
95
|
+
node_id: int = node.node_id
|
97
96
|
|
98
97
|
# Retrieve TaskIns from State
|
99
98
|
task_ins_list: list[TaskIns] = state.get_task_ins(node_id=node_id, limit=1)
|
@@ -111,7 +110,7 @@ def pull_messages(
|
|
111
110
|
"""Pull Messages handler."""
|
112
111
|
# Get node_id if client node is not anonymous
|
113
112
|
node = request.node # pylint: disable=no-member
|
114
|
-
node_id:
|
113
|
+
node_id: int = node.node_id
|
115
114
|
|
116
115
|
# Retrieve TaskIns from State
|
117
116
|
task_ins_list: list[TaskIns] = state.get_task_ins(node_id=node_id, limit=1)
|
@@ -28,6 +28,7 @@ from flwr.common.constant import (
|
|
28
28
|
MESSAGE_TTL_TOLERANCE,
|
29
29
|
NODE_ID_NUM_BYTES,
|
30
30
|
RUN_ID_NUM_BYTES,
|
31
|
+
SUPERLINK_NODE_ID,
|
31
32
|
Status,
|
32
33
|
)
|
33
34
|
from flwr.common.record import ConfigsRecord
|
@@ -90,7 +91,7 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
90
91
|
log(ERROR, "Invalid run ID for TaskIns: %s", task_ins.run_id)
|
91
92
|
return None
|
92
93
|
# Validate source node ID
|
93
|
-
if task_ins.task.producer.node_id !=
|
94
|
+
if task_ins.task.producer.node_id != SUPERLINK_NODE_ID:
|
94
95
|
log(
|
95
96
|
ERROR,
|
96
97
|
"Invalid source node ID for TaskIns: %s",
|
@@ -98,14 +99,13 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
98
99
|
)
|
99
100
|
return None
|
100
101
|
# Validate destination node ID
|
101
|
-
if
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
return None
|
102
|
+
if task_ins.task.consumer.node_id not in self.node_ids:
|
103
|
+
log(
|
104
|
+
ERROR,
|
105
|
+
"Invalid destination node ID for TaskIns: %s",
|
106
|
+
task_ins.task.consumer.node_id,
|
107
|
+
)
|
108
|
+
return None
|
109
109
|
|
110
110
|
# Create task_id
|
111
111
|
task_id = uuid4()
|
@@ -118,9 +118,7 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
118
118
|
# Return the new task_id
|
119
119
|
return task_id
|
120
120
|
|
121
|
-
def get_task_ins(
|
122
|
-
self, node_id: Optional[int], limit: Optional[int]
|
123
|
-
) -> list[TaskIns]:
|
121
|
+
def get_task_ins(self, node_id: int, limit: Optional[int]) -> list[TaskIns]:
|
124
122
|
"""Get all TaskIns that have not been delivered yet."""
|
125
123
|
if limit is not None and limit < 1:
|
126
124
|
raise AssertionError("`limit` must be >= 1")
|
@@ -130,17 +128,8 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
130
128
|
current_time = time.time()
|
131
129
|
with self.lock:
|
132
130
|
for _, task_ins in self.task_ins_store.items():
|
133
|
-
# pylint: disable=too-many-boolean-expressions
|
134
131
|
if (
|
135
|
-
node_id
|
136
|
-
and task_ins.task.consumer.anonymous is False
|
137
|
-
and task_ins.task.consumer.node_id == node_id
|
138
|
-
and task_ins.task.delivered_at == ""
|
139
|
-
and task_ins.task.created_at + task_ins.task.ttl > current_time
|
140
|
-
) or (
|
141
|
-
node_id is None # Anonymous
|
142
|
-
and task_ins.task.consumer.anonymous is True
|
143
|
-
and task_ins.task.consumer.node_id == 0
|
132
|
+
task_ins.task.consumer.node_id == node_id
|
144
133
|
and task_ins.task.delivered_at == ""
|
145
134
|
and task_ins.task.created_at + task_ins.task.ttl > current_time
|
146
135
|
):
|
@@ -174,9 +163,6 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
174
163
|
if (
|
175
164
|
task_ins
|
176
165
|
and task_res
|
177
|
-
and not (
|
178
|
-
task_ins.task.consumer.anonymous or task_res.task.producer.anonymous
|
179
|
-
)
|
180
166
|
and task_ins.task.consumer.node_id != task_res.task.producer.node_id
|
181
167
|
):
|
182
168
|
return None
|
@@ -310,7 +296,9 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
310
296
|
def create_node(self, ping_interval: float) -> int:
|
311
297
|
"""Create, store in the link state, and return `node_id`."""
|
312
298
|
# Sample a random int64 as node_id
|
313
|
-
node_id = generate_rand_int_from_bytes(
|
299
|
+
node_id = generate_rand_int_from_bytes(
|
300
|
+
NODE_ID_NUM_BYTES, exclude=[SUPERLINK_NODE_ID, 0]
|
301
|
+
)
|
314
302
|
|
315
303
|
with self.lock:
|
316
304
|
if node_id in self.node_ids:
|
@@ -40,20 +40,14 @@ class LinkState(abc.ABC): # pylint: disable=R0904
|
|
40
40
|
|
41
41
|
Constraints
|
42
42
|
-----------
|
43
|
-
|
44
|
-
`task_ins.task.consumer.node_id` MUST NOT be set (equal 0).
|
45
|
-
|
46
|
-
If `task_ins.task.consumer.anonymous` is `False`, then
|
47
|
-
`task_ins.task.consumer.node_id` MUST be set (not 0)
|
43
|
+
`task_ins.task.consumer.node_id` MUST be set (not constant.DRIVER_NODE_ID)
|
48
44
|
|
49
45
|
If `task_ins.run_id` is invalid, then
|
50
46
|
storing the `task_ins` MUST fail.
|
51
47
|
"""
|
52
48
|
|
53
49
|
@abc.abstractmethod
|
54
|
-
def get_task_ins(
|
55
|
-
self, node_id: Optional[int], limit: Optional[int]
|
56
|
-
) -> list[TaskIns]:
|
50
|
+
def get_task_ins(self, node_id: int, limit: Optional[int]) -> list[TaskIns]:
|
57
51
|
"""Get TaskIns optionally filtered by node_id.
|
58
52
|
|
59
53
|
Usually, the Fleet API calls this for Nodes planning to work on one or more
|
@@ -61,15 +55,11 @@ class LinkState(abc.ABC): # pylint: disable=R0904
|
|
61
55
|
|
62
56
|
Constraints
|
63
57
|
-----------
|
64
|
-
|
58
|
+
Retrieve all TaskIns where
|
65
59
|
|
66
60
|
1. the `task_ins.task.consumer.node_id` equals `node_id` AND
|
67
|
-
2. the `task_ins.task.
|
68
|
-
3. the `task_ins.task.delivered_at` equals `""`.
|
61
|
+
2. the `task_ins.task.delivered_at` equals `""`.
|
69
62
|
|
70
|
-
If `node_id` is `None`, retrieve all TaskIns where the
|
71
|
-
`task_ins.task.consumer.node_id` equals `0` and
|
72
|
-
`task_ins.task.consumer.anonymous` is set to `True`.
|
73
63
|
|
74
64
|
If `delivered_at` MUST BE set (not `""`) otherwise the TaskIns MUST not be in
|
75
65
|
the result.
|
@@ -89,11 +79,8 @@ class LinkState(abc.ABC): # pylint: disable=R0904
|
|
89
79
|
|
90
80
|
Constraints
|
91
81
|
-----------
|
92
|
-
If `task_res.task.consumer.anonymous` is `True`, then
|
93
|
-
`task_res.task.consumer.node_id` MUST NOT be set (equal 0).
|
94
82
|
|
95
|
-
|
96
|
-
`task_res.task.consumer.node_id` MUST be set (not 0)
|
83
|
+
`task_res.task.consumer.node_id` MUST be set (not constant.DRIVER_NODE_ID)
|
97
84
|
|
98
85
|
If `task_res.run_id` is invalid, then
|
99
86
|
storing the `task_res` MUST fail.
|
@@ -31,6 +31,7 @@ from flwr.common.constant import (
|
|
31
31
|
MESSAGE_TTL_TOLERANCE,
|
32
32
|
NODE_ID_NUM_BYTES,
|
33
33
|
RUN_ID_NUM_BYTES,
|
34
|
+
SUPERLINK_NODE_ID,
|
34
35
|
Status,
|
35
36
|
)
|
36
37
|
from flwr.common.record import ConfigsRecord
|
@@ -128,9 +129,7 @@ CREATE TABLE IF NOT EXISTS task_ins(
|
|
128
129
|
task_id TEXT UNIQUE,
|
129
130
|
group_id TEXT,
|
130
131
|
run_id INTEGER,
|
131
|
-
producer_anonymous BOOLEAN,
|
132
132
|
producer_node_id INTEGER,
|
133
|
-
consumer_anonymous BOOLEAN,
|
134
133
|
consumer_node_id INTEGER,
|
135
134
|
created_at REAL,
|
136
135
|
delivered_at TEXT,
|
@@ -148,9 +147,7 @@ CREATE TABLE IF NOT EXISTS task_res(
|
|
148
147
|
task_id TEXT UNIQUE,
|
149
148
|
group_id TEXT,
|
150
149
|
run_id INTEGER,
|
151
|
-
producer_anonymous BOOLEAN,
|
152
150
|
producer_node_id INTEGER,
|
153
|
-
consumer_anonymous BOOLEAN,
|
154
151
|
consumer_node_id INTEGER,
|
155
152
|
created_at REAL,
|
156
153
|
delivered_at TEXT,
|
@@ -263,11 +260,8 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
263
260
|
|
264
261
|
Constraints
|
265
262
|
-----------
|
266
|
-
If `task_ins.task.consumer.anonymous` is `True`, then
|
267
|
-
`task_ins.task.consumer.node_id` MUST NOT be set (equal 0).
|
268
263
|
|
269
|
-
|
270
|
-
`task_ins.task.consumer.node_id` MUST be set (not 0)
|
264
|
+
`task_ins.task.consumer.node_id` MUST be set (not constant.DRIVER_NODE_ID)
|
271
265
|
"""
|
272
266
|
# Validate task
|
273
267
|
errors = validate_task_ins_or_res(task_ins)
|
@@ -292,7 +286,7 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
292
286
|
log(ERROR, "Invalid run ID for TaskIns: %s", task_ins.run_id)
|
293
287
|
return None
|
294
288
|
# Validate source node ID
|
295
|
-
if task_ins.task.producer.node_id !=
|
289
|
+
if task_ins.task.producer.node_id != SUPERLINK_NODE_ID:
|
296
290
|
log(
|
297
291
|
ERROR,
|
298
292
|
"Invalid source node ID for TaskIns: %s",
|
@@ -301,14 +295,13 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
301
295
|
return None
|
302
296
|
# Validate destination node ID
|
303
297
|
query = "SELECT node_id FROM node WHERE node_id = ?;"
|
304
|
-
if not
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
return None
|
298
|
+
if not self.query(query, (data[0]["consumer_node_id"],)):
|
299
|
+
log(
|
300
|
+
ERROR,
|
301
|
+
"Invalid destination node ID for TaskIns: %s",
|
302
|
+
task_ins.task.consumer.node_id,
|
303
|
+
)
|
304
|
+
return None
|
312
305
|
|
313
306
|
columns = ", ".join([f":{key}" for key in data[0]])
|
314
307
|
query = f"INSERT INTO task_ins VALUES({columns});"
|
@@ -319,25 +312,18 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
319
312
|
|
320
313
|
return task_id
|
321
314
|
|
322
|
-
def get_task_ins(
|
323
|
-
|
324
|
-
) -> list[TaskIns]:
|
325
|
-
"""Get undelivered TaskIns for one node (either anonymous or with ID).
|
315
|
+
def get_task_ins(self, node_id: int, limit: Optional[int]) -> list[TaskIns]:
|
316
|
+
"""Get undelivered TaskIns for one node.
|
326
317
|
|
327
318
|
Usually, the Fleet API calls this for Nodes planning to work on one or more
|
328
319
|
TaskIns.
|
329
320
|
|
330
321
|
Constraints
|
331
322
|
-----------
|
332
|
-
|
323
|
+
Retrieve all TaskIns where
|
333
324
|
|
334
325
|
1. the `task_ins.task.consumer.node_id` equals `node_id` AND
|
335
|
-
2. the `task_ins.task.
|
336
|
-
3. the `task_ins.task.delivered_at` equals `""`.
|
337
|
-
|
338
|
-
If `node_id` is `None`, retrieve all TaskIns where the
|
339
|
-
`task_ins.task.consumer.node_id` equals `0` and
|
340
|
-
`task_ins.task.consumer.anonymous` is set to `True`.
|
326
|
+
2. the `task_ins.task.delivered_at` equals `""`.
|
341
327
|
|
342
328
|
`delivered_at` MUST BE set (i.e., not `""`) otherwise the TaskIns MUST not be in
|
343
329
|
the result.
|
@@ -348,38 +334,23 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
348
334
|
if limit is not None and limit < 1:
|
349
335
|
raise AssertionError("`limit` must be >= 1")
|
350
336
|
|
351
|
-
if node_id ==
|
352
|
-
msg =
|
353
|
-
"`node_id` must be >= 1"
|
354
|
-
"\n\n For requesting anonymous tasks use `node_id` equal `None`"
|
355
|
-
)
|
337
|
+
if node_id == SUPERLINK_NODE_ID:
|
338
|
+
msg = f"`node_id` must be != {SUPERLINK_NODE_ID}"
|
356
339
|
raise AssertionError(msg)
|
357
340
|
|
358
341
|
data: dict[str, Union[str, int]] = {}
|
359
342
|
|
360
|
-
|
361
|
-
|
362
|
-
query = """
|
363
|
-
SELECT task_id
|
364
|
-
FROM task_ins
|
365
|
-
WHERE consumer_anonymous == 1
|
366
|
-
AND consumer_node_id == 0
|
367
|
-
AND delivered_at = ""
|
368
|
-
AND (created_at + ttl) > CAST(strftime('%s', 'now') AS REAL)
|
369
|
-
"""
|
370
|
-
else:
|
371
|
-
# Convert the uint64 value to sint64 for SQLite
|
372
|
-
data["node_id"] = convert_uint64_to_sint64(node_id)
|
343
|
+
# Convert the uint64 value to sint64 for SQLite
|
344
|
+
data["node_id"] = convert_uint64_to_sint64(node_id)
|
373
345
|
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
"""
|
346
|
+
# Retrieve all TaskIns for node_id
|
347
|
+
query = """
|
348
|
+
SELECT task_id
|
349
|
+
FROM task_ins
|
350
|
+
WHERE consumer_node_id == :node_id
|
351
|
+
AND delivered_at = ""
|
352
|
+
AND (created_at + ttl) > CAST(strftime('%s', 'now') AS REAL)
|
353
|
+
"""
|
383
354
|
|
384
355
|
if limit is not None:
|
385
356
|
query += " LIMIT :limit"
|
@@ -429,11 +400,7 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
429
400
|
|
430
401
|
Constraints
|
431
402
|
-----------
|
432
|
-
|
433
|
-
`task_res.task.consumer.node_id` MUST NOT be set (equal 0).
|
434
|
-
|
435
|
-
If `task_res.task.consumer.anonymous` is `False`, then
|
436
|
-
`task_res.task.consumer.node_id` MUST be set (not 0)
|
403
|
+
`task_res.task.consumer.node_id` MUST be set (not constant.DRIVER_NODE_ID)
|
437
404
|
"""
|
438
405
|
# Validate task
|
439
406
|
errors = validate_task_ins_or_res(task_res)
|
@@ -459,7 +426,6 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
459
426
|
if (
|
460
427
|
task_ins
|
461
428
|
and task_res
|
462
|
-
and not (task_ins["consumer_anonymous"] or task_res.task.producer.anonymous)
|
463
429
|
and convert_sint64_to_uint64(task_ins["consumer_node_id"])
|
464
430
|
!= task_res.task.producer.node_id
|
465
431
|
):
|
@@ -638,7 +604,9 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
638
604
|
def create_node(self, ping_interval: float) -> int:
|
639
605
|
"""Create, store in the link state, and return `node_id`."""
|
640
606
|
# Sample a random uint64 as node_id
|
641
|
-
uint64_node_id = generate_rand_int_from_bytes(
|
607
|
+
uint64_node_id = generate_rand_int_from_bytes(
|
608
|
+
NODE_ID_NUM_BYTES, exclude=[SUPERLINK_NODE_ID, 0]
|
609
|
+
)
|
642
610
|
|
643
611
|
# Convert the uint64 value to sint64 for SQLite
|
644
612
|
sint64_node_id = convert_uint64_to_sint64(uint64_node_id)
|
@@ -1126,9 +1094,7 @@ def task_ins_to_dict(task_msg: TaskIns) -> dict[str, Any]:
|
|
1126
1094
|
"task_id": task_msg.task_id,
|
1127
1095
|
"group_id": task_msg.group_id,
|
1128
1096
|
"run_id": task_msg.run_id,
|
1129
|
-
"producer_anonymous": task_msg.task.producer.anonymous,
|
1130
1097
|
"producer_node_id": task_msg.task.producer.node_id,
|
1131
|
-
"consumer_anonymous": task_msg.task.consumer.anonymous,
|
1132
1098
|
"consumer_node_id": task_msg.task.consumer.node_id,
|
1133
1099
|
"created_at": task_msg.task.created_at,
|
1134
1100
|
"delivered_at": task_msg.task.delivered_at,
|
@@ -1147,9 +1113,7 @@ def task_res_to_dict(task_msg: TaskRes) -> dict[str, Any]:
|
|
1147
1113
|
"task_id": task_msg.task_id,
|
1148
1114
|
"group_id": task_msg.group_id,
|
1149
1115
|
"run_id": task_msg.run_id,
|
1150
|
-
"producer_anonymous": task_msg.task.producer.anonymous,
|
1151
1116
|
"producer_node_id": task_msg.task.producer.node_id,
|
1152
|
-
"consumer_anonymous": task_msg.task.consumer.anonymous,
|
1153
1117
|
"consumer_node_id": task_msg.task.consumer.node_id,
|
1154
1118
|
"created_at": task_msg.task.created_at,
|
1155
1119
|
"delivered_at": task_msg.task.delivered_at,
|
@@ -1174,11 +1138,9 @@ def dict_to_task_ins(task_dict: dict[str, Any]) -> TaskIns:
|
|
1174
1138
|
task=Task(
|
1175
1139
|
producer=Node(
|
1176
1140
|
node_id=task_dict["producer_node_id"],
|
1177
|
-
anonymous=task_dict["producer_anonymous"],
|
1178
1141
|
),
|
1179
1142
|
consumer=Node(
|
1180
1143
|
node_id=task_dict["consumer_node_id"],
|
1181
|
-
anonymous=task_dict["consumer_anonymous"],
|
1182
1144
|
),
|
1183
1145
|
created_at=task_dict["created_at"],
|
1184
1146
|
delivered_at=task_dict["delivered_at"],
|
@@ -1204,11 +1166,9 @@ def dict_to_task_res(task_dict: dict[str, Any]) -> TaskRes:
|
|
1204
1166
|
task=Task(
|
1205
1167
|
producer=Node(
|
1206
1168
|
node_id=task_dict["producer_node_id"],
|
1207
|
-
anonymous=task_dict["producer_anonymous"],
|
1208
1169
|
),
|
1209
1170
|
consumer=Node(
|
1210
1171
|
node_id=task_dict["consumer_node_id"],
|
1211
|
-
anonymous=task_dict["consumer_anonymous"],
|
1212
1172
|
),
|
1213
1173
|
created_at=task_dict["created_at"],
|
1214
1174
|
delivered_at=task_dict["delivered_at"],
|
@@ -21,7 +21,7 @@ from typing import Optional, Union
|
|
21
21
|
from uuid import UUID, uuid4
|
22
22
|
|
23
23
|
from flwr.common import ConfigsRecord, Context, log, now, serde
|
24
|
-
from flwr.common.constant import ErrorCode, Status, SubStatus
|
24
|
+
from flwr.common.constant import SUPERLINK_NODE_ID, ErrorCode, Status, SubStatus
|
25
25
|
from flwr.common.typing import RunStatus
|
26
26
|
|
27
27
|
# pylint: disable=E0611
|
@@ -60,9 +60,19 @@ REPLY_MESSAGE_UNAVAILABLE_ERROR_REASON = (
|
|
60
60
|
)
|
61
61
|
|
62
62
|
|
63
|
-
def generate_rand_int_from_bytes(
|
64
|
-
|
65
|
-
|
63
|
+
def generate_rand_int_from_bytes(
|
64
|
+
num_bytes: int, exclude: Optional[list[int]] = None
|
65
|
+
) -> int:
|
66
|
+
"""Generate a random unsigned integer from `num_bytes` bytes.
|
67
|
+
|
68
|
+
If `exclude` is set, this function guarantees such number is not returned.
|
69
|
+
"""
|
70
|
+
num = int.from_bytes(urandom(num_bytes), "little", signed=False)
|
71
|
+
|
72
|
+
if exclude:
|
73
|
+
while num in exclude:
|
74
|
+
num = int.from_bytes(urandom(num_bytes), "little", signed=False)
|
75
|
+
return num
|
66
76
|
|
67
77
|
|
68
78
|
def convert_uint64_to_sint64(u: int) -> int:
|
@@ -246,8 +256,8 @@ def create_taskres_for_unavailable_taskins(taskins_id: Union[str, UUID]) -> Task
|
|
246
256
|
run_id=0, # Unknown run ID
|
247
257
|
task=Task(
|
248
258
|
# This function is only called by SuperLink, and thus it's the producer.
|
249
|
-
producer=Node(node_id=
|
250
|
-
consumer=Node(node_id=
|
259
|
+
producer=Node(node_id=SUPERLINK_NODE_ID),
|
260
|
+
consumer=Node(node_id=SUPERLINK_NODE_ID),
|
251
261
|
created_at=current_time,
|
252
262
|
ttl=0,
|
253
263
|
ancestry=[str(taskins_id)],
|
@@ -285,8 +295,8 @@ def create_taskres_for_unavailable_taskres(ref_taskins: TaskIns) -> TaskRes:
|
|
285
295
|
run_id=ref_taskins.run_id,
|
286
296
|
task=Task(
|
287
297
|
# This function is only called by SuperLink, and thus it's the producer.
|
288
|
-
producer=Node(node_id=
|
289
|
-
consumer=Node(node_id=
|
298
|
+
producer=Node(node_id=SUPERLINK_NODE_ID),
|
299
|
+
consumer=Node(node_id=SUPERLINK_NODE_ID),
|
290
300
|
created_at=current_time,
|
291
301
|
ttl=ttl,
|
292
302
|
ancestry=[ref_taskins.task_id],
|
flwr/server/utils/validator.py
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
import time
|
19
19
|
from typing import Union
|
20
20
|
|
21
|
+
from flwr.common.constant import SUPERLINK_NODE_ID
|
21
22
|
from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611
|
22
23
|
|
23
24
|
|
@@ -58,24 +59,14 @@ def validate_task_ins_or_res(tasks_ins_res: Union[TaskIns, TaskRes]) -> list[str
|
|
58
59
|
# Task producer
|
59
60
|
if not tasks_ins_res.task.HasField("producer"):
|
60
61
|
validation_errors.append("`producer` does not set field `producer`")
|
61
|
-
if tasks_ins_res.task.producer.node_id !=
|
62
|
-
validation_errors.append("`producer.node_id` is not
|
63
|
-
if not tasks_ins_res.task.producer.anonymous:
|
64
|
-
validation_errors.append("`producer` is not anonymous")
|
62
|
+
if tasks_ins_res.task.producer.node_id != SUPERLINK_NODE_ID:
|
63
|
+
validation_errors.append(f"`producer.node_id` is not {SUPERLINK_NODE_ID}")
|
65
64
|
|
66
65
|
# Task consumer
|
67
66
|
if not tasks_ins_res.task.HasField("consumer"):
|
68
67
|
validation_errors.append("`consumer` does not set field `consumer`")
|
69
|
-
if
|
70
|
-
|
71
|
-
and tasks_ins_res.task.consumer.node_id != 0
|
72
|
-
):
|
73
|
-
validation_errors.append("anonymous consumers MUST NOT set a `node_id`")
|
74
|
-
if (
|
75
|
-
not tasks_ins_res.task.consumer.anonymous
|
76
|
-
and tasks_ins_res.task.consumer.node_id == 0
|
77
|
-
):
|
78
|
-
validation_errors.append("non-anonymous consumer MUST provide a `node_id`")
|
68
|
+
if tasks_ins_res.task.consumer.node_id == SUPERLINK_NODE_ID:
|
69
|
+
validation_errors.append("consumer MUST provide a valid `node_id`")
|
79
70
|
|
80
71
|
# Content check
|
81
72
|
if tasks_ins_res.task.task_type == "":
|
@@ -95,30 +86,14 @@ def validate_task_ins_or_res(tasks_ins_res: Union[TaskIns, TaskRes]) -> list[str
|
|
95
86
|
# Task producer
|
96
87
|
if not tasks_ins_res.task.HasField("producer"):
|
97
88
|
validation_errors.append("`producer` does not set field `producer`")
|
98
|
-
if
|
99
|
-
|
100
|
-
and tasks_ins_res.task.producer.node_id != 0
|
101
|
-
):
|
102
|
-
validation_errors.append("anonymous producers MUST NOT set a `node_id`")
|
103
|
-
if (
|
104
|
-
not tasks_ins_res.task.producer.anonymous
|
105
|
-
and tasks_ins_res.task.producer.node_id == 0
|
106
|
-
):
|
107
|
-
validation_errors.append("non-anonymous producer MUST provide a `node_id`")
|
89
|
+
if tasks_ins_res.task.producer.node_id == SUPERLINK_NODE_ID:
|
90
|
+
validation_errors.append("producer MUST provide a valid `node_id`")
|
108
91
|
|
109
92
|
# Task consumer
|
110
93
|
if not tasks_ins_res.task.HasField("consumer"):
|
111
94
|
validation_errors.append("`consumer` does not set field `consumer`")
|
112
|
-
if
|
113
|
-
|
114
|
-
and tasks_ins_res.task.consumer.node_id != 0
|
115
|
-
):
|
116
|
-
validation_errors.append("anonymous consumers MUST NOT set a `node_id`")
|
117
|
-
if (
|
118
|
-
not tasks_ins_res.task.consumer.anonymous
|
119
|
-
and tasks_ins_res.task.consumer.node_id == 0
|
120
|
-
):
|
121
|
-
validation_errors.append("non-anonymous consumer MUST provide a `node_id`")
|
95
|
+
if tasks_ins_res.task.consumer.node_id != SUPERLINK_NODE_ID:
|
96
|
+
validation_errors.append(f"consumer is not {SUPERLINK_NODE_ID}")
|
122
97
|
|
123
98
|
# Content check
|
124
99
|
if tasks_ins_res.task.task_type == "":
|
flwr/simulation/legacy_app.py
CHANGED
@@ -29,7 +29,7 @@ from ray.util.scheduling_strategies import NodeAffinitySchedulingStrategy
|
|
29
29
|
|
30
30
|
from flwr.client import ClientFnExt
|
31
31
|
from flwr.common import EventType, event
|
32
|
-
from flwr.common.constant import NODE_ID_NUM_BYTES
|
32
|
+
from flwr.common.constant import NODE_ID_NUM_BYTES, SUPERLINK_NODE_ID
|
33
33
|
from flwr.common.logger import (
|
34
34
|
log,
|
35
35
|
set_logger_propagation,
|
@@ -87,7 +87,9 @@ def _create_node_id_to_partition_mapping(
|
|
87
87
|
nodes_mapping: NodeToPartitionMapping = {} # {node-id; partition-id}
|
88
88
|
for i in range(num_clients):
|
89
89
|
while True:
|
90
|
-
node_id = generate_rand_int_from_bytes(
|
90
|
+
node_id = generate_rand_int_from_bytes(
|
91
|
+
NODE_ID_NUM_BYTES, exclude=[SUPERLINK_NODE_ID, 0]
|
92
|
+
)
|
91
93
|
if node_id not in nodes_mapping:
|
92
94
|
break
|
93
95
|
nodes_mapping[node_id] = i
|
{flwr_nightly-1.15.0.dev20250114.dist-info → flwr_nightly-1.15.0.dev20250116.dist-info}/RECORD
RENAMED
@@ -114,7 +114,7 @@ flwr/common/args.py,sha256=bCvtG0hhh_hVjl9NoWsY_g7kLMIN3jCN7B883HvZ7hg,6223
|
|
114
114
|
flwr/common/auth_plugin/__init__.py,sha256=1Y8Oj3iB49IHDu9tvDih1J74Ygu7k85V9s2A4WORPyA,887
|
115
115
|
flwr/common/auth_plugin/auth_plugin.py,sha256=p_3oDuKiHtMMLLCyEe_fuRi_g5GwRKb4HJCnBkVK74I,3840
|
116
116
|
flwr/common/config.py,sha256=vmPwtRu7JIoGCke03pJlsyrA6zTlN43flzQx-4AX1mE,8099
|
117
|
-
flwr/common/constant.py,sha256=
|
117
|
+
flwr/common/constant.py,sha256=VkjMN5TH5YbLwP42f74b4tcHVtSge2ZBfW8iKB1dR0A,6114
|
118
118
|
flwr/common/context.py,sha256=uJ-mnoC_8y_udEb3kAX-r8CPphNTWM72z1AlsvQEu54,2403
|
119
119
|
flwr/common/date.py,sha256=NHHpESce5wYqEwoDXf09gp9U9l_5Bmlh2BsOcwS-kDM,1554
|
120
120
|
flwr/common/differential_privacy.py,sha256=XwcJ3rWr8S8BZUocc76vLSJAXIf6OHnWkBV6-xlIRuw,6106
|
@@ -122,7 +122,7 @@ flwr/common/differential_privacy_constants.py,sha256=c7b7tqgvT7yMK0XN9ndiTBs4mQf
|
|
122
122
|
flwr/common/dp.py,sha256=vddkvyjV2FhRoN4VuU2LeAM1UBn7dQB8_W-Qdiveal8,1978
|
123
123
|
flwr/common/exit_handlers.py,sha256=MracJaBeoCOC7TaXK9zCJQxhrMSx9ZtczK237qvhBpU,2806
|
124
124
|
flwr/common/grpc.py,sha256=amBroQiRdRrczDAGbEZjaYsVoeH_52pyfyOvTSvIF_c,9362
|
125
|
-
flwr/common/logger.py,sha256=
|
125
|
+
flwr/common/logger.py,sha256=UPyI_98EDibqgf3epgWxFHxdXgYReSWtaKFf9Mj0hd0,12306
|
126
126
|
flwr/common/message.py,sha256=Zv4ID2BLQsbff0F03DI_MeFoHbSqVZAdDD9NcKYv6Zo,13832
|
127
127
|
flwr/common/object_ref.py,sha256=fIXf8aP5mG6Nuni7dvcKK5Di3zRfRWGs4ljvqIXplds,10115
|
128
128
|
flwr/common/parameter.py,sha256=-bFAUayToYDF50FZGrBC1hQYJCQDtB2bbr3ZuVLMtdE,2095
|
@@ -144,7 +144,7 @@ flwr/common/secure_aggregation/ndarrays_arithmetic.py,sha256=zvVAIrIyI6OSzGhpCi8
|
|
144
144
|
flwr/common/secure_aggregation/quantization.py,sha256=mC4uLf05zeONo8Ke-BY0Tj8UCMOS7VD93zHCzuv3MHU,2304
|
145
145
|
flwr/common/secure_aggregation/secaggplus_constants.py,sha256=9MF-oQh62uD7rt9VeNB-rHf2gBLd5GL3S9OejCxmILY,2183
|
146
146
|
flwr/common/secure_aggregation/secaggplus_utils.py,sha256=OgYd68YBRaHQYLc-YdExj9CSpwL58bVTaPrdHoAj2AE,3214
|
147
|
-
flwr/common/serde.py,sha256=
|
147
|
+
flwr/common/serde.py,sha256=iDVS5IXGKqEuzQAvnroH9c6KFEHxKFEWmkGP89PMOO0,31064
|
148
148
|
flwr/common/telemetry.py,sha256=APKVubU_zJNrE-M_rip6S6Fsu41DxY3tAjFWNOgTmC0,9086
|
149
149
|
flwr/common/typing.py,sha256=IMgs_7nDJWn8Eb7y16Hl4HC3imQV7_Hdla1IFs3B5u8,6382
|
150
150
|
flwr/common/version.py,sha256=aNSxLL49RKeLz8sPcZrsTEWtrAeQ0uxu6tjmfba4O60,1325
|
@@ -181,8 +181,8 @@ flwr/proto/message_pb2.py,sha256=5Aa7whiLywAL4sRnWpLuAu0gk0U2L7hc1sxHhBojFSk,318
|
|
181
181
|
flwr/proto/message_pb2.pyi,sha256=kAFVgSi8j6ZYzkCQ9MkbrpUtVKgZsTYVIoQmcMB6BX0,5735
|
182
182
|
flwr/proto/message_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
183
183
|
flwr/proto/message_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
|
184
|
-
flwr/proto/node_pb2.py,sha256=
|
185
|
-
flwr/proto/node_pb2.pyi,sha256=
|
184
|
+
flwr/proto/node_pb2.py,sha256=73fBFaYUGE6p0-1mTvR60l2q7bT8ArIua__PHCyWTis,1045
|
185
|
+
flwr/proto/node_pb2.pyi,sha256=CPMeIPzUeI5-Csw9sHktV9UBH4GbqiGuYzGQQKftm6Q,616
|
186
186
|
flwr/proto/node_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
187
187
|
flwr/proto/node_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
|
188
188
|
flwr/proto/recordset_pb2.py,sha256=XjEIDU-YlKSY59qNd0qXTFB4COvMHGiszQ5O1krJ1Ks,6367
|
@@ -216,14 +216,14 @@ flwr/server/client_manager.py,sha256=7Ese0tgrH-i-ms363feYZJKwB8gWnXSmg_hYF2Bju4U
|
|
216
216
|
flwr/server/client_proxy.py,sha256=4G-oTwhb45sfWLx2uZdcXD98IZwdTS6F88xe3akCdUg,2399
|
217
217
|
flwr/server/compat/__init__.py,sha256=VxnJtJyOjNFQXMNi9hIuzNlZM5n0Hj1p3aq_Pm2udw4,892
|
218
218
|
flwr/server/compat/app.py,sha256=5vkHHm_h-4cMthvWD1GJo1ZW3eihytjGgvsgfXUK9gA,3298
|
219
|
-
flwr/server/compat/app_utils.py,sha256=
|
220
|
-
flwr/server/compat/driver_client_proxy.py,sha256=
|
219
|
+
flwr/server/compat/app_utils.py,sha256=Kggcoi5vQCBQmYvXBBUxhtDUcIwFiQyfphkHp2K1WxM,3546
|
220
|
+
flwr/server/compat/driver_client_proxy.py,sha256=jMmrfqSm4-qW0jOCTpHhN9Kw0ohfMwsyKU9buBzrfG0,4958
|
221
221
|
flwr/server/compat/legacy_context.py,sha256=wBzBcfV6YO6IQGriM_FdJ5XZfiBBEEJdS_OdAiF47dY,1804
|
222
222
|
flwr/server/criterion.py,sha256=ypbAexbztzGUxNen9RCHF91QeqiEQix4t4Ih3E-42MM,1061
|
223
223
|
flwr/server/driver/__init__.py,sha256=bikRv6CjTwSvYh7tf10gziU5o2YotOWhhftz2tr3KDc,886
|
224
224
|
flwr/server/driver/driver.py,sha256=u_fMfqLYTroTafGCNwKPHI4lttRL-Z5CqeT3_FHSq-Q,5701
|
225
|
-
flwr/server/driver/grpc_driver.py,sha256=
|
226
|
-
flwr/server/driver/inmemory_driver.py,sha256=
|
225
|
+
flwr/server/driver/grpc_driver.py,sha256=jJBQOlbPXT-qn1MzjReyFGFPTA6WpiJQoiXISrkAVsc,9668
|
226
|
+
flwr/server/driver/inmemory_driver.py,sha256=b1U1PrB_Vpn--vav8SX-sn0THD9BTlV9UFIpuWTWLro,6665
|
227
227
|
flwr/server/history.py,sha256=qSb5_pPTrwofpSYGsZWzMPkl_4uJ4mJFWesxXDrEvDU,5026
|
228
228
|
flwr/server/run_serverapp.py,sha256=vIPhvJx0i5sEZO4IKM6ruCXmx4ncat76rh0B4KhdhhM,2446
|
229
229
|
flwr/server/server.py,sha256=1ZsFEptmAV-L2vP2etNC9Ed5CLSxpuKzUFkAPQ4l5Xc,17893
|
@@ -259,7 +259,7 @@ flwr/server/strategy/strategy.py,sha256=cXapkD5uDrt5C-RbmWDn9FLoap3Q41i7GKvbmfbC
|
|
259
259
|
flwr/server/superlink/__init__.py,sha256=8tHYCfodUlRD8PCP9fHgvu8cz5N31A2QoRVL0jDJ15E,707
|
260
260
|
flwr/server/superlink/driver/__init__.py,sha256=5soEK5QSvxNjmJQ-CGTWROc4alSAeU0e9Ad9RDhsd3E,717
|
261
261
|
flwr/server/superlink/driver/serverappio_grpc.py,sha256=UzHwo6qYZMeOhr7nn1iZbcyDSmwvnq_kpYH0mEAndW0,2173
|
262
|
-
flwr/server/superlink/driver/serverappio_servicer.py,sha256=
|
262
|
+
flwr/server/superlink/driver/serverappio_servicer.py,sha256=ww2pCqxL31F1noGIBBjT-3GUIzINYQrPExd-lm44v4k,12708
|
263
263
|
flwr/server/superlink/ffs/__init__.py,sha256=FAY-zShcfPmOxosok2QyT6hTNMNctG8cH9s_nIl8jkI,840
|
264
264
|
flwr/server/superlink/ffs/disk_ffs.py,sha256=n_Ah0sQwXGVQ9wj5965nLjdkQQbpoHCljjXKFnwftsU,3297
|
265
265
|
flwr/server/superlink/ffs/ffs.py,sha256=qLI1UfosJugu2BKOJWqHIhafTm-YiuKqGf3OGWPH0NM,2395
|
@@ -274,9 +274,9 @@ flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py,sha256=h3EhqgelegVC4E
|
|
274
274
|
flwr/server/superlink/fleet/grpc_bidi/grpc_server.py,sha256=mxPxyEF0IW0vV41Bqk1zfKOdRDEvXPwzJyMiRMg7nTI,5173
|
275
275
|
flwr/server/superlink/fleet/grpc_rere/__init__.py,sha256=j2hyC342am-_Hgp1g80Y3fGDzfTI6n8QOOn2PyWf4eg,758
|
276
276
|
flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py,sha256=EVx3rHX8WjUXVX7Svki5ihsA1aIZkpOMLv0aQv9Rjjw,6656
|
277
|
-
flwr/server/superlink/fleet/grpc_rere/server_interceptor.py,sha256=
|
277
|
+
flwr/server/superlink/fleet/grpc_rere/server_interceptor.py,sha256=NXih_xTErEp13CaeQKKPoM38vcXAQl7mXZgps4no9l4,8308
|
278
278
|
flwr/server/superlink/fleet/message_handler/__init__.py,sha256=h8oLD7uo5lKICPy0rRdKRjTYe62u8PKkT_fA4xF5JPA,731
|
279
|
-
flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=
|
279
|
+
flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=5QRqE0w8Kb-M2cEiPNIdKkPc17CEGHvNYjMpGOfgOlE,6886
|
280
280
|
flwr/server/superlink/fleet/rest_rere/__init__.py,sha256=5jbYbAn75sGv-gBwOPDySE0kz96F6dTYLeMrGqNi4lM,735
|
281
281
|
flwr/server/superlink/fleet/rest_rere/rest_api.py,sha256=zC9WsbO48GSEmtaeE9s5DBtakt7VNeW0nkXBQeCM22c,7673
|
282
282
|
flwr/server/superlink/fleet/vce/__init__.py,sha256=TZJsKTpYO_djv2EXx9Ji62I8TA0JiZF8jvRyJRZkAes,784
|
@@ -285,11 +285,11 @@ flwr/server/superlink/fleet/vce/backend/backend.py,sha256=LBAQxnbfPAphVOVIvYMj0Q
|
|
285
285
|
flwr/server/superlink/fleet/vce/backend/raybackend.py,sha256=jsUkFEVQTnrucK1jNQ_cUM8YwL7W4MQNA1GAf8ibRdg,7156
|
286
286
|
flwr/server/superlink/fleet/vce/vce_api.py,sha256=WTnUILr1OHS8LfjXQUA3FyWJYdJgdqpFAybyJUD-1Xo,13025
|
287
287
|
flwr/server/superlink/linkstate/__init__.py,sha256=v-2JyJlCB3qyhMNwMjmcNVOq4rkooqFU0LHH8Zo1jls,1064
|
288
|
-
flwr/server/superlink/linkstate/in_memory_linkstate.py,sha256=
|
289
|
-
flwr/server/superlink/linkstate/linkstate.py,sha256=
|
288
|
+
flwr/server/superlink/linkstate/in_memory_linkstate.py,sha256=v02iAvIlUqNnHodj_nERZh5lE5s-V3SxF3OiuoCnMXE,21561
|
289
|
+
flwr/server/superlink/linkstate/linkstate.py,sha256=oHqOOgmsbi7V8zc0pbZeypcvXEtPXRckrp6cdGG52Qo,12694
|
290
290
|
flwr/server/superlink/linkstate/linkstate_factory.py,sha256=ISSMjDlwuN7swxjOeYlTNpI_kuZ8PGkMcJnf1dbhUSE,2069
|
291
|
-
flwr/server/superlink/linkstate/sqlite_linkstate.py,sha256=
|
292
|
-
flwr/server/superlink/linkstate/utils.py,sha256=
|
291
|
+
flwr/server/superlink/linkstate/sqlite_linkstate.py,sha256=zk3V63_sgRqKOpXXX02TfqLZpHpcxUHrVAGfxPq0yvA,42101
|
292
|
+
flwr/server/superlink/linkstate/utils.py,sha256=EpRehwI4NeEW3oINICPWP9STK49N0aszd5s5jtle7DQ,13602
|
293
293
|
flwr/server/superlink/simulation/__init__.py,sha256=mg-oapC9dkzEfjXPQFior5lpWj4g9kwbLovptyYM_g0,718
|
294
294
|
flwr/server/superlink/simulation/simulationio_grpc.py,sha256=8aUrZZLdvprKUfLLqFID4aItus9beU6m1qLQYIPB7k0,2224
|
295
295
|
flwr/server/superlink/simulation/simulationio_servicer.py,sha256=J_TmdqM-Bxgp-iPEI3tvCuBpykw1UX0FouMQalEYAF4,6907
|
@@ -297,7 +297,7 @@ flwr/server/superlink/utils.py,sha256=KVb3K_g2vYfu9TnftcN0ewmev133WZcjuEePMm8d7G
|
|
297
297
|
flwr/server/typing.py,sha256=5kaRLZuxTEse9A0g7aVna2VhYxU3wTq1f3d3mtw7kXs,1019
|
298
298
|
flwr/server/utils/__init__.py,sha256=pltsPHJoXmUIr3utjwwYxu7_ZAGy5u4MVHzv9iA5Un8,908
|
299
299
|
flwr/server/utils/tensorboard.py,sha256=gEBD8w_5uaIfp5aw5RYH66lYZpd_SfkObHQ7eDd9MUk,5466
|
300
|
-
flwr/server/utils/validator.py,sha256=
|
300
|
+
flwr/server/utils/validator.py,sha256=SpoKWDlVfFI5aJr2jXWfwJjBc5OZUMMacQbOxj6wPdI,4603
|
301
301
|
flwr/server/workflow/__init__.py,sha256=SXY0XkwbkezFBxxrFB5hKUtmtAgnYISBkPouR1V71ss,902
|
302
302
|
flwr/server/workflow/constant.py,sha256=q4DLdR8Krlxuewq2AQjwTL75hphxE5ODNz4AhViHMXk,1082
|
303
303
|
flwr/server/workflow/default_workflows.py,sha256=UMC9JgdomKwxql5G0OV4AeRXWI-bMClaLAOn5OrZMnw,14073
|
@@ -306,7 +306,7 @@ flwr/server/workflow/secure_aggregation/secagg_workflow.py,sha256=l2IdMdJjs1bgHs
|
|
306
306
|
flwr/server/workflow/secure_aggregation/secaggplus_workflow.py,sha256=rfn2etO1nb7u-1oRl-H9q3enJZz3shMINZaBB7rPsC4,29671
|
307
307
|
flwr/simulation/__init__.py,sha256=5UcDVJNjFoSwWqHbGM1hKfTTUUNdwAtuoNvNrfvdkUY,1556
|
308
308
|
flwr/simulation/app.py,sha256=cQgIJJujFUpBCcydxgakNygibf3Iww6OAWRo7Sq6y8w,9754
|
309
|
-
flwr/simulation/legacy_app.py,sha256=
|
309
|
+
flwr/simulation/legacy_app.py,sha256=qpZI4Vvzr5TyWSLTRrMP-jN4rH2C25JI9nVSSjhFwSQ,15861
|
310
310
|
flwr/simulation/ray_transport/__init__.py,sha256=wzcEEwUUlulnXsg6raCA1nGpP3LlAQDtJ8zNkCXcVbA,734
|
311
311
|
flwr/simulation/ray_transport/ray_actor.py,sha256=k11yoAPQzFGQU-KnCCP0ZrfPPdUPXXrBe-1DKM5VdW4,18997
|
312
312
|
flwr/simulation/ray_transport/ray_client_proxy.py,sha256=2vjOKoom3B74C6XU-jC3N6DwYmsLdB-lmkHZ_Xrv96o,7367
|
@@ -321,8 +321,8 @@ flwr/superexec/exec_servicer.py,sha256=X10ILT-AoGMrB3IgI2mBe9i-QcIVUAl9bucuqVOPY
|
|
321
321
|
flwr/superexec/exec_user_auth_interceptor.py,sha256=K06OU-l4LnYhTDg071hGJuOaQWEJbZsYi5qxUmmtiG0,3704
|
322
322
|
flwr/superexec/executor.py,sha256=_B55WW2TD1fBINpabSSDRenVHXYmvlfhv-k8hJKU4lQ,3115
|
323
323
|
flwr/superexec/simulation.py,sha256=WQDon15oqpMopAZnwRZoTICYCfHqtkvFSqiTQ2hLD_g,4088
|
324
|
-
flwr_nightly-1.15.0.
|
325
|
-
flwr_nightly-1.15.0.
|
326
|
-
flwr_nightly-1.15.0.
|
327
|
-
flwr_nightly-1.15.0.
|
328
|
-
flwr_nightly-1.15.0.
|
324
|
+
flwr_nightly-1.15.0.dev20250116.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
325
|
+
flwr_nightly-1.15.0.dev20250116.dist-info/METADATA,sha256=n236sjdcXowCNu6E_nqQei67A0H7zJoykVnvjhDA8O4,15882
|
326
|
+
flwr_nightly-1.15.0.dev20250116.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
327
|
+
flwr_nightly-1.15.0.dev20250116.dist-info/entry_points.txt,sha256=JlNxX3qhaV18_2yj5a3kJW1ESxm31cal9iS_N_pf1Rk,538
|
328
|
+
flwr_nightly-1.15.0.dev20250116.dist-info/RECORD,,
|
{flwr_nightly-1.15.0.dev20250114.dist-info → flwr_nightly-1.15.0.dev20250116.dist-info}/LICENSE
RENAMED
File without changes
|
{flwr_nightly-1.15.0.dev20250114.dist-info → flwr_nightly-1.15.0.dev20250116.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|