flwr-nightly 1.11.0.dev20240809__py3-none-any.whl → 1.11.0.dev20240812__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/run/run.py +9 -6
- flwr/client/supernode/__init__.py +2 -0
- flwr/client/supernode/app.py +25 -0
- flwr/proto/clientappio_pb2.py +41 -0
- flwr/proto/clientappio_pb2.pyi +110 -0
- flwr/proto/clientappio_pb2_grpc.py +101 -0
- flwr/proto/clientappio_pb2_grpc.pyi +40 -0
- flwr/proto/message_pb2.py +41 -0
- flwr/proto/message_pb2.pyi +122 -0
- flwr/proto/message_pb2_grpc.py +4 -0
- flwr/proto/message_pb2_grpc.pyi +4 -0
- flwr/server/superlink/ffs/__init__.py +24 -0
- flwr/server/superlink/ffs/disk_ffs.py +104 -0
- flwr/server/superlink/ffs/ffs.py +79 -0
- {flwr_nightly-1.11.0.dev20240809.dist-info → flwr_nightly-1.11.0.dev20240812.dist-info}/METADATA +2 -2
- {flwr_nightly-1.11.0.dev20240809.dist-info → flwr_nightly-1.11.0.dev20240812.dist-info}/RECORD +19 -8
- {flwr_nightly-1.11.0.dev20240809.dist-info → flwr_nightly-1.11.0.dev20240812.dist-info}/entry_points.txt +1 -0
- {flwr_nightly-1.11.0.dev20240809.dist-info → flwr_nightly-1.11.0.dev20240812.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.11.0.dev20240809.dist-info → flwr_nightly-1.11.0.dev20240812.dist-info}/WHEEL +0 -0
flwr/cli/run/run.py
CHANGED
|
@@ -109,14 +109,14 @@ def run(
|
|
|
109
109
|
raise typer.Exit(code=1)
|
|
110
110
|
|
|
111
111
|
if "address" in federation_config:
|
|
112
|
-
_run_with_superexec(
|
|
112
|
+
_run_with_superexec(app, federation_config, config_overrides)
|
|
113
113
|
else:
|
|
114
|
-
_run_without_superexec(app, federation_config,
|
|
114
|
+
_run_without_superexec(app, federation_config, config_overrides, federation)
|
|
115
115
|
|
|
116
116
|
|
|
117
117
|
def _run_with_superexec(
|
|
118
|
-
federation_config: Dict[str, Any],
|
|
119
118
|
app: Optional[Path],
|
|
119
|
+
federation_config: Dict[str, Any],
|
|
120
120
|
config_overrides: Optional[List[str]],
|
|
121
121
|
) -> None:
|
|
122
122
|
|
|
@@ -162,10 +162,10 @@ def _run_with_superexec(
|
|
|
162
162
|
channel.subscribe(on_channel_state_change)
|
|
163
163
|
stub = ExecStub(channel)
|
|
164
164
|
|
|
165
|
-
fab_path = build(app)
|
|
165
|
+
fab_path = Path(build(app))
|
|
166
166
|
|
|
167
167
|
req = StartRunRequest(
|
|
168
|
-
fab_file=
|
|
168
|
+
fab_file=fab_path.read_bytes(),
|
|
169
169
|
override_config=user_config_to_proto(
|
|
170
170
|
parse_config_args(config_overrides, separator=",")
|
|
171
171
|
),
|
|
@@ -174,14 +174,17 @@ def _run_with_superexec(
|
|
|
174
174
|
),
|
|
175
175
|
)
|
|
176
176
|
res = stub.StartRun(req)
|
|
177
|
+
|
|
178
|
+
# Delete FAB file once it has been sent to the SuperExec
|
|
179
|
+
fab_path.unlink()
|
|
177
180
|
typer.secho(f"🎊 Successfully started run {res.run_id}", fg=typer.colors.GREEN)
|
|
178
181
|
|
|
179
182
|
|
|
180
183
|
def _run_without_superexec(
|
|
181
184
|
app: Optional[Path],
|
|
182
185
|
federation_config: Dict[str, Any],
|
|
183
|
-
federation: str,
|
|
184
186
|
config_overrides: Optional[List[str]],
|
|
187
|
+
federation: str,
|
|
185
188
|
) -> None:
|
|
186
189
|
try:
|
|
187
190
|
num_supernodes = federation_config["options"]["num-supernodes"]
|
|
@@ -15,10 +15,12 @@
|
|
|
15
15
|
"""Flower SuperNode."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
from .app import flwr_clientapp as flwr_clientapp
|
|
18
19
|
from .app import run_client_app as run_client_app
|
|
19
20
|
from .app import run_supernode as run_supernode
|
|
20
21
|
|
|
21
22
|
__all__ = [
|
|
23
|
+
"flwr_clientapp",
|
|
22
24
|
"run_client_app",
|
|
23
25
|
"run_supernode",
|
|
24
26
|
]
|
flwr/client/supernode/app.py
CHANGED
|
@@ -120,6 +120,31 @@ def run_client_app() -> None:
|
|
|
120
120
|
register_exit_handlers(event_type=EventType.RUN_CLIENT_APP_LEAVE)
|
|
121
121
|
|
|
122
122
|
|
|
123
|
+
def flwr_clientapp() -> None:
|
|
124
|
+
"""Run process-isolated Flower ClientApp."""
|
|
125
|
+
log(INFO, "Starting Flower ClientApp")
|
|
126
|
+
|
|
127
|
+
parser = argparse.ArgumentParser(
|
|
128
|
+
description="Run a Flower ClientApp",
|
|
129
|
+
)
|
|
130
|
+
parser.add_argument(
|
|
131
|
+
"--address",
|
|
132
|
+
help="Address of SuperNode ClientAppIo gRPC servicer",
|
|
133
|
+
)
|
|
134
|
+
parser.add_argument(
|
|
135
|
+
"--token",
|
|
136
|
+
help="Unique token generated by SuperNode for each ClientApp execution",
|
|
137
|
+
)
|
|
138
|
+
args = parser.parse_args()
|
|
139
|
+
log(
|
|
140
|
+
DEBUG,
|
|
141
|
+
"Staring isolated `ClientApp` connected to SuperNode ClientAppIo at %s "
|
|
142
|
+
"with the token %s",
|
|
143
|
+
args.address,
|
|
144
|
+
args.token,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
123
148
|
def _warn_deprecated_server_arg(args: argparse.Namespace) -> None:
|
|
124
149
|
"""Warn about the deprecated argument `--server`."""
|
|
125
150
|
if args.server != ADDRESS_FLEET_API_GRPC_RERE:
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# source: flwr/proto/clientappio.proto
|
|
4
|
+
# Protobuf Python Version: 4.25.0
|
|
5
|
+
"""Generated protocol buffer code."""
|
|
6
|
+
from google.protobuf import descriptor as _descriptor
|
|
7
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
8
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
9
|
+
from google.protobuf.internal import builder as _builder
|
|
10
|
+
# @@protoc_insertion_point(imports)
|
|
11
|
+
|
|
12
|
+
_sym_db = _symbol_database.Default()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
|
|
16
|
+
from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2
|
|
17
|
+
from flwr.proto import message_pb2 as flwr_dot_proto_dot_message__pb2
|
|
18
|
+
|
|
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\"+\n\x1aPullClientAppInputsRequest\x12\r\n\x05token\x18\x01 \x01(\x12\"\x87\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\"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\xe4\x01\n\x0b\x43lientAppIo\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
|
+
|
|
22
|
+
_globals = globals()
|
|
23
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
24
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.clientappio_pb2', _globals)
|
|
25
|
+
if _descriptor._USE_C_DESCRIPTORS == False:
|
|
26
|
+
DESCRIPTOR._options = None
|
|
27
|
+
_globals['_CLIENTAPPOUTPUTCODE']._serialized_start=591
|
|
28
|
+
_globals['_CLIENTAPPOUTPUTCODE']._serialized_end=667
|
|
29
|
+
_globals['_CLIENTAPPOUTPUTSTATUS']._serialized_start=114
|
|
30
|
+
_globals['_CLIENTAPPOUTPUTSTATUS']._serialized_end=201
|
|
31
|
+
_globals['_PULLCLIENTAPPINPUTSREQUEST']._serialized_start=203
|
|
32
|
+
_globals['_PULLCLIENTAPPINPUTSREQUEST']._serialized_end=246
|
|
33
|
+
_globals['_PULLCLIENTAPPINPUTSRESPONSE']._serialized_start=249
|
|
34
|
+
_globals['_PULLCLIENTAPPINPUTSRESPONSE']._serialized_end=384
|
|
35
|
+
_globals['_PUSHCLIENTAPPOUTPUTSREQUEST']._serialized_start=386
|
|
36
|
+
_globals['_PUSHCLIENTAPPOUTPUTSREQUEST']._serialized_end=506
|
|
37
|
+
_globals['_PUSHCLIENTAPPOUTPUTSRESPONSE']._serialized_start=508
|
|
38
|
+
_globals['_PUSHCLIENTAPPOUTPUTSRESPONSE']._serialized_end=589
|
|
39
|
+
_globals['_CLIENTAPPIO']._serialized_start=670
|
|
40
|
+
_globals['_CLIENTAPPIO']._serialized_end=898
|
|
41
|
+
# @@protoc_insertion_point(module_scope)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""
|
|
2
|
+
@generated by mypy-protobuf. Do not edit manually!
|
|
3
|
+
isort:skip_file
|
|
4
|
+
"""
|
|
5
|
+
import builtins
|
|
6
|
+
import flwr.proto.message_pb2
|
|
7
|
+
import flwr.proto.run_pb2
|
|
8
|
+
import google.protobuf.descriptor
|
|
9
|
+
import google.protobuf.internal.enum_type_wrapper
|
|
10
|
+
import google.protobuf.message
|
|
11
|
+
import typing
|
|
12
|
+
import typing_extensions
|
|
13
|
+
|
|
14
|
+
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
|
|
15
|
+
|
|
16
|
+
class _ClientAppOutputCode:
|
|
17
|
+
ValueType = typing.NewType('ValueType', builtins.int)
|
|
18
|
+
V: typing_extensions.TypeAlias = ValueType
|
|
19
|
+
class _ClientAppOutputCodeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_ClientAppOutputCode.ValueType], builtins.type):
|
|
20
|
+
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
|
|
21
|
+
SUCCESS: _ClientAppOutputCode.ValueType # 0
|
|
22
|
+
DEADLINE_EXCEEDED: _ClientAppOutputCode.ValueType # 1
|
|
23
|
+
UNKNOWN_ERROR: _ClientAppOutputCode.ValueType # 2
|
|
24
|
+
class ClientAppOutputCode(_ClientAppOutputCode, metaclass=_ClientAppOutputCodeEnumTypeWrapper):
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
SUCCESS: ClientAppOutputCode.ValueType # 0
|
|
28
|
+
DEADLINE_EXCEEDED: ClientAppOutputCode.ValueType # 1
|
|
29
|
+
UNKNOWN_ERROR: ClientAppOutputCode.ValueType # 2
|
|
30
|
+
global___ClientAppOutputCode = ClientAppOutputCode
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ClientAppOutputStatus(google.protobuf.message.Message):
|
|
34
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
35
|
+
CODE_FIELD_NUMBER: builtins.int
|
|
36
|
+
MESSAGE_FIELD_NUMBER: builtins.int
|
|
37
|
+
code: global___ClientAppOutputCode.ValueType
|
|
38
|
+
message: typing.Text
|
|
39
|
+
def __init__(self,
|
|
40
|
+
*,
|
|
41
|
+
code: global___ClientAppOutputCode.ValueType = ...,
|
|
42
|
+
message: typing.Text = ...,
|
|
43
|
+
) -> None: ...
|
|
44
|
+
def ClearField(self, field_name: typing_extensions.Literal["code",b"code","message",b"message"]) -> None: ...
|
|
45
|
+
global___ClientAppOutputStatus = ClientAppOutputStatus
|
|
46
|
+
|
|
47
|
+
class PullClientAppInputsRequest(google.protobuf.message.Message):
|
|
48
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
49
|
+
TOKEN_FIELD_NUMBER: builtins.int
|
|
50
|
+
token: builtins.int
|
|
51
|
+
def __init__(self,
|
|
52
|
+
*,
|
|
53
|
+
token: builtins.int = ...,
|
|
54
|
+
) -> None: ...
|
|
55
|
+
def ClearField(self, field_name: typing_extensions.Literal["token",b"token"]) -> None: ...
|
|
56
|
+
global___PullClientAppInputsRequest = PullClientAppInputsRequest
|
|
57
|
+
|
|
58
|
+
class PullClientAppInputsResponse(google.protobuf.message.Message):
|
|
59
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
60
|
+
MESSAGE_FIELD_NUMBER: builtins.int
|
|
61
|
+
CONTEXT_FIELD_NUMBER: builtins.int
|
|
62
|
+
RUN_FIELD_NUMBER: builtins.int
|
|
63
|
+
@property
|
|
64
|
+
def message(self) -> flwr.proto.message_pb2.Message: ...
|
|
65
|
+
@property
|
|
66
|
+
def context(self) -> flwr.proto.message_pb2.Context: ...
|
|
67
|
+
@property
|
|
68
|
+
def run(self) -> flwr.proto.run_pb2.Run: ...
|
|
69
|
+
def __init__(self,
|
|
70
|
+
*,
|
|
71
|
+
message: typing.Optional[flwr.proto.message_pb2.Message] = ...,
|
|
72
|
+
context: typing.Optional[flwr.proto.message_pb2.Context] = ...,
|
|
73
|
+
run: typing.Optional[flwr.proto.run_pb2.Run] = ...,
|
|
74
|
+
) -> None: ...
|
|
75
|
+
def HasField(self, field_name: typing_extensions.Literal["context",b"context","message",b"message","run",b"run"]) -> builtins.bool: ...
|
|
76
|
+
def ClearField(self, field_name: typing_extensions.Literal["context",b"context","message",b"message","run",b"run"]) -> None: ...
|
|
77
|
+
global___PullClientAppInputsResponse = PullClientAppInputsResponse
|
|
78
|
+
|
|
79
|
+
class PushClientAppOutputsRequest(google.protobuf.message.Message):
|
|
80
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
81
|
+
TOKEN_FIELD_NUMBER: builtins.int
|
|
82
|
+
MESSAGE_FIELD_NUMBER: builtins.int
|
|
83
|
+
CONTEXT_FIELD_NUMBER: builtins.int
|
|
84
|
+
token: builtins.int
|
|
85
|
+
@property
|
|
86
|
+
def message(self) -> flwr.proto.message_pb2.Message: ...
|
|
87
|
+
@property
|
|
88
|
+
def context(self) -> flwr.proto.message_pb2.Context: ...
|
|
89
|
+
def __init__(self,
|
|
90
|
+
*,
|
|
91
|
+
token: builtins.int = ...,
|
|
92
|
+
message: typing.Optional[flwr.proto.message_pb2.Message] = ...,
|
|
93
|
+
context: typing.Optional[flwr.proto.message_pb2.Context] = ...,
|
|
94
|
+
) -> None: ...
|
|
95
|
+
def HasField(self, field_name: typing_extensions.Literal["context",b"context","message",b"message"]) -> builtins.bool: ...
|
|
96
|
+
def ClearField(self, field_name: typing_extensions.Literal["context",b"context","message",b"message","token",b"token"]) -> None: ...
|
|
97
|
+
global___PushClientAppOutputsRequest = PushClientAppOutputsRequest
|
|
98
|
+
|
|
99
|
+
class PushClientAppOutputsResponse(google.protobuf.message.Message):
|
|
100
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
101
|
+
STATUS_FIELD_NUMBER: builtins.int
|
|
102
|
+
@property
|
|
103
|
+
def status(self) -> global___ClientAppOutputStatus: ...
|
|
104
|
+
def __init__(self,
|
|
105
|
+
*,
|
|
106
|
+
status: typing.Optional[global___ClientAppOutputStatus] = ...,
|
|
107
|
+
) -> None: ...
|
|
108
|
+
def HasField(self, field_name: typing_extensions.Literal["status",b"status"]) -> builtins.bool: ...
|
|
109
|
+
def ClearField(self, field_name: typing_extensions.Literal["status",b"status"]) -> None: ...
|
|
110
|
+
global___PushClientAppOutputsResponse = PushClientAppOutputsResponse
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
|
2
|
+
"""Client and server classes corresponding to protobuf-defined services."""
|
|
3
|
+
import grpc
|
|
4
|
+
|
|
5
|
+
from flwr.proto import clientappio_pb2 as flwr_dot_proto_dot_clientappio__pb2
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ClientAppIoStub(object):
|
|
9
|
+
"""Missing associated documentation comment in .proto file."""
|
|
10
|
+
|
|
11
|
+
def __init__(self, channel):
|
|
12
|
+
"""Constructor.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
channel: A grpc.Channel.
|
|
16
|
+
"""
|
|
17
|
+
self.PullClientAppInputs = channel.unary_unary(
|
|
18
|
+
'/flwr.proto.ClientAppIo/PullClientAppInputs',
|
|
19
|
+
request_serializer=flwr_dot_proto_dot_clientappio__pb2.PullClientAppInputsRequest.SerializeToString,
|
|
20
|
+
response_deserializer=flwr_dot_proto_dot_clientappio__pb2.PullClientAppInputsResponse.FromString,
|
|
21
|
+
)
|
|
22
|
+
self.PushClientAppOutputs = channel.unary_unary(
|
|
23
|
+
'/flwr.proto.ClientAppIo/PushClientAppOutputs',
|
|
24
|
+
request_serializer=flwr_dot_proto_dot_clientappio__pb2.PushClientAppOutputsRequest.SerializeToString,
|
|
25
|
+
response_deserializer=flwr_dot_proto_dot_clientappio__pb2.PushClientAppOutputsResponse.FromString,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ClientAppIoServicer(object):
|
|
30
|
+
"""Missing associated documentation comment in .proto file."""
|
|
31
|
+
|
|
32
|
+
def PullClientAppInputs(self, request, context):
|
|
33
|
+
"""Get Message, Context, and Run
|
|
34
|
+
"""
|
|
35
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
36
|
+
context.set_details('Method not implemented!')
|
|
37
|
+
raise NotImplementedError('Method not implemented!')
|
|
38
|
+
|
|
39
|
+
def PushClientAppOutputs(self, request, context):
|
|
40
|
+
"""Send updated Message and Context
|
|
41
|
+
"""
|
|
42
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
43
|
+
context.set_details('Method not implemented!')
|
|
44
|
+
raise NotImplementedError('Method not implemented!')
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def add_ClientAppIoServicer_to_server(servicer, server):
|
|
48
|
+
rpc_method_handlers = {
|
|
49
|
+
'PullClientAppInputs': grpc.unary_unary_rpc_method_handler(
|
|
50
|
+
servicer.PullClientAppInputs,
|
|
51
|
+
request_deserializer=flwr_dot_proto_dot_clientappio__pb2.PullClientAppInputsRequest.FromString,
|
|
52
|
+
response_serializer=flwr_dot_proto_dot_clientappio__pb2.PullClientAppInputsResponse.SerializeToString,
|
|
53
|
+
),
|
|
54
|
+
'PushClientAppOutputs': grpc.unary_unary_rpc_method_handler(
|
|
55
|
+
servicer.PushClientAppOutputs,
|
|
56
|
+
request_deserializer=flwr_dot_proto_dot_clientappio__pb2.PushClientAppOutputsRequest.FromString,
|
|
57
|
+
response_serializer=flwr_dot_proto_dot_clientappio__pb2.PushClientAppOutputsResponse.SerializeToString,
|
|
58
|
+
),
|
|
59
|
+
}
|
|
60
|
+
generic_handler = grpc.method_handlers_generic_handler(
|
|
61
|
+
'flwr.proto.ClientAppIo', rpc_method_handlers)
|
|
62
|
+
server.add_generic_rpc_handlers((generic_handler,))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# This class is part of an EXPERIMENTAL API.
|
|
66
|
+
class ClientAppIo(object):
|
|
67
|
+
"""Missing associated documentation comment in .proto file."""
|
|
68
|
+
|
|
69
|
+
@staticmethod
|
|
70
|
+
def PullClientAppInputs(request,
|
|
71
|
+
target,
|
|
72
|
+
options=(),
|
|
73
|
+
channel_credentials=None,
|
|
74
|
+
call_credentials=None,
|
|
75
|
+
insecure=False,
|
|
76
|
+
compression=None,
|
|
77
|
+
wait_for_ready=None,
|
|
78
|
+
timeout=None,
|
|
79
|
+
metadata=None):
|
|
80
|
+
return grpc.experimental.unary_unary(request, target, '/flwr.proto.ClientAppIo/PullClientAppInputs',
|
|
81
|
+
flwr_dot_proto_dot_clientappio__pb2.PullClientAppInputsRequest.SerializeToString,
|
|
82
|
+
flwr_dot_proto_dot_clientappio__pb2.PullClientAppInputsResponse.FromString,
|
|
83
|
+
options, channel_credentials,
|
|
84
|
+
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
85
|
+
|
|
86
|
+
@staticmethod
|
|
87
|
+
def PushClientAppOutputs(request,
|
|
88
|
+
target,
|
|
89
|
+
options=(),
|
|
90
|
+
channel_credentials=None,
|
|
91
|
+
call_credentials=None,
|
|
92
|
+
insecure=False,
|
|
93
|
+
compression=None,
|
|
94
|
+
wait_for_ready=None,
|
|
95
|
+
timeout=None,
|
|
96
|
+
metadata=None):
|
|
97
|
+
return grpc.experimental.unary_unary(request, target, '/flwr.proto.ClientAppIo/PushClientAppOutputs',
|
|
98
|
+
flwr_dot_proto_dot_clientappio__pb2.PushClientAppOutputsRequest.SerializeToString,
|
|
99
|
+
flwr_dot_proto_dot_clientappio__pb2.PushClientAppOutputsResponse.FromString,
|
|
100
|
+
options, channel_credentials,
|
|
101
|
+
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""
|
|
2
|
+
@generated by mypy-protobuf. Do not edit manually!
|
|
3
|
+
isort:skip_file
|
|
4
|
+
"""
|
|
5
|
+
import abc
|
|
6
|
+
import flwr.proto.clientappio_pb2
|
|
7
|
+
import grpc
|
|
8
|
+
|
|
9
|
+
class ClientAppIoStub:
|
|
10
|
+
def __init__(self, channel: grpc.Channel) -> None: ...
|
|
11
|
+
PullClientAppInputs: grpc.UnaryUnaryMultiCallable[
|
|
12
|
+
flwr.proto.clientappio_pb2.PullClientAppInputsRequest,
|
|
13
|
+
flwr.proto.clientappio_pb2.PullClientAppInputsResponse]
|
|
14
|
+
"""Get Message, Context, and Run"""
|
|
15
|
+
|
|
16
|
+
PushClientAppOutputs: grpc.UnaryUnaryMultiCallable[
|
|
17
|
+
flwr.proto.clientappio_pb2.PushClientAppOutputsRequest,
|
|
18
|
+
flwr.proto.clientappio_pb2.PushClientAppOutputsResponse]
|
|
19
|
+
"""Send updated Message and Context"""
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ClientAppIoServicer(metaclass=abc.ABCMeta):
|
|
23
|
+
@abc.abstractmethod
|
|
24
|
+
def PullClientAppInputs(self,
|
|
25
|
+
request: flwr.proto.clientappio_pb2.PullClientAppInputsRequest,
|
|
26
|
+
context: grpc.ServicerContext,
|
|
27
|
+
) -> flwr.proto.clientappio_pb2.PullClientAppInputsResponse:
|
|
28
|
+
"""Get Message, Context, and Run"""
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
@abc.abstractmethod
|
|
32
|
+
def PushClientAppOutputs(self,
|
|
33
|
+
request: flwr.proto.clientappio_pb2.PushClientAppOutputsRequest,
|
|
34
|
+
context: grpc.ServicerContext,
|
|
35
|
+
) -> flwr.proto.clientappio_pb2.PushClientAppOutputsResponse:
|
|
36
|
+
"""Send updated Message and Context"""
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def add_ClientAppIoServicer_to_server(servicer: ClientAppIoServicer, server: grpc.Server) -> None: ...
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# source: flwr/proto/message.proto
|
|
4
|
+
# Protobuf Python Version: 4.25.0
|
|
5
|
+
"""Generated protocol buffer code."""
|
|
6
|
+
from google.protobuf import descriptor as _descriptor
|
|
7
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
8
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
9
|
+
from google.protobuf.internal import builder as _builder
|
|
10
|
+
# @@protoc_insertion_point(imports)
|
|
11
|
+
|
|
12
|
+
_sym_db = _symbol_database.Default()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
from flwr.proto import error_pb2 as flwr_dot_proto_dot_error__pb2
|
|
16
|
+
from flwr.proto import recordset_pb2 as flwr_dot_proto_dot_recordset__pb2
|
|
17
|
+
from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x66lwr/proto/message.proto\x12\nflwr.proto\x1a\x16\x66lwr/proto/error.proto\x1a\x1a\x66lwr/proto/recordset.proto\x1a\x1a\x66lwr/proto/transport.proto\"{\n\x07Message\x12&\n\x08metadata\x18\x01 \x01(\x0b\x32\x14.flwr.proto.Metadata\x12&\n\x07\x63ontent\x18\x02 \x01(\x0b\x32\x15.flwr.proto.RecordSet\x12 \n\x05\x65rror\x18\x03 \x01(\x0b\x32\x11.flwr.proto.Error\"\xbf\x02\n\x07\x43ontext\x12\x0f\n\x07node_id\x18\x01 \x01(\x12\x12\x38\n\x0bnode_config\x18\x02 \x03(\x0b\x32#.flwr.proto.Context.NodeConfigEntry\x12$\n\x05state\x18\x03 \x01(\x0b\x32\x15.flwr.proto.RecordSet\x12\x36\n\nrun_config\x18\x04 \x03(\x0b\x32\".flwr.proto.Context.RunConfigEntry\x1a\x45\n\x0fNodeConfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\x1a\x44\n\x0eRunConfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\"\xa7\x01\n\x08Metadata\x12\x0e\n\x06run_id\x18\x01 \x01(\x12\x12\x12\n\nmessage_id\x18\x02 \x01(\t\x12\x13\n\x0bsrc_node_id\x18\x03 \x01(\x12\x12\x13\n\x0b\x64st_node_id\x18\x04 \x01(\x12\x12\x18\n\x10reply_to_message\x18\x05 \x01(\t\x12\x10\n\x08group_id\x18\x06 \x01(\t\x12\x0b\n\x03ttl\x18\x07 \x01(\x01\x12\x14\n\x0cmessage_type\x18\x08 \x01(\tb\x06proto3')
|
|
21
|
+
|
|
22
|
+
_globals = globals()
|
|
23
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
24
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.message_pb2', _globals)
|
|
25
|
+
if _descriptor._USE_C_DESCRIPTORS == False:
|
|
26
|
+
DESCRIPTOR._options = None
|
|
27
|
+
_globals['_CONTEXT_NODECONFIGENTRY']._options = None
|
|
28
|
+
_globals['_CONTEXT_NODECONFIGENTRY']._serialized_options = b'8\001'
|
|
29
|
+
_globals['_CONTEXT_RUNCONFIGENTRY']._options = None
|
|
30
|
+
_globals['_CONTEXT_RUNCONFIGENTRY']._serialized_options = b'8\001'
|
|
31
|
+
_globals['_MESSAGE']._serialized_start=120
|
|
32
|
+
_globals['_MESSAGE']._serialized_end=243
|
|
33
|
+
_globals['_CONTEXT']._serialized_start=246
|
|
34
|
+
_globals['_CONTEXT']._serialized_end=565
|
|
35
|
+
_globals['_CONTEXT_NODECONFIGENTRY']._serialized_start=426
|
|
36
|
+
_globals['_CONTEXT_NODECONFIGENTRY']._serialized_end=495
|
|
37
|
+
_globals['_CONTEXT_RUNCONFIGENTRY']._serialized_start=497
|
|
38
|
+
_globals['_CONTEXT_RUNCONFIGENTRY']._serialized_end=565
|
|
39
|
+
_globals['_METADATA']._serialized_start=568
|
|
40
|
+
_globals['_METADATA']._serialized_end=735
|
|
41
|
+
# @@protoc_insertion_point(module_scope)
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""
|
|
2
|
+
@generated by mypy-protobuf. Do not edit manually!
|
|
3
|
+
isort:skip_file
|
|
4
|
+
"""
|
|
5
|
+
import builtins
|
|
6
|
+
import flwr.proto.error_pb2
|
|
7
|
+
import flwr.proto.recordset_pb2
|
|
8
|
+
import flwr.proto.transport_pb2
|
|
9
|
+
import google.protobuf.descriptor
|
|
10
|
+
import google.protobuf.internal.containers
|
|
11
|
+
import google.protobuf.message
|
|
12
|
+
import typing
|
|
13
|
+
import typing_extensions
|
|
14
|
+
|
|
15
|
+
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
|
|
16
|
+
|
|
17
|
+
class Message(google.protobuf.message.Message):
|
|
18
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
19
|
+
METADATA_FIELD_NUMBER: builtins.int
|
|
20
|
+
CONTENT_FIELD_NUMBER: builtins.int
|
|
21
|
+
ERROR_FIELD_NUMBER: builtins.int
|
|
22
|
+
@property
|
|
23
|
+
def metadata(self) -> global___Metadata: ...
|
|
24
|
+
@property
|
|
25
|
+
def content(self) -> flwr.proto.recordset_pb2.RecordSet: ...
|
|
26
|
+
@property
|
|
27
|
+
def error(self) -> flwr.proto.error_pb2.Error: ...
|
|
28
|
+
def __init__(self,
|
|
29
|
+
*,
|
|
30
|
+
metadata: typing.Optional[global___Metadata] = ...,
|
|
31
|
+
content: typing.Optional[flwr.proto.recordset_pb2.RecordSet] = ...,
|
|
32
|
+
error: typing.Optional[flwr.proto.error_pb2.Error] = ...,
|
|
33
|
+
) -> None: ...
|
|
34
|
+
def HasField(self, field_name: typing_extensions.Literal["content",b"content","error",b"error","metadata",b"metadata"]) -> builtins.bool: ...
|
|
35
|
+
def ClearField(self, field_name: typing_extensions.Literal["content",b"content","error",b"error","metadata",b"metadata"]) -> None: ...
|
|
36
|
+
global___Message = Message
|
|
37
|
+
|
|
38
|
+
class Context(google.protobuf.message.Message):
|
|
39
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
40
|
+
class NodeConfigEntry(google.protobuf.message.Message):
|
|
41
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
42
|
+
KEY_FIELD_NUMBER: builtins.int
|
|
43
|
+
VALUE_FIELD_NUMBER: builtins.int
|
|
44
|
+
key: typing.Text
|
|
45
|
+
@property
|
|
46
|
+
def value(self) -> flwr.proto.transport_pb2.Scalar: ...
|
|
47
|
+
def __init__(self,
|
|
48
|
+
*,
|
|
49
|
+
key: typing.Text = ...,
|
|
50
|
+
value: typing.Optional[flwr.proto.transport_pb2.Scalar] = ...,
|
|
51
|
+
) -> None: ...
|
|
52
|
+
def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ...
|
|
53
|
+
def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
|
|
54
|
+
|
|
55
|
+
class RunConfigEntry(google.protobuf.message.Message):
|
|
56
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
57
|
+
KEY_FIELD_NUMBER: builtins.int
|
|
58
|
+
VALUE_FIELD_NUMBER: builtins.int
|
|
59
|
+
key: typing.Text
|
|
60
|
+
@property
|
|
61
|
+
def value(self) -> flwr.proto.transport_pb2.Scalar: ...
|
|
62
|
+
def __init__(self,
|
|
63
|
+
*,
|
|
64
|
+
key: typing.Text = ...,
|
|
65
|
+
value: typing.Optional[flwr.proto.transport_pb2.Scalar] = ...,
|
|
66
|
+
) -> None: ...
|
|
67
|
+
def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ...
|
|
68
|
+
def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
|
|
69
|
+
|
|
70
|
+
NODE_ID_FIELD_NUMBER: builtins.int
|
|
71
|
+
NODE_CONFIG_FIELD_NUMBER: builtins.int
|
|
72
|
+
STATE_FIELD_NUMBER: builtins.int
|
|
73
|
+
RUN_CONFIG_FIELD_NUMBER: builtins.int
|
|
74
|
+
node_id: builtins.int
|
|
75
|
+
@property
|
|
76
|
+
def node_config(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.transport_pb2.Scalar]: ...
|
|
77
|
+
@property
|
|
78
|
+
def state(self) -> flwr.proto.recordset_pb2.RecordSet: ...
|
|
79
|
+
@property
|
|
80
|
+
def run_config(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.transport_pb2.Scalar]: ...
|
|
81
|
+
def __init__(self,
|
|
82
|
+
*,
|
|
83
|
+
node_id: builtins.int = ...,
|
|
84
|
+
node_config: typing.Optional[typing.Mapping[typing.Text, flwr.proto.transport_pb2.Scalar]] = ...,
|
|
85
|
+
state: typing.Optional[flwr.proto.recordset_pb2.RecordSet] = ...,
|
|
86
|
+
run_config: typing.Optional[typing.Mapping[typing.Text, flwr.proto.transport_pb2.Scalar]] = ...,
|
|
87
|
+
) -> None: ...
|
|
88
|
+
def HasField(self, field_name: typing_extensions.Literal["state",b"state"]) -> builtins.bool: ...
|
|
89
|
+
def ClearField(self, field_name: typing_extensions.Literal["node_config",b"node_config","node_id",b"node_id","run_config",b"run_config","state",b"state"]) -> None: ...
|
|
90
|
+
global___Context = Context
|
|
91
|
+
|
|
92
|
+
class Metadata(google.protobuf.message.Message):
|
|
93
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
94
|
+
RUN_ID_FIELD_NUMBER: builtins.int
|
|
95
|
+
MESSAGE_ID_FIELD_NUMBER: builtins.int
|
|
96
|
+
SRC_NODE_ID_FIELD_NUMBER: builtins.int
|
|
97
|
+
DST_NODE_ID_FIELD_NUMBER: builtins.int
|
|
98
|
+
REPLY_TO_MESSAGE_FIELD_NUMBER: builtins.int
|
|
99
|
+
GROUP_ID_FIELD_NUMBER: builtins.int
|
|
100
|
+
TTL_FIELD_NUMBER: builtins.int
|
|
101
|
+
MESSAGE_TYPE_FIELD_NUMBER: builtins.int
|
|
102
|
+
run_id: builtins.int
|
|
103
|
+
message_id: typing.Text
|
|
104
|
+
src_node_id: builtins.int
|
|
105
|
+
dst_node_id: builtins.int
|
|
106
|
+
reply_to_message: typing.Text
|
|
107
|
+
group_id: typing.Text
|
|
108
|
+
ttl: builtins.float
|
|
109
|
+
message_type: typing.Text
|
|
110
|
+
def __init__(self,
|
|
111
|
+
*,
|
|
112
|
+
run_id: builtins.int = ...,
|
|
113
|
+
message_id: typing.Text = ...,
|
|
114
|
+
src_node_id: builtins.int = ...,
|
|
115
|
+
dst_node_id: builtins.int = ...,
|
|
116
|
+
reply_to_message: typing.Text = ...,
|
|
117
|
+
group_id: typing.Text = ...,
|
|
118
|
+
ttl: builtins.float = ...,
|
|
119
|
+
message_type: typing.Text = ...,
|
|
120
|
+
) -> None: ...
|
|
121
|
+
def ClearField(self, field_name: typing_extensions.Literal["dst_node_id",b"dst_node_id","group_id",b"group_id","message_id",b"message_id","message_type",b"message_type","reply_to_message",b"reply_to_message","run_id",b"run_id","src_node_id",b"src_node_id","ttl",b"ttl"]) -> None: ...
|
|
122
|
+
global___Metadata = Metadata
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Copyright 2024 Flower Labs GmbH. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
# ==============================================================================
|
|
15
|
+
"""Flower File Storage for large objects."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
from .disk_ffs import DiskFfs as DiskFfs
|
|
19
|
+
from .ffs import Ffs as Ffs
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"DiskFfs",
|
|
23
|
+
"Ffs",
|
|
24
|
+
]
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Copyright 2024 Flower Labs GmbH. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
# ==============================================================================
|
|
15
|
+
"""Disk based Flower File Storage."""
|
|
16
|
+
|
|
17
|
+
import hashlib
|
|
18
|
+
import json
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Dict, List, Tuple
|
|
21
|
+
|
|
22
|
+
from flwr.server.superlink.ffs.ffs import Ffs
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class DiskFfs(Ffs): # pylint: disable=R0904
|
|
26
|
+
"""Disk-based Flower File Storage interface for large objects."""
|
|
27
|
+
|
|
28
|
+
def __init__(self, base_dir: str) -> None:
|
|
29
|
+
"""Create a new DiskFfs instance.
|
|
30
|
+
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
base_dir : str
|
|
34
|
+
The base directory to store the objects.
|
|
35
|
+
"""
|
|
36
|
+
self.base_dir = Path(base_dir)
|
|
37
|
+
|
|
38
|
+
def put(self, content: bytes, meta: Dict[str, str]) -> str:
|
|
39
|
+
"""Store bytes and metadata and return key (hash of content).
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
content : bytes
|
|
44
|
+
The content to be stored.
|
|
45
|
+
meta : Dict[str, str]
|
|
46
|
+
The metadata to be stored.
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
key : str
|
|
51
|
+
The key (sha256hex hash) of the content.
|
|
52
|
+
"""
|
|
53
|
+
content_hash = hashlib.sha256(content).hexdigest()
|
|
54
|
+
|
|
55
|
+
self.base_dir.mkdir(exist_ok=True, parents=True)
|
|
56
|
+
(self.base_dir / content_hash).write_bytes(content)
|
|
57
|
+
(self.base_dir / f"{content_hash}.META").write_text(json.dumps(meta))
|
|
58
|
+
|
|
59
|
+
return content_hash
|
|
60
|
+
|
|
61
|
+
def get(self, key: str) -> Tuple[bytes, Dict[str, str]]:
|
|
62
|
+
"""Return tuple containing the object content and metadata.
|
|
63
|
+
|
|
64
|
+
Parameters
|
|
65
|
+
----------
|
|
66
|
+
key : str
|
|
67
|
+
The sha256hex hash of the object to be retrieved.
|
|
68
|
+
|
|
69
|
+
Returns
|
|
70
|
+
-------
|
|
71
|
+
Tuple[bytes, Dict[str, str]]
|
|
72
|
+
A tuple containing the object content and metadata.
|
|
73
|
+
"""
|
|
74
|
+
content = (self.base_dir / key).read_bytes()
|
|
75
|
+
meta = json.loads((self.base_dir / f"{key}.META").read_text())
|
|
76
|
+
|
|
77
|
+
return content, meta
|
|
78
|
+
|
|
79
|
+
def delete(self, key: str) -> None:
|
|
80
|
+
"""Delete object with hash.
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
key : str
|
|
85
|
+
The sha256hex hash of the object to be deleted.
|
|
86
|
+
"""
|
|
87
|
+
(self.base_dir / key).unlink()
|
|
88
|
+
(self.base_dir / f"{key}.META").unlink()
|
|
89
|
+
|
|
90
|
+
def list(self) -> List[str]:
|
|
91
|
+
"""List all keys.
|
|
92
|
+
|
|
93
|
+
Return all available keys in this `Ffs` instance.
|
|
94
|
+
This can be combined with, for example,
|
|
95
|
+
the `delete` method to delete objects.
|
|
96
|
+
|
|
97
|
+
Returns
|
|
98
|
+
-------
|
|
99
|
+
List[str]
|
|
100
|
+
A list of all available keys.
|
|
101
|
+
"""
|
|
102
|
+
return [
|
|
103
|
+
item.name for item in self.base_dir.iterdir() if not item.suffix == ".META"
|
|
104
|
+
]
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Copyright 2024 Flower Labs GmbH. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
# ==============================================================================
|
|
15
|
+
"""Abstract base class for Flower File Storage interface."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
import abc
|
|
19
|
+
from typing import Dict, List, Tuple
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Ffs(abc.ABC): # pylint: disable=R0904
|
|
23
|
+
"""Abstract Flower File Storage interface for large objects."""
|
|
24
|
+
|
|
25
|
+
@abc.abstractmethod
|
|
26
|
+
def put(self, content: bytes, meta: Dict[str, str]) -> str:
|
|
27
|
+
"""Store bytes and metadata and return sha256hex hash of data as str.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
content : bytes
|
|
32
|
+
The content to be stored.
|
|
33
|
+
meta : Dict[str, str]
|
|
34
|
+
The metadata to be stored.
|
|
35
|
+
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
key : str
|
|
39
|
+
The key (sha256hex hash) of the content.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
@abc.abstractmethod
|
|
43
|
+
def get(self, key: str) -> Tuple[bytes, Dict[str, str]]:
|
|
44
|
+
"""Return tuple containing the object content and metadata.
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
key : str
|
|
49
|
+
The key (sha256hex hash) of the object to be retrieved.
|
|
50
|
+
|
|
51
|
+
Returns
|
|
52
|
+
-------
|
|
53
|
+
Tuple[bytes, Dict[str, str]]
|
|
54
|
+
A tuple containing the object content and metadata.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
@abc.abstractmethod
|
|
58
|
+
def delete(self, key: str) -> None:
|
|
59
|
+
"""Delete object with hash.
|
|
60
|
+
|
|
61
|
+
Parameters
|
|
62
|
+
----------
|
|
63
|
+
key : str
|
|
64
|
+
The key (sha256hex hash) of the object to be deleted.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
@abc.abstractmethod
|
|
68
|
+
def list(self) -> List[str]:
|
|
69
|
+
"""List keys of all stored objects.
|
|
70
|
+
|
|
71
|
+
Return all available keys in this `Ffs` instance.
|
|
72
|
+
This can be combined with, for example,
|
|
73
|
+
the `delete` method to delete objects.
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
List[str]
|
|
78
|
+
A list of all available keys.
|
|
79
|
+
"""
|
{flwr_nightly-1.11.0.dev20240809.dist-info → flwr_nightly-1.11.0.dev20240812.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.dev20240812
|
|
4
4
|
Summary: Flower: A Friendly Federated Learning Framework
|
|
5
5
|
Home-page: https://flower.ai
|
|
6
6
|
License: Apache-2.0
|
|
@@ -33,7 +33,7 @@ Classifier: Typing :: Typed
|
|
|
33
33
|
Provides-Extra: rest
|
|
34
34
|
Provides-Extra: simulation
|
|
35
35
|
Requires-Dist: cryptography (>=42.0.4,<43.0.0)
|
|
36
|
-
Requires-Dist: grpcio (>=1.60.0,<2.0.0,!=1.64.2,!=1.65.1)
|
|
36
|
+
Requires-Dist: grpcio (>=1.60.0,<2.0.0,!=1.64.2,!=1.65.1,!=1.65.2,!=1.65.4)
|
|
37
37
|
Requires-Dist: iterators (>=0.0.2,<0.0.3)
|
|
38
38
|
Requires-Dist: numpy (>=1.21.0,<2.0.0)
|
|
39
39
|
Requires-Dist: pathspec (>=0.12.1,<0.13.0)
|
{flwr_nightly-1.11.0.dev20240809.dist-info → flwr_nightly-1.11.0.dev20240812.dist-info}/RECORD
RENAMED
|
@@ -50,7 +50,7 @@ flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl,sha256=vIO1ArukTC76ogYLNmJ
|
|
|
50
50
|
flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl,sha256=jk_5teoyOVM9QdBea8J-nk10S6TKw81QZiiKB54ATF0,654
|
|
51
51
|
flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl,sha256=bRIvPCPvTTI4Eo5b61Rmw8WdDw3sjcohciTXgULN5l8,702
|
|
52
52
|
flwr/cli/run/__init__.py,sha256=oCd6HmQDx-sqver1gecgx-uMA38BLTSiiKpl7RGNceg,789
|
|
53
|
-
flwr/cli/run/run.py,sha256=
|
|
53
|
+
flwr/cli/run/run.py,sha256=te6J1HxOOzyC47HMIrvbh-_4xVEGM1x_yXLIhlCBkb8,7521
|
|
54
54
|
flwr/cli/utils.py,sha256=l65Ul0YsSBPuypk0uorAtEDmLEYiUrzpCXi6zCg9mJ4,4506
|
|
55
55
|
flwr/client/__init__.py,sha256=wzJZsYJIHf_8-PMzvfbinyzzjgh1UP1vLrAw2_yEbKI,1345
|
|
56
56
|
flwr/client/app.py,sha256=VJ_vPMVfur5_SqUjHa18VWLB6I9kOav78f5myC_iWuk,26110
|
|
@@ -82,8 +82,8 @@ flwr/client/node_state_tests.py,sha256=-4fVsn7y-z9NYBuhq-cjepgxgVuPqqQgDOL4Sofrd
|
|
|
82
82
|
flwr/client/numpy_client.py,sha256=u76GWAdHmJM88Agm2EgLQSvO8Jnk225mJTk-_TmPjFE,10283
|
|
83
83
|
flwr/client/rest_client/__init__.py,sha256=5KGlp7pjc1dhNRkKlaNtUfQmg8wrRFh9lS3P3uRS-7Q,735
|
|
84
84
|
flwr/client/rest_client/connection.py,sha256=8LPk7zPvX3l3-5QQXNym8DkIe6V14uEHmTzQ8jCcsnQ,12198
|
|
85
|
-
flwr/client/supernode/__init__.py,sha256=
|
|
86
|
-
flwr/client/supernode/app.py,sha256=
|
|
85
|
+
flwr/client/supernode/__init__.py,sha256=8JuFMx5B06SymNWZ9ndvUimD0mopq0Yp2RdQaUANsw8,937
|
|
86
|
+
flwr/client/supernode/app.py,sha256=mbSs612GCpRsv6xIi_TD_V2Gi7aYBdpo_e4nKs8kAvI,15910
|
|
87
87
|
flwr/client/typing.py,sha256=dxoTBnTMfqXr5J7G3y-uNjqxYCddvxhu89spfj4Lm2U,1048
|
|
88
88
|
flwr/common/__init__.py,sha256=4cBLNNnNTwHDnL_HCxhU5ILCSZ6fYh3A_aMBtlvHTVw,3721
|
|
89
89
|
flwr/common/address.py,sha256=wRu1Luezx1PWadwV9OA_KNko01oVvbRnPqfzaDn8QOk,1882
|
|
@@ -123,6 +123,10 @@ flwr/common/telemetry.py,sha256=nSjJHDitPhzB2qUl6LeSMT9Zld5lIk9uW98RpxQwiZw,8366
|
|
|
123
123
|
flwr/common/typing.py,sha256=ISp8UF94dtqml7ElaR6NeGCqcZX3xeab7KWMdjQEqcU,4730
|
|
124
124
|
flwr/common/version.py,sha256=W1ntylR04xkCP6zeSet6sRtBn7P1cje2lOqBJgYBjJY,1349
|
|
125
125
|
flwr/proto/__init__.py,sha256=hbY7JYakwZwCkYgCNlmHdc8rtvfoJbAZLalMdc--CGc,683
|
|
126
|
+
flwr/proto/clientappio_pb2.py,sha256=018Lj2HBXmEeq6KsmqFVVx2DGO2nDQqTA6YHEPjCTbc,3242
|
|
127
|
+
flwr/proto/clientappio_pb2.pyi,sha256=M0-zbx5cNMUtGY7orsSQWwXo5EbN0CvwQPTuQFwXaCg,4855
|
|
128
|
+
flwr/proto/clientappio_pb2_grpc.py,sha256=7WjUVfUUKctIloX3bkKjDprhtkqj2d9Xj3UlYxKzp1s,4513
|
|
129
|
+
flwr/proto/clientappio_pb2_grpc.pyi,sha256=30X6jhMIjy5w3iZsDCBGDDwNwj3vj3RslZVWkRvzTn0,1413
|
|
126
130
|
flwr/proto/common_pb2.py,sha256=uzSmq0FJdC-MriN9UGPFs7QVIFTKJmX5lyLnzcyZ5WE,2405
|
|
127
131
|
flwr/proto/common_pb2.pyi,sha256=0ylFO7G79qqLuRg9IQUCBdgyIIFv4m8VzrfoWad4xXU,5394
|
|
128
132
|
flwr/proto/common_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
|
@@ -151,6 +155,10 @@ flwr/proto/grpcadapter_pb2.py,sha256=bb8mW09XzNCpMdr1KuYQkefPFWR8lc8y1uL6Uk0TtsM
|
|
|
151
155
|
flwr/proto/grpcadapter_pb2.pyi,sha256=AR77gDsF6f8zqSIQp3877DUd7S8lP95lFak5Ir_WPkw,1716
|
|
152
156
|
flwr/proto/grpcadapter_pb2_grpc.py,sha256=rRNuNES5nBugUZWfeA8oAy8dMHgzqU_PF1srTseo3b8,2634
|
|
153
157
|
flwr/proto/grpcadapter_pb2_grpc.pyi,sha256=AgA9Qo_lnANb9SNuPzbZGAxupau-xcqYawZz6vqf-24,735
|
|
158
|
+
flwr/proto/message_pb2.py,sha256=7sP1PEOoZnfynNcM_KmlHn2bFM8eZpHYJbzkCSoAT2E,3110
|
|
159
|
+
flwr/proto/message_pb2.pyi,sha256=0IF_l1-fgQOs2uBNqu6PszzfulRQppdUIvDA-T6XeJ8,5475
|
|
160
|
+
flwr/proto/message_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
|
161
|
+
flwr/proto/message_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
|
|
154
162
|
flwr/proto/node_pb2.py,sha256=1zfXEvgGObglIcaVb4SLFmOcHZvA8eHzEtMFM5A6FYY,1081
|
|
155
163
|
flwr/proto/node_pb2.pyi,sha256=aX3BHhgXvJE1rvcRnEE_gB-5GcaFQ0SJ88yTE223bjI,751
|
|
156
164
|
flwr/proto/node_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
|
@@ -220,6 +228,9 @@ flwr/server/superlink/__init__.py,sha256=8tHYCfodUlRD8PCP9fHgvu8cz5N31A2QoRVL0jD
|
|
|
220
228
|
flwr/server/superlink/driver/__init__.py,sha256=_JaRW-FdyikHc7souUrnk3mwTGViraEJCeUBY_M_ocs,712
|
|
221
229
|
flwr/server/superlink/driver/driver_grpc.py,sha256=wMqYVeDwIc_FEfQPbCzd9p1YyIcjwiFUMX4QZjGSx5k,1932
|
|
222
230
|
flwr/server/superlink/driver/driver_servicer.py,sha256=UWJKw7-eVILw97MdTGjZt9yV0noXnrzcO72bYZ0b2kM,6010
|
|
231
|
+
flwr/server/superlink/ffs/__init__.py,sha256=FAY-zShcfPmOxosok2QyT6hTNMNctG8cH9s_nIl8jkI,840
|
|
232
|
+
flwr/server/superlink/ffs/disk_ffs.py,sha256=ZsBCQVpuScm5QNul_XWlXU65XEaOGbH9ULIls6h7p1A,3213
|
|
233
|
+
flwr/server/superlink/ffs/ffs.py,sha256=AVl1AM7ZfVTPOIEQJuMR-aXUUd2foSkRe49NWoPecL8,2384
|
|
223
234
|
flwr/server/superlink/fleet/__init__.py,sha256=76od-HhYjOUoZFLFDFCFnNHI4JLAmaXQEAyp7LWlQpc,711
|
|
224
235
|
flwr/server/superlink/fleet/grpc_adapter/__init__.py,sha256=spBQQJeYz8zPOBOfyMLv87kqWPASGB73AymcLXdFaYA,742
|
|
225
236
|
flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py,sha256=K4LkOsVzIdsR7Py_9cfo6CR-bDocpP15ktHTc2UnJ9k,4957
|
|
@@ -270,8 +281,8 @@ flwr/superexec/exec_grpc.py,sha256=PhqGoZEpTMxSQmUSV8Wgtzb1Za_pHJ-adZqo5RYnDyE,1
|
|
|
270
281
|
flwr/superexec/exec_servicer.py,sha256=fxQAKfgmQRSnYq5anjryfGeRbsZrNFEkuiNcTZhRwiE,2320
|
|
271
282
|
flwr/superexec/executor.py,sha256=k_adivto6R2U82DADOHNvdtobehBYreRek1gOEBIQnQ,2318
|
|
272
283
|
flwr/superexec/simulation.py,sha256=lfdClQYSAIMHe43aJ0Pk-kBw_xoV09LsIMfHo2eo-Ck,6775
|
|
273
|
-
flwr_nightly-1.11.0.
|
|
274
|
-
flwr_nightly-1.11.0.
|
|
275
|
-
flwr_nightly-1.11.0.
|
|
276
|
-
flwr_nightly-1.11.0.
|
|
277
|
-
flwr_nightly-1.11.0.
|
|
284
|
+
flwr_nightly-1.11.0.dev20240812.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
285
|
+
flwr_nightly-1.11.0.dev20240812.dist-info/METADATA,sha256=TNyTp6A3S0aqD5I1nfK5bT8EHYl2-guApoBwCUzmRQI,15690
|
|
286
|
+
flwr_nightly-1.11.0.dev20240812.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
287
|
+
flwr_nightly-1.11.0.dev20240812.dist-info/entry_points.txt,sha256=KqQQGNjnr-2IT-bheOkO9yM4Gv5BtjaBgYKRkp-NhVg,388
|
|
288
|
+
flwr_nightly-1.11.0.dev20240812.dist-info/RECORD,,
|
{flwr_nightly-1.11.0.dev20240809.dist-info → flwr_nightly-1.11.0.dev20240812.dist-info}/LICENSE
RENAMED
|
File without changes
|
{flwr_nightly-1.11.0.dev20240809.dist-info → flwr_nightly-1.11.0.dev20240812.dist-info}/WHEEL
RENAMED
|
File without changes
|