flwr-nightly 1.11.0.dev20240818__py3-none-any.whl → 1.11.0.dev20240819__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/install.py +3 -1
- flwr/client/app.py +55 -31
- flwr/client/clientapp/app.py +101 -54
- flwr/client/clientapp/clientappio_servicer.py +23 -19
- flwr/client/supernode/app.py +20 -6
- flwr/proto/clientappio_pb2.py +10 -10
- flwr/proto/clientappio_pb2.pyi +7 -2
- flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +3 -1
- flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +8 -2
- {flwr_nightly-1.11.0.dev20240818.dist-info → flwr_nightly-1.11.0.dev20240819.dist-info}/METADATA +2 -2
- {flwr_nightly-1.11.0.dev20240818.dist-info → flwr_nightly-1.11.0.dev20240819.dist-info}/RECORD +14 -14
- {flwr_nightly-1.11.0.dev20240818.dist-info → flwr_nightly-1.11.0.dev20240819.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.11.0.dev20240818.dist-info → flwr_nightly-1.11.0.dev20240819.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.11.0.dev20240818.dist-info → flwr_nightly-1.11.0.dev20240819.dist-info}/entry_points.txt +0 -0
flwr/cli/install.py
CHANGED
|
@@ -173,7 +173,9 @@ def validate_and_install(
|
|
|
173
173
|
/ project_name
|
|
174
174
|
/ version
|
|
175
175
|
)
|
|
176
|
-
if install_dir.exists()
|
|
176
|
+
if install_dir.exists():
|
|
177
|
+
if skip_prompt:
|
|
178
|
+
return install_dir
|
|
177
179
|
if not typer.confirm(
|
|
178
180
|
typer.style(
|
|
179
181
|
f"\n💬 {project_name} version {version} is already installed, "
|
flwr/client/app.py
CHANGED
|
@@ -52,7 +52,7 @@ from flwr.proto.clientappio_pb2_grpc import add_ClientAppIoServicer_to_server
|
|
|
52
52
|
from flwr.server.superlink.fleet.grpc_bidi.grpc_server import generic_create_grpc_server
|
|
53
53
|
from flwr.server.superlink.state.utils import generate_rand_int_from_bytes
|
|
54
54
|
|
|
55
|
-
from .clientapp.clientappio_servicer import
|
|
55
|
+
from .clientapp.clientappio_servicer import ClientAppInputs, ClientAppIoServicer
|
|
56
56
|
from .grpc_adapter_client.connection import grpc_adapter
|
|
57
57
|
from .grpc_client.connection import grpc_connection
|
|
58
58
|
from .grpc_rere_client.connection import grpc_request_response
|
|
@@ -62,6 +62,9 @@ from .numpy_client import NumPyClient
|
|
|
62
62
|
|
|
63
63
|
ADDRESS_CLIENTAPPIO_API_GRPC_RERE = "0.0.0.0:9094"
|
|
64
64
|
|
|
65
|
+
ISOLATION_MODE_SUBPROCESS = "subprocess"
|
|
66
|
+
ISOLATION_MODE_PROCESS = "process"
|
|
67
|
+
|
|
65
68
|
|
|
66
69
|
def _check_actionable_client(
|
|
67
70
|
client: Optional[Client], client_fn: Optional[ClientFnExt]
|
|
@@ -207,7 +210,7 @@ def start_client_internal(
|
|
|
207
210
|
max_retries: Optional[int] = None,
|
|
208
211
|
max_wait_time: Optional[float] = None,
|
|
209
212
|
flwr_path: Optional[Path] = None,
|
|
210
|
-
|
|
213
|
+
isolation: Optional[str] = None,
|
|
211
214
|
supernode_address: Optional[str] = ADDRESS_CLIENTAPPIO_API_GRPC_RERE,
|
|
212
215
|
) -> None:
|
|
213
216
|
"""Start a Flower client node which connects to a Flower server.
|
|
@@ -256,11 +259,13 @@ def start_client_internal(
|
|
|
256
259
|
If set to None, there is no limit to the total time.
|
|
257
260
|
flwr_path: Optional[Path] (default: None)
|
|
258
261
|
The fully resolved path containing installed Flower Apps.
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
`
|
|
262
|
-
`
|
|
263
|
-
gRPC at the address
|
|
262
|
+
isolation : Optional[str] (default: None)
|
|
263
|
+
Isolation mode for `ClientApp`. Possible values are `subprocess` and
|
|
264
|
+
`process`. Defaults to `None`, which runs the `ClientApp` in the same process
|
|
265
|
+
as the SuperNode. If `subprocess`, the `ClientApp` runs in a subprocess started
|
|
266
|
+
by the SueprNode and communicates using gRPC at the address
|
|
267
|
+
`supernode_address`. If `process`, the `ClientApp` runs in a separate isolated
|
|
268
|
+
process and communicates using gRPC at the address `supernode_address`.
|
|
264
269
|
supernode_address : Optional[str] (default: `ADDRESS_CLIENTAPPIO_API_GRPC_RERE`)
|
|
265
270
|
The SuperNode gRPC server address.
|
|
266
271
|
"""
|
|
@@ -288,9 +293,12 @@ def start_client_internal(
|
|
|
288
293
|
|
|
289
294
|
load_client_app_fn = _load_client_app
|
|
290
295
|
|
|
291
|
-
if
|
|
296
|
+
if isolation:
|
|
292
297
|
if supernode_address is None:
|
|
293
|
-
raise ValueError(
|
|
298
|
+
raise ValueError(
|
|
299
|
+
f"`supernode_address` required when `isolation` is "
|
|
300
|
+
f"{ISOLATION_MODE_SUBPROCESS} or {ISOLATION_MODE_PROCESS}",
|
|
301
|
+
)
|
|
294
302
|
_clientappio_grpc_server, clientappio_servicer = run_clientappio_api_grpc(
|
|
295
303
|
address=supernode_address
|
|
296
304
|
)
|
|
@@ -390,6 +398,7 @@ def start_client_internal(
|
|
|
390
398
|
)
|
|
391
399
|
|
|
392
400
|
app_state_tracker.register_signal_handler()
|
|
401
|
+
# pylint: disable=too-many-nested-blocks
|
|
393
402
|
while not app_state_tracker.interrupt:
|
|
394
403
|
try:
|
|
395
404
|
# Receive
|
|
@@ -431,7 +440,9 @@ def start_client_internal(
|
|
|
431
440
|
run: Run = runs[run_id]
|
|
432
441
|
if get_fab is not None and run.fab_hash:
|
|
433
442
|
fab = get_fab(run.fab_hash)
|
|
434
|
-
|
|
443
|
+
if not isolation:
|
|
444
|
+
# If `ClientApp` runs in the same process, install the FAB
|
|
445
|
+
install_from_fab(fab.content, flwr_path, True)
|
|
435
446
|
fab_id, fab_version = get_fab_metadata(fab.content)
|
|
436
447
|
else:
|
|
437
448
|
fab = None
|
|
@@ -455,39 +466,51 @@ def start_client_internal(
|
|
|
455
466
|
|
|
456
467
|
# Handle app loading and task message
|
|
457
468
|
try:
|
|
458
|
-
if
|
|
469
|
+
if isolation:
|
|
470
|
+
# Two isolation modes:
|
|
471
|
+
# 1. `subprocess`: SuperNode is starting the ClientApp
|
|
472
|
+
# process as a subprocess.
|
|
473
|
+
# 2. `process`: ClientApp process gets started separately
|
|
474
|
+
# (via `flwr-clientapp`), for example, in a separate
|
|
475
|
+
# Docker container.
|
|
476
|
+
|
|
459
477
|
# Generate SuperNode token
|
|
460
478
|
token: int = generate_rand_int_from_bytes(RUN_ID_NUM_BYTES)
|
|
461
479
|
|
|
480
|
+
# Mode 1: SuperNode starts ClientApp as subprocess
|
|
481
|
+
start_subprocess = isolation == ISOLATION_MODE_SUBPROCESS
|
|
482
|
+
|
|
462
483
|
# Share Message and Context with servicer
|
|
463
484
|
clientappio_servicer.set_inputs(
|
|
464
|
-
clientapp_input=
|
|
485
|
+
clientapp_input=ClientAppInputs(
|
|
465
486
|
message=message,
|
|
466
487
|
context=context,
|
|
467
488
|
run=run,
|
|
489
|
+
fab=fab,
|
|
468
490
|
token=token,
|
|
469
491
|
),
|
|
470
|
-
token_returned=
|
|
471
|
-
)
|
|
472
|
-
|
|
473
|
-
# Run `ClientApp` in subprocess
|
|
474
|
-
command = [
|
|
475
|
-
"flwr-clientapp",
|
|
476
|
-
"--supernode",
|
|
477
|
-
supernode_address,
|
|
478
|
-
"--token",
|
|
479
|
-
str(token),
|
|
480
|
-
]
|
|
481
|
-
subprocess.run(
|
|
482
|
-
command,
|
|
483
|
-
stdout=None,
|
|
484
|
-
stderr=None,
|
|
485
|
-
check=True,
|
|
492
|
+
token_returned=start_subprocess,
|
|
486
493
|
)
|
|
487
494
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
495
|
+
if start_subprocess:
|
|
496
|
+
# Start ClientApp subprocess
|
|
497
|
+
command = [
|
|
498
|
+
"flwr-clientapp",
|
|
499
|
+
"--supernode",
|
|
500
|
+
supernode_address,
|
|
501
|
+
"--token",
|
|
502
|
+
str(token),
|
|
503
|
+
]
|
|
504
|
+
subprocess.run(
|
|
505
|
+
command,
|
|
506
|
+
stdout=None,
|
|
507
|
+
stderr=None,
|
|
508
|
+
check=True,
|
|
509
|
+
)
|
|
510
|
+
else:
|
|
511
|
+
# Wait for output to become available
|
|
512
|
+
while not clientappio_servicer.has_outputs():
|
|
513
|
+
time.sleep(0.1)
|
|
491
514
|
|
|
492
515
|
outputs = clientappio_servicer.get_outputs()
|
|
493
516
|
reply_message, context = outputs.message, outputs.context
|
|
@@ -544,6 +567,7 @@ def start_client_internal(
|
|
|
544
567
|
except StopIteration:
|
|
545
568
|
sleep_duration = 0
|
|
546
569
|
break
|
|
570
|
+
# pylint: enable=too-many-nested-blocks
|
|
547
571
|
|
|
548
572
|
# Unregister node
|
|
549
573
|
if delete_node is not None and app_state_tracker.is_connected:
|
flwr/client/clientapp/app.py
CHANGED
|
@@ -15,11 +15,13 @@
|
|
|
15
15
|
"""Flower ClientApp process."""
|
|
16
16
|
|
|
17
17
|
import argparse
|
|
18
|
+
import time
|
|
18
19
|
from logging import DEBUG, ERROR, INFO
|
|
19
20
|
from typing import Optional, Tuple
|
|
20
21
|
|
|
21
22
|
import grpc
|
|
22
23
|
|
|
24
|
+
from flwr.cli.install import install_from_fab
|
|
23
25
|
from flwr.client.client_app import ClientApp, LoadClientAppError
|
|
24
26
|
from flwr.common import Context, Message
|
|
25
27
|
from flwr.common.constant import ErrorCode
|
|
@@ -29,11 +31,12 @@ from flwr.common.message import Error
|
|
|
29
31
|
from flwr.common.serde import (
|
|
30
32
|
context_from_proto,
|
|
31
33
|
context_to_proto,
|
|
34
|
+
fab_from_proto,
|
|
32
35
|
message_from_proto,
|
|
33
36
|
message_to_proto,
|
|
34
37
|
run_from_proto,
|
|
35
38
|
)
|
|
36
|
-
from flwr.common.typing import Run
|
|
39
|
+
from flwr.common.typing import Fab, Run
|
|
37
40
|
|
|
38
41
|
# pylint: disable=E0611
|
|
39
42
|
from flwr.proto.clientappio_pb2 import (
|
|
@@ -68,10 +71,11 @@ def flwr_clientapp() -> None:
|
|
|
68
71
|
help="Unique token generated by SuperNode for each ClientApp execution",
|
|
69
72
|
)
|
|
70
73
|
args = parser.parse_args()
|
|
74
|
+
|
|
71
75
|
log(
|
|
72
76
|
DEBUG,
|
|
73
77
|
"Staring isolated `ClientApp` connected to SuperNode ClientAppIo at %s "
|
|
74
|
-
"with
|
|
78
|
+
"with token %s",
|
|
75
79
|
args.supernode,
|
|
76
80
|
args.token,
|
|
77
81
|
)
|
|
@@ -105,46 +109,67 @@ def run_clientapp( # pylint: disable=R0914
|
|
|
105
109
|
try:
|
|
106
110
|
stub = ClientAppIoStub(channel)
|
|
107
111
|
|
|
108
|
-
|
|
109
|
-
while
|
|
110
|
-
token
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
# Don't update/change NodeState
|
|
130
|
-
|
|
131
|
-
e_code = ErrorCode.CLIENT_APP_RAISED_EXCEPTION
|
|
132
|
-
# Ex fmt: "<class 'ZeroDivisionError'>:<'division by zero'>"
|
|
133
|
-
reason = str(type(ex)) + ":<'" + str(ex) + "'>"
|
|
134
|
-
exc_entity = "ClientApp"
|
|
135
|
-
if isinstance(ex, LoadClientAppError):
|
|
136
|
-
reason = "An exception was raised when attempting to load `ClientApp`"
|
|
137
|
-
e_code = ErrorCode.LOAD_CLIENT_APP_EXCEPTION
|
|
138
|
-
|
|
139
|
-
log(ERROR, "%s raised an exception", exc_entity, exc_info=ex)
|
|
112
|
+
only_once = token is not None
|
|
113
|
+
while True:
|
|
114
|
+
# If token is not set, loop until token is received from SuperNode
|
|
115
|
+
while token is None:
|
|
116
|
+
token = get_token(stub)
|
|
117
|
+
time.sleep(1)
|
|
118
|
+
|
|
119
|
+
# Pull Message, Context, Run and (optional) FAB from SuperNode
|
|
120
|
+
message, context, run, fab = pull_message(stub=stub, token=token)
|
|
121
|
+
|
|
122
|
+
# Install FAB, if provided
|
|
123
|
+
if fab:
|
|
124
|
+
log(DEBUG, "Flower ClientApp starts FAB installation.")
|
|
125
|
+
install_from_fab(fab.content, flwr_dir=None, skip_prompt=True)
|
|
126
|
+
|
|
127
|
+
load_client_app_fn = get_load_client_app_fn(
|
|
128
|
+
default_app_ref="",
|
|
129
|
+
app_path=None,
|
|
130
|
+
multi_app=True,
|
|
131
|
+
flwr_dir=None,
|
|
132
|
+
)
|
|
140
133
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
134
|
+
try:
|
|
135
|
+
# Load ClientApp
|
|
136
|
+
client_app: ClientApp = load_client_app_fn(run.fab_id, run.fab_version)
|
|
137
|
+
|
|
138
|
+
# Execute ClientApp
|
|
139
|
+
reply_message = client_app(message=message, context=context)
|
|
140
|
+
except Exception as ex: # pylint: disable=broad-exception-caught
|
|
141
|
+
# Don't update/change NodeState
|
|
142
|
+
|
|
143
|
+
e_code = ErrorCode.CLIENT_APP_RAISED_EXCEPTION
|
|
144
|
+
# Ex fmt: "<class 'ZeroDivisionError'>:<'division by zero'>"
|
|
145
|
+
reason = str(type(ex)) + ":<'" + str(ex) + "'>"
|
|
146
|
+
exc_entity = "ClientApp"
|
|
147
|
+
if isinstance(ex, LoadClientAppError):
|
|
148
|
+
reason = (
|
|
149
|
+
"An exception was raised when attempting to load `ClientApp`"
|
|
150
|
+
)
|
|
151
|
+
e_code = ErrorCode.LOAD_CLIENT_APP_EXCEPTION
|
|
152
|
+
|
|
153
|
+
log(ERROR, "%s raised an exception", exc_entity, exc_info=ex)
|
|
154
|
+
|
|
155
|
+
# Create error message
|
|
156
|
+
reply_message = message.create_error_reply(
|
|
157
|
+
error=Error(code=e_code, reason=reason)
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# Push Message and Context to SuperNode
|
|
161
|
+
_ = push_message(
|
|
162
|
+
stub=stub, token=token, message=reply_message, context=context
|
|
144
163
|
)
|
|
145
164
|
|
|
146
|
-
|
|
147
|
-
|
|
165
|
+
# Reset token to `None` to prevent flwr-clientapp from trying to pull the
|
|
166
|
+
# same inputs again
|
|
167
|
+
token = None
|
|
168
|
+
|
|
169
|
+
# Stop the loop if `flwr-clientapp` is expected to process only a single
|
|
170
|
+
# message
|
|
171
|
+
if only_once:
|
|
172
|
+
break
|
|
148
173
|
|
|
149
174
|
except KeyboardInterrupt:
|
|
150
175
|
log(INFO, "Closing connection")
|
|
@@ -157,30 +182,52 @@ def run_clientapp( # pylint: disable=R0914
|
|
|
157
182
|
def get_token(stub: grpc.Channel) -> Optional[int]:
|
|
158
183
|
"""Get a token from SuperNode."""
|
|
159
184
|
log(DEBUG, "Flower ClientApp process requests token")
|
|
160
|
-
|
|
161
|
-
|
|
185
|
+
try:
|
|
186
|
+
res: GetTokenResponse = stub.GetToken(GetTokenRequest())
|
|
187
|
+
log(DEBUG, "[GetToken] Received token: %s", res.token)
|
|
188
|
+
return res.token
|
|
189
|
+
except grpc.RpcError as e:
|
|
190
|
+
if e.code() == grpc.StatusCode.FAILED_PRECONDITION: # pylint: disable=no-member
|
|
191
|
+
log(DEBUG, "[GetToken] No token available yet")
|
|
192
|
+
else:
|
|
193
|
+
log(ERROR, "[GetToken] gRPC error occurred: %s", str(e))
|
|
194
|
+
return None
|
|
162
195
|
|
|
163
196
|
|
|
164
|
-
def pull_message(
|
|
197
|
+
def pull_message(
|
|
198
|
+
stub: grpc.Channel, token: int
|
|
199
|
+
) -> Tuple[Message, Context, Run, Optional[Fab]]:
|
|
165
200
|
"""Pull message from SuperNode to ClientApp."""
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
201
|
+
log(INFO, "Pulling ClientAppInputs for token %s", token)
|
|
202
|
+
try:
|
|
203
|
+
res: PullClientAppInputsResponse = stub.PullClientAppInputs(
|
|
204
|
+
PullClientAppInputsRequest(token=token)
|
|
205
|
+
)
|
|
206
|
+
message = message_from_proto(res.message)
|
|
207
|
+
context = context_from_proto(res.context)
|
|
208
|
+
run = run_from_proto(res.run)
|
|
209
|
+
fab = fab_from_proto(res.fab) if res.fab else None
|
|
210
|
+
return message, context, run, fab
|
|
211
|
+
except grpc.RpcError as e:
|
|
212
|
+
log(ERROR, "[PullClientAppInputs] gRPC error occurred: %s", str(e))
|
|
213
|
+
raise e
|
|
173
214
|
|
|
174
215
|
|
|
175
216
|
def push_message(
|
|
176
217
|
stub: grpc.Channel, token: int, message: Message, context: Context
|
|
177
218
|
) -> PushClientAppOutputsResponse:
|
|
178
219
|
"""Push message to SuperNode from ClientApp."""
|
|
220
|
+
log(INFO, "Pushing ClientAppOutputs for token %s", token)
|
|
179
221
|
proto_message = message_to_proto(message)
|
|
180
222
|
proto_context = context_to_proto(context)
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
223
|
+
|
|
224
|
+
try:
|
|
225
|
+
res: PushClientAppOutputsResponse = stub.PushClientAppOutputs(
|
|
226
|
+
PushClientAppOutputsRequest(
|
|
227
|
+
token=token, message=proto_message, context=proto_context
|
|
228
|
+
)
|
|
184
229
|
)
|
|
185
|
-
|
|
186
|
-
|
|
230
|
+
return res
|
|
231
|
+
except grpc.RpcError as e:
|
|
232
|
+
log(ERROR, "[PushClientAppOutputs] gRPC error occurred: %s", str(e))
|
|
233
|
+
raise e
|
|
@@ -27,11 +27,12 @@ from flwr.common.serde import (
|
|
|
27
27
|
clientappstatus_to_proto,
|
|
28
28
|
context_from_proto,
|
|
29
29
|
context_to_proto,
|
|
30
|
+
fab_to_proto,
|
|
30
31
|
message_from_proto,
|
|
31
32
|
message_to_proto,
|
|
32
33
|
run_to_proto,
|
|
33
34
|
)
|
|
34
|
-
from flwr.common.typing import Run
|
|
35
|
+
from flwr.common.typing import Fab, Run
|
|
35
36
|
|
|
36
37
|
# pylint: disable=E0611
|
|
37
38
|
from flwr.proto import clientappio_pb2_grpc
|
|
@@ -46,17 +47,18 @@ from flwr.proto.clientappio_pb2 import ( # pylint: disable=E0401
|
|
|
46
47
|
|
|
47
48
|
|
|
48
49
|
@dataclass
|
|
49
|
-
class
|
|
50
|
+
class ClientAppInputs:
|
|
50
51
|
"""Specify the inputs to the ClientApp."""
|
|
51
52
|
|
|
52
53
|
message: Message
|
|
53
54
|
context: Context
|
|
54
55
|
run: Run
|
|
56
|
+
fab: Optional[Fab]
|
|
55
57
|
token: int
|
|
56
58
|
|
|
57
59
|
|
|
58
60
|
@dataclass
|
|
59
|
-
class
|
|
61
|
+
class ClientAppOutputs:
|
|
60
62
|
"""Specify the outputs from the ClientApp."""
|
|
61
63
|
|
|
62
64
|
message: Message
|
|
@@ -68,8 +70,8 @@ class ClientAppIoServicer(clientappio_pb2_grpc.ClientAppIoServicer):
|
|
|
68
70
|
"""ClientAppIo API servicer."""
|
|
69
71
|
|
|
70
72
|
def __init__(self) -> None:
|
|
71
|
-
self.clientapp_input: Optional[
|
|
72
|
-
self.clientapp_output: Optional[
|
|
73
|
+
self.clientapp_input: Optional[ClientAppInputs] = None
|
|
74
|
+
self.clientapp_output: Optional[ClientAppOutputs] = None
|
|
73
75
|
self.token_returned: bool = False
|
|
74
76
|
self.inputs_returned: bool = False
|
|
75
77
|
|
|
@@ -79,13 +81,13 @@ class ClientAppIoServicer(clientappio_pb2_grpc.ClientAppIoServicer):
|
|
|
79
81
|
"""Get token."""
|
|
80
82
|
log(DEBUG, "ClientAppIo.GetToken")
|
|
81
83
|
|
|
82
|
-
# Fail if no
|
|
84
|
+
# Fail if no ClientAppInputs are available
|
|
83
85
|
if self.clientapp_input is None:
|
|
84
86
|
context.abort(
|
|
85
87
|
grpc.StatusCode.FAILED_PRECONDITION,
|
|
86
88
|
"No inputs available.",
|
|
87
89
|
)
|
|
88
|
-
clientapp_input = cast(
|
|
90
|
+
clientapp_input = cast(ClientAppInputs, self.clientapp_input)
|
|
89
91
|
|
|
90
92
|
# Fail if token was already returned in a previous call
|
|
91
93
|
if self.token_returned:
|
|
@@ -95,7 +97,7 @@ class ClientAppIoServicer(clientappio_pb2_grpc.ClientAppIoServicer):
|
|
|
95
97
|
)
|
|
96
98
|
|
|
97
99
|
# If
|
|
98
|
-
# -
|
|
100
|
+
# - ClientAppInputs is set, and
|
|
99
101
|
# - token hasn't been returned before,
|
|
100
102
|
# return token
|
|
101
103
|
self.token_returned = True
|
|
@@ -107,13 +109,13 @@ class ClientAppIoServicer(clientappio_pb2_grpc.ClientAppIoServicer):
|
|
|
107
109
|
"""Pull Message, Context, and Run."""
|
|
108
110
|
log(DEBUG, "ClientAppIo.PullClientAppInputs")
|
|
109
111
|
|
|
110
|
-
# Fail if no
|
|
112
|
+
# Fail if no ClientAppInputs are available
|
|
111
113
|
if self.clientapp_input is None:
|
|
112
114
|
context.abort(
|
|
113
115
|
grpc.StatusCode.FAILED_PRECONDITION,
|
|
114
116
|
"No inputs available.",
|
|
115
117
|
)
|
|
116
|
-
clientapp_input = cast(
|
|
118
|
+
clientapp_input = cast(ClientAppInputs, self.clientapp_input)
|
|
117
119
|
|
|
118
120
|
# Fail if token wasn't returned in a previous call
|
|
119
121
|
if not self.token_returned:
|
|
@@ -136,6 +138,7 @@ class ClientAppIoServicer(clientappio_pb2_grpc.ClientAppIoServicer):
|
|
|
136
138
|
message=message_to_proto(clientapp_input.message),
|
|
137
139
|
context=context_to_proto(clientapp_input.context),
|
|
138
140
|
run=run_to_proto(clientapp_input.run),
|
|
141
|
+
fab=fab_to_proto(clientapp_input.fab) if clientapp_input.fab else None,
|
|
139
142
|
)
|
|
140
143
|
|
|
141
144
|
def PushClientAppOutputs(
|
|
@@ -144,13 +147,13 @@ class ClientAppIoServicer(clientappio_pb2_grpc.ClientAppIoServicer):
|
|
|
144
147
|
"""Push Message and Context."""
|
|
145
148
|
log(DEBUG, "ClientAppIo.PushClientAppOutputs")
|
|
146
149
|
|
|
147
|
-
# Fail if no
|
|
150
|
+
# Fail if no ClientAppInputs are available
|
|
148
151
|
if not self.clientapp_input:
|
|
149
152
|
context.abort(
|
|
150
153
|
grpc.StatusCode.FAILED_PRECONDITION,
|
|
151
154
|
"No inputs available.",
|
|
152
155
|
)
|
|
153
|
-
clientapp_input = cast(
|
|
156
|
+
clientapp_input = cast(ClientAppInputs, self.clientapp_input)
|
|
154
157
|
|
|
155
158
|
# Fail if token wasn't returned in a previous call
|
|
156
159
|
if not self.token_returned:
|
|
@@ -178,7 +181,7 @@ class ClientAppIoServicer(clientappio_pb2_grpc.ClientAppIoServicer):
|
|
|
178
181
|
# Preconditions met
|
|
179
182
|
try:
|
|
180
183
|
# Update Message and Context
|
|
181
|
-
self.clientapp_output =
|
|
184
|
+
self.clientapp_output = ClientAppOutputs(
|
|
182
185
|
message=message_from_proto(request.message),
|
|
183
186
|
context=context_from_proto(request.context),
|
|
184
187
|
)
|
|
@@ -196,13 +199,13 @@ class ClientAppIoServicer(clientappio_pb2_grpc.ClientAppIoServicer):
|
|
|
196
199
|
return PushClientAppOutputsResponse(status=proto_status)
|
|
197
200
|
|
|
198
201
|
def set_inputs(
|
|
199
|
-
self, clientapp_input:
|
|
202
|
+
self, clientapp_input: ClientAppInputs, token_returned: bool
|
|
200
203
|
) -> None:
|
|
201
204
|
"""Set ClientApp inputs.
|
|
202
205
|
|
|
203
206
|
Parameters
|
|
204
207
|
----------
|
|
205
|
-
clientapp_input :
|
|
208
|
+
clientapp_input : ClientAppInputs
|
|
206
209
|
The inputs to the ClientApp.
|
|
207
210
|
token_returned : bool
|
|
208
211
|
A boolean indicating if the token has been returned.
|
|
@@ -215,9 +218,10 @@ class ClientAppIoServicer(clientappio_pb2_grpc.ClientAppIoServicer):
|
|
|
215
218
|
or self.token_returned
|
|
216
219
|
):
|
|
217
220
|
raise ValueError(
|
|
218
|
-
"
|
|
221
|
+
"ClientAppInputs and ClientAppOutputs must not be set before "
|
|
219
222
|
"calling `set_inputs`."
|
|
220
223
|
)
|
|
224
|
+
log(DEBUG, "ClientAppInputs set (token: %s)", clientapp_input.token)
|
|
221
225
|
self.clientapp_input = clientapp_input
|
|
222
226
|
self.token_returned = token_returned
|
|
223
227
|
|
|
@@ -225,13 +229,13 @@ class ClientAppIoServicer(clientappio_pb2_grpc.ClientAppIoServicer):
|
|
|
225
229
|
"""Check if ClientAppOutputs are available."""
|
|
226
230
|
return self.clientapp_output is not None
|
|
227
231
|
|
|
228
|
-
def get_outputs(self) ->
|
|
232
|
+
def get_outputs(self) -> ClientAppOutputs:
|
|
229
233
|
"""Get ClientApp outputs."""
|
|
230
234
|
if self.clientapp_output is None:
|
|
231
|
-
raise ValueError("
|
|
235
|
+
raise ValueError("ClientAppOutputs not set before calling `get_outputs`.")
|
|
232
236
|
|
|
233
237
|
# Set outputs to a local variable and clear state
|
|
234
|
-
output:
|
|
238
|
+
output: ClientAppOutputs = self.clientapp_output
|
|
235
239
|
self.clientapp_input = None
|
|
236
240
|
self.clientapp_output = None
|
|
237
241
|
self.token_returned = False
|
flwr/client/supernode/app.py
CHANGED
|
@@ -37,7 +37,11 @@ from flwr.common.constant import (
|
|
|
37
37
|
from flwr.common.exit_handlers import register_exit_handlers
|
|
38
38
|
from flwr.common.logger import log, warn_deprecated_feature
|
|
39
39
|
|
|
40
|
-
from ..app import
|
|
40
|
+
from ..app import (
|
|
41
|
+
ISOLATION_MODE_PROCESS,
|
|
42
|
+
ISOLATION_MODE_SUBPROCESS,
|
|
43
|
+
start_client_internal,
|
|
44
|
+
)
|
|
41
45
|
from ..clientapp.utils import get_load_client_app_fn
|
|
42
46
|
|
|
43
47
|
ADDRESS_FLEET_API_GRPC_RERE = "0.0.0.0:9092"
|
|
@@ -62,6 +66,8 @@ def run_supernode() -> None:
|
|
|
62
66
|
)
|
|
63
67
|
authentication_keys = _try_setup_client_authentication(args)
|
|
64
68
|
|
|
69
|
+
log(DEBUG, "Isolation mode: %s", args.isolation)
|
|
70
|
+
|
|
65
71
|
start_client_internal(
|
|
66
72
|
server_address=args.superlink,
|
|
67
73
|
load_client_app_fn=load_fn,
|
|
@@ -72,7 +78,7 @@ def run_supernode() -> None:
|
|
|
72
78
|
max_retries=args.max_retries,
|
|
73
79
|
max_wait_time=args.max_wait_time,
|
|
74
80
|
node_config=parse_config_args([args.node_config]),
|
|
75
|
-
|
|
81
|
+
isolation=args.isolation,
|
|
76
82
|
supernode_address=args.supernode_address,
|
|
77
83
|
)
|
|
78
84
|
|
|
@@ -199,10 +205,18 @@ def _parse_args_run_supernode() -> argparse.ArgumentParser:
|
|
|
199
205
|
""",
|
|
200
206
|
)
|
|
201
207
|
parser.add_argument(
|
|
202
|
-
"--
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
208
|
+
"--isolation",
|
|
209
|
+
default=None,
|
|
210
|
+
required=False,
|
|
211
|
+
choices=[
|
|
212
|
+
ISOLATION_MODE_SUBPROCESS,
|
|
213
|
+
ISOLATION_MODE_PROCESS,
|
|
214
|
+
],
|
|
215
|
+
help="Isolation mode when running `ClientApp` (optional, possible values: "
|
|
216
|
+
"`subprocess`, `process`). By default, `ClientApp` runs in the same process "
|
|
217
|
+
"that executes the SuperNode. Use `subprocess` to configure SuperNode to run "
|
|
218
|
+
"`ClientApp` in a subprocess. Use `process` to indicate that a separate "
|
|
219
|
+
"independent process gets created outside of SuperNode.",
|
|
206
220
|
)
|
|
207
221
|
parser.add_argument(
|
|
208
222
|
"--supernode-address",
|
flwr/proto/clientappio_pb2.py
CHANGED
|
@@ -17,15 +17,15 @@ from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2
|
|
|
17
17
|
from flwr.proto import message_pb2 as flwr_dot_proto_dot_message__pb2
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x66lwr/proto/clientappio.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x18\x66lwr/proto/message.proto\"W\n\x15\x43lientAppOutputStatus\x12-\n\x04\x63ode\x18\x01 \x01(\x0e\x32\x1f.flwr.proto.ClientAppOutputCode\x12\x0f\n\x07message\x18\x02 \x01(\t\"\x11\n\x0fGetTokenRequest\"!\n\x10GetTokenResponse\x12\r\n\x05token\x18\x01 \x01(\x12\"+\n\x1aPullClientAppInputsRequest\x12\r\n\x05token\x18\x01 \x01(\x12\"\
|
|
20
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x66lwr/proto/clientappio.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x18\x66lwr/proto/message.proto\"W\n\x15\x43lientAppOutputStatus\x12-\n\x04\x63ode\x18\x01 \x01(\x0e\x32\x1f.flwr.proto.ClientAppOutputCode\x12\x0f\n\x07message\x18\x02 \x01(\t\"\x11\n\x0fGetTokenRequest\"!\n\x10GetTokenResponse\x12\r\n\x05token\x18\x01 \x01(\x12\"+\n\x1aPullClientAppInputsRequest\x12\r\n\x05token\x18\x01 \x01(\x12\"\xa5\x01\n\x1bPullClientAppInputsResponse\x12$\n\x07message\x18\x01 \x01(\x0b\x32\x13.flwr.proto.Message\x12$\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x13.flwr.proto.Context\x12\x1c\n\x03run\x18\x03 \x01(\x0b\x32\x0f.flwr.proto.Run\x12\x1c\n\x03\x66\x61\x62\x18\x04 \x01(\x0b\x32\x0f.flwr.proto.Fab\"x\n\x1bPushClientAppOutputsRequest\x12\r\n\x05token\x18\x01 \x01(\x12\x12$\n\x07message\x18\x02 \x01(\x0b\x32\x13.flwr.proto.Message\x12$\n\x07\x63ontext\x18\x03 \x01(\x0b\x32\x13.flwr.proto.Context\"Q\n\x1cPushClientAppOutputsResponse\x12\x31\n\x06status\x18\x01 \x01(\x0b\x32!.flwr.proto.ClientAppOutputStatus*L\n\x13\x43lientAppOutputCode\x12\x0b\n\x07SUCCESS\x10\x00\x12\x15\n\x11\x44\x45\x41\x44LINE_EXCEEDED\x10\x01\x12\x11\n\rUNKNOWN_ERROR\x10\x02\x32\xad\x02\n\x0b\x43lientAppIo\x12G\n\x08GetToken\x12\x1b.flwr.proto.GetTokenRequest\x1a\x1c.flwr.proto.GetTokenResponse\"\x00\x12h\n\x13PullClientAppInputs\x12&.flwr.proto.PullClientAppInputsRequest\x1a\'.flwr.proto.PullClientAppInputsResponse\"\x00\x12k\n\x14PushClientAppOutputs\x12\'.flwr.proto.PushClientAppOutputsRequest\x1a(.flwr.proto.PushClientAppOutputsResponse\"\x00\x62\x06proto3')
|
|
21
21
|
|
|
22
22
|
_globals = globals()
|
|
23
23
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
24
24
|
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.clientappio_pb2', _globals)
|
|
25
25
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
|
26
26
|
DESCRIPTOR._options = None
|
|
27
|
-
_globals['_CLIENTAPPOUTPUTCODE']._serialized_start=
|
|
28
|
-
_globals['_CLIENTAPPOUTPUTCODE']._serialized_end=
|
|
27
|
+
_globals['_CLIENTAPPOUTPUTCODE']._serialized_start=675
|
|
28
|
+
_globals['_CLIENTAPPOUTPUTCODE']._serialized_end=751
|
|
29
29
|
_globals['_CLIENTAPPOUTPUTSTATUS']._serialized_start=114
|
|
30
30
|
_globals['_CLIENTAPPOUTPUTSTATUS']._serialized_end=201
|
|
31
31
|
_globals['_GETTOKENREQUEST']._serialized_start=203
|
|
@@ -35,11 +35,11 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|
|
35
35
|
_globals['_PULLCLIENTAPPINPUTSREQUEST']._serialized_start=257
|
|
36
36
|
_globals['_PULLCLIENTAPPINPUTSREQUEST']._serialized_end=300
|
|
37
37
|
_globals['_PULLCLIENTAPPINPUTSRESPONSE']._serialized_start=303
|
|
38
|
-
_globals['_PULLCLIENTAPPINPUTSRESPONSE']._serialized_end=
|
|
39
|
-
_globals['_PUSHCLIENTAPPOUTPUTSREQUEST']._serialized_start=
|
|
40
|
-
_globals['_PUSHCLIENTAPPOUTPUTSREQUEST']._serialized_end=
|
|
41
|
-
_globals['_PUSHCLIENTAPPOUTPUTSRESPONSE']._serialized_start=
|
|
42
|
-
_globals['_PUSHCLIENTAPPOUTPUTSRESPONSE']._serialized_end=
|
|
43
|
-
_globals['_CLIENTAPPIO']._serialized_start=
|
|
44
|
-
_globals['_CLIENTAPPIO']._serialized_end=
|
|
38
|
+
_globals['_PULLCLIENTAPPINPUTSRESPONSE']._serialized_end=468
|
|
39
|
+
_globals['_PUSHCLIENTAPPOUTPUTSREQUEST']._serialized_start=470
|
|
40
|
+
_globals['_PUSHCLIENTAPPOUTPUTSREQUEST']._serialized_end=590
|
|
41
|
+
_globals['_PUSHCLIENTAPPOUTPUTSRESPONSE']._serialized_start=592
|
|
42
|
+
_globals['_PUSHCLIENTAPPOUTPUTSRESPONSE']._serialized_end=673
|
|
43
|
+
_globals['_CLIENTAPPIO']._serialized_start=754
|
|
44
|
+
_globals['_CLIENTAPPIO']._serialized_end=1055
|
|
45
45
|
# @@protoc_insertion_point(module_scope)
|
flwr/proto/clientappio_pb2.pyi
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
isort:skip_file
|
|
4
4
|
"""
|
|
5
5
|
import builtins
|
|
6
|
+
import flwr.proto.fab_pb2
|
|
6
7
|
import flwr.proto.message_pb2
|
|
7
8
|
import flwr.proto.run_pb2
|
|
8
9
|
import google.protobuf.descriptor
|
|
@@ -77,20 +78,24 @@ class PullClientAppInputsResponse(google.protobuf.message.Message):
|
|
|
77
78
|
MESSAGE_FIELD_NUMBER: builtins.int
|
|
78
79
|
CONTEXT_FIELD_NUMBER: builtins.int
|
|
79
80
|
RUN_FIELD_NUMBER: builtins.int
|
|
81
|
+
FAB_FIELD_NUMBER: builtins.int
|
|
80
82
|
@property
|
|
81
83
|
def message(self) -> flwr.proto.message_pb2.Message: ...
|
|
82
84
|
@property
|
|
83
85
|
def context(self) -> flwr.proto.message_pb2.Context: ...
|
|
84
86
|
@property
|
|
85
87
|
def run(self) -> flwr.proto.run_pb2.Run: ...
|
|
88
|
+
@property
|
|
89
|
+
def fab(self) -> flwr.proto.fab_pb2.Fab: ...
|
|
86
90
|
def __init__(self,
|
|
87
91
|
*,
|
|
88
92
|
message: typing.Optional[flwr.proto.message_pb2.Message] = ...,
|
|
89
93
|
context: typing.Optional[flwr.proto.message_pb2.Context] = ...,
|
|
90
94
|
run: typing.Optional[flwr.proto.run_pb2.Run] = ...,
|
|
95
|
+
fab: typing.Optional[flwr.proto.fab_pb2.Fab] = ...,
|
|
91
96
|
) -> None: ...
|
|
92
|
-
def HasField(self, field_name: typing_extensions.Literal["context",b"context","message",b"message","run",b"run"]) -> builtins.bool: ...
|
|
93
|
-
def ClearField(self, field_name: typing_extensions.Literal["context",b"context","message",b"message","run",b"run"]) -> None: ...
|
|
97
|
+
def HasField(self, field_name: typing_extensions.Literal["context",b"context","fab",b"fab","message",b"message","run",b"run"]) -> builtins.bool: ...
|
|
98
|
+
def ClearField(self, field_name: typing_extensions.Literal["context",b"context","fab",b"fab","message",b"message","run",b"run"]) -> None: ...
|
|
94
99
|
global___PullClientAppInputsResponse = PullClientAppInputsResponse
|
|
95
100
|
|
|
96
101
|
class PushClientAppOutputsRequest(google.protobuf.message.Message):
|
|
@@ -52,10 +52,12 @@ class FleetServicer(fleet_pb2_grpc.FleetServicer):
|
|
|
52
52
|
) -> CreateNodeResponse:
|
|
53
53
|
"""."""
|
|
54
54
|
log(INFO, "FleetServicer.CreateNode")
|
|
55
|
-
|
|
55
|
+
response = message_handler.create_node(
|
|
56
56
|
request=request,
|
|
57
57
|
state=self.state_factory.state(),
|
|
58
58
|
)
|
|
59
|
+
log(INFO, "FleetServicer: Created node_id=%s", response.node.node_id)
|
|
60
|
+
return response
|
|
59
61
|
|
|
60
62
|
def DeleteNode(
|
|
61
63
|
self, request: DeleteNodeRequest, context: grpc.ServicerContext
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
import base64
|
|
19
|
-
from logging import WARNING
|
|
19
|
+
from logging import INFO, WARNING
|
|
20
20
|
from typing import Any, Callable, Optional, Sequence, Tuple, Union
|
|
21
21
|
|
|
22
22
|
import grpc
|
|
@@ -128,9 +128,15 @@ class AuthenticateServerInterceptor(grpc.ServerInterceptor): # type: ignore
|
|
|
128
128
|
context.abort(grpc.StatusCode.UNAUTHENTICATED, "Access denied")
|
|
129
129
|
|
|
130
130
|
if isinstance(request, CreateNodeRequest):
|
|
131
|
-
|
|
131
|
+
response = self._create_authenticated_node(
|
|
132
132
|
client_public_key_bytes, request, context
|
|
133
133
|
)
|
|
134
|
+
log(
|
|
135
|
+
INFO,
|
|
136
|
+
"AuthenticateServerInterceptor: Created node_id=%s",
|
|
137
|
+
response.node.node_id,
|
|
138
|
+
)
|
|
139
|
+
return response
|
|
134
140
|
|
|
135
141
|
# Verify hmac value
|
|
136
142
|
hmac_value = base64.urlsafe_b64decode(
|
{flwr_nightly-1.11.0.dev20240818.dist-info → flwr_nightly-1.11.0.dev20240819.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: flwr-nightly
|
|
3
|
-
Version: 1.11.0.
|
|
3
|
+
Version: 1.11.0.dev20240819
|
|
4
4
|
Summary: Flower: A Friendly Federated Learning Framework
|
|
5
5
|
Home-page: https://flower.ai
|
|
6
6
|
License: Apache-2.0
|
|
@@ -212,7 +212,7 @@ Other [examples](https://github.com/adap/flower/tree/main/examples):
|
|
|
212
212
|
Flower is built by a wonderful community of researchers and engineers. [Join Slack](https://flower.ai/join-slack) to meet them, [contributions](#contributing-to-flower) are welcome.
|
|
213
213
|
|
|
214
214
|
<a href="https://github.com/adap/flower/graphs/contributors">
|
|
215
|
-
<img src="https://contrib.rocks/image?repo=adap/flower" />
|
|
215
|
+
<img src="https://contrib.rocks/image?repo=adap/flower&columns=10" />
|
|
216
216
|
</a>
|
|
217
217
|
|
|
218
218
|
## Citation
|
{flwr_nightly-1.11.0.dev20240818.dist-info → flwr_nightly-1.11.0.dev20240819.dist-info}/RECORD
RENAMED
|
@@ -4,7 +4,7 @@ flwr/cli/app.py,sha256=FBcSrE35ll88VE11ib67qgsJe2GYDN25UswV9-cYcX8,1267
|
|
|
4
4
|
flwr/cli/build.py,sha256=gIR-nTgmLJY5ZtJFLN5ebFBCN3_hoqaioFT77AHojNU,5159
|
|
5
5
|
flwr/cli/config_utils.py,sha256=mDGXbcIxG14UpkUplILBYUkSk5M1LeTzZYDGNx-pFpU,7540
|
|
6
6
|
flwr/cli/example.py,sha256=1bGDYll3BXQY2kRqSN-oICqS5n1b9m0g0RvXTopXHl4,2215
|
|
7
|
-
flwr/cli/install.py,sha256=
|
|
7
|
+
flwr/cli/install.py,sha256=tUncrbZYRbC9QEcWSeTER16plPEoU-ERP0-nMgWiSPo,7094
|
|
8
8
|
flwr/cli/new/__init__.py,sha256=cQzK1WH4JP2awef1t2UQ2xjl1agVEz9rwutV18SWV1k,789
|
|
9
9
|
flwr/cli/new/new.py,sha256=VNb31-NLedm-_OK_D0aed0QxHO-tVlXjnf9UWVhC_Jk,9612
|
|
10
10
|
flwr/cli/new/templates/__init__.py,sha256=4luU8RL-CK8JJCstQ_ON809W9bNTkY1l9zSaPKBkgwY,725
|
|
@@ -53,12 +53,12 @@ flwr/cli/run/__init__.py,sha256=oCd6HmQDx-sqver1gecgx-uMA38BLTSiiKpl7RGNceg,789
|
|
|
53
53
|
flwr/cli/run/run.py,sha256=Ero4hxwZqx5ztFWvaJqslYCUBgp-AmImkomRosdGXyc,7661
|
|
54
54
|
flwr/cli/utils.py,sha256=l65Ul0YsSBPuypk0uorAtEDmLEYiUrzpCXi6zCg9mJ4,4506
|
|
55
55
|
flwr/client/__init__.py,sha256=wzJZsYJIHf_8-PMzvfbinyzzjgh1UP1vLrAw2_yEbKI,1345
|
|
56
|
-
flwr/client/app.py,sha256=
|
|
56
|
+
flwr/client/app.py,sha256=_nRrzltWI3_aAMaU3UbloPUkm08hgwr2LB7cGv4C-m4,31875
|
|
57
57
|
flwr/client/client.py,sha256=Vp9UkOkoHdNfn6iMYZsj_5m_GICiFfUlKEVaLad-YhM,8183
|
|
58
58
|
flwr/client/client_app.py,sha256=WcO4r6wrdfaus__3s22D2sYjfcptdgmVujUAYdNE6HU,10393
|
|
59
59
|
flwr/client/clientapp/__init__.py,sha256=kZqChGnTChQ1WGSUkIlW2S5bc0d0mzDubCAmZUGRpEY,800
|
|
60
|
-
flwr/client/clientapp/app.py,sha256=
|
|
61
|
-
flwr/client/clientapp/clientappio_servicer.py,sha256=
|
|
60
|
+
flwr/client/clientapp/app.py,sha256=4QtblvJsZ0-V-QBbzyNqWV13ugrgJmkZnsHpBCuqgi8,7797
|
|
61
|
+
flwr/client/clientapp/clientappio_servicer.py,sha256=5L6bjw_j3Mnx9kRFwYwxDNABKurBO5q1jZOWE_X11wQ,8522
|
|
62
62
|
flwr/client/clientapp/utils.py,sha256=2fYKY1LfZPalG5Cm5FbSuNMIDtouQg17GbrzPINyM_A,3990
|
|
63
63
|
flwr/client/dpfedavg_numpy_client.py,sha256=ylZ-LpBIKmL1HCiS8kq4pkp2QGalc8rYEzDHdRG3VRQ,7435
|
|
64
64
|
flwr/client/grpc_adapter_client/__init__.py,sha256=QyNWIbsq9DpyMk7oemiO1P3TBFfkfkctnJ1JoAkTl3s,742
|
|
@@ -87,7 +87,7 @@ flwr/client/numpy_client.py,sha256=u76GWAdHmJM88Agm2EgLQSvO8Jnk225mJTk-_TmPjFE,1
|
|
|
87
87
|
flwr/client/rest_client/__init__.py,sha256=5KGlp7pjc1dhNRkKlaNtUfQmg8wrRFh9lS3P3uRS-7Q,735
|
|
88
88
|
flwr/client/rest_client/connection.py,sha256=SglZC4jpqc_0-VBo9cBHa1_2RO9TfPUULQ49DnYeFS0,12767
|
|
89
89
|
flwr/client/supernode/__init__.py,sha256=SUhWOzcgXRNXk1V9UgB5-FaWukqqrOEajVUHEcPkwyQ,865
|
|
90
|
-
flwr/client/supernode/app.py,sha256=
|
|
90
|
+
flwr/client/supernode/app.py,sha256=_hIbD2pyXQmtRw7D_qKOnkD-Zi5SiLcOLzIuEDlrlNA,13101
|
|
91
91
|
flwr/client/typing.py,sha256=dxoTBnTMfqXr5J7G3y-uNjqxYCddvxhu89spfj4Lm2U,1048
|
|
92
92
|
flwr/common/__init__.py,sha256=4cBLNNnNTwHDnL_HCxhU5ILCSZ6fYh3A_aMBtlvHTVw,3721
|
|
93
93
|
flwr/common/address.py,sha256=wRu1Luezx1PWadwV9OA_KNko01oVvbRnPqfzaDn8QOk,1882
|
|
@@ -127,8 +127,8 @@ flwr/common/telemetry.py,sha256=nSjJHDitPhzB2qUl6LeSMT9Zld5lIk9uW98RpxQwiZw,8366
|
|
|
127
127
|
flwr/common/typing.py,sha256=rGabiSkjFvGIHwmhDqtuu-LBvz7LVSj1vyMlNtA7VA0,5004
|
|
128
128
|
flwr/common/version.py,sha256=W1ntylR04xkCP6zeSet6sRtBn7P1cje2lOqBJgYBjJY,1349
|
|
129
129
|
flwr/proto/__init__.py,sha256=hbY7JYakwZwCkYgCNlmHdc8rtvfoJbAZLalMdc--CGc,683
|
|
130
|
-
flwr/proto/clientappio_pb2.py,sha256=
|
|
131
|
-
flwr/proto/clientappio_pb2.pyi,sha256=
|
|
130
|
+
flwr/proto/clientappio_pb2.py,sha256=3qT-IbcGPFGh9WKpa9ZRKCYzUtwrDf-ziEY9uBhd_gU,3703
|
|
131
|
+
flwr/proto/clientappio_pb2.pyi,sha256=iL6pOPmnot5wP3aXGiDfiUpp-eJIkysyju0ebPehS8Y,5670
|
|
132
132
|
flwr/proto/clientappio_pb2_grpc.py,sha256=G35GhZ3iEOL8N6tu7Kn_ip4QUx4O2HveXngHAuU2YEM,6112
|
|
133
133
|
flwr/proto/clientappio_pb2_grpc.pyi,sha256=cybktpMPaIMwrItd8hQaQDnRv4zNu_wgRddSqR9REyI,1822
|
|
134
134
|
flwr/proto/common_pb2.py,sha256=uzSmq0FJdC-MriN9UGPFs7QVIFTKJmX5lyLnzcyZ5WE,2405
|
|
@@ -245,8 +245,8 @@ flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py,sha256=hh7ykcLMA_ymmD72eWFM
|
|
|
245
245
|
flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py,sha256=h3EhqgelegVC4EjOXH5birmAnMoCBJcP7jpHYCnHZPk,4887
|
|
246
246
|
flwr/server/superlink/fleet/grpc_bidi/grpc_server.py,sha256=ROH-dr7TQZ9nVXjkKOzMhxidJguX2li8--nDnXRi-dU,12095
|
|
247
247
|
flwr/server/superlink/fleet/grpc_rere/__init__.py,sha256=j2hyC342am-_Hgp1g80Y3fGDzfTI6n8QOOn2PyWf4eg,758
|
|
248
|
-
flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py,sha256=
|
|
249
|
-
flwr/server/superlink/fleet/grpc_rere/server_interceptor.py,sha256=
|
|
248
|
+
flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py,sha256=9vZPmdNuRcXsCJQUv9hrzQvdvUJO4-gvxxCHJJTFvGE,4047
|
|
249
|
+
flwr/server/superlink/fleet/grpc_rere/server_interceptor.py,sha256=DsHj6XaE0pBSWLYFsUYE44NPqx6IWWTJ9sqbh3GpmvY,7961
|
|
250
250
|
flwr/server/superlink/fleet/message_handler/__init__.py,sha256=h8oLD7uo5lKICPy0rRdKRjTYe62u8PKkT_fA4xF5JPA,731
|
|
251
251
|
flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=9qDDPwj3txHPo2dNaWQiO3UpGno5Zm9IMhJXnAPZbqg,4439
|
|
252
252
|
flwr/server/superlink/fleet/rest_rere/__init__.py,sha256=5jbYbAn75sGv-gBwOPDySE0kz96F6dTYLeMrGqNi4lM,735
|
|
@@ -286,8 +286,8 @@ flwr/superexec/exec_grpc.py,sha256=PhqGoZEpTMxSQmUSV8Wgtzb1Za_pHJ-adZqo5RYnDyE,1
|
|
|
286
286
|
flwr/superexec/exec_servicer.py,sha256=jl0aKVjm0PLQABcTL5c3jdSIzb0Z6hpVOtrAn4Ob7ts,2323
|
|
287
287
|
flwr/superexec/executor.py,sha256=k_adivto6R2U82DADOHNvdtobehBYreRek1gOEBIQnQ,2318
|
|
288
288
|
flwr/superexec/simulation.py,sha256=lfdClQYSAIMHe43aJ0Pk-kBw_xoV09LsIMfHo2eo-Ck,6775
|
|
289
|
-
flwr_nightly-1.11.0.
|
|
290
|
-
flwr_nightly-1.11.0.
|
|
291
|
-
flwr_nightly-1.11.0.
|
|
292
|
-
flwr_nightly-1.11.0.
|
|
293
|
-
flwr_nightly-1.11.0.
|
|
289
|
+
flwr_nightly-1.11.0.dev20240819.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
290
|
+
flwr_nightly-1.11.0.dev20240819.dist-info/METADATA,sha256=1TgmV-BxAz7GtNVJuJ9Ov1zrQl6dQwiZvsanz-EbQLM,15701
|
|
291
|
+
flwr_nightly-1.11.0.dev20240819.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
292
|
+
flwr_nightly-1.11.0.dev20240819.dist-info/entry_points.txt,sha256=3cDQVJEBRCSLzJrVYAgjXpoCjuQ74I3A9NZ61DOHdVo,388
|
|
293
|
+
flwr_nightly-1.11.0.dev20240819.dist-info/RECORD,,
|
{flwr_nightly-1.11.0.dev20240818.dist-info → flwr_nightly-1.11.0.dev20240819.dist-info}/LICENSE
RENAMED
|
File without changes
|
{flwr_nightly-1.11.0.dev20240818.dist-info → flwr_nightly-1.11.0.dev20240819.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|