flwr-nightly 1.16.0.dev20250202__py3-none-any.whl → 1.16.0.dev20250205__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/auth_plugin/oidc_cli_plugin.py +2 -2
- flwr/cli/utils.py +2 -2
- flwr/common/constant.py +9 -7
- flwr/common/exit_handlers.py +17 -29
- flwr/server/app.py +2 -2
- flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +17 -4
- {flwr_nightly-1.16.0.dev20250202.dist-info → flwr_nightly-1.16.0.dev20250205.dist-info}/METADATA +1 -1
- {flwr_nightly-1.16.0.dev20250202.dist-info → flwr_nightly-1.16.0.dev20250205.dist-info}/RECORD +11 -11
- {flwr_nightly-1.16.0.dev20250202.dist-info → flwr_nightly-1.16.0.dev20250205.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.16.0.dev20250202.dist-info → flwr_nightly-1.16.0.dev20250205.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.16.0.dev20250202.dist-info → flwr_nightly-1.16.0.dev20250205.dist-info}/entry_points.txt +0 -0
@@ -26,7 +26,7 @@ import typer
|
|
26
26
|
from flwr.common.auth_plugin import CliAuthPlugin
|
27
27
|
from flwr.common.constant import (
|
28
28
|
ACCESS_TOKEN_KEY,
|
29
|
-
|
29
|
+
AUTH_TYPE_JSON_KEY,
|
30
30
|
REFRESH_TOKEN_KEY,
|
31
31
|
AuthType,
|
32
32
|
)
|
@@ -97,7 +97,7 @@ class OidcCliPlugin(CliAuthPlugin):
|
|
97
97
|
self.access_token = credentials.access_token
|
98
98
|
self.refresh_token = credentials.refresh_token
|
99
99
|
json_dict = {
|
100
|
-
|
100
|
+
AUTH_TYPE_JSON_KEY: AuthType.OIDC,
|
101
101
|
ACCESS_TOKEN_KEY: credentials.access_token,
|
102
102
|
REFRESH_TOKEN_KEY: credentials.refresh_token,
|
103
103
|
}
|
flwr/cli/utils.py
CHANGED
@@ -28,7 +28,7 @@ import typer
|
|
28
28
|
|
29
29
|
from flwr.cli.cli_user_auth_interceptor import CliUserAuthInterceptor
|
30
30
|
from flwr.common.auth_plugin import CliAuthPlugin
|
31
|
-
from flwr.common.constant import
|
31
|
+
from flwr.common.constant import AUTH_TYPE_JSON_KEY, CREDENTIALS_DIR, FLWR_DIR
|
32
32
|
from flwr.common.grpc import (
|
33
33
|
GRPC_MAX_MESSAGE_LENGTH,
|
34
34
|
create_channel,
|
@@ -239,7 +239,7 @@ def try_obtain_cli_auth_plugin(
|
|
239
239
|
try:
|
240
240
|
with config_path.open("r", encoding="utf-8") as file:
|
241
241
|
json_file = json.load(file)
|
242
|
-
auth_type = json_file[
|
242
|
+
auth_type = json_file[AUTH_TYPE_JSON_KEY]
|
243
243
|
except (FileNotFoundError, KeyError):
|
244
244
|
typer.secho(
|
245
245
|
"❌ Missing or invalid credentials for user authentication. "
|
flwr/common/constant.py
CHANGED
@@ -108,15 +108,17 @@ MAX_RETRY_DELAY = 20 # Maximum delay duration between two consecutive retries.
|
|
108
108
|
|
109
109
|
# Constants for user authentication
|
110
110
|
CREDENTIALS_DIR = ".credentials"
|
111
|
-
|
112
|
-
|
113
|
-
|
111
|
+
AUTH_TYPE_JSON_KEY = "auth-type" # For key name in JSON file
|
112
|
+
AUTH_TYPE_YAML_KEY = "auth_type" # For key name in YAML file
|
113
|
+
ACCESS_TOKEN_KEY = "flwr-oidc-access-token"
|
114
|
+
REFRESH_TOKEN_KEY = "flwr-oidc-refresh-token"
|
114
115
|
|
115
116
|
# Constants for node authentication
|
116
|
-
PUBLIC_KEY_HEADER = "public-key-bin" # Must end with "-bin" for binary data
|
117
|
-
SIGNATURE_HEADER = "signature-bin" # Must end with "-bin" for binary data
|
118
|
-
TIMESTAMP_HEADER = "timestamp"
|
119
|
-
TIMESTAMP_TOLERANCE = 10 #
|
117
|
+
PUBLIC_KEY_HEADER = "flwr-public-key-bin" # Must end with "-bin" for binary data
|
118
|
+
SIGNATURE_HEADER = "flwr-signature-bin" # Must end with "-bin" for binary data
|
119
|
+
TIMESTAMP_HEADER = "flwr-timestamp"
|
120
|
+
TIMESTAMP_TOLERANCE = 10 # General tolerance for timestamp verification
|
121
|
+
SYSTEM_TIME_TOLERANCE = 5 # Allowance for system time drift
|
120
122
|
|
121
123
|
|
122
124
|
class MessageType:
|
flwr/common/exit_handlers.py
CHANGED
@@ -15,10 +15,10 @@
|
|
15
15
|
"""Common function to register exit handlers for server and client."""
|
16
16
|
|
17
17
|
|
18
|
-
|
18
|
+
import signal
|
19
19
|
from threading import Thread
|
20
20
|
from types import FrameType
|
21
|
-
from typing import Optional
|
21
|
+
from typing import Callable, Optional
|
22
22
|
|
23
23
|
from grpc import Server
|
24
24
|
|
@@ -26,12 +26,15 @@ from flwr.common.telemetry import EventType
|
|
26
26
|
|
27
27
|
from .exit import ExitCode, flwr_exit
|
28
28
|
|
29
|
-
SIGNAL_TO_EXIT_CODE = {
|
30
|
-
SIGINT: ExitCode.GRACEFUL_EXIT_SIGINT,
|
31
|
-
|
32
|
-
SIGTERM: ExitCode.GRACEFUL_EXIT_SIGTERM,
|
29
|
+
SIGNAL_TO_EXIT_CODE: dict[int, int] = {
|
30
|
+
signal.SIGINT: ExitCode.GRACEFUL_EXIT_SIGINT,
|
31
|
+
signal.SIGTERM: ExitCode.GRACEFUL_EXIT_SIGTERM,
|
33
32
|
}
|
34
33
|
|
34
|
+
# SIGQUIT is not available on Windows
|
35
|
+
if hasattr(signal, "SIGQUIT"):
|
36
|
+
SIGNAL_TO_EXIT_CODE[signal.SIGQUIT] = ExitCode.GRACEFUL_EXIT_SIGQUIT
|
37
|
+
|
35
38
|
|
36
39
|
def register_exit_handlers(
|
37
40
|
event_type: EventType,
|
@@ -54,23 +57,16 @@ def register_exit_handlers(
|
|
54
57
|
An optional list of threads that need to be gracefully
|
55
58
|
terminated before exiting.
|
56
59
|
"""
|
57
|
-
default_handlers = {
|
58
|
-
|
59
|
-
|
60
|
-
SIGTERM: None,
|
61
|
-
}
|
62
|
-
|
63
|
-
def graceful_exit_handler( # type: ignore
|
64
|
-
signalnum,
|
65
|
-
frame: FrameType, # pylint: disable=unused-argument
|
66
|
-
) -> None:
|
60
|
+
default_handlers: dict[int, Callable[[int, FrameType], None]] = {}
|
61
|
+
|
62
|
+
def graceful_exit_handler(signalnum: int, _frame: FrameType) -> None:
|
67
63
|
"""Exit handler to be registered with `signal.signal`.
|
68
64
|
|
69
65
|
When called will reset signal handler to original signal handler from
|
70
66
|
default_handlers.
|
71
67
|
"""
|
72
68
|
# Reset to default handler
|
73
|
-
signal(signalnum, default_handlers[signalnum])
|
69
|
+
signal.signal(signalnum, default_handlers[signalnum]) # type: ignore
|
74
70
|
|
75
71
|
if grpc_servers is not None:
|
76
72
|
for grpc_server in grpc_servers:
|
@@ -87,15 +83,7 @@ def register_exit_handlers(
|
|
87
83
|
event_type=event_type,
|
88
84
|
)
|
89
85
|
|
90
|
-
|
91
|
-
|
92
|
-
graceful_exit_handler
|
93
|
-
|
94
|
-
default_handlers[SIGQUIT] = signal( # type: ignore
|
95
|
-
SIGQUIT,
|
96
|
-
graceful_exit_handler, # type: ignore
|
97
|
-
)
|
98
|
-
default_handlers[SIGTERM] = signal( # type: ignore
|
99
|
-
SIGTERM,
|
100
|
-
graceful_exit_handler, # type: ignore
|
101
|
-
)
|
86
|
+
# Register signal handlers
|
87
|
+
for sig in SIGNAL_TO_EXIT_CODE:
|
88
|
+
default_handler = signal.signal(sig, graceful_exit_handler) # type: ignore
|
89
|
+
default_handlers[sig] = default_handler # type: ignore
|
flwr/server/app.py
CHANGED
@@ -40,7 +40,7 @@ from flwr.common.args import try_obtain_server_certificates
|
|
40
40
|
from flwr.common.auth_plugin import ExecAuthPlugin
|
41
41
|
from flwr.common.config import get_flwr_dir, parse_config_args
|
42
42
|
from flwr.common.constant import (
|
43
|
-
|
43
|
+
AUTH_TYPE_YAML_KEY,
|
44
44
|
CLIENT_OCTET,
|
45
45
|
EXEC_API_DEFAULT_SERVER_ADDRESS,
|
46
46
|
FLEET_API_GRPC_BIDI_DEFAULT_ADDRESS,
|
@@ -578,7 +578,7 @@ def _try_obtain_exec_auth_plugin(
|
|
578
578
|
|
579
579
|
# Load authentication configuration
|
580
580
|
auth_config: dict[str, Any] = config.get("authentication", {})
|
581
|
-
auth_type: str = auth_config.get(
|
581
|
+
auth_type: str = auth_config.get(AUTH_TYPE_YAML_KEY, "")
|
582
582
|
|
583
583
|
# Load authentication plugin
|
584
584
|
try:
|
@@ -25,6 +25,7 @@ from flwr.common import now
|
|
25
25
|
from flwr.common.constant import (
|
26
26
|
PUBLIC_KEY_HEADER,
|
27
27
|
SIGNATURE_HEADER,
|
28
|
+
SYSTEM_TIME_TOLERANCE,
|
28
29
|
TIMESTAMP_HEADER,
|
29
30
|
TIMESTAMP_TOLERANCE,
|
30
31
|
)
|
@@ -38,10 +39,15 @@ from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
|
|
38
39
|
)
|
39
40
|
from flwr.server.superlink.linkstate import LinkStateFactory
|
40
41
|
|
42
|
+
MIN_TIMESTAMP_DIFF = -SYSTEM_TIME_TOLERANCE
|
43
|
+
MAX_TIMESTAMP_DIFF = TIMESTAMP_TOLERANCE + SYSTEM_TIME_TOLERANCE
|
41
44
|
|
42
|
-
|
45
|
+
|
46
|
+
def _unary_unary_rpc_terminator(
|
47
|
+
message: str, code: Any = grpc.StatusCode.UNAUTHENTICATED
|
48
|
+
) -> grpc.RpcMethodHandler:
|
43
49
|
def terminate(_request: GrpcMessage, context: grpc.ServicerContext) -> GrpcMessage:
|
44
|
-
context.abort(
|
50
|
+
context.abort(code, message)
|
45
51
|
raise RuntimeError("Should not reach this point") # Make mypy happy
|
46
52
|
|
47
53
|
return grpc.unary_unary_rpc_method_handler(terminate)
|
@@ -64,7 +70,7 @@ class AuthenticateServerInterceptor(grpc.ServerInterceptor): # type: ignore
|
|
64
70
|
self.state_factory = state_factory
|
65
71
|
self.auto_auth = auto_auth
|
66
72
|
|
67
|
-
def intercept_service(
|
73
|
+
def intercept_service( # pylint: disable=too-many-return-statements
|
68
74
|
self,
|
69
75
|
continuation: Callable[[Any], Any],
|
70
76
|
handler_call_details: grpc.HandlerCallDetails,
|
@@ -75,6 +81,13 @@ class AuthenticateServerInterceptor(grpc.ServerInterceptor): # type: ignore
|
|
75
81
|
metadata sent by the node. Continue RPC call if node is authenticated, else,
|
76
82
|
terminate RPC call by setting context to abort.
|
77
83
|
"""
|
84
|
+
# Filter out non-Fleet service calls
|
85
|
+
if not handler_call_details.method.startswith("/flwr.proto.Fleet/"):
|
86
|
+
return _unary_unary_rpc_terminator(
|
87
|
+
"This request should be sent to a different service.",
|
88
|
+
grpc.StatusCode.FAILED_PRECONDITION,
|
89
|
+
)
|
90
|
+
|
78
91
|
state = self.state_factory.state()
|
79
92
|
metadata_dict = dict(handler_call_details.invocation_metadata)
|
80
93
|
|
@@ -100,7 +113,7 @@ class AuthenticateServerInterceptor(grpc.ServerInterceptor): # type: ignore
|
|
100
113
|
current = now()
|
101
114
|
time_diff = current - datetime.datetime.fromisoformat(timestamp_iso)
|
102
115
|
# Abort the RPC call if the timestamp is too old or in the future
|
103
|
-
if not
|
116
|
+
if not MIN_TIMESTAMP_DIFF < time_diff.total_seconds() < MAX_TIMESTAMP_DIFF:
|
104
117
|
return _unary_unary_rpc_terminator("Invalid timestamp")
|
105
118
|
|
106
119
|
# Continue the RPC call
|
{flwr_nightly-1.16.0.dev20250202.dist-info → flwr_nightly-1.16.0.dev20250205.dist-info}/RECORD
RENAMED
@@ -2,7 +2,7 @@ flwr/__init__.py,sha256=VmBWedrCxqmt4QvUHBLqyVEH6p7zaFMD_oCHerXHSVw,937
|
|
2
2
|
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
|
-
flwr/cli/auth_plugin/oidc_cli_plugin.py,sha256=
|
5
|
+
flwr/cli/auth_plugin/oidc_cli_plugin.py,sha256=gIhW6Jg9QAo-jL43LYPpw_kn7pdUZZae0s0H8dEgjLM,5384
|
6
6
|
flwr/cli/build.py,sha256=4P70i_FnUs0P21aTwjTXtFQSAfY-C04hUDF-2npfJdo,6345
|
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
|
@@ -70,7 +70,7 @@ flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl,sha256=ctdB84ZADY3LH6f8
|
|
70
70
|
flwr/cli/run/__init__.py,sha256=cCsKVB0SFzh2b3QmGba6BHckB85xlhjh3mh4pBpACtY,790
|
71
71
|
flwr/cli/run/run.py,sha256=kEOYKin9qPJy8SODxcAvIWk-OskKPsxvcbvhDhf2VD4,8299
|
72
72
|
flwr/cli/stop.py,sha256=E4TGynmYQss5iWJ_fjSdYIW8nrNta2KOiK4sfvHKO_g,4976
|
73
|
-
flwr/cli/utils.py,sha256=
|
73
|
+
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
|
@@ -117,7 +117,7 @@ flwr/common/args.py,sha256=MgkTUXACuySHyNdxrb7-pK0_R-S2Q7W5MnE3onYUf5I,5183
|
|
117
117
|
flwr/common/auth_plugin/__init__.py,sha256=1Y8Oj3iB49IHDu9tvDih1J74Ygu7k85V9s2A4WORPyA,887
|
118
118
|
flwr/common/auth_plugin/auth_plugin.py,sha256=wgDorBUB4IkK6twQ8vNawRVz7BDPmKdXZBNLqhU9RSs,3871
|
119
119
|
flwr/common/config.py,sha256=SAkG3BztnA6iupXxF3GAIpGmWVVCH0ptyMpC9yjr_14,13965
|
120
|
-
flwr/common/constant.py,sha256=
|
120
|
+
flwr/common/constant.py,sha256=AdNCrHi4sgMCecdX7hHWxMFz3y9pWsjSGU25mA4OJyE,6619
|
121
121
|
flwr/common/context.py,sha256=uJ-mnoC_8y_udEb3kAX-r8CPphNTWM72z1AlsvQEu54,2403
|
122
122
|
flwr/common/date.py,sha256=NHHpESce5wYqEwoDXf09gp9U9l_5Bmlh2BsOcwS-kDM,1554
|
123
123
|
flwr/common/differential_privacy.py,sha256=YA01NqjddKNAEVmf7hXmOVxOjhekgzvJudk3mBGq-2k,6148
|
@@ -126,7 +126,7 @@ flwr/common/dp.py,sha256=vddkvyjV2FhRoN4VuU2LeAM1UBn7dQB8_W-Qdiveal8,1978
|
|
126
126
|
flwr/common/exit/__init__.py,sha256=-ZOJYLaNnR729a7VzZiFsLiqngzKQh3xc27svYStZ_Q,826
|
127
127
|
flwr/common/exit/exit.py,sha256=DmZFyksp-w1sFDQekq5Z-qfnr-ivCAv78aQkqj-TDps,3458
|
128
128
|
flwr/common/exit/exit_code.py,sha256=PNEnCrZfOILjfDAFu5m-2YWEJBrk97xglq4zCUlqV7E,3470
|
129
|
-
flwr/common/exit_handlers.py,sha256=
|
129
|
+
flwr/common/exit_handlers.py,sha256=yclujry30954o0lI7vtknTajskPCvK8TXw2V3RdldXU,3174
|
130
130
|
flwr/common/grpc.py,sha256=K60AIvIqH0CvkkiqBfw5HoxQfbFOL2DrhKPjbZ8raIE,9786
|
131
131
|
flwr/common/logger.py,sha256=Hund1C6bEhMw3GemlzuFK22tXZ27YeHLrFB0b4LP5f8,13041
|
132
132
|
flwr/common/message.py,sha256=Zv4ID2BLQsbff0F03DI_MeFoHbSqVZAdDD9NcKYv6Zo,13832
|
@@ -217,7 +217,7 @@ flwr/proto/transport_pb2_grpc.py,sha256=vLN3EHtx2aEEMCO4f1Upu-l27BPzd3-5pV-u8wPc
|
|
217
217
|
flwr/proto/transport_pb2_grpc.pyi,sha256=AGXf8RiIiW2J5IKMlm_3qT3AzcDa4F3P5IqUjve_esA,766
|
218
218
|
flwr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
219
219
|
flwr/server/__init__.py,sha256=cEg1oecBu4cKB69iJCqWEylC8b5XW47bl7rQiJsdTvM,1528
|
220
|
-
flwr/server/app.py,sha256=
|
220
|
+
flwr/server/app.py,sha256=CVj7lDAYJ4GYnBvAIa0R3A8JV5Dt-ATxDOrLxafLFV8,30545
|
221
221
|
flwr/server/client_manager.py,sha256=7Ese0tgrH-i-ms363feYZJKwB8gWnXSmg_hYF2Bju4U,6227
|
222
222
|
flwr/server/client_proxy.py,sha256=4G-oTwhb45sfWLx2uZdcXD98IZwdTS6F88xe3akCdUg,2399
|
223
223
|
flwr/server/compat/__init__.py,sha256=VxnJtJyOjNFQXMNi9hIuzNlZM5n0Hj1p3aq_Pm2udw4,892
|
@@ -280,7 +280,7 @@ flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py,sha256=h3EhqgelegVC4E
|
|
280
280
|
flwr/server/superlink/fleet/grpc_bidi/grpc_server.py,sha256=mxPxyEF0IW0vV41Bqk1zfKOdRDEvXPwzJyMiRMg7nTI,5173
|
281
281
|
flwr/server/superlink/fleet/grpc_rere/__init__.py,sha256=j2hyC342am-_Hgp1g80Y3fGDzfTI6n8QOOn2PyWf4eg,758
|
282
282
|
flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py,sha256=syWWZgsU3PHvIuvSoJxUTbEdkOtyV6psXAbRowNE_yY,5533
|
283
|
-
flwr/server/superlink/fleet/grpc_rere/server_interceptor.py,sha256=
|
283
|
+
flwr/server/superlink/fleet/grpc_rere/server_interceptor.py,sha256=KPgAcnYsKPPI7_iYNSnqGbyv4tsqZuBqrTiREwVBJiM,6984
|
284
284
|
flwr/server/superlink/fleet/message_handler/__init__.py,sha256=h8oLD7uo5lKICPy0rRdKRjTYe62u8PKkT_fA4xF5JPA,731
|
285
285
|
flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=DM53K4yLOmzXikTe6i6KJ0v8IvlJKDifvFEV09GFKhI,5510
|
286
286
|
flwr/server/superlink/fleet/rest_rere/__init__.py,sha256=5jbYbAn75sGv-gBwOPDySE0kz96F6dTYLeMrGqNi4lM,735
|
@@ -327,8 +327,8 @@ flwr/superexec/exec_servicer.py,sha256=X10ILT-AoGMrB3IgI2mBe9i-QcIVUAl9bucuqVOPY
|
|
327
327
|
flwr/superexec/exec_user_auth_interceptor.py,sha256=K06OU-l4LnYhTDg071hGJuOaQWEJbZsYi5qxUmmtiG0,3704
|
328
328
|
flwr/superexec/executor.py,sha256=_B55WW2TD1fBINpabSSDRenVHXYmvlfhv-k8hJKU4lQ,3115
|
329
329
|
flwr/superexec/simulation.py,sha256=WQDon15oqpMopAZnwRZoTICYCfHqtkvFSqiTQ2hLD_g,4088
|
330
|
-
flwr_nightly-1.16.0.
|
331
|
-
flwr_nightly-1.16.0.
|
332
|
-
flwr_nightly-1.16.0.
|
333
|
-
flwr_nightly-1.16.0.
|
334
|
-
flwr_nightly-1.16.0.
|
330
|
+
flwr_nightly-1.16.0.dev20250205.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
331
|
+
flwr_nightly-1.16.0.dev20250205.dist-info/METADATA,sha256=WKm99h3uLWPbfmQCecvvugCPsm4Ukwm1Sx5kF4VTvzM,15873
|
332
|
+
flwr_nightly-1.16.0.dev20250205.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
333
|
+
flwr_nightly-1.16.0.dev20250205.dist-info/entry_points.txt,sha256=JlNxX3qhaV18_2yj5a3kJW1ESxm31cal9iS_N_pf1Rk,538
|
334
|
+
flwr_nightly-1.16.0.dev20250205.dist-info/RECORD,,
|
{flwr_nightly-1.16.0.dev20250202.dist-info → flwr_nightly-1.16.0.dev20250205.dist-info}/LICENSE
RENAMED
File without changes
|
{flwr_nightly-1.16.0.dev20250202.dist-info → flwr_nightly-1.16.0.dev20250205.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|