flwr 1.15.2__py3-none-any.whl → 1.17.0__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/cli/build.py +2 -0
- flwr/cli/log.py +20 -21
- flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.jax.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +1 -1
- flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +1 -1
- flwr/cli/run/run.py +5 -9
- flwr/client/app.py +6 -4
- flwr/client/client_app.py +260 -86
- flwr/client/clientapp/app.py +6 -2
- flwr/client/grpc_client/connection.py +24 -21
- flwr/client/message_handler/message_handler.py +28 -28
- flwr/client/mod/__init__.py +2 -2
- flwr/client/mod/centraldp_mods.py +7 -7
- flwr/client/mod/comms_mods.py +16 -22
- flwr/client/mod/localdp_mod.py +4 -4
- flwr/client/mod/secure_aggregation/secaggplus_mod.py +31 -31
- flwr/client/rest_client/connection.py +4 -6
- flwr/client/run_info_store.py +2 -2
- flwr/client/supernode/__init__.py +0 -2
- flwr/client/supernode/app.py +1 -11
- flwr/common/__init__.py +12 -4
- flwr/common/address.py +35 -0
- flwr/common/args.py +8 -2
- flwr/common/auth_plugin/auth_plugin.py +2 -1
- flwr/common/config.py +4 -4
- flwr/common/constant.py +16 -0
- flwr/common/context.py +4 -4
- flwr/common/event_log_plugin/__init__.py +22 -0
- flwr/common/event_log_plugin/event_log_plugin.py +60 -0
- flwr/common/grpc.py +1 -1
- flwr/common/logger.py +2 -2
- flwr/common/message.py +338 -102
- flwr/common/object_ref.py +0 -10
- flwr/common/record/__init__.py +8 -4
- flwr/common/record/arrayrecord.py +626 -0
- flwr/common/record/{configsrecord.py → configrecord.py} +75 -29
- flwr/common/record/conversion_utils.py +9 -18
- flwr/common/record/{metricsrecord.py → metricrecord.py} +78 -32
- flwr/common/record/recorddict.py +288 -0
- flwr/common/recorddict_compat.py +410 -0
- flwr/common/secure_aggregation/quantization.py +5 -1
- flwr/common/secure_aggregation/secaggplus_constants.py +1 -1
- flwr/common/serde.py +67 -190
- flwr/common/telemetry.py +0 -10
- flwr/common/typing.py +44 -8
- flwr/proto/exec_pb2.py +3 -3
- flwr/proto/exec_pb2.pyi +3 -3
- flwr/proto/message_pb2.py +12 -12
- flwr/proto/message_pb2.pyi +9 -9
- flwr/proto/recorddict_pb2.py +70 -0
- flwr/proto/{recordset_pb2.pyi → recorddict_pb2.pyi} +35 -35
- flwr/proto/run_pb2.py +31 -31
- flwr/proto/run_pb2.pyi +3 -3
- flwr/server/__init__.py +3 -1
- flwr/server/app.py +74 -3
- flwr/server/compat/__init__.py +2 -2
- flwr/server/compat/app.py +15 -12
- flwr/server/compat/app_utils.py +26 -18
- flwr/server/compat/{driver_client_proxy.py → grid_client_proxy.py} +41 -41
- flwr/server/fleet_event_log_interceptor.py +94 -0
- flwr/server/{driver → grid}/__init__.py +8 -7
- flwr/server/{driver/driver.py → grid/grid.py} +48 -19
- flwr/server/{driver/grpc_driver.py → grid/grpc_grid.py} +88 -56
- flwr/server/{driver/inmemory_driver.py → grid/inmemory_grid.py} +41 -54
- flwr/server/run_serverapp.py +6 -17
- flwr/server/server_app.py +126 -33
- flwr/server/serverapp/app.py +10 -10
- flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +2 -2
- flwr/server/superlink/fleet/message_handler/message_handler.py +8 -12
- flwr/server/superlink/fleet/vce/backend/backend.py +3 -3
- flwr/server/superlink/fleet/vce/backend/raybackend.py +2 -2
- flwr/server/superlink/fleet/vce/vce_api.py +33 -38
- flwr/server/superlink/linkstate/in_memory_linkstate.py +171 -132
- flwr/server/superlink/linkstate/linkstate.py +51 -64
- flwr/server/superlink/linkstate/sqlite_linkstate.py +253 -285
- flwr/server/superlink/linkstate/utils.py +171 -133
- flwr/server/superlink/{driver → serverappio}/__init__.py +1 -1
- flwr/server/superlink/{driver → serverappio}/serverappio_grpc.py +1 -1
- flwr/server/superlink/{driver → serverappio}/serverappio_servicer.py +27 -29
- flwr/server/superlink/simulation/simulationio_servicer.py +2 -2
- flwr/server/typing.py +3 -3
- flwr/server/utils/__init__.py +2 -2
- flwr/server/utils/validator.py +53 -68
- flwr/server/workflow/default_workflows.py +52 -58
- flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +48 -50
- flwr/simulation/app.py +2 -2
- flwr/simulation/ray_transport/ray_actor.py +4 -2
- flwr/simulation/ray_transport/ray_client_proxy.py +34 -32
- flwr/simulation/run_simulation.py +15 -15
- flwr/superexec/app.py +0 -14
- flwr/superexec/deployment.py +4 -4
- flwr/superexec/exec_event_log_interceptor.py +135 -0
- flwr/superexec/exec_grpc.py +10 -4
- flwr/superexec/exec_servicer.py +6 -6
- flwr/superexec/exec_user_auth_interceptor.py +22 -4
- flwr/superexec/executor.py +3 -3
- flwr/superexec/simulation.py +3 -3
- {flwr-1.15.2.dist-info → flwr-1.17.0.dist-info}/METADATA +5 -5
- {flwr-1.15.2.dist-info → flwr-1.17.0.dist-info}/RECORD +111 -112
- {flwr-1.15.2.dist-info → flwr-1.17.0.dist-info}/entry_points.txt +0 -3
- flwr/client/message_handler/task_handler.py +0 -37
- flwr/common/record/parametersrecord.py +0 -204
- flwr/common/record/recordset.py +0 -202
- flwr/common/recordset_compat.py +0 -418
- flwr/proto/recordset_pb2.py +0 -70
- flwr/proto/task_pb2.py +0 -33
- flwr/proto/task_pb2.pyi +0 -100
- flwr/proto/task_pb2_grpc.py +0 -4
- flwr/proto/task_pb2_grpc.pyi +0 -4
- /flwr/proto/{recordset_pb2_grpc.py → recorddict_pb2_grpc.py} +0 -0
- /flwr/proto/{recordset_pb2_grpc.pyi → recorddict_pb2_grpc.pyi} +0 -0
- {flwr-1.15.2.dist-info → flwr-1.17.0.dist-info}/LICENSE +0 -0
- {flwr-1.15.2.dist-info → flwr-1.17.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Copyright 2025 Flower Labs GmbH. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
# ==============================================================================
|
|
15
|
+
"""Flower Exec API event log interceptor."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
from collections.abc import Iterator
|
|
19
|
+
from typing import Any, Callable, Union, cast
|
|
20
|
+
|
|
21
|
+
import grpc
|
|
22
|
+
from google.protobuf.message import Message as GrpcMessage
|
|
23
|
+
|
|
24
|
+
from flwr.common.event_log_plugin.event_log_plugin import EventLogWriterPlugin
|
|
25
|
+
from flwr.common.typing import LogEntry
|
|
26
|
+
|
|
27
|
+
from .exec_user_auth_interceptor import shared_user_info
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ExecEventLogInterceptor(grpc.ServerInterceptor): # type: ignore
|
|
31
|
+
"""Exec API interceptor for logging events."""
|
|
32
|
+
|
|
33
|
+
def __init__(self, log_plugin: EventLogWriterPlugin) -> None:
|
|
34
|
+
self.log_plugin = log_plugin
|
|
35
|
+
|
|
36
|
+
def intercept_service(
|
|
37
|
+
self,
|
|
38
|
+
continuation: Callable[[Any], Any],
|
|
39
|
+
handler_call_details: grpc.HandlerCallDetails,
|
|
40
|
+
) -> grpc.RpcMethodHandler:
|
|
41
|
+
"""Flower server interceptor logging logic.
|
|
42
|
+
|
|
43
|
+
Intercept all unary-unary/unary-stream calls from users and log the event.
|
|
44
|
+
Continue RPC call if event logger is enabled on the SuperLink, else, terminate
|
|
45
|
+
RPC call by setting context to abort.
|
|
46
|
+
"""
|
|
47
|
+
# One of the method handlers in
|
|
48
|
+
# `flwr.superexec.exec_servicer.ExecServicer`
|
|
49
|
+
method_handler: grpc.RpcMethodHandler = continuation(handler_call_details)
|
|
50
|
+
method_name: str = handler_call_details.method
|
|
51
|
+
return self._generic_event_log_unary_method_handler(method_handler, method_name)
|
|
52
|
+
|
|
53
|
+
def _generic_event_log_unary_method_handler(
|
|
54
|
+
self, method_handler: grpc.RpcMethodHandler, method_name: str
|
|
55
|
+
) -> grpc.RpcMethodHandler:
|
|
56
|
+
def _generic_method_handler(
|
|
57
|
+
request: GrpcMessage,
|
|
58
|
+
context: grpc.ServicerContext,
|
|
59
|
+
) -> Union[GrpcMessage, Iterator[GrpcMessage], BaseException]:
|
|
60
|
+
log_entry: LogEntry
|
|
61
|
+
# Log before call
|
|
62
|
+
log_entry = self.log_plugin.compose_log_before_event(
|
|
63
|
+
request=request,
|
|
64
|
+
context=context,
|
|
65
|
+
user_info=shared_user_info.get(),
|
|
66
|
+
method_name=method_name,
|
|
67
|
+
)
|
|
68
|
+
self.log_plugin.write_log(log_entry)
|
|
69
|
+
|
|
70
|
+
# For unary-unary calls, log after the call immediately
|
|
71
|
+
if method_handler.unary_unary:
|
|
72
|
+
unary_response, error = None, None
|
|
73
|
+
try:
|
|
74
|
+
unary_response = cast(
|
|
75
|
+
GrpcMessage, method_handler.unary_unary(request, context)
|
|
76
|
+
)
|
|
77
|
+
except BaseException as e:
|
|
78
|
+
error = e
|
|
79
|
+
raise
|
|
80
|
+
finally:
|
|
81
|
+
log_entry = self.log_plugin.compose_log_after_event(
|
|
82
|
+
request=request,
|
|
83
|
+
context=context,
|
|
84
|
+
user_info=shared_user_info.get(),
|
|
85
|
+
method_name=method_name,
|
|
86
|
+
response=unary_response or error,
|
|
87
|
+
)
|
|
88
|
+
self.log_plugin.write_log(log_entry)
|
|
89
|
+
return unary_response
|
|
90
|
+
|
|
91
|
+
# For unary-stream calls, wrap the response iterator and write the event log
|
|
92
|
+
# after iteration completes
|
|
93
|
+
if method_handler.unary_stream:
|
|
94
|
+
response_iterator = cast(
|
|
95
|
+
Iterator[GrpcMessage],
|
|
96
|
+
method_handler.unary_stream(request, context),
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
def response_wrapper() -> Iterator[GrpcMessage]:
|
|
100
|
+
stream_response, error = None, None
|
|
101
|
+
try:
|
|
102
|
+
# pylint: disable=use-yield-from
|
|
103
|
+
for stream_response in response_iterator:
|
|
104
|
+
yield stream_response
|
|
105
|
+
except BaseException as e:
|
|
106
|
+
error = e
|
|
107
|
+
raise
|
|
108
|
+
finally:
|
|
109
|
+
# This block is executed after the client has consumed
|
|
110
|
+
# the entire stream, or if iteration is interrupted
|
|
111
|
+
log_entry = self.log_plugin.compose_log_after_event(
|
|
112
|
+
request=request,
|
|
113
|
+
context=context,
|
|
114
|
+
user_info=shared_user_info.get(),
|
|
115
|
+
method_name=method_name,
|
|
116
|
+
response=stream_response or error,
|
|
117
|
+
)
|
|
118
|
+
self.log_plugin.write_log(log_entry)
|
|
119
|
+
|
|
120
|
+
return response_wrapper()
|
|
121
|
+
|
|
122
|
+
raise RuntimeError() # This line is unreachable
|
|
123
|
+
|
|
124
|
+
if method_handler.unary_unary:
|
|
125
|
+
message_handler = grpc.unary_unary_rpc_method_handler
|
|
126
|
+
elif method_handler.unary_stream:
|
|
127
|
+
message_handler = grpc.unary_stream_rpc_method_handler
|
|
128
|
+
else:
|
|
129
|
+
# If the method type is not `unary_unary` or `unary_stream`, raise an error
|
|
130
|
+
raise NotImplementedError("This RPC method type is not supported.")
|
|
131
|
+
return message_handler(
|
|
132
|
+
_generic_method_handler,
|
|
133
|
+
request_deserializer=method_handler.request_deserializer,
|
|
134
|
+
response_serializer=method_handler.response_serializer,
|
|
135
|
+
)
|
flwr/superexec/exec_grpc.py
CHANGED
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
"""SuperExec gRPC API."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from collections.abc import Sequence
|
|
19
18
|
from logging import INFO
|
|
20
19
|
from typing import Optional
|
|
21
20
|
|
|
@@ -23,12 +22,14 @@ import grpc
|
|
|
23
22
|
|
|
24
23
|
from flwr.common import GRPC_MAX_MESSAGE_LENGTH
|
|
25
24
|
from flwr.common.auth_plugin import ExecAuthPlugin
|
|
25
|
+
from flwr.common.event_log_plugin import EventLogWriterPlugin
|
|
26
26
|
from flwr.common.grpc import generic_create_grpc_server
|
|
27
27
|
from flwr.common.logger import log
|
|
28
28
|
from flwr.common.typing import UserConfig
|
|
29
29
|
from flwr.proto.exec_pb2_grpc import add_ExecServicer_to_server
|
|
30
30
|
from flwr.server.superlink.ffs.ffs_factory import FfsFactory
|
|
31
31
|
from flwr.server.superlink.linkstate import LinkStateFactory
|
|
32
|
+
from flwr.superexec.exec_event_log_interceptor import ExecEventLogInterceptor
|
|
32
33
|
from flwr.superexec.exec_user_auth_interceptor import ExecUserAuthInterceptor
|
|
33
34
|
|
|
34
35
|
from .exec_servicer import ExecServicer
|
|
@@ -44,6 +45,7 @@ def run_exec_api_grpc(
|
|
|
44
45
|
certificates: Optional[tuple[bytes, bytes, bytes]],
|
|
45
46
|
config: UserConfig,
|
|
46
47
|
auth_plugin: Optional[ExecAuthPlugin] = None,
|
|
48
|
+
event_log_plugin: Optional[EventLogWriterPlugin] = None,
|
|
47
49
|
) -> grpc.Server:
|
|
48
50
|
"""Run Exec API (gRPC, request-response)."""
|
|
49
51
|
executor.set_config(config)
|
|
@@ -54,16 +56,20 @@ def run_exec_api_grpc(
|
|
|
54
56
|
executor=executor,
|
|
55
57
|
auth_plugin=auth_plugin,
|
|
56
58
|
)
|
|
57
|
-
interceptors:
|
|
59
|
+
interceptors: list[grpc.ServerInterceptor] = []
|
|
58
60
|
if auth_plugin is not None:
|
|
59
|
-
interceptors
|
|
61
|
+
interceptors.append(ExecUserAuthInterceptor(auth_plugin))
|
|
62
|
+
# Event log interceptor must be added after user auth interceptor
|
|
63
|
+
if event_log_plugin is not None:
|
|
64
|
+
interceptors.append(ExecEventLogInterceptor(event_log_plugin))
|
|
65
|
+
log(INFO, "Flower event logging enabled")
|
|
60
66
|
exec_add_servicer_to_server_fn = add_ExecServicer_to_server
|
|
61
67
|
exec_grpc_server = generic_create_grpc_server(
|
|
62
68
|
servicer_and_add_fn=(exec_servicer, exec_add_servicer_to_server_fn),
|
|
63
69
|
server_address=address,
|
|
64
70
|
max_message_length=GRPC_MAX_MESSAGE_LENGTH,
|
|
65
71
|
certificates=certificates,
|
|
66
|
-
interceptors=interceptors,
|
|
72
|
+
interceptors=interceptors or None,
|
|
67
73
|
)
|
|
68
74
|
|
|
69
75
|
if auth_plugin is None:
|
flwr/superexec/exec_servicer.py
CHANGED
|
@@ -28,7 +28,7 @@ from flwr.common.auth_plugin import ExecAuthPlugin
|
|
|
28
28
|
from flwr.common.constant import LOG_STREAM_INTERVAL, Status, SubStatus
|
|
29
29
|
from flwr.common.logger import log
|
|
30
30
|
from flwr.common.serde import (
|
|
31
|
-
|
|
31
|
+
config_record_from_proto,
|
|
32
32
|
run_to_proto,
|
|
33
33
|
user_config_from_proto,
|
|
34
34
|
)
|
|
@@ -79,7 +79,7 @@ class ExecServicer(exec_pb2_grpc.ExecServicer):
|
|
|
79
79
|
run_id = self.executor.start_run(
|
|
80
80
|
request.fab.content,
|
|
81
81
|
user_config_from_proto(request.override_config),
|
|
82
|
-
|
|
82
|
+
config_record_from_proto(request.federation_options),
|
|
83
83
|
)
|
|
84
84
|
|
|
85
85
|
if run_id is None:
|
|
@@ -120,7 +120,7 @@ class ExecServicer(exec_pb2_grpc.ExecServicer):
|
|
|
120
120
|
run_status = state.get_run_status({run_id})[run_id]
|
|
121
121
|
if run_status.status == Status.FINISHED:
|
|
122
122
|
log(INFO, "All logs for run ID `%s` returned", request.run_id)
|
|
123
|
-
|
|
123
|
+
break
|
|
124
124
|
|
|
125
125
|
time.sleep(LOG_STREAM_INTERVAL) # Sleep briefly to avoid busy waiting
|
|
126
126
|
|
|
@@ -163,10 +163,10 @@ class ExecServicer(exec_pb2_grpc.ExecServicer):
|
|
|
163
163
|
)
|
|
164
164
|
|
|
165
165
|
if update_success:
|
|
166
|
-
|
|
166
|
+
message_ids: set[UUID] = state.get_message_ids_from_run_id(request.run_id)
|
|
167
167
|
|
|
168
|
-
# Delete
|
|
169
|
-
state.
|
|
168
|
+
# Delete Messages and their replies for the `run_id`
|
|
169
|
+
state.delete_messages(message_ids)
|
|
170
170
|
|
|
171
171
|
return StopRunResponse(success=update_success)
|
|
172
172
|
|
|
@@ -15,11 +15,13 @@
|
|
|
15
15
|
"""Flower Exec API interceptor."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
import contextvars
|
|
19
|
+
from typing import Any, Callable, Union, cast
|
|
19
20
|
|
|
20
21
|
import grpc
|
|
21
22
|
|
|
22
23
|
from flwr.common.auth_plugin import ExecAuthPlugin
|
|
24
|
+
from flwr.common.typing import UserInfo
|
|
23
25
|
from flwr.proto.exec_pb2 import ( # pylint: disable=E0611
|
|
24
26
|
GetAuthTokensRequest,
|
|
25
27
|
GetAuthTokensResponse,
|
|
@@ -43,6 +45,11 @@ Response = Union[
|
|
|
43
45
|
]
|
|
44
46
|
|
|
45
47
|
|
|
48
|
+
shared_user_info: contextvars.ContextVar[UserInfo] = contextvars.ContextVar(
|
|
49
|
+
"user_info", default=UserInfo(user_id=None, user_name=None)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
46
53
|
class ExecUserAuthInterceptor(grpc.ServerInterceptor): # type: ignore
|
|
47
54
|
"""Exec API interceptor for user authentication."""
|
|
48
55
|
|
|
@@ -77,11 +84,22 @@ class ExecUserAuthInterceptor(grpc.ServerInterceptor): # type: ignore
|
|
|
77
84
|
) -> Response:
|
|
78
85
|
call = method_handler.unary_unary or method_handler.unary_stream
|
|
79
86
|
metadata = context.invocation_metadata()
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
87
|
+
|
|
88
|
+
# Intercept GetLoginDetails and GetAuthTokens requests, and return
|
|
89
|
+
# the response without authentication
|
|
90
|
+
if isinstance(request, (GetLoginDetailsRequest, GetAuthTokensRequest)):
|
|
91
|
+
return call(request, context) # type: ignore
|
|
92
|
+
|
|
93
|
+
# For other requests, check if the user is authenticated
|
|
94
|
+
valid_tokens, user_info = self.auth_plugin.validate_tokens_in_metadata(
|
|
95
|
+
metadata
|
|
96
|
+
)
|
|
97
|
+
if valid_tokens:
|
|
98
|
+
# Store user info in contextvars for authenticated users
|
|
99
|
+
shared_user_info.set(cast(UserInfo, user_info))
|
|
83
100
|
return call(request, context) # type: ignore
|
|
84
101
|
|
|
102
|
+
# If the user is not authenticated, refresh tokens
|
|
85
103
|
tokens = self.auth_plugin.refresh_tokens(context.invocation_metadata())
|
|
86
104
|
if tokens is not None:
|
|
87
105
|
context.send_initial_metadata(tokens)
|
flwr/superexec/executor.py
CHANGED
|
@@ -20,7 +20,7 @@ from dataclasses import dataclass, field
|
|
|
20
20
|
from subprocess import Popen
|
|
21
21
|
from typing import Optional
|
|
22
22
|
|
|
23
|
-
from flwr.common import
|
|
23
|
+
from flwr.common import ConfigRecord
|
|
24
24
|
from flwr.common.typing import UserConfig
|
|
25
25
|
from flwr.server.superlink.ffs.ffs_factory import FfsFactory
|
|
26
26
|
from flwr.server.superlink.linkstate import LinkStateFactory
|
|
@@ -73,7 +73,7 @@ class Executor(ABC):
|
|
|
73
73
|
self,
|
|
74
74
|
fab_file: bytes,
|
|
75
75
|
override_config: UserConfig,
|
|
76
|
-
federation_options:
|
|
76
|
+
federation_options: ConfigRecord,
|
|
77
77
|
) -> Optional[int]:
|
|
78
78
|
"""Start a run using the given Flower FAB ID and version.
|
|
79
79
|
|
|
@@ -86,7 +86,7 @@ class Executor(ABC):
|
|
|
86
86
|
The Flower App Bundle file bytes.
|
|
87
87
|
override_config: UserConfig
|
|
88
88
|
The config overrides dict sent by the user (using `flwr run`).
|
|
89
|
-
federation_options:
|
|
89
|
+
federation_options: ConfigRecord
|
|
90
90
|
The federation options sent by the user (using `flwr run`).
|
|
91
91
|
|
|
92
92
|
Returns
|
flwr/superexec/simulation.py
CHANGED
|
@@ -22,7 +22,7 @@ from typing import Optional
|
|
|
22
22
|
from typing_extensions import override
|
|
23
23
|
|
|
24
24
|
from flwr.cli.config_utils import get_fab_metadata
|
|
25
|
-
from flwr.common import
|
|
25
|
+
from flwr.common import ConfigRecord, Context, RecordDict
|
|
26
26
|
from flwr.common.logger import log
|
|
27
27
|
from flwr.common.typing import Fab, UserConfig
|
|
28
28
|
from flwr.server.superlink.ffs import Ffs
|
|
@@ -76,7 +76,7 @@ class SimulationEngine(Executor):
|
|
|
76
76
|
self,
|
|
77
77
|
fab_file: bytes,
|
|
78
78
|
override_config: UserConfig,
|
|
79
|
-
federation_options:
|
|
79
|
+
federation_options: ConfigRecord,
|
|
80
80
|
) -> Optional[int]:
|
|
81
81
|
"""Start run using the Flower Simulation Engine."""
|
|
82
82
|
try:
|
|
@@ -104,7 +104,7 @@ class SimulationEngine(Executor):
|
|
|
104
104
|
run_id=run_id,
|
|
105
105
|
node_id=0,
|
|
106
106
|
node_config={},
|
|
107
|
-
state=
|
|
107
|
+
state=RecordDict(),
|
|
108
108
|
run_config={},
|
|
109
109
|
)
|
|
110
110
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: flwr
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.17.0
|
|
4
4
|
Summary: Flower: A Friendly Federated AI Framework
|
|
5
5
|
Home-page: https://flower.ai
|
|
6
6
|
License: Apache-2.0
|
|
7
7
|
Keywords: Artificial Intelligence,Federated AI,Federated Analytics,Federated Evaluation,Federated Learning,Flower,Machine Learning
|
|
8
8
|
Author: The Flower Authors
|
|
9
9
|
Author-email: hello@flower.ai
|
|
10
|
-
Requires-Python: >=3.9,<4.0
|
|
10
|
+
Requires-Python: >=3.9.2,<4.0.0
|
|
11
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -16,12 +16,12 @@ Classifier: Operating System :: MacOS :: MacOS X
|
|
|
16
16
|
Classifier: Operating System :: POSIX :: Linux
|
|
17
17
|
Classifier: Programming Language :: Python
|
|
18
18
|
Classifier: Programming Language :: Python :: 3
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.10
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.11
|
|
22
21
|
Classifier: Programming Language :: Python :: 3.12
|
|
23
22
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
24
23
|
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
25
25
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
26
26
|
Classifier: Topic :: Scientific/Engineering
|
|
27
27
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
@@ -32,7 +32,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
32
32
|
Classifier: Typing :: Typed
|
|
33
33
|
Provides-Extra: rest
|
|
34
34
|
Provides-Extra: simulation
|
|
35
|
-
Requires-Dist: cryptography (>=
|
|
35
|
+
Requires-Dist: cryptography (>=44.0.1,<45.0.0)
|
|
36
36
|
Requires-Dist: grpcio (>=1.62.3,<2.0.0,!=1.65.0)
|
|
37
37
|
Requires-Dist: iterators (>=0.0.2,<0.0.3)
|
|
38
38
|
Requires-Dist: numpy (>=1.26.0,<3.0.0)
|
|
@@ -63,7 +63,7 @@ Description-Content-Type: text/markdown
|
|
|
63
63
|
<a href="https://flower.ai/">Website</a> |
|
|
64
64
|
<a href="https://flower.ai/blog">Blog</a> |
|
|
65
65
|
<a href="https://flower.ai/docs/">Docs</a> |
|
|
66
|
-
<a href="https://flower.ai/
|
|
66
|
+
<a href="https://flower.ai/events/flower-ai-summit-2025">Summit</a> |
|
|
67
67
|
<a href="https://flower.ai/join-slack">Slack</a>
|
|
68
68
|
<br /><br />
|
|
69
69
|
</p>
|