flwr-nightly 1.5.0.dev20230614__py3-none-any.whl → 1.5.0.dev20230615__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/client/dpfedavg_numpy_client.py +97 -0
- flwr/driver/driver_client_manager.py +9 -0
- flwr/server/state/in_memory_state.py +8 -0
- flwr/server/strategy/dpfedavg_adaptive.py +1 -0
- flwr/server/strategy/dpfedavg_fixed.py +46 -1
- flwr/server/utils/tensorboard.py +1 -2
- {flwr_nightly-1.5.0.dev20230614.dist-info → flwr_nightly-1.5.0.dev20230615.dist-info}/METADATA +1 -1
- {flwr_nightly-1.5.0.dev20230614.dist-info → flwr_nightly-1.5.0.dev20230615.dist-info}/RECORD +11 -11
- {flwr_nightly-1.5.0.dev20230614.dist-info → flwr_nightly-1.5.0.dev20230615.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.5.0.dev20230614.dist-info → flwr_nightly-1.5.0.dev20230615.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.5.0.dev20230614.dist-info → flwr_nightly-1.5.0.dev20230615.dist-info}/entry_points.txt +0 -0
@@ -33,14 +33,82 @@ class DPFedAvgNumPyClient(NumPyClient):
|
|
33
33
|
self.client = client
|
34
34
|
|
35
35
|
def get_properties(self, config: Config) -> Dict[str, Scalar]:
|
36
|
+
"""Get client properties using the given Numpy client.
|
37
|
+
|
38
|
+
Parameters
|
39
|
+
----------
|
40
|
+
config : Config
|
41
|
+
Configuration parameters requested by the server.
|
42
|
+
This can be used to tell the client which properties
|
43
|
+
are needed along with some Scalar attributes.
|
44
|
+
|
45
|
+
Returns
|
46
|
+
-------
|
47
|
+
properties : Dict[str, Scalar]
|
48
|
+
A dictionary mapping arbitrary string keys to values of type
|
49
|
+
bool, bytes, float, int, or str. It can be used to communicate
|
50
|
+
arbitrary property values back to the server.
|
51
|
+
"""
|
36
52
|
return self.client.get_properties(config)
|
37
53
|
|
38
54
|
def get_parameters(self, config: Dict[str, Scalar]) -> NDArrays:
|
55
|
+
"""Return the current local model parameters.
|
56
|
+
|
57
|
+
Parameters
|
58
|
+
----------
|
59
|
+
config : Config
|
60
|
+
Configuration parameters requested by the server.
|
61
|
+
This can be used to tell the client which parameters
|
62
|
+
are needed along with some Scalar attributes.
|
63
|
+
|
64
|
+
Returns
|
65
|
+
-------
|
66
|
+
parameters : NDArrays
|
67
|
+
The local model parameters as a list of NumPy ndarrays.
|
68
|
+
"""
|
39
69
|
return self.client.get_parameters(config)
|
40
70
|
|
41
71
|
def fit(
|
42
72
|
self, parameters: NDArrays, config: Dict[str, Scalar]
|
43
73
|
) -> Tuple[NDArrays, int, Dict[str, Scalar]]:
|
74
|
+
"""Train the provided parameters using the locally held dataset.
|
75
|
+
|
76
|
+
This method first updates the local model using the original parameters
|
77
|
+
provided. It then calculates the update by subtracting the original
|
78
|
+
parameters from the updated model. The update is then clipped by an L2
|
79
|
+
norm and Gaussian noise is added if specified by the configuration.
|
80
|
+
|
81
|
+
The update is then applied to the original parameters to obtain the
|
82
|
+
updated parameters which are returned along with the number of examples
|
83
|
+
used and metrics computed during the fitting process.
|
84
|
+
|
85
|
+
Parameters
|
86
|
+
----------
|
87
|
+
parameters : NDArrays
|
88
|
+
The current (global) model parameters.
|
89
|
+
config : Dict[str, Scalar]
|
90
|
+
Configuration parameters which allow the
|
91
|
+
server to influence training on the client. It can be used to
|
92
|
+
communicate arbitrary values from the server to the client, for
|
93
|
+
example, to set the number of (local) training epochs.
|
94
|
+
|
95
|
+
Returns
|
96
|
+
-------
|
97
|
+
parameters : NDArrays
|
98
|
+
The locally updated model parameters.
|
99
|
+
num_examples : int
|
100
|
+
The number of examples used for training.
|
101
|
+
metrics : Dict[str, Scalar]
|
102
|
+
A dictionary mapping arbitrary string keys to values of type
|
103
|
+
bool, bytes, float, int, or str. It can be used to communicate
|
104
|
+
arbitrary values back to the server.
|
105
|
+
|
106
|
+
Raises
|
107
|
+
------
|
108
|
+
Exception
|
109
|
+
If any required configuration parameters are not provided or are of
|
110
|
+
the wrong type.
|
111
|
+
"""
|
44
112
|
original_params = copy.deepcopy(parameters)
|
45
113
|
# Getting the updated model from the wrapped client
|
46
114
|
updated_params, num_examples, metrics = self.client.fit(parameters, config)
|
@@ -80,4 +148,33 @@ class DPFedAvgNumPyClient(NumPyClient):
|
|
80
148
|
def evaluate(
|
81
149
|
self, parameters: NDArrays, config: Dict[str, Scalar]
|
82
150
|
) -> Tuple[float, int, Dict[str, Scalar]]:
|
151
|
+
"""Evaluate the provided parameters using the locally held dataset.
|
152
|
+
|
153
|
+
Parameters
|
154
|
+
----------
|
155
|
+
parameters : NDArrays
|
156
|
+
The current (global) model parameters.
|
157
|
+
config : Dict[str, Scalar]
|
158
|
+
Configuration parameters which allow the server to influence
|
159
|
+
evaluation on the client. It can be used to communicate
|
160
|
+
arbitrary values from the server to the client, for example,
|
161
|
+
to influence the number of examples used for evaluation.
|
162
|
+
|
163
|
+
Returns
|
164
|
+
-------
|
165
|
+
loss : float
|
166
|
+
The evaluation loss of the model on the local dataset.
|
167
|
+
num_examples : int
|
168
|
+
The number of examples used for evaluation.
|
169
|
+
metrics : Dict[str, Scalar]
|
170
|
+
A dictionary mapping arbitrary string keys to values of
|
171
|
+
type bool, bytes, float, int, or str. It can be used to
|
172
|
+
communicate arbitrary values back to the server.
|
173
|
+
|
174
|
+
Warning
|
175
|
+
-------
|
176
|
+
The previous return type format (int, float, float) and the
|
177
|
+
extended format (int, float, float, Dict[str, Scalar]) have been
|
178
|
+
deprecated and removed since Flower 0.19.
|
179
|
+
"""
|
83
180
|
return self.client.evaluate(parameters, config)
|
@@ -85,10 +85,12 @@ class DriverClientManager(ClientManager):
|
|
85
85
|
raise NotImplementedError("DriverClientManager.unregister is not implemented")
|
86
86
|
|
87
87
|
def all(self) -> Dict[str, ClientProxy]:
|
88
|
+
"""Return all available clients."""
|
88
89
|
self._update_nodes()
|
89
90
|
return self.clients
|
90
91
|
|
91
92
|
def wait_for(self, num_clients: int, timeout: int = 86400) -> bool:
|
93
|
+
"""Wait until at least `num_clients` are available."""
|
92
94
|
start_time = time.time()
|
93
95
|
while time.time() < start_time + timeout:
|
94
96
|
self._update_nodes()
|
@@ -103,6 +105,7 @@ class DriverClientManager(ClientManager):
|
|
103
105
|
min_num_clients: Optional[int] = None,
|
104
106
|
criterion: Optional[Criterion] = None,
|
105
107
|
) -> List[ClientProxy]:
|
108
|
+
"""Sample a number of Flower ClientProxy instances."""
|
106
109
|
if min_num_clients is None:
|
107
110
|
min_num_clients = num_clients
|
108
111
|
self.wait_for(min_num_clients)
|
@@ -128,6 +131,12 @@ class DriverClientManager(ClientManager):
|
|
128
131
|
return [self.clients[cid] for cid in sampled_cids]
|
129
132
|
|
130
133
|
def _update_nodes(self) -> None:
|
134
|
+
"""Update the nodes list in the client manager.
|
135
|
+
|
136
|
+
This method communicates with the associated driver to get all node ids. Each
|
137
|
+
node id is then converted into a `DriverClientProxy` instance and stored in the
|
138
|
+
`clients` dictionary with node id as key.
|
139
|
+
"""
|
131
140
|
get_nodes_res = self.driver.get_nodes(req=driver_pb2.GetNodesRequest())
|
132
141
|
all_node_ids = get_nodes_res.node_ids
|
133
142
|
for node_id in all_node_ids:
|
@@ -158,9 +158,17 @@ class InMemoryState(State):
|
|
158
158
|
del self.task_res_store[task_id]
|
159
159
|
|
160
160
|
def num_task_ins(self) -> int:
|
161
|
+
"""Calculate the number of task_ins in store.
|
162
|
+
|
163
|
+
This includes delivered but not yet deleted task_ins.
|
164
|
+
"""
|
161
165
|
return len(self.task_ins_store)
|
162
166
|
|
163
167
|
def num_task_res(self) -> int:
|
168
|
+
"""Calculate the number of task_res in store.
|
169
|
+
|
170
|
+
This includes delivered but not yet deleted task_res.
|
171
|
+
"""
|
164
172
|
return len(self.task_res_store)
|
165
173
|
|
166
174
|
def register_node(self, node_id: int) -> None:
|
@@ -113,6 +113,7 @@ class DPFedAvgAdaptive(DPFedAvgFixed):
|
|
113
113
|
results: List[Tuple[ClientProxy, FitRes]],
|
114
114
|
failures: List[Union[Tuple[ClientProxy, FitRes], BaseException]],
|
115
115
|
) -> Tuple[Optional[Parameters], Dict[str, Scalar]]:
|
116
|
+
"""Aggregate training results as in DPFedAvgFixed and update clip norms."""
|
116
117
|
if failures:
|
117
118
|
return None, {}
|
118
119
|
new_global_model = super().aggregate_fit(server_round, results, failures)
|
@@ -67,12 +67,34 @@ class DPFedAvgFixed(Strategy):
|
|
67
67
|
def initialize_parameters(
|
68
68
|
self, client_manager: ClientManager
|
69
69
|
) -> Optional[Parameters]:
|
70
|
+
"""Initialize global model parameters using given strategy."""
|
70
71
|
return self.strategy.initialize_parameters(client_manager)
|
71
72
|
|
72
73
|
def configure_fit(
|
73
74
|
self, server_round: int, parameters: Parameters, client_manager: ClientManager
|
74
75
|
) -> List[Tuple[ClientProxy, FitIns]]:
|
75
|
-
"""Configure the next round of training.
|
76
|
+
"""Configure the next round of training incorporating Differential Privacy (DP).
|
77
|
+
|
78
|
+
Configuration of the next training round includes information related to DP,
|
79
|
+
such as clip norm and noise stddev.
|
80
|
+
|
81
|
+
Parameters
|
82
|
+
----------
|
83
|
+
server_round : int
|
84
|
+
The current round of federated learning.
|
85
|
+
parameters : Parameters
|
86
|
+
The current (global) model parameters.
|
87
|
+
client_manager : ClientManager
|
88
|
+
The client manager which holds all currently connected clients.
|
89
|
+
|
90
|
+
Returns
|
91
|
+
-------
|
92
|
+
fit_configuration : List[Tuple[ClientProxy, FitIns]]
|
93
|
+
A list of tuples. Each tuple in the list identifies a `ClientProxy` and the
|
94
|
+
`FitIns` for this particular `ClientProxy`. If a particular `ClientProxy`
|
95
|
+
is not included in this list, it means that this `ClientProxy`
|
96
|
+
will not participate in the next round of federated learning.
|
97
|
+
"""
|
76
98
|
additional_config = {"dpfedavg_clip_norm": self.clip_norm}
|
77
99
|
if not self.server_side_noising:
|
78
100
|
additional_config[
|
@@ -91,6 +113,26 @@ class DPFedAvgFixed(Strategy):
|
|
91
113
|
def configure_evaluate(
|
92
114
|
self, server_round: int, parameters: Parameters, client_manager: ClientManager
|
93
115
|
) -> List[Tuple[ClientProxy, EvaluateIns]]:
|
116
|
+
"""Configure the next round of evaluation using the specified strategy.
|
117
|
+
|
118
|
+
Parameters
|
119
|
+
----------
|
120
|
+
server_round : int
|
121
|
+
The current round of federated learning.
|
122
|
+
parameters : Parameters
|
123
|
+
The current (global) model parameters.
|
124
|
+
client_manager : ClientManager
|
125
|
+
The client manager which holds all currently connected clients.
|
126
|
+
|
127
|
+
Returns
|
128
|
+
-------
|
129
|
+
evaluate_configuration : List[Tuple[ClientProxy, EvaluateIns]]
|
130
|
+
A list of tuples. Each tuple in the list identifies a `ClientProxy` and the
|
131
|
+
`EvaluateIns` for this particular `ClientProxy`. If a particular
|
132
|
+
`ClientProxy` is not included in this list, it means that this
|
133
|
+
`ClientProxy` will not participate in the next round of federated
|
134
|
+
evaluation.
|
135
|
+
"""
|
94
136
|
return self.strategy.configure_evaluate(
|
95
137
|
server_round, parameters, client_manager
|
96
138
|
)
|
@@ -101,6 +143,7 @@ class DPFedAvgFixed(Strategy):
|
|
101
143
|
results: List[Tuple[ClientProxy, FitRes]],
|
102
144
|
failures: List[Union[Tuple[ClientProxy, FitRes], BaseException]],
|
103
145
|
) -> Tuple[Optional[Parameters], Dict[str, Scalar]]:
|
146
|
+
"""Aggregate training results using unweighted aggregation."""
|
104
147
|
if failures:
|
105
148
|
return None, {}
|
106
149
|
# Forcing unweighted aggregation, as in https://arxiv.org/abs/1905.03871.
|
@@ -121,9 +164,11 @@ class DPFedAvgFixed(Strategy):
|
|
121
164
|
results: List[Tuple[ClientProxy, EvaluateRes]],
|
122
165
|
failures: List[Union[Tuple[ClientProxy, EvaluateRes], BaseException]],
|
123
166
|
) -> Tuple[Optional[float], Dict[str, Scalar]]:
|
167
|
+
"""Aggregate evaluation losses using the given strategy."""
|
124
168
|
return self.strategy.aggregate_evaluate(server_round, results, failures)
|
125
169
|
|
126
170
|
def evaluate(
|
127
171
|
self, server_round: int, parameters: Parameters
|
128
172
|
) -> Optional[Tuple[float, Dict[str, Scalar]]]:
|
173
|
+
"""Evaluate model parameters using an evaluation function from the strategy."""
|
129
174
|
return self.strategy.evaluate(server_round, parameters)
|
flwr/server/utils/tensorboard.py
CHANGED
@@ -73,8 +73,7 @@ def tensorboard(logdir: str) -> Callable[[Strategy], Strategy]:
|
|
73
73
|
"""Return overloaded Strategy Wrapper."""
|
74
74
|
|
75
75
|
class TBWrapper(strategy_class): # type: ignore
|
76
|
-
"""Strategy wrapper
|
77
|
-
logging."""
|
76
|
+
"""Strategy wrapper that hooks into some methods for TensorBoard logging."""
|
78
77
|
|
79
78
|
def aggregate_evaluate(
|
80
79
|
self,
|
{flwr_nightly-1.5.0.dev20230614.dist-info → flwr_nightly-1.5.0.dev20230615.dist-info}/RECORD
RENAMED
@@ -2,7 +2,7 @@ flwr/__init__.py,sha256=kuBqHEfjUCwKVS60acHjXOEQhxfqg5S3ldIh3FJ4VYk,952
|
|
2
2
|
flwr/client/__init__.py,sha256=UkiAEKds0mtpmVTZvvpJHKfTC_VWzflwL5IQUdbAf6U,1164
|
3
3
|
flwr/client/app.py,sha256=0pRrsuqThwOGFv8tBEV-7YU_1t4mLQCMCVG2nGzyvq0,13835
|
4
4
|
flwr/client/client.py,sha256=-jPs28BQC3h5QFahPEHn1zHdiy6fTyk7TG9NS5Nw_e8,7677
|
5
|
-
flwr/client/dpfedavg_numpy_client.py,sha256=
|
5
|
+
flwr/client/dpfedavg_numpy_client.py,sha256=5mOZuwdnwYtoytlxD0RsVLcIENkFM7a5amScSBzVpDw,7209
|
6
6
|
flwr/client/grpc_client/__init__.py,sha256=svcQQhSaBJujNfZevHBsQrMKmqggpq-3I8Y6FUm_trM,728
|
7
7
|
flwr/client/grpc_client/connection.py,sha256=SyQRnlfdXkuoc9aYXbwRU6GlPDwmNB5O_u_JMxCzO6Q,4293
|
8
8
|
flwr/client/grpc_rere_client/__init__.py,sha256=9v4H6EumqwZePsY9icP0WdVSJ4UzH1t9MRyYX-a0--Q,745
|
@@ -28,7 +28,7 @@ flwr/common/version.py,sha256=lSE8kmuIEtB4E9Es2JmLi0W6CMn3YB74L_-VQyGNknI,848
|
|
28
28
|
flwr/driver/__init__.py,sha256=G9gvW60tQNN_yfXHr5gqwR5p_LSitE1r4I0GquysHZo,809
|
29
29
|
flwr/driver/app.py,sha256=BSFOBQpIS_3gSpfZ-D_McuuYac0-gG13h7mBrz_QExI,4826
|
30
30
|
flwr/driver/driver.py,sha256=XpdgPMLbWzKIPS3g0PW9o8eU8-rIFD5mMG3lTKs-eTI,3906
|
31
|
-
flwr/driver/driver_client_manager.py,sha256=
|
31
|
+
flwr/driver/driver_client_manager.py,sha256=Xt4HxI88DVv7Oq1OPPtn0ceWJo2at_dc06nlmDYdL4Q,4877
|
32
32
|
flwr/driver/driver_client_proxy.py,sha256=tpMb8Ti-OV0Qv-TwfCzG6Lt9IYRHE3JuZt3SnRKtV0k,5653
|
33
33
|
flwr/proto/__init__.py,sha256=fg57BzxAeODasVkv19rCvp5UMA0Gh8E2HVhw3ietB6Q,676
|
34
34
|
flwr/proto/driver_pb2.py,sha256=aQSzL3aUlyeazgt_JKfP64D-1pI1uz9QoCAlcH_2uNU,4663
|
@@ -76,14 +76,14 @@ flwr/server/fleet/rest_rere/rest_api.py,sha256=4FYkB7aGC7qR5Qmdgbkm_FzYW0pWw3EYp
|
|
76
76
|
flwr/server/history.py,sha256=xI7LfjV67VQZkKoHRpzILG1zKb_a0pMyL2vpn15BsxM,4897
|
77
77
|
flwr/server/server.py,sha256=amrh_Xpfkq8EQdnDubDn3NPyIuv8-SIm6wZ8bhdb9mE,15958
|
78
78
|
flwr/server/state/__init__.py,sha256=jcTV_f7T8w72NWkAY9kNPFis-FOd3Zm5jLE3CRmvOkE,996
|
79
|
-
flwr/server/state/in_memory_state.py,sha256=
|
79
|
+
flwr/server/state/in_memory_state.py,sha256=jnnQ5xmXbOISUxud2XJZC2U5AAX2_8AOsoTR2QXkg28,6774
|
80
80
|
flwr/server/state/sqlite_state.py,sha256=A25q1qioWo-_oP4ThM-CuLIH6FCTBRKPBKxbzn9_GAY,19296
|
81
81
|
flwr/server/state/state.py,sha256=nIzCzAzNwPrfXTltn1sroG6JN-Ti0PJAE4Mhhhm7lzU,4833
|
82
82
|
flwr/server/state/state_factory.py,sha256=nrHildx-4O6ko48TCHRwJSWg7ebAxCAqdENdcIlrSkA,1647
|
83
83
|
flwr/server/strategy/__init__.py,sha256=_y7B6IAmP7e6m09yNLtS26M8wc8JQLmuezgsKpdgxV4,1667
|
84
84
|
flwr/server/strategy/aggregate.py,sha256=lshQsPyTRx5VxxRGejLw1klsg4mtGcYQJtMVXJou3sY,6099
|
85
|
-
flwr/server/strategy/dpfedavg_adaptive.py,sha256=
|
86
|
-
flwr/server/strategy/dpfedavg_fixed.py,sha256=
|
85
|
+
flwr/server/strategy/dpfedavg_adaptive.py,sha256=ZqcVBgA1YZ0JCsXbxkgHNCef9xG3Ri1MhZoA7Pxk6xI,4591
|
86
|
+
flwr/server/strategy/dpfedavg_fixed.py,sha256=FCY0KaVvNZ81H-KN3HSujRG44Tu8uVOnGeDg-7v4dG0,6932
|
87
87
|
flwr/server/strategy/fault_tolerant_fedavg.py,sha256=nuDBxqXjH4Qo9BMgsxnvFMo3MNE-xsxdteVw-1QqSg4,5830
|
88
88
|
flwr/server/strategy/fedadagrad.py,sha256=Z-L2-C0IpdBO_sypKXakTMPdKNYOEHEoNXylky3Uwq4,6722
|
89
89
|
flwr/server/strategy/fedadam.py,sha256=sjpIfZankmvEBOZMiWvO4GlynxtoqMtaSiGzl2O4EpE,7004
|
@@ -100,14 +100,14 @@ flwr/server/strategy/krum.py,sha256=70aRw6_J2Ny9i8-kEOAyVLnONn-oGefgM0Ks5OHLa0A,
|
|
100
100
|
flwr/server/strategy/qfedavg.py,sha256=V9p0jRLnEbQaO4UDNB7675XQfGXrbw_E-_p-Lq6LrzE,10131
|
101
101
|
flwr/server/strategy/strategy.py,sha256=wrlVh4Kam-B5Np1Q7NxMNk6lF6EnwhUowjovVsUKPWo,7484
|
102
102
|
flwr/server/utils/__init__.py,sha256=I3aifvGufkoK1Od-w1Xz_nicgAYllqXScQiRU6A5xvA,901
|
103
|
-
flwr/server/utils/tensorboard.py,sha256=
|
103
|
+
flwr/server/utils/tensorboard.py,sha256=VNxz2BvOMu4q1Y5s-Mgoweb63YvYb0Hqu5hhMJK3SDU,5069
|
104
104
|
flwr/server/utils/validator.py,sha256=hp4PU5FB-W68HaFT8fLLWba-ftGhfTBB880Opes_pok,4940
|
105
105
|
flwr/simulation/__init__.py,sha256=ZtAt5bMbbp9IJp1QQOhACN6_qhSPDtGmHF8gypUOZ9s,1271
|
106
106
|
flwr/simulation/app.py,sha256=vYnyaX9pjAYAosFtciSunUYLY7UQ15nBhOFZt8mW45Q,7826
|
107
107
|
flwr/simulation/ray_transport/__init__.py,sha256=eJ3pijYkI7XhbX2rLu6FBGTo8hZkFL8RSj4twhApOGw,727
|
108
108
|
flwr/simulation/ray_transport/ray_client_proxy.py,sha256=EE11BBsvM1zOGfQK1ilpWXTPyaJrgH4ehDN3XSe1rsw,5535
|
109
|
-
flwr_nightly-1.5.0.
|
110
|
-
flwr_nightly-1.5.0.
|
111
|
-
flwr_nightly-1.5.0.
|
112
|
-
flwr_nightly-1.5.0.
|
113
|
-
flwr_nightly-1.5.0.
|
109
|
+
flwr_nightly-1.5.0.dev20230615.dist-info/METADATA,sha256=9TIY9A0TWNWC8o0GeAMW1uhVfAJ_2_tw6ZEG5HbAMKM,12838
|
110
|
+
flwr_nightly-1.5.0.dev20230615.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
111
|
+
flwr_nightly-1.5.0.dev20230615.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
|
112
|
+
flwr_nightly-1.5.0.dev20230615.dist-info/entry_points.txt,sha256=1uLlD5tIunkzALMfMWnqjdE_D5hRUX_I1iMmOMv6tZI,181
|
113
|
+
flwr_nightly-1.5.0.dev20230615.dist-info/RECORD,,
|
{flwr_nightly-1.5.0.dev20230614.dist-info → flwr_nightly-1.5.0.dev20230615.dist-info}/LICENSE
RENAMED
File without changes
|
File without changes
|
File without changes
|