flwr-nightly 1.16.0.dev20250301__py3-none-any.whl → 1.16.0.dev20250304__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
flwr/cli/build.py CHANGED
@@ -138,6 +138,8 @@ def build(
138
138
  and f.name != "pyproject.toml" # Exclude the original pyproject.toml
139
139
  ]
140
140
 
141
+ all_files.sort()
142
+
141
143
  for file_path in all_files:
142
144
  # Read the file content manually
143
145
  with open(file_path, "rb") as f:
flwr/client/client_app.py CHANGED
@@ -74,7 +74,7 @@ def _inspect_maybe_adapt_client_fn_signature(client_fn: ClientFnExt) -> ClientFn
74
74
 
75
75
 
76
76
  @contextmanager
77
- def _empty_lifecycle(_: Context) -> Iterator[None]:
77
+ def _empty_lifespan(_: Context) -> Iterator[None]:
78
78
  yield
79
79
 
80
80
 
@@ -142,11 +142,11 @@ class ClientApp:
142
142
  self._train: Optional[ClientAppCallable] = None
143
143
  self._evaluate: Optional[ClientAppCallable] = None
144
144
  self._query: Optional[ClientAppCallable] = None
145
- self._lifecycle = _empty_lifecycle
145
+ self._lifespan = _empty_lifespan
146
146
 
147
147
  def __call__(self, message: Message, context: Context) -> Message:
148
148
  """Execute `ClientApp`."""
149
- with self._lifecycle(context):
149
+ with self._lifespan(context):
150
150
  # Execute message using `client_fn`
151
151
  if self._call:
152
152
  return self._call(message, context)
@@ -305,12 +305,12 @@ class ClientApp:
305
305
 
306
306
  return query_decorator
307
307
 
308
- def lifecycle(
308
+ def lifespan(
309
309
  self,
310
310
  ) -> Callable[
311
311
  [Callable[[Context], Iterator[None]]], Callable[[Context], Iterator[None]]
312
312
  ]:
313
- """Return a decorator that registers the lifecycle fn with the client app.
313
+ """Return a decorator that registers the lifespan fn with the client app.
314
314
 
315
315
  The decorated function should accept a `Context` object and use `yield`
316
316
  to define enter and exit behavior.
@@ -319,29 +319,33 @@ class ClientApp:
319
319
  --------
320
320
  >>> app = ClientApp()
321
321
  >>>
322
- >>> @app.lifecycle()
323
- >>> def lifecycle(context: Context) -> None:
322
+ >>> @app.lifespan()
323
+ >>> def lifespan(context: Context) -> None:
324
+ >>> # Perform initialization tasks before the app starts
324
325
  >>> print("Initializing ClientApp")
325
- >>> yield
326
+ >>>
327
+ >>> yield # ClientApp is running
328
+ >>>
329
+ >>> # Perform cleanup tasks after the app stops
326
330
  >>> print("Cleaning up ClientApp")
327
331
  """
328
332
 
329
- def lifecycle_decorator(
330
- lifecycle_fn: Callable[[Context], Iterator[None]]
333
+ def lifespan_decorator(
334
+ lifespan_fn: Callable[[Context], Iterator[None]]
331
335
  ) -> Callable[[Context], Iterator[None]]:
332
- """Register the lifecycle fn with the ServerApp object."""
333
- warn_preview_feature("ClientApp-register-lifecycle-function")
336
+ """Register the lifespan fn with the ServerApp object."""
337
+ warn_preview_feature("ClientApp-register-lifespan-function")
334
338
 
335
339
  @contextmanager
336
- def decorated_lifecycle(context: Context) -> Iterator[None]:
337
- # Execute the code before `yield` in lifecycle_fn
340
+ def decorated_lifespan(context: Context) -> Iterator[None]:
341
+ # Execute the code before `yield` in lifespan_fn
338
342
  try:
339
- if not isinstance(it := lifecycle_fn(context), Iterator):
343
+ if not isinstance(it := lifespan_fn(context), Iterator):
340
344
  raise StopIteration
341
345
  next(it)
342
346
  except StopIteration:
343
347
  raise RuntimeError(
344
- "Lifecycle function should yield at least once."
348
+ "lifespan function should yield at least once."
345
349
  ) from None
346
350
 
347
351
  try:
@@ -349,21 +353,21 @@ class ClientApp:
349
353
  yield
350
354
  finally:
351
355
  try:
352
- # Execute the code after `yield` in lifecycle_fn
356
+ # Execute the code after `yield` in lifespan_fn
353
357
  next(it)
354
358
  except StopIteration:
355
359
  pass
356
360
  else:
357
- raise RuntimeError("Lifecycle function should only yield once.")
361
+ raise RuntimeError("lifespan function should only yield once.")
358
362
 
359
363
  # Register provided function with the ClientApp object
360
364
  # Ignore mypy error because of different argument names (`_` vs `context`)
361
- self._lifecycle = decorated_lifecycle # type: ignore
365
+ self._lifespan = decorated_lifespan # type: ignore
362
366
 
363
367
  # Return provided function unmodified
364
- return lifecycle_fn
368
+ return lifespan_fn
365
369
 
366
- return lifecycle_decorator
370
+ return lifespan_decorator
367
371
 
368
372
 
369
373
  class LoadClientAppError(Exception):
flwr/common/message.py CHANGED
@@ -126,6 +126,16 @@ class Metadata: # pylint: disable=too-many-instance-attributes
126
126
  """Set creation timestamp for this message."""
127
127
  self.__dict__["_created_at"] = value
128
128
 
129
+ @property
130
+ def delivered_at(self) -> str:
131
+ """Unix timestamp when the message was delivered."""
132
+ return cast(str, self.__dict__["_delivered_at"])
133
+
134
+ @delivered_at.setter
135
+ def delivered_at(self, value: str) -> None:
136
+ """Set delivery timestamp of this message."""
137
+ self.__dict__["_delivered_at"] = value
138
+
129
139
  @property
130
140
  def ttl(self) -> float:
131
141
  """Time-to-live for this message."""
@@ -223,6 +233,7 @@ class Message:
223
233
  raise ValueError("Either `content` or `error` must be set, but not both.")
224
234
 
225
235
  metadata.created_at = time.time() # Set the message creation timestamp
236
+ metadata.delivered_at = ""
226
237
  var_dict = {
227
238
  "_metadata": metadata,
228
239
  "_content": content,
flwr/server/server_app.py CHANGED
@@ -48,7 +48,7 @@ SERVER_FN_USAGE_EXAMPLE = """
48
48
 
49
49
 
50
50
  @contextmanager
51
- def _empty_lifecycle(_: Context) -> Iterator[None]:
51
+ def _empty_lifespan(_: Context) -> Iterator[None]:
52
52
  yield
53
53
 
54
54
 
@@ -112,11 +112,11 @@ class ServerApp: # pylint: disable=too-many-instance-attributes
112
112
  self._client_manager = client_manager
113
113
  self._server_fn = server_fn
114
114
  self._main: Optional[ServerAppCallable] = None
115
- self._lifecycle = _empty_lifecycle
115
+ self._lifespan = _empty_lifespan
116
116
 
117
117
  def __call__(self, driver: Driver, context: Context) -> None:
118
118
  """Execute `ServerApp`."""
119
- with self._lifecycle(context):
119
+ with self._lifespan(context):
120
120
  # Compatibility mode
121
121
  if not self._main:
122
122
  if self._server_fn:
@@ -186,12 +186,12 @@ class ServerApp: # pylint: disable=too-many-instance-attributes
186
186
 
187
187
  return main_decorator
188
188
 
189
- def lifecycle(
189
+ def lifespan(
190
190
  self,
191
191
  ) -> Callable[
192
192
  [Callable[[Context], Iterator[None]]], Callable[[Context], Iterator[None]]
193
193
  ]:
194
- """Return a decorator that registers the lifecycle fn with the server app.
194
+ """Return a decorator that registers the lifespan fn with the server app.
195
195
 
196
196
  The decorated function should accept a `Context` object and use `yield`
197
197
  to define enter and exit behavior.
@@ -200,29 +200,33 @@ class ServerApp: # pylint: disable=too-many-instance-attributes
200
200
  --------
201
201
  >>> app = ServerApp()
202
202
  >>>
203
- >>> @app.lifecycle()
204
- >>> def lifecycle(context: Context) -> None:
203
+ >>> @app.lifespan()
204
+ >>> def lifespan(context: Context) -> None:
205
+ >>> # Perform initialization tasks before the app starts
205
206
  >>> print("Initializing ServerApp")
206
- >>> yield
207
+ >>>
208
+ >>> yield # ServerApp is running
209
+ >>>
210
+ >>> # Perform cleanup tasks after the app stops
207
211
  >>> print("Cleaning up ServerApp")
208
212
  """
209
213
 
210
- def lifecycle_decorator(
211
- lifecycle_fn: Callable[[Context], Iterator[None]]
214
+ def lifespan_decorator(
215
+ lifespan_fn: Callable[[Context], Iterator[None]]
212
216
  ) -> Callable[[Context], Iterator[None]]:
213
- """Register the lifecycle fn with the ServerApp object."""
214
- warn_preview_feature("ServerApp-register-lifecycle-function")
217
+ """Register the lifespan fn with the ServerApp object."""
218
+ warn_preview_feature("ServerApp-register-lifespan-function")
215
219
 
216
220
  @contextmanager
217
- def decorated_lifecycle(context: Context) -> Iterator[None]:
218
- # Execute the code before `yield` in lifecycle_fn
221
+ def decorated_lifespan(context: Context) -> Iterator[None]:
222
+ # Execute the code before `yield` in lifespan_fn
219
223
  try:
220
- if not isinstance(it := lifecycle_fn(context), Iterator):
224
+ if not isinstance(it := lifespan_fn(context), Iterator):
221
225
  raise StopIteration
222
226
  next(it)
223
227
  except StopIteration:
224
228
  raise RuntimeError(
225
- "Lifecycle function should yield at least once."
229
+ "lifespan function should yield at least once."
226
230
  ) from None
227
231
 
228
232
  try:
@@ -230,21 +234,21 @@ class ServerApp: # pylint: disable=too-many-instance-attributes
230
234
  yield
231
235
  finally:
232
236
  try:
233
- # Execute the code after `yield` in lifecycle_fn
237
+ # Execute the code after `yield` in lifespan_fn
234
238
  next(it)
235
239
  except StopIteration:
236
240
  pass
237
241
  else:
238
- raise RuntimeError("Lifecycle function should only yield once.")
242
+ raise RuntimeError("lifespan function should only yield once.")
239
243
 
240
244
  # Register provided function with the ServerApp object
241
245
  # Ignore mypy error because of different argument names (`_` vs `context`)
242
- self._lifecycle = decorated_lifecycle # type: ignore
246
+ self._lifespan = decorated_lifespan # type: ignore
243
247
 
244
248
  # Return provided function unmodified
245
- return lifecycle_fn
249
+ return lifespan_fn
246
250
 
247
- return lifecycle_decorator
251
+ return lifespan_decorator
248
252
 
249
253
 
250
254
  class LoadServerAppError(Exception):
@@ -16,9 +16,11 @@
16
16
 
17
17
 
18
18
  from .tensorboard import tensorboard as tensorboard
19
+ from .validator import validate_message as validate_message
19
20
  from .validator import validate_task_ins_or_res as validate_task_ins_or_res
20
21
 
21
22
  __all__ = [
22
23
  "tensorboard",
24
+ "validate_message",
23
25
  "validate_task_ins_or_res",
24
26
  ]
@@ -18,6 +18,7 @@
18
18
  import time
19
19
  from typing import Union
20
20
 
21
+ from flwr.common import Message
21
22
  from flwr.common.constant import SUPERLINK_NODE_ID
22
23
  from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611
23
24
 
@@ -106,3 +107,75 @@ def validate_task_ins_or_res(tasks_ins_res: Union[TaskIns, TaskRes]) -> list[str
106
107
  validation_errors.append("`ancestry` is empty")
107
108
 
108
109
  return validation_errors
110
+
111
+
112
+ # pylint: disable-next=too-many-branches
113
+ def validate_message(message: Message, is_reply_message: bool) -> list[str]:
114
+ """Validate a Message."""
115
+ validation_errors = []
116
+ metadata = message.metadata
117
+
118
+ if metadata.message_id != "":
119
+ validation_errors.append("non-empty `metadata.message_id`")
120
+
121
+ # Created/delivered/TTL/Pushed
122
+ if (
123
+ metadata.created_at < 1740700800.0
124
+ ): # unix timestamp of 28 February 2025 00h:00m:00s UTC
125
+ validation_errors.append(
126
+ "`metadata.created_at` must be a float that records the unix timestamp "
127
+ "in seconds when the message was created."
128
+ )
129
+ if metadata.delivered_at != "":
130
+ validation_errors.append("`metadata.delivered_at` must be an empty str")
131
+ if metadata.ttl <= 0:
132
+ validation_errors.append("`metadata.ttl` must be higher than zero")
133
+
134
+ # Verify TTL and created_at time
135
+ current_time = time.time()
136
+ if metadata.created_at + metadata.ttl <= current_time:
137
+ validation_errors.append("Message TTL has expired")
138
+
139
+ # Source node is set and is not zero
140
+ if not metadata.src_node_id:
141
+ validation_errors.append("`metadata.src_node_id` is not set.")
142
+
143
+ # Destination node is set and is not zero
144
+ if not metadata.dst_node_id:
145
+ validation_errors.append("`metadata.dst_node_id` is not set.")
146
+
147
+ # Message type
148
+ if metadata.message_type == "":
149
+ validation_errors.append("`metadata.message_type` MUST be set")
150
+
151
+ # Content
152
+ if not message.has_content() != message.has_error():
153
+ validation_errors.append(
154
+ "Either message `content` or `error` MUST be set (but not both)"
155
+ )
156
+
157
+ # Link respose to original message
158
+ if not is_reply_message:
159
+ if metadata.reply_to_message != "":
160
+ validation_errors.append("`metadata.reply_to_message` MUST not be set.")
161
+ if metadata.src_node_id != SUPERLINK_NODE_ID:
162
+ validation_errors.append(
163
+ f"`metadata.src_node_id` is not {SUPERLINK_NODE_ID} (SuperLink node ID)"
164
+ )
165
+ if metadata.dst_node_id == SUPERLINK_NODE_ID:
166
+ validation_errors.append(
167
+ f"`metadata.dst_node_id` is {SUPERLINK_NODE_ID} (SuperLink node ID)"
168
+ )
169
+ else:
170
+ if metadata.reply_to_message == "":
171
+ validation_errors.append("`metadata.reply_to_message` MUST be set.")
172
+ if metadata.src_node_id == SUPERLINK_NODE_ID:
173
+ validation_errors.append(
174
+ f"`metadata.src_node_id` is {SUPERLINK_NODE_ID} (SuperLink node ID)"
175
+ )
176
+ if metadata.dst_node_id != SUPERLINK_NODE_ID:
177
+ validation_errors.append(
178
+ f"`metadata.dst_node_id` is not {SUPERLINK_NODE_ID} (SuperLink node ID)"
179
+ )
180
+
181
+ return validation_errors
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flwr-nightly
3
- Version: 1.16.0.dev20250301
3
+ Version: 1.16.0.dev20250304
4
4
  Summary: Flower: A Friendly Federated AI Framework
5
5
  Home-page: https://flower.ai
6
6
  License: Apache-2.0
@@ -3,7 +3,7 @@ flwr/cli/__init__.py,sha256=cZJVgozlkC6Ni2Hd_FAIrqefrkCGOV18fikToq-6iLw,720
3
3
  flwr/cli/app.py,sha256=UeXrW5gxrUnFViDjAMIxGNZZKwu3a1oAj83v53IWIWM,1382
4
4
  flwr/cli/auth_plugin/__init__.py,sha256=FyaoqPzcxlBTFfJ2sBRC5USwQLmAhFr5KuBwfMO4bmo,1052
5
5
  flwr/cli/auth_plugin/oidc_cli_plugin.py,sha256=gIhW6Jg9QAo-jL43LYPpw_kn7pdUZZae0s0H8dEgjLM,5384
6
- flwr/cli/build.py,sha256=4P70i_FnUs0P21aTwjTXtFQSAfY-C04hUDF-2npfJdo,6345
6
+ flwr/cli/build.py,sha256=BbS6yrBz0Q0PkNqaEk_VD261iRMfMmkEuQ3GdJpZW54,6375
7
7
  flwr/cli/cli_user_auth_interceptor.py,sha256=aZepPA298s-HjGmkJGMvI_uZe72O5aLC3jri-ilG53o,3126
8
8
  flwr/cli/config_utils.py,sha256=LelRR960I36n1IPw7BIu79fKoOh0JePA58kAtoXSTH0,7518
9
9
  flwr/cli/constant.py,sha256=g7Ad7o3DJDkJNrWS0T3SSJETWSTkkVJWGpLM8zlbpcY,1289
@@ -74,7 +74,7 @@ flwr/cli/utils.py,sha256=D9XcpxzwkGPNdwX16o0kI-sYnRDMlWYyKNIpz6npRhQ,11236
74
74
  flwr/client/__init__.py,sha256=DGDoO0AEAfz-0CUFmLdyUUweAS64-07AOnmDfWUefK4,1192
75
75
  flwr/client/app.py,sha256=tNnef5wGVfqMiiGiWzAuULyy1QpvCKukiRmNi_a2cQc,34261
76
76
  flwr/client/client.py,sha256=8o58nd9o6ZFcMIaVYPGcV4MSjBG4H0oFgWiv8ZEO3oA,7895
77
- flwr/client/client_app.py,sha256=WwKvP-22FRP1419oGYZdvRV5Z3JTNDDUse-Z8ikPkZA,14692
77
+ flwr/client/client_app.py,sha256=glgQOWgFB_6NQ3YAzekXJDoy8R5T1JPhOSiFem1-fS8,14847
78
78
  flwr/client/clientapp/__init__.py,sha256=kZqChGnTChQ1WGSUkIlW2S5bc0d0mzDubCAmZUGRpEY,800
79
79
  flwr/client/clientapp/app.py,sha256=Us5Mw3wvGd_6P1zHOf3TNcRGBBulVZDo3LuZOs17WgM,8963
80
80
  flwr/client/clientapp/clientappio_servicer.py,sha256=5L6bjw_j3Mnx9kRFwYwxDNABKurBO5q1jZOWE_X11wQ,8522
@@ -131,7 +131,7 @@ flwr/common/exit/exit_code.py,sha256=PNEnCrZfOILjfDAFu5m-2YWEJBrk97xglq4zCUlqV7E
131
131
  flwr/common/exit_handlers.py,sha256=yclujry30954o0lI7vtknTajskPCvK8TXw2V3RdldXU,3174
132
132
  flwr/common/grpc.py,sha256=K60AIvIqH0CvkkiqBfw5HoxQfbFOL2DrhKPjbZ8raIE,9786
133
133
  flwr/common/logger.py,sha256=Hund1C6bEhMw3GemlzuFK22tXZ27YeHLrFB0b4LP5f8,13041
134
- flwr/common/message.py,sha256=Zv4ID2BLQsbff0F03DI_MeFoHbSqVZAdDD9NcKYv6Zo,13832
134
+ flwr/common/message.py,sha256=VcGIBkb0te_OIKy22k4oHiOVrx0B2-8S1Gxmq0QLzTg,14210
135
135
  flwr/common/object_ref.py,sha256=DXL8NtbN17DSYaR-Zc8WYhaG8rv0_D_cclvP7Sa66So,9134
136
136
  flwr/common/parameter.py,sha256=-bFAUayToYDF50FZGrBC1hQYJCQDtB2bbr3ZuVLMtdE,2095
137
137
  flwr/common/pyproject.py,sha256=vEAxl800XiJ1JNJDui8vuVV-08msnB6hLt7o95viZl0,1386
@@ -235,7 +235,7 @@ flwr/server/driver/inmemory_driver.py,sha256=7ZtWDDJa8xupPAHNaDdCE2DOIOIYgrffmJM
235
235
  flwr/server/history.py,sha256=qSb5_pPTrwofpSYGsZWzMPkl_4uJ4mJFWesxXDrEvDU,5026
236
236
  flwr/server/run_serverapp.py,sha256=vIPhvJx0i5sEZO4IKM6ruCXmx4ncat76rh0B4KhdhhM,2446
237
237
  flwr/server/server.py,sha256=1ZsFEptmAV-L2vP2etNC9Ed5CLSxpuKzUFkAPQ4l5Xc,17893
238
- flwr/server/server_app.py,sha256=QtxZKdqP8GUDBIilKRLP7smLjabHPnzS8XhtdqRWbIU,8880
238
+ flwr/server/server_app.py,sha256=Kb0ayKy19awnkslwN9Jx3eBWZJvDeA8VfFBvImmMf_E,9035
239
239
  flwr/server/server_config.py,sha256=CZaHVAsMvGLjpWVcLPkiYxgJN4xfIyAiUrCI3fETKY4,1349
240
240
  flwr/server/serverapp/__init__.py,sha256=L0K-94UDdTyEZ8LDtYybGIIIv3HW6AhSVjXMUfYJQnQ,800
241
241
  flwr/server/serverapp/app.py,sha256=5nFRYYzC2vh0l1fKJofBfKwFam93In4b80wvH9eFfQ8,8651
@@ -303,9 +303,9 @@ flwr/server/superlink/simulation/simulationio_grpc.py,sha256=8aUrZZLdvprKUfLLqFI
303
303
  flwr/server/superlink/simulation/simulationio_servicer.py,sha256=J_TmdqM-Bxgp-iPEI3tvCuBpykw1UX0FouMQalEYAF4,6907
304
304
  flwr/server/superlink/utils.py,sha256=KVb3K_g2vYfu9TnftcN0ewmev133WZcjuEePMm8d7GE,2137
305
305
  flwr/server/typing.py,sha256=5kaRLZuxTEse9A0g7aVna2VhYxU3wTq1f3d3mtw7kXs,1019
306
- flwr/server/utils/__init__.py,sha256=pltsPHJoXmUIr3utjwwYxu7_ZAGy5u4MVHzv9iA5Un8,908
306
+ flwr/server/utils/__init__.py,sha256=myLB6L0ycQ0rd_nnL1pI-NLdFoOfXcj_z4gIqqj8Ye4,992
307
307
  flwr/server/utils/tensorboard.py,sha256=gEBD8w_5uaIfp5aw5RYH66lYZpd_SfkObHQ7eDd9MUk,5466
308
- flwr/server/utils/validator.py,sha256=BQ56tDrrOOG52q3RVeeCODz-oEBxu4L19wbfkBPdCqw,4419
308
+ flwr/server/utils/validator.py,sha256=UzYFMIyXyORXYRYXbFhOk6q6GDpOE-eIqLhlNFnR__0,7256
309
309
  flwr/server/workflow/__init__.py,sha256=SXY0XkwbkezFBxxrFB5hKUtmtAgnYISBkPouR1V71ss,902
310
310
  flwr/server/workflow/constant.py,sha256=q4DLdR8Krlxuewq2AQjwTL75hphxE5ODNz4AhViHMXk,1082
311
311
  flwr/server/workflow/default_workflows.py,sha256=UMC9JgdomKwxql5G0OV4AeRXWI-bMClaLAOn5OrZMnw,14073
@@ -329,8 +329,8 @@ flwr/superexec/exec_servicer.py,sha256=72AL60LBbWD-OTxTvtPBrnb_M5rccMtU_JAYcEVQV
329
329
  flwr/superexec/exec_user_auth_interceptor.py,sha256=YtvcjrD2hMVmZ3y9wHuGI6FwmG_Y__q112t4fFnypy0,3793
330
330
  flwr/superexec/executor.py,sha256=_B55WW2TD1fBINpabSSDRenVHXYmvlfhv-k8hJKU4lQ,3115
331
331
  flwr/superexec/simulation.py,sha256=WQDon15oqpMopAZnwRZoTICYCfHqtkvFSqiTQ2hLD_g,4088
332
- flwr_nightly-1.16.0.dev20250301.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
333
- flwr_nightly-1.16.0.dev20250301.dist-info/METADATA,sha256=7SD9nmJ4XJXWi7PwV6MkAC_L-4mFriQVvn2823eLLmE,15877
334
- flwr_nightly-1.16.0.dev20250301.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
335
- flwr_nightly-1.16.0.dev20250301.dist-info/entry_points.txt,sha256=JlNxX3qhaV18_2yj5a3kJW1ESxm31cal9iS_N_pf1Rk,538
336
- flwr_nightly-1.16.0.dev20250301.dist-info/RECORD,,
332
+ flwr_nightly-1.16.0.dev20250304.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
333
+ flwr_nightly-1.16.0.dev20250304.dist-info/METADATA,sha256=9UmUVO9D8c2kO1ENirbWqVGKtkre0B99yYfu3kfqLvs,15877
334
+ flwr_nightly-1.16.0.dev20250304.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
335
+ flwr_nightly-1.16.0.dev20250304.dist-info/entry_points.txt,sha256=JlNxX3qhaV18_2yj5a3kJW1ESxm31cal9iS_N_pf1Rk,538
336
+ flwr_nightly-1.16.0.dev20250304.dist-info/RECORD,,