flwr-nightly 1.23.0.dev20251029__py3-none-any.whl → 1.23.0.dev20251031__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/new.py +187 -35
- flwr/client/grpc_adapter_client/connection.py +4 -6
- flwr/client/grpc_rere_client/connection.py +47 -24
- flwr/client/grpc_rere_client/grpc_adapter.py +0 -16
- flwr/client/rest_client/connection.py +70 -33
- flwr/common/constant.py +3 -1
- flwr/proto/fleet_pb2.py +31 -39
- flwr/proto/fleet_pb2.pyi +0 -48
- flwr/proto/fleet_pb2_grpc.py +0 -66
- flwr/proto/fleet_pb2_grpc.pyi +0 -20
- flwr/server/app.py +30 -16
- flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +0 -6
- flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +92 -124
- flwr/server/superlink/fleet/grpc_rere/node_auth_server_interceptor.py +14 -5
- flwr/server/superlink/fleet/message_handler/message_handler.py +66 -23
- flwr/server/superlink/fleet/rest_rere/rest_api.py +20 -28
- flwr/server/superlink/fleet/vce/vce_api.py +3 -3
- flwr/server/superlink/linkstate/in_memory_linkstate.py +4 -3
- flwr/server/superlink/linkstate/sqlite_linkstate.py +4 -4
- flwr/supercore/constant.py +4 -0
- flwr/supernode/cli/flower_supernode.py +7 -0
- flwr/supernode/start_client_internal.py +3 -9
- {flwr_nightly-1.23.0.dev20251029.dist-info → flwr_nightly-1.23.0.dev20251031.dist-info}/METADATA +1 -1
- {flwr_nightly-1.23.0.dev20251029.dist-info → flwr_nightly-1.23.0.dev20251031.dist-info}/RECORD +26 -26
- {flwr_nightly-1.23.0.dev20251029.dist-info → flwr_nightly-1.23.0.dev20251031.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.23.0.dev20251029.dist-info → flwr_nightly-1.23.0.dev20251031.dist-info}/entry_points.txt +0 -0
|
@@ -29,7 +29,10 @@ from flwr.common.constant import (
|
|
|
29
29
|
TIMESTAMP_HEADER,
|
|
30
30
|
TIMESTAMP_TOLERANCE,
|
|
31
31
|
)
|
|
32
|
-
from flwr.proto.fleet_pb2 import
|
|
32
|
+
from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
|
|
33
|
+
ActivateNodeRequest,
|
|
34
|
+
RegisterNodeFleetRequest,
|
|
35
|
+
)
|
|
33
36
|
from flwr.server.superlink.linkstate import LinkStateFactory
|
|
34
37
|
from flwr.supercore.primitives.asymmetric import bytes_to_public_key, verify_signature
|
|
35
38
|
|
|
@@ -110,15 +113,21 @@ class NodeAuthServerInterceptor(grpc.ServerInterceptor): # type: ignore
|
|
|
110
113
|
request: GrpcMessage,
|
|
111
114
|
context: grpc.ServicerContext,
|
|
112
115
|
) -> GrpcMessage:
|
|
116
|
+
# Note: This function runs in a different thread
|
|
117
|
+
# than the `intercept_service` function.
|
|
118
|
+
|
|
113
119
|
# Retrieve the public key
|
|
114
|
-
if isinstance(request,
|
|
120
|
+
if isinstance(request, (RegisterNodeFleetRequest, ActivateNodeRequest)):
|
|
115
121
|
actual_public_key = request.public_key
|
|
116
122
|
else:
|
|
117
|
-
|
|
118
|
-
|
|
123
|
+
if hasattr(request, "node"):
|
|
124
|
+
node_id = request.node.node_id
|
|
125
|
+
else:
|
|
126
|
+
node_id = request.node_id # type: ignore[attr-defined]
|
|
119
127
|
actual_public_key = self.state_factory.state().get_node_public_key(
|
|
120
|
-
|
|
128
|
+
node_id
|
|
121
129
|
)
|
|
130
|
+
|
|
122
131
|
# Verify the public key
|
|
123
132
|
if actual_public_key != expected_public_key:
|
|
124
133
|
context.abort(grpc.StatusCode.UNAUTHENTICATED, "Invalid node ID")
|
|
@@ -18,7 +18,12 @@ from logging import ERROR
|
|
|
18
18
|
from typing import Optional
|
|
19
19
|
|
|
20
20
|
from flwr.common import Message, log
|
|
21
|
-
from flwr.common.constant import
|
|
21
|
+
from flwr.common.constant import (
|
|
22
|
+
HEARTBEAT_MAX_INTERVAL,
|
|
23
|
+
HEARTBEAT_MIN_INTERVAL,
|
|
24
|
+
NOOP_FLWR_AID,
|
|
25
|
+
Status,
|
|
26
|
+
)
|
|
22
27
|
from flwr.common.inflatable import UnexpectedObjectContentError
|
|
23
28
|
from flwr.common.serde import (
|
|
24
29
|
fab_to_proto,
|
|
@@ -29,15 +34,19 @@ from flwr.common.serde import (
|
|
|
29
34
|
from flwr.common.typing import Fab, InvalidRunStatusException
|
|
30
35
|
from flwr.proto.fab_pb2 import GetFabRequest, GetFabResponse # pylint: disable=E0611
|
|
31
36
|
from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
ActivateNodeRequest,
|
|
38
|
+
ActivateNodeResponse,
|
|
39
|
+
DeactivateNodeRequest,
|
|
40
|
+
DeactivateNodeResponse,
|
|
36
41
|
PullMessagesRequest,
|
|
37
42
|
PullMessagesResponse,
|
|
38
43
|
PushMessagesRequest,
|
|
39
44
|
PushMessagesResponse,
|
|
40
45
|
Reconnect,
|
|
46
|
+
RegisterNodeFleetRequest,
|
|
47
|
+
RegisterNodeFleetResponse,
|
|
48
|
+
UnregisterNodeFleetRequest,
|
|
49
|
+
UnregisterNodeFleetResponse,
|
|
41
50
|
)
|
|
42
51
|
from flwr.proto.heartbeat_pb2 import ( # pylint: disable=E0611
|
|
43
52
|
SendNodeHeartbeatRequest,
|
|
@@ -51,7 +60,6 @@ from flwr.proto.message_pb2 import ( # pylint: disable=E0611
|
|
|
51
60
|
PushObjectRequest,
|
|
52
61
|
PushObjectResponse,
|
|
53
62
|
)
|
|
54
|
-
from flwr.proto.node_pb2 import Node # pylint: disable=E0611
|
|
55
63
|
from flwr.proto.run_pb2 import ( # pylint: disable=E0611
|
|
56
64
|
GetRunRequest,
|
|
57
65
|
GetRunResponse,
|
|
@@ -64,27 +72,52 @@ from flwr.supercore.object_store import NoObjectInStoreError, ObjectStore
|
|
|
64
72
|
from flwr.supercore.object_store.utils import store_mapping_and_register_objects
|
|
65
73
|
|
|
66
74
|
|
|
67
|
-
|
|
68
|
-
|
|
75
|
+
class InvalidHeartbeatIntervalError(Exception):
|
|
76
|
+
"""Invalid heartbeat interval exception."""
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def register_node(
|
|
80
|
+
request: RegisterNodeFleetRequest,
|
|
69
81
|
state: LinkState,
|
|
70
|
-
) ->
|
|
71
|
-
"""."""
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
NOOP_FLWR_AID, request.public_key, request.heartbeat_interval
|
|
75
|
-
)
|
|
76
|
-
return CreateNodeResponse(node=Node(node_id=node_id))
|
|
82
|
+
) -> RegisterNodeFleetResponse:
|
|
83
|
+
"""Register a node (Fleet API only)."""
|
|
84
|
+
state.create_node(NOOP_FLWR_AID, request.public_key, 0)
|
|
85
|
+
return RegisterNodeFleetResponse()
|
|
77
86
|
|
|
78
87
|
|
|
79
|
-
def
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
88
|
+
def activate_node(
|
|
89
|
+
request: ActivateNodeRequest,
|
|
90
|
+
state: LinkState,
|
|
91
|
+
) -> ActivateNodeResponse:
|
|
92
|
+
"""Activate a node."""
|
|
93
|
+
node_id = state.get_node_id_by_public_key(request.public_key)
|
|
94
|
+
if node_id is None:
|
|
95
|
+
raise ValueError("No SuperNode found with the given public key.")
|
|
96
|
+
_validate_heartbeat_interval(request.heartbeat_interval)
|
|
97
|
+
if not state.activate_node(node_id, request.heartbeat_interval):
|
|
98
|
+
raise ValueError(f"SuperNode with node ID {node_id} could not be activated.")
|
|
99
|
+
return ActivateNodeResponse(node_id=node_id)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def deactivate_node(
|
|
103
|
+
request: DeactivateNodeRequest,
|
|
104
|
+
state: LinkState,
|
|
105
|
+
) -> DeactivateNodeResponse:
|
|
106
|
+
"""Deactivate a node."""
|
|
107
|
+
if not state.deactivate_node(request.node_id):
|
|
108
|
+
raise ValueError(
|
|
109
|
+
f"SuperNode with node ID {request.node_id} could not be deactivated."
|
|
110
|
+
)
|
|
111
|
+
return DeactivateNodeResponse()
|
|
84
112
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
113
|
+
|
|
114
|
+
def unregister_node(
|
|
115
|
+
request: UnregisterNodeFleetRequest,
|
|
116
|
+
state: LinkState,
|
|
117
|
+
) -> UnregisterNodeFleetResponse:
|
|
118
|
+
"""Unregister a node (Fleet API only)."""
|
|
119
|
+
state.delete_node(NOOP_FLWR_AID, request.node_id)
|
|
120
|
+
return UnregisterNodeFleetResponse()
|
|
88
121
|
|
|
89
122
|
|
|
90
123
|
def send_node_heartbeat(
|
|
@@ -92,6 +125,7 @@ def send_node_heartbeat(
|
|
|
92
125
|
state: LinkState, # pylint: disable=unused-argument
|
|
93
126
|
) -> SendNodeHeartbeatResponse:
|
|
94
127
|
"""."""
|
|
128
|
+
_validate_heartbeat_interval(request.heartbeat_interval)
|
|
95
129
|
res = state.acknowledge_node_heartbeat(
|
|
96
130
|
request.node.node_id, request.heartbeat_interval
|
|
97
131
|
)
|
|
@@ -286,3 +320,12 @@ def confirm_message_received(
|
|
|
286
320
|
store.delete(request.message_object_id)
|
|
287
321
|
|
|
288
322
|
return ConfirmMessageReceivedResponse()
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def _validate_heartbeat_interval(interval: float) -> None:
|
|
326
|
+
"""Raise if heartbeat interval is out of bounds."""
|
|
327
|
+
if not HEARTBEAT_MIN_INTERVAL <= interval <= HEARTBEAT_MAX_INTERVAL:
|
|
328
|
+
raise InvalidHeartbeatIntervalError(
|
|
329
|
+
f"Heartbeat interval {interval} is out of bounds "
|
|
330
|
+
f"[{HEARTBEAT_MIN_INTERVAL}, {HEARTBEAT_MAX_INTERVAL}]."
|
|
331
|
+
)
|
|
@@ -27,12 +27,8 @@ from flwr.proto.fab_pb2 import GetFabRequest, GetFabResponse # pylint: disable=
|
|
|
27
27
|
from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
|
|
28
28
|
ActivateNodeRequest,
|
|
29
29
|
ActivateNodeResponse,
|
|
30
|
-
CreateNodeRequest,
|
|
31
|
-
CreateNodeResponse,
|
|
32
30
|
DeactivateNodeRequest,
|
|
33
31
|
DeactivateNodeResponse,
|
|
34
|
-
DeleteNodeRequest,
|
|
35
|
-
DeleteNodeResponse,
|
|
36
32
|
PullMessagesRequest,
|
|
37
33
|
PullMessagesResponse,
|
|
38
34
|
PushMessagesRequest,
|
|
@@ -110,32 +106,16 @@ def rest_request_response(
|
|
|
110
106
|
return decorator
|
|
111
107
|
|
|
112
108
|
|
|
113
|
-
@rest_request_response(CreateNodeRequest)
|
|
114
|
-
async def create_node(request: CreateNodeRequest) -> CreateNodeResponse:
|
|
115
|
-
"""Create Node."""
|
|
116
|
-
# Get state from app
|
|
117
|
-
state: LinkState = cast(LinkStateFactory, app.state.STATE_FACTORY).state()
|
|
118
|
-
|
|
119
|
-
# Handle message
|
|
120
|
-
return message_handler.create_node(request=request, state=state)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
@rest_request_response(DeleteNodeRequest)
|
|
124
|
-
async def delete_node(request: DeleteNodeRequest) -> DeleteNodeResponse:
|
|
125
|
-
"""Delete Node Id."""
|
|
126
|
-
# Get state from app
|
|
127
|
-
state: LinkState = cast(LinkStateFactory, app.state.STATE_FACTORY).state()
|
|
128
|
-
|
|
129
|
-
# Handle message
|
|
130
|
-
return message_handler.delete_node(request=request, state=state)
|
|
131
|
-
|
|
132
|
-
|
|
133
109
|
@rest_request_response(RegisterNodeFleetRequest)
|
|
134
110
|
async def register_node(
|
|
135
111
|
request: RegisterNodeFleetRequest,
|
|
136
112
|
) -> RegisterNodeFleetResponse:
|
|
137
113
|
"""Register a node (Fleet API only)."""
|
|
138
|
-
|
|
114
|
+
# Get state from app
|
|
115
|
+
state: LinkState = cast(LinkStateFactory, app.state.STATE_FACTORY).state()
|
|
116
|
+
|
|
117
|
+
# Handle message
|
|
118
|
+
return message_handler.register_node(request=request, state=state)
|
|
139
119
|
|
|
140
120
|
|
|
141
121
|
@rest_request_response(ActivateNodeRequest)
|
|
@@ -143,7 +123,11 @@ async def activate_node(
|
|
|
143
123
|
request: ActivateNodeRequest,
|
|
144
124
|
) -> ActivateNodeResponse:
|
|
145
125
|
"""Activate a node."""
|
|
146
|
-
|
|
126
|
+
# Get state from app
|
|
127
|
+
state: LinkState = cast(LinkStateFactory, app.state.STATE_FACTORY).state()
|
|
128
|
+
|
|
129
|
+
# Handle message
|
|
130
|
+
return message_handler.activate_node(request=request, state=state)
|
|
147
131
|
|
|
148
132
|
|
|
149
133
|
@rest_request_response(DeactivateNodeRequest)
|
|
@@ -151,7 +135,11 @@ async def deactivate_node(
|
|
|
151
135
|
request: DeactivateNodeRequest,
|
|
152
136
|
) -> DeactivateNodeResponse:
|
|
153
137
|
"""Deactivate a node."""
|
|
154
|
-
|
|
138
|
+
# Get state from app
|
|
139
|
+
state: LinkState = cast(LinkStateFactory, app.state.STATE_FACTORY).state()
|
|
140
|
+
|
|
141
|
+
# Handle message
|
|
142
|
+
return message_handler.deactivate_node(request=request, state=state)
|
|
155
143
|
|
|
156
144
|
|
|
157
145
|
@rest_request_response(UnregisterNodeFleetRequest)
|
|
@@ -159,7 +147,11 @@ async def unregister_node(
|
|
|
159
147
|
request: UnregisterNodeFleetRequest,
|
|
160
148
|
) -> UnregisterNodeFleetResponse:
|
|
161
149
|
"""Unregister a node (Fleet API only)."""
|
|
162
|
-
|
|
150
|
+
# Get state from app
|
|
151
|
+
state: LinkState = cast(LinkStateFactory, app.state.STATE_FACTORY).state()
|
|
152
|
+
|
|
153
|
+
# Handle message
|
|
154
|
+
return message_handler.unregister_node(request=request, state=state)
|
|
163
155
|
|
|
164
156
|
|
|
165
157
|
@rest_request_response(PullMessagesRequest)
|
|
@@ -33,7 +33,7 @@ from flwr.clientapp.client_app import ClientApp, ClientAppException, LoadClientA
|
|
|
33
33
|
from flwr.clientapp.utils import get_load_client_app_fn
|
|
34
34
|
from flwr.common import Message
|
|
35
35
|
from flwr.common.constant import (
|
|
36
|
-
|
|
36
|
+
HEARTBEAT_INTERVAL_INF,
|
|
37
37
|
NOOP_FLWR_AID,
|
|
38
38
|
NUM_PARTITIONS_KEY,
|
|
39
39
|
PARTITION_ID_KEY,
|
|
@@ -62,10 +62,10 @@ def _register_nodes(
|
|
|
62
62
|
# use random bytes as public key
|
|
63
63
|
NOOP_FLWR_AID,
|
|
64
64
|
secrets.token_bytes(32),
|
|
65
|
-
heartbeat_interval=
|
|
65
|
+
heartbeat_interval=HEARTBEAT_INTERVAL_INF,
|
|
66
66
|
)
|
|
67
67
|
state.acknowledge_node_heartbeat(
|
|
68
|
-
node_id=node_id, heartbeat_interval=
|
|
68
|
+
node_id=node_id, heartbeat_interval=HEARTBEAT_INTERVAL_INF
|
|
69
69
|
)
|
|
70
70
|
nodes_mapping[node_id] = i
|
|
71
71
|
log(DEBUG, "Registered %i nodes", len(nodes_mapping))
|
|
@@ -28,7 +28,7 @@ from typing import Optional
|
|
|
28
28
|
from flwr.common import Context, Message, log, now
|
|
29
29
|
from flwr.common.constant import (
|
|
30
30
|
FLWR_APP_TOKEN_LENGTH,
|
|
31
|
-
|
|
31
|
+
HEARTBEAT_INTERVAL_INF,
|
|
32
32
|
HEARTBEAT_PATIENCE,
|
|
33
33
|
MESSAGE_TTL_TOLERANCE,
|
|
34
34
|
NODE_ID_NUM_BYTES,
|
|
@@ -117,7 +117,8 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
|
117
117
|
)
|
|
118
118
|
return None
|
|
119
119
|
# Validate destination node ID
|
|
120
|
-
|
|
120
|
+
dst_node = self.nodes.get(message.metadata.dst_node_id)
|
|
121
|
+
if dst_node is None or dst_node.status == NodeStatus.UNREGISTERED:
|
|
121
122
|
log(
|
|
122
123
|
ERROR,
|
|
123
124
|
"Invalid destination node ID for Message: %s",
|
|
@@ -641,7 +642,7 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
|
641
642
|
current = now()
|
|
642
643
|
run_record = self.run_ids[run_id]
|
|
643
644
|
if new_status.status in (Status.STARTING, Status.RUNNING):
|
|
644
|
-
run_record.heartbeat_interval =
|
|
645
|
+
run_record.heartbeat_interval = HEARTBEAT_INTERVAL_INF
|
|
645
646
|
run_record.active_until = (
|
|
646
647
|
current.timestamp() + run_record.heartbeat_interval
|
|
647
648
|
)
|
|
@@ -27,7 +27,7 @@ from typing import Any, Optional, Union, cast
|
|
|
27
27
|
from flwr.common import Context, Message, Metadata, log, now
|
|
28
28
|
from flwr.common.constant import (
|
|
29
29
|
FLWR_APP_TOKEN_LENGTH,
|
|
30
|
-
|
|
30
|
+
HEARTBEAT_INTERVAL_INF,
|
|
31
31
|
HEARTBEAT_PATIENCE,
|
|
32
32
|
MESSAGE_TTL_TOLERANCE,
|
|
33
33
|
NODE_ID_NUM_BYTES,
|
|
@@ -239,8 +239,8 @@ class SqliteLinkState(LinkState, SqliteMixin): # pylint: disable=R0904
|
|
|
239
239
|
return None
|
|
240
240
|
|
|
241
241
|
# Validate destination node ID
|
|
242
|
-
query = "SELECT node_id FROM node WHERE node_id = ?;"
|
|
243
|
-
if not self.query(query, (data[0]["dst_node_id"],)):
|
|
242
|
+
query = "SELECT node_id FROM node WHERE node_id = ? AND status != ?;"
|
|
243
|
+
if not self.query(query, (data[0]["dst_node_id"], NodeStatus.UNREGISTERED)):
|
|
244
244
|
log(
|
|
245
245
|
ERROR,
|
|
246
246
|
"Invalid destination node ID for Message: %s",
|
|
@@ -982,7 +982,7 @@ class SqliteLinkState(LinkState, SqliteMixin): # pylint: disable=R0904
|
|
|
982
982
|
# when switching to starting or running
|
|
983
983
|
current = now()
|
|
984
984
|
if new_status.status in (Status.STARTING, Status.RUNNING):
|
|
985
|
-
heartbeat_interval =
|
|
985
|
+
heartbeat_interval = HEARTBEAT_INTERVAL_INF
|
|
986
986
|
active_until = current.timestamp() + heartbeat_interval
|
|
987
987
|
else:
|
|
988
988
|
heartbeat_interval = 0
|
flwr/supercore/constant.py
CHANGED
|
@@ -23,6 +23,10 @@ EXEC_PLUGIN_SECTION = "exec_plugin"
|
|
|
23
23
|
# Flower in-memory Python-based database name
|
|
24
24
|
FLWR_IN_MEMORY_DB_NAME = ":flwr-in-memory:"
|
|
25
25
|
|
|
26
|
+
# Constants for Hub
|
|
27
|
+
APP_ID_PATTERN = r"^@(?P<user>[^/]+)/(?P<app>[^/]+)$"
|
|
28
|
+
PLATFORM_API_URL = "https://api.flower.ai/v1"
|
|
29
|
+
|
|
26
30
|
|
|
27
31
|
class NodeStatus:
|
|
28
32
|
"""Event log writer types."""
|
|
@@ -61,6 +61,13 @@ def flower_supernode() -> None:
|
|
|
61
61
|
root_certificates = try_obtain_root_certificates(args, args.superlink)
|
|
62
62
|
authentication_keys = _try_setup_client_authentication(args)
|
|
63
63
|
|
|
64
|
+
# Warn if authentication keys are provided but transport is not grpc-rere
|
|
65
|
+
if authentication_keys is not None and args.transport != TRANSPORT_TYPE_GRPC_RERE:
|
|
66
|
+
log(
|
|
67
|
+
WARN,
|
|
68
|
+
"SuperNode Authentication is only supported with the grpc-rere transport.",
|
|
69
|
+
)
|
|
70
|
+
|
|
64
71
|
log(DEBUG, "Isolation mode: %s", args.isolation)
|
|
65
72
|
|
|
66
73
|
start_client_internal(
|
|
@@ -207,21 +207,16 @@ def start_client_internal(
|
|
|
207
207
|
max_wait_time=max_wait_time,
|
|
208
208
|
) as conn:
|
|
209
209
|
(
|
|
210
|
+
node_id,
|
|
210
211
|
receive,
|
|
211
212
|
send,
|
|
212
|
-
create_node,
|
|
213
|
-
_,
|
|
214
213
|
get_run,
|
|
215
214
|
get_fab,
|
|
216
215
|
pull_object,
|
|
217
216
|
push_object,
|
|
218
217
|
confirm_message_received,
|
|
219
218
|
) = conn
|
|
220
|
-
|
|
221
|
-
# Call create_node fn to register node
|
|
222
|
-
# and store node_id in state
|
|
223
|
-
if (node_id := create_node()) is None:
|
|
224
|
-
raise ValueError("Failed to register SuperNode with the SuperLink")
|
|
219
|
+
# Store node_id in state
|
|
225
220
|
state.set_node_id(node_id)
|
|
226
221
|
|
|
227
222
|
# pylint: disable=too-many-nested-blocks
|
|
@@ -457,10 +452,9 @@ def _init_connection( # pylint: disable=too-many-positional-arguments
|
|
|
457
452
|
max_wait_time: Optional[float] = None,
|
|
458
453
|
) -> Iterator[
|
|
459
454
|
tuple[
|
|
455
|
+
int,
|
|
460
456
|
Callable[[], Optional[tuple[Message, ObjectTree]]],
|
|
461
457
|
Callable[[Message, ObjectTree], set[str]],
|
|
462
|
-
Callable[[], Optional[int]],
|
|
463
|
-
Callable[[], None],
|
|
464
458
|
Callable[[int], Run],
|
|
465
459
|
Callable[[str, int], Fab],
|
|
466
460
|
Callable[[int, str], bytes],
|
{flwr_nightly-1.23.0.dev20251029.dist-info → flwr_nightly-1.23.0.dev20251031.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: flwr-nightly
|
|
3
|
-
Version: 1.23.0.
|
|
3
|
+
Version: 1.23.0.dev20251031
|
|
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
|
{flwr_nightly-1.23.0.dev20251029.dist-info → flwr_nightly-1.23.0.dev20251031.dist-info}/RECORD
RENAMED
|
@@ -20,7 +20,7 @@ flwr/cli/login/__init__.py,sha256=B1SXKU3HCQhWfFDMJhlC7FOl8UsvH4mxysxeBnrfyUE,80
|
|
|
20
20
|
flwr/cli/login/login.py,sha256=XeA6K9rZn3CBvtiFP3XWTAk7s8766BCqHvCsO_tJEuY,4558
|
|
21
21
|
flwr/cli/ls.py,sha256=MUlWSjO0yhVTupN5Fr0zvdvRqfRBGWliuoyWA0D-Pzg,11107
|
|
22
22
|
flwr/cli/new/__init__.py,sha256=QA1E2QtzPvFCjLTUHnFnJbufuFiGyT_0Y53Wpbvg1F0,790
|
|
23
|
-
flwr/cli/new/new.py,sha256=
|
|
23
|
+
flwr/cli/new/new.py,sha256=NOzI72lLAk1U9-g54Re04DBpgK81JOqMiXHRE5l-_Fo,15301
|
|
24
24
|
flwr/cli/new/templates/__init__.py,sha256=FpjWCfIySU2DB4kh0HOXLAjlZNNFDTVU4w3HoE2TzcI,725
|
|
25
25
|
flwr/cli/new/templates/app/.gitignore.tpl,sha256=HZJcGQoxp7aUzaPg8Uqch3kNrIESwr9yjimDxJYgXVY,3104
|
|
26
26
|
flwr/cli/new/templates/app/LICENSE.tpl,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
@@ -95,10 +95,10 @@ flwr/client/__init__.py,sha256=Q0MIF442vLIGSkcwHKq_sIfECQynLARJrumAscq2Q6E,1241
|
|
|
95
95
|
flwr/client/client.py,sha256=3HAchxvknKG9jYbB7swNyDj-e5vUWDuMKoLvbT7jCVM,7895
|
|
96
96
|
flwr/client/dpfedavg_numpy_client.py,sha256=3hul067cT2E9jBhzp7bFnFAZ_D2nWcIUEdHYE05FpzU,7404
|
|
97
97
|
flwr/client/grpc_adapter_client/__init__.py,sha256=RQWP5mFPROLHKgombiRvPXVWSoVrQ81wvZm0-lOuuBA,742
|
|
98
|
-
flwr/client/grpc_adapter_client/connection.py,sha256=
|
|
98
|
+
flwr/client/grpc_adapter_client/connection.py,sha256=jCwvteuzGfCjasBtsq1e_GSBvJ5fAp_ci0l5wM99kRw,4305
|
|
99
99
|
flwr/client/grpc_rere_client/__init__.py,sha256=i7iS0Lt8B7q0E2L72e4F_YrKm6ClRKnd71PNA6PW2O0,752
|
|
100
|
-
flwr/client/grpc_rere_client/connection.py,sha256=
|
|
101
|
-
flwr/client/grpc_rere_client/grpc_adapter.py,sha256=
|
|
100
|
+
flwr/client/grpc_rere_client/connection.py,sha256=LqRbo_rkZsPIiIT1goclNYDIsdsEfIz3qrQGPU6QNoY,13771
|
|
101
|
+
flwr/client/grpc_rere_client/grpc_adapter.py,sha256=1s1suFIGxAbx6UiIZH-VtLpZlkct5FI4OF4bb589A0o,7358
|
|
102
102
|
flwr/client/grpc_rere_client/node_auth_client_interceptor.py,sha256=EdTyb5ThFrpkeyXy9_nTKH7E9GnfAdXjcNZ_-uxt1AA,2410
|
|
103
103
|
flwr/client/message_handler/__init__.py,sha256=0lyljDVqre3WljiZbPcwCCf8GiIaSVI_yo_ylEyPwSE,719
|
|
104
104
|
flwr/client/message_handler/message_handler.py,sha256=X9SXX6et97Lw9_DGD93HKsEBGNjXClcFgc_5aLK0oiU,6541
|
|
@@ -112,7 +112,7 @@ flwr/client/mod/secure_aggregation/secaggplus_mod.py,sha256=Ib-HlhZOXB6-hAWGZ0Ip
|
|
|
112
112
|
flwr/client/mod/utils.py,sha256=FUgD2TfcWqSeF6jUKZ4i6Ke56U4Nrv85AeVb93s6R9g,1201
|
|
113
113
|
flwr/client/numpy_client.py,sha256=Qq6ghsIAop2slKqAfgiI5NiHJ4LIxGmrik3Ror4_XVc,9581
|
|
114
114
|
flwr/client/rest_client/__init__.py,sha256=MBiuK62hj439m9rtwSwI184Hth6Tt5GbmpNMyl3zkZY,735
|
|
115
|
-
flwr/client/rest_client/connection.py,sha256=
|
|
115
|
+
flwr/client/rest_client/connection.py,sha256=HtEHtKuX32ff4W86NZiqtTU3PbCtcTYcPUs6jp84Ghw,17501
|
|
116
116
|
flwr/client/run_info_store.py,sha256=MaJ3UQ-07hWtK67wnWu0zR29jrk0fsfgJX506dvEOfE,4042
|
|
117
117
|
flwr/client/typing.py,sha256=Jw3rawDzI_-ZDcRmEQcs5gZModY7oeQlEeltYsdOhlU,1048
|
|
118
118
|
flwr/clientapp/__init__.py,sha256=dsXH29kvCk1meJj9UYMCIak8zehuuhVp0uDJ2COU_1c,829
|
|
@@ -126,7 +126,7 @@ flwr/common/__init__.py,sha256=5GCLVk399Az_rTJHNticRlL0Sl_oPw_j5_LuFKfX7-M,4171
|
|
|
126
126
|
flwr/common/address.py,sha256=9JucdTwlc-jpeJkRKeUboZoacUtErwSVtnDR9kAtLqE,4119
|
|
127
127
|
flwr/common/args.py,sha256=Nq2u4yePbkSY0CWFamn0hZY6Rms8G1xYDeDGIcLIITE,5849
|
|
128
128
|
flwr/common/config.py,sha256=glcZDjco-amw1YfQcYTFJ4S1pt9APoexT-mf1QscuHs,13960
|
|
129
|
-
flwr/common/constant.py,sha256=
|
|
129
|
+
flwr/common/constant.py,sha256=du408_dylfRx6H-YXzpc_2BvpI1bnFUcz0RiQryM_n8,10254
|
|
130
130
|
flwr/common/context.py,sha256=Be8obQR_OvEDy1OmshuUKxGRQ7Qx89mf5F4xlhkR10s,2407
|
|
131
131
|
flwr/common/date.py,sha256=1ZT2cRSpC2DJqprOVTLXYCR_O2_OZR0zXO_brJ3LqWc,1554
|
|
132
132
|
flwr/common/differential_privacy.py,sha256=FdlpdpPl_H_2HJa8CQM1iCUGBBQ5Dc8CzxmHERM-EoE,6148
|
|
@@ -203,10 +203,10 @@ flwr/proto/fab_pb2.py,sha256=AQAUJmTt31Kq-lJQid3CJpQPrply2-OA_aSHokpVF84,2070
|
|
|
203
203
|
flwr/proto/fab_pb2.pyi,sha256=GOxeDi-UYzQVwIEzRk9YkzkriowmNdibZu3jMMtBPFo,3273
|
|
204
204
|
flwr/proto/fab_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
|
205
205
|
flwr/proto/fab_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
|
|
206
|
-
flwr/proto/fleet_pb2.py,sha256=
|
|
207
|
-
flwr/proto/fleet_pb2.pyi,sha256
|
|
208
|
-
flwr/proto/fleet_pb2_grpc.py,sha256=
|
|
209
|
-
flwr/proto/fleet_pb2_grpc.pyi,sha256=
|
|
206
|
+
flwr/proto/fleet_pb2.py,sha256=wl1uxtBDEZulKo8pBMv3Q0AZy0_I1YY-_6Bf33mGQJk,6198
|
|
207
|
+
flwr/proto/fleet_pb2.pyi,sha256=F41lGrsI64MYwj7yCzEviU1BrN0abOR7K88vqwhSwyE,9168
|
|
208
|
+
flwr/proto/fleet_pb2_grpc.py,sha256=GKBHMa6j__vpArCgALT_1p47FVuPurgpYDG7ZjFgjls,20853
|
|
209
|
+
flwr/proto/fleet_pb2_grpc.pyi,sha256=uO5EmcGdzw6VDsifmb5rCbs7FmyyOGs4bNfitFNONik,5773
|
|
210
210
|
flwr/proto/grpcadapter_pb2.py,sha256=PJ8DtfeV29g_y4Z3aNZlSZocLqSxeLmTsYCdOZDYCiE,1843
|
|
211
211
|
flwr/proto/grpcadapter_pb2.pyi,sha256=AR77gDsF6f8zqSIQp3877DUd7S8lP95lFak5Ir_WPkw,1716
|
|
212
212
|
flwr/proto/grpcadapter_pb2_grpc.py,sha256=rRNuNES5nBugUZWfeA8oAy8dMHgzqU_PF1srTseo3b8,2634
|
|
@@ -249,7 +249,7 @@ flwr/proto/transport_pb2_grpc.py,sha256=vLN3EHtx2aEEMCO4f1Upu-l27BPzd3-5pV-u8wPc
|
|
|
249
249
|
flwr/proto/transport_pb2_grpc.pyi,sha256=AGXf8RiIiW2J5IKMlm_3qT3AzcDa4F3P5IqUjve_esA,766
|
|
250
250
|
flwr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
251
251
|
flwr/server/__init__.py,sha256=LQQHiuL2jy7TpNaKastRdGsexlxSt5ZWAQNVqitDnrY,1598
|
|
252
|
-
flwr/server/app.py,sha256=
|
|
252
|
+
flwr/server/app.py,sha256=vnRG6PxZYOqi6VKbDxD0wRaDoNq2Ip3TYV3HjDew1I0,30940
|
|
253
253
|
flwr/server/client_manager.py,sha256=5jCGavVli7XdupvWWo7ru3PdFTlRU8IGvHFSSoUVLRs,6227
|
|
254
254
|
flwr/server/client_proxy.py,sha256=sv0E9AldBYOvc3pusqFh-GnyreeMfsXQ1cuTtxTq_wY,2399
|
|
255
255
|
flwr/server/compat/__init__.py,sha256=0IsttWvY15qO98_1GyzVC-vR1e_ZPXOdu2qUlOkYMPE,886
|
|
@@ -298,29 +298,29 @@ flwr/server/strategy/strategy.py,sha256=n4r52i5gK4KGToZvcJUeWuEif1tuI0HZUT3YJPTC
|
|
|
298
298
|
flwr/server/superlink/__init__.py,sha256=GNSuJ4-N6Z8wun2iZNlXqENt5beUyzC0Gi_tN396bbM,707
|
|
299
299
|
flwr/server/superlink/fleet/__init__.py,sha256=Uiwr33yfW_eL-pEfj80c_JUhIKRkCPsN1JSs2v4aglU,711
|
|
300
300
|
flwr/server/superlink/fleet/grpc_adapter/__init__.py,sha256=fUu1V63YrzjxAOZnBJx99WjuD4Mro7dJIFH-1V4NLV8,742
|
|
301
|
-
flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py,sha256=
|
|
301
|
+
flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py,sha256=1XGkP6DKEKf-GehK8lGhPIACmHz4wsbOXx9wLaxaj44,5527
|
|
302
302
|
flwr/server/superlink/fleet/grpc_bidi/__init__.py,sha256=dOM49q1b9MrtUr5jldjEnQ38NhcUyYs-zC3gsJb1TtI,735
|
|
303
303
|
flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py,sha256=UKEp-3YBaTvNt7vKZW7KLgK5xsAiO7jxU-omG7CaO_s,6021
|
|
304
304
|
flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py,sha256=KouR9PUcrPmMtoLooF4O9SRAwIvfiroo8mPmqUc2EZc,6485
|
|
305
305
|
flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py,sha256=iSf0mbBAlig7G6subQwBSVjcUCgSihONKdZ1RmQPTOk,4887
|
|
306
306
|
flwr/server/superlink/fleet/grpc_bidi/grpc_server.py,sha256=OsS-6GgCIzMMZDVu5Y-OKjynHVUrpdc_5OrtuB-IbU0,5174
|
|
307
307
|
flwr/server/superlink/fleet/grpc_rere/__init__.py,sha256=ahDJJ1e-lDxBpeBMgPk7YZt2wB38_QltcpOC0gLbpFs,758
|
|
308
|
-
flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py,sha256=
|
|
309
|
-
flwr/server/superlink/fleet/grpc_rere/node_auth_server_interceptor.py,sha256=
|
|
308
|
+
flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py,sha256=Rit-x6l7EhhyZX_RWxGNaeKIyFTDjKelBKZ2q-vfVOo,12181
|
|
309
|
+
flwr/server/superlink/fleet/grpc_rere/node_auth_server_interceptor.py,sha256=Q1t2cGLPrp_jw0_x3BZTc-SxeLP6BzRaEJZQFH075dA,5641
|
|
310
310
|
flwr/server/superlink/fleet/message_handler/__init__.py,sha256=fHsRV0KvJ8HtgSA4_YBsEzuhJLjO8p6xx4aCY2oE1p4,731
|
|
311
|
-
flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=
|
|
311
|
+
flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=HatVb3UuutXb9coJ9D6as6HQIMiu1UF0KIOvJO4hPKw,10200
|
|
312
312
|
flwr/server/superlink/fleet/rest_rere/__init__.py,sha256=Lzc93nA7tDqoy-zRUaPG316oqFiZX1HUCL5ELaXY_xw,735
|
|
313
|
-
flwr/server/superlink/fleet/rest_rere/rest_api.py,sha256=
|
|
313
|
+
flwr/server/superlink/fleet/rest_rere/rest_api.py,sha256=FK-xehmTfOBNjOLSeTYv-YDeyPvkiQI4UQhbwyYWt60,9616
|
|
314
314
|
flwr/server/superlink/fleet/vce/__init__.py,sha256=XOKbAWOzlCqEOQ3M2cBYkH7HKA7PxlbCJMunt-ty-DY,784
|
|
315
315
|
flwr/server/superlink/fleet/vce/backend/__init__.py,sha256=PPH89Yqd1XKm-sRJN6R0WQlKT_b4v54Kzl2yzHAFzM8,1437
|
|
316
316
|
flwr/server/superlink/fleet/vce/backend/backend.py,sha256=cSrHZ5SjCCvy4vI0pgsyjtx3cDMuMQve8KcKkK-dWWo,2196
|
|
317
317
|
flwr/server/superlink/fleet/vce/backend/raybackend.py,sha256=cBZYTmfiAsb1HmVUmOQXYLU-UJmJTFWkj1wW4RYRDuc,7218
|
|
318
|
-
flwr/server/superlink/fleet/vce/vce_api.py,sha256=
|
|
318
|
+
flwr/server/superlink/fleet/vce/vce_api.py,sha256=7dJdxRjXttXfZSflZHd-TwX9278ZzrdJxmmWbRiEH_I,13389
|
|
319
319
|
flwr/server/superlink/linkstate/__init__.py,sha256=OtsgvDTnZLU3k0sUbkHbqoVwW6ql2FDmb6uT6DbNkZo,1064
|
|
320
|
-
flwr/server/superlink/linkstate/in_memory_linkstate.py,sha256=
|
|
320
|
+
flwr/server/superlink/linkstate/in_memory_linkstate.py,sha256=1qMnE9j3gdHaCTVDBjGX1rLP7b0cesJovM0H-0yBhmk,31909
|
|
321
321
|
flwr/server/superlink/linkstate/linkstate.py,sha256=DabTgFFissJhT_MCPiluz5eFrS3c412q8FnRqQrAidY,15945
|
|
322
322
|
flwr/server/superlink/linkstate/linkstate_factory.py,sha256=KVBpc8UxVrJCQ7IkOjVZVWb-kqWx08AGVi7qXzZS190,2126
|
|
323
|
-
flwr/server/superlink/linkstate/sqlite_linkstate.py,sha256=
|
|
323
|
+
flwr/server/superlink/linkstate/sqlite_linkstate.py,sha256=TYNqEkhBaklv2hvjW8zF17GUcfjbJBrAKxbW8-6If_8,47568
|
|
324
324
|
flwr/server/superlink/linkstate/utils.py,sha256=ZtyqSo4HzGrHXW3Wn_4irYMpIiq4onNI2XCIVOOJmJM,13971
|
|
325
325
|
flwr/server/superlink/serverappio/__init__.py,sha256=Fy4zJuoccZe5mZSEIpOmQvU6YeXFBa1M4eZuXXmJcn8,717
|
|
326
326
|
flwr/server/superlink/serverappio/serverappio_grpc.py,sha256=-I7kBbr4w4ZVYwBZoAIle-xHKthFnZrsVfxa6WR8uxA,2310
|
|
@@ -375,7 +375,7 @@ flwr/supercore/__init__.py,sha256=pqkFoow_E6UhbBlhmoD1gmTH-33yJRhBsIZqxRPFZ7U,75
|
|
|
375
375
|
flwr/supercore/app_utils.py,sha256=K76Zt6R670b1hUmxOsNc1WUCVYvF7lejXPcCO9K0Q0g,1753
|
|
376
376
|
flwr/supercore/cli/__init__.py,sha256=EDl2aO-fuQfxSbL-T1W9RAfA2N0hpWHmqX_GSwblJbQ,845
|
|
377
377
|
flwr/supercore/cli/flower_superexec.py,sha256=JtqYrEWVu3BxLkjavsdohTOwvMwzuFqWP5j4Mo9dqsk,6155
|
|
378
|
-
flwr/supercore/constant.py,sha256=
|
|
378
|
+
flwr/supercore/constant.py,sha256=LZiryorWpCNvry55EiQinPHazPVhIQHmxdSQMaPu_R4,1374
|
|
379
379
|
flwr/supercore/corestate/__init__.py,sha256=Vau6-L_JG5QzNqtCTa9xCKGGljc09wY8avZmIjSJemg,774
|
|
380
380
|
flwr/supercore/corestate/corestate.py,sha256=rDAWWeG5DcpCyQso9Z3RhwL4zr2IroPlRMcDzqoSu8s,2328
|
|
381
381
|
flwr/supercore/ffs/__init__.py,sha256=U3KXwG_SplEvchat27K0LYPoPHzh-cwwT_NHsGlYMt8,908
|
|
@@ -421,7 +421,7 @@ flwr/superlink/servicer/control/control_license_interceptor.py,sha256=T3AzmRt-PP
|
|
|
421
421
|
flwr/superlink/servicer/control/control_servicer.py,sha256=93-lZ2pSjbpod-zhu_5ZSOK2ZZVTiBT-0mzl53pFlLw,19454
|
|
422
422
|
flwr/supernode/__init__.py,sha256=KgeCaVvXWrU3rptNR1y0oBp4YtXbAcrnCcJAiOoWkI4,707
|
|
423
423
|
flwr/supernode/cli/__init__.py,sha256=JuEMr0-s9zv-PEWKuLB9tj1ocNfroSyNJ-oyv7ati9A,887
|
|
424
|
-
flwr/supernode/cli/flower_supernode.py,sha256=
|
|
424
|
+
flwr/supernode/cli/flower_supernode.py,sha256=3XJ_VRGSiQIwIcDp62B3J7aFvKQyGRzTGiq9JMXFF8Y,8629
|
|
425
425
|
flwr/supernode/cli/flwr_clientapp.py,sha256=W3tAyqSfeHbPhqBC4Pfo9bsyFdkBKPqdKlhGmeUKwKg,3173
|
|
426
426
|
flwr/supernode/nodestate/__init__.py,sha256=CyLLObbmmVgfRO88UCM0VMait1dL57mUauUDfuSHsbU,976
|
|
427
427
|
flwr/supernode/nodestate/in_memory_nodestate.py,sha256=rr_tg7YXhf_seYFipSB59TAfheKPratx3rrvHUOJ80g,7343
|
|
@@ -432,8 +432,8 @@ flwr/supernode/runtime/run_clientapp.py,sha256=BuaAKTzRuFmNX-IJky3kJzoWMmZkz9joH
|
|
|
432
432
|
flwr/supernode/servicer/__init__.py,sha256=lucTzre5WPK7G1YLCfaqg3rbFWdNSb7ZTt-ca8gxdEo,717
|
|
433
433
|
flwr/supernode/servicer/clientappio/__init__.py,sha256=7Oy62Y_oijqF7Dxi6tpcUQyOpLc_QpIRZ83NvwmB0Yg,813
|
|
434
434
|
flwr/supernode/servicer/clientappio/clientappio_servicer.py,sha256=ZvKosLV7GN1_fOF-tOmhqFQysYQywCysRc-m23DVIWA,10265
|
|
435
|
-
flwr/supernode/start_client_internal.py,sha256=
|
|
436
|
-
flwr_nightly-1.23.0.
|
|
437
|
-
flwr_nightly-1.23.0.
|
|
438
|
-
flwr_nightly-1.23.0.
|
|
439
|
-
flwr_nightly-1.23.0.
|
|
435
|
+
flwr/supernode/start_client_internal.py,sha256=opgc3fQPNbCRKQJ39NNYHWsygx6WDsc-n_1t6nvRmdc,21317
|
|
436
|
+
flwr_nightly-1.23.0.dev20251031.dist-info/METADATA,sha256=7rjulx0S0gaQBaaDEw_o8roftwZy4H9giVDefS4AF0M,14559
|
|
437
|
+
flwr_nightly-1.23.0.dev20251031.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
438
|
+
flwr_nightly-1.23.0.dev20251031.dist-info/entry_points.txt,sha256=hxHD2ixb_vJFDOlZV-zB4Ao32_BQlL34ftsDh1GXv14,420
|
|
439
|
+
flwr_nightly-1.23.0.dev20251031.dist-info/RECORD,,
|
{flwr_nightly-1.23.0.dev20251029.dist-info → flwr_nightly-1.23.0.dev20251031.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|