flwr-nightly 1.19.0.dev20250524__py3-none-any.whl → 1.19.0.dev20250527__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.
@@ -17,8 +17,10 @@
17
17
 
18
18
  from .auth_plugin import CliAuthPlugin as CliAuthPlugin
19
19
  from .auth_plugin import ExecAuthPlugin as ExecAuthPlugin
20
+ from .auth_plugin import ExecAuthzPlugin as ExecAuthzPlugin
20
21
 
21
22
  __all__ = [
22
23
  "CliAuthPlugin",
23
24
  "ExecAuthPlugin",
25
+ "ExecAuthzPlugin",
24
26
  ]
@@ -64,6 +64,24 @@ class ExecAuthPlugin(ABC):
64
64
  """Refresh authentication tokens in the provided metadata."""
65
65
 
66
66
 
67
+ class ExecAuthzPlugin(ABC): # pylint: disable=too-few-public-methods
68
+ """Abstract Flower Authorization Plugin class for ExecServicer.
69
+
70
+ Parameters
71
+ ----------
72
+ user_authz_config_path : Path
73
+ Path to the YAML file containing the authorization configuration.
74
+ """
75
+
76
+ @abstractmethod
77
+ def __init__(self, user_authz_config_path: Path, verify_tls_cert: bool):
78
+ """Abstract constructor."""
79
+
80
+ @abstractmethod
81
+ def verify_user_authorization(self, user_info: UserInfo) -> bool:
82
+ """Verify user authorization request."""
83
+
84
+
67
85
  class CliAuthPlugin(ABC):
68
86
  """Abstract Flower Auth Plugin class for CLI.
69
87
 
flwr/common/constant.py CHANGED
@@ -115,6 +115,9 @@ AUTH_TYPE_YAML_KEY = "auth_type" # For key name in YAML file
115
115
  ACCESS_TOKEN_KEY = "flwr-oidc-access-token"
116
116
  REFRESH_TOKEN_KEY = "flwr-oidc-refresh-token"
117
117
 
118
+ # Constants for user authorization
119
+ AUTHZ_TYPE_YAML_KEY = "authz_type" # For key name in YAML file
120
+
118
121
  # Constants for node authentication
119
122
  PUBLIC_KEY_HEADER = "flwr-public-key-bin" # Must end with "-bin" for binary data
120
123
  SIGNATURE_HEADER = "flwr-signature-bin" # Must end with "-bin" for binary data
flwr/common/message.py CHANGED
@@ -23,6 +23,7 @@ from typing import Any, cast, overload
23
23
  from flwr.common.date import now
24
24
  from flwr.common.logger import warn_deprecated_feature
25
25
  from flwr.proto.message_pb2 import Message as ProtoMessage # pylint: disable=E0611
26
+ from flwr.proto.message_pb2 import Metadata as ProtoMetadata # pylint: disable=E0611
26
27
 
27
28
  from ..app.error import Error
28
29
  from ..app.metadata import Metadata
@@ -351,9 +352,12 @@ class Message(InflatableObject):
351
352
 
352
353
  def deflate(self) -> bytes:
353
354
  """Deflate message."""
355
+ # Exclude message_id from serialization
356
+ proto_metadata: ProtoMetadata = metadata_to_proto(self.metadata)
357
+ proto_metadata.message_id = ""
354
358
  # Store message metadata and error in object body
355
359
  obj_body = ProtoMessage(
356
- metadata=metadata_to_proto(self.metadata),
360
+ metadata=proto_metadata,
357
361
  content=None,
358
362
  error=error_to_proto(self.error) if self.has_error() else None,
359
363
  ).SerializeToString(deterministic=True)
flwr/compat/client/app.py CHANGED
@@ -15,18 +15,12 @@
15
15
  """Flower client app."""
16
16
 
17
17
 
18
- import multiprocessing
19
- import os
20
- import sys
21
- import threading
22
18
  import time
23
19
  from contextlib import AbstractContextManager
24
20
  from logging import ERROR, INFO, WARN
25
- from os import urandom
26
21
  from pathlib import Path
27
- from typing import Callable, Optional, Union, cast
22
+ from typing import Callable, Optional, Union
28
23
 
29
- import grpc
30
24
  from cryptography.hazmat.primitives.asymmetric import ec
31
25
  from grpc import RpcError
32
26
 
@@ -35,11 +29,6 @@ from flwr.cli.config_utils import get_fab_metadata
35
29
  from flwr.cli.install import install_from_fab
36
30
  from flwr.client.client import Client
37
31
  from flwr.client.client_app import ClientApp, LoadClientAppError
38
- from flwr.client.clientapp.app import flwr_clientapp
39
- from flwr.client.clientapp.clientappio_servicer import (
40
- ClientAppInputs,
41
- ClientAppIoServicer,
42
- )
43
32
  from flwr.client.grpc_adapter_client.connection import grpc_adapter
44
33
  from flwr.client.grpc_rere_client.connection import grpc_request_response
45
34
  from flwr.client.message_handler.message_handler import handle_control_message
@@ -49,13 +38,7 @@ from flwr.client.typing import ClientFnExt
49
38
  from flwr.common import GRPC_MAX_MESSAGE_LENGTH, Context, EventType, Message, event
50
39
  from flwr.common.address import parse_address
51
40
  from flwr.common.constant import (
52
- CLIENT_OCTET,
53
- CLIENTAPPIO_API_DEFAULT_SERVER_ADDRESS,
54
- ISOLATION_MODE_PROCESS,
55
- ISOLATION_MODE_SUBPROCESS,
56
41
  MAX_RETRY_DELAY,
57
- RUN_ID_NUM_BYTES,
58
- SERVER_OCTET,
59
42
  TRANSPORT_TYPE_GRPC_ADAPTER,
60
43
  TRANSPORT_TYPE_GRPC_BIDI,
61
44
  TRANSPORT_TYPE_GRPC_RERE,
@@ -64,12 +47,10 @@ from flwr.common.constant import (
64
47
  ErrorCode,
65
48
  )
66
49
  from flwr.common.exit import ExitCode, flwr_exit
67
- from flwr.common.grpc import generic_create_grpc_server
68
50
  from flwr.common.logger import log, warn_deprecated_feature
69
51
  from flwr.common.retry_invoker import RetryInvoker, RetryState, exponential
70
52
  from flwr.common.typing import Fab, Run, RunNotRunningException, UserConfig
71
53
  from flwr.compat.client.grpc_client.connection import grpc_connection
72
- from flwr.proto.clientappio_pb2_grpc import add_ClientAppIoServicer_to_server
73
54
  from flwr.supernode.nodestate import NodeStateFactory
74
55
 
75
56
 
@@ -238,8 +219,6 @@ def start_client_internal(
238
219
  max_retries: Optional[int] = None,
239
220
  max_wait_time: Optional[float] = None,
240
221
  flwr_path: Optional[Path] = None,
241
- isolation: Optional[str] = None,
242
- clientappio_api_address: Optional[str] = CLIENTAPPIO_API_DEFAULT_SERVER_ADDRESS,
243
222
  ) -> None:
244
223
  """Start a Flower client node which connects to a Flower server.
245
224
 
@@ -292,17 +271,6 @@ def start_client_internal(
292
271
  If set to None, there is no limit to the total time.
293
272
  flwr_path: Optional[Path] (default: None)
294
273
  The fully resolved path containing installed Flower Apps.
295
- isolation : Optional[str] (default: None)
296
- Isolation mode for `ClientApp`. Possible values are `subprocess` and
297
- `process`. Defaults to `None`, which runs the `ClientApp` in the same process
298
- as the SuperNode. If `subprocess`, the `ClientApp` runs in a subprocess started
299
- by the SueprNode and communicates using gRPC at the address
300
- `clientappio_api_address`. If `process`, the `ClientApp` runs in a separate
301
- isolated process and communicates using gRPC at the address
302
- `clientappio_api_address`.
303
- clientappio_api_address : Optional[str]
304
- (default: `CLIENTAPPIO_API_DEFAULT_SERVER_ADDRESS`)
305
- The SuperNode gRPC server address.
306
274
  """
307
275
  if insecure is None:
308
276
  insecure = root_certificates is None
@@ -328,18 +296,6 @@ def start_client_internal(
328
296
 
329
297
  load_client_app_fn = _load_client_app
330
298
 
331
- if isolation:
332
- if clientappio_api_address is None:
333
- raise ValueError(
334
- f"`clientappio_api_address` required when `isolation` is "
335
- f"{ISOLATION_MODE_SUBPROCESS} or {ISOLATION_MODE_PROCESS}",
336
- )
337
- _clientappio_grpc_server, clientappio_servicer = run_clientappio_api_grpc(
338
- address=clientappio_api_address,
339
- certificates=None,
340
- )
341
- clientappio_api_address = cast(str, clientappio_api_address)
342
-
343
299
  # At this point, only `load_client_app_fn` should be used
344
300
  # Both `client` and `client_fn` must not be used directly
345
301
 
@@ -390,7 +346,6 @@ def start_client_internal(
390
346
  run_info_store: Optional[DeprecatedRunInfoStore] = None
391
347
  state_factory = NodeStateFactory()
392
348
  state = state_factory.state()
393
- mp_spawn_context = multiprocessing.get_context("spawn")
394
349
 
395
350
  runs: dict[int, Run] = {}
396
351
 
@@ -475,9 +430,8 @@ def start_client_internal(
475
430
  run: Run = runs[run_id]
476
431
  if get_fab is not None and run.fab_hash:
477
432
  fab = get_fab(run.fab_hash, run_id)
478
- if not isolation:
479
- # If `ClientApp` runs in the same process, install the FAB
480
- install_from_fab(fab.content, flwr_path, True)
433
+ # If `ClientApp` runs in the same process, install the FAB
434
+ install_from_fab(fab.content, flwr_path, True)
481
435
  fab_id, fab_version = get_fab_metadata(fab.content)
482
436
  else:
483
437
  fab = None
@@ -504,73 +458,13 @@ def start_client_internal(
504
458
 
505
459
  # Handle app loading and task message
506
460
  try:
507
- if isolation:
508
- # Two isolation modes:
509
- # 1. `subprocess`: SuperNode is starting the ClientApp
510
- # process as a subprocess.
511
- # 2. `process`: ClientApp process gets started separately
512
- # (via `flwr-clientapp`), for example, in a separate
513
- # Docker container.
514
-
515
- # Generate SuperNode token
516
- token = int.from_bytes(urandom(RUN_ID_NUM_BYTES), "little")
517
-
518
- # Mode 1: SuperNode starts ClientApp as subprocess
519
- start_subprocess = isolation == ISOLATION_MODE_SUBPROCESS
520
-
521
- # Share Message and Context with servicer
522
- clientappio_servicer.set_inputs(
523
- clientapp_input=ClientAppInputs(
524
- message=message,
525
- context=context,
526
- run=run,
527
- fab=fab,
528
- token=token,
529
- ),
530
- token_returned=start_subprocess,
531
- )
532
-
533
- if start_subprocess:
534
- _octet, _colon, _port = (
535
- clientappio_api_address.rpartition(":")
536
- )
537
- io_address = (
538
- f"{CLIENT_OCTET}:{_port}"
539
- if _octet == SERVER_OCTET
540
- else clientappio_api_address
541
- )
542
- # Start ClientApp subprocess
543
- command = [
544
- "flwr-clientapp",
545
- "--clientappio-api-address",
546
- io_address,
547
- "--token",
548
- str(token),
549
- ]
550
- command.append("--insecure")
551
-
552
- proc = mp_spawn_context.Process(
553
- target=_run_flwr_clientapp,
554
- args=(command, os.getpid()),
555
- daemon=True,
556
- )
557
- proc.start()
558
- proc.join()
559
- else:
560
- # Wait for output to become available
561
- while not clientappio_servicer.has_outputs():
562
- time.sleep(0.1)
563
-
564
- outputs = clientappio_servicer.get_outputs()
565
- reply_message, context = outputs.message, outputs.context
566
- else:
567
- # Load ClientApp instance
568
- client_app: ClientApp = load_client_app_fn(
569
- fab_id, fab_version, run.fab_hash
570
- )
461
+ # Load ClientApp instance
462
+ client_app: ClientApp = load_client_app_fn(
463
+ fab_id, fab_version, run.fab_hash
464
+ )
571
465
 
572
- # Execute ClientApp
573
- reply_message = client_app(message=message, context=context)
466
+ # Execute ClientApp
467
+ reply_message = client_app(message=message, context=context)
574
468
  except Exception as ex: # pylint: disable=broad-exception-caught
575
469
 
576
470
  # Legacy grpc-bidi
@@ -801,39 +695,3 @@ def _init_connection(transport: Optional[str], server_address: str) -> tuple[
801
695
  )
802
696
 
803
697
  return connection, address, error_type
804
-
805
-
806
- def _run_flwr_clientapp(args: list[str], main_pid: int) -> None:
807
- # Monitor the main process in case of SIGKILL
808
- def main_process_monitor() -> None:
809
- while True:
810
- time.sleep(1)
811
- if os.getppid() != main_pid:
812
- os.kill(os.getpid(), 9)
813
-
814
- threading.Thread(target=main_process_monitor, daemon=True).start()
815
-
816
- # Run the command
817
- sys.argv = args
818
- flwr_clientapp()
819
-
820
-
821
- def run_clientappio_api_grpc(
822
- address: str,
823
- certificates: Optional[tuple[bytes, bytes, bytes]],
824
- ) -> tuple[grpc.Server, ClientAppIoServicer]:
825
- """Run ClientAppIo API gRPC server."""
826
- clientappio_servicer: grpc.Server = ClientAppIoServicer()
827
- clientappio_add_servicer_to_server_fn = add_ClientAppIoServicer_to_server
828
- clientappio_grpc_server = generic_create_grpc_server(
829
- servicer_and_add_fn=(
830
- clientappio_servicer,
831
- clientappio_add_servicer_to_server_fn,
832
- ),
833
- server_address=address,
834
- max_message_length=GRPC_MAX_MESSAGE_LENGTH,
835
- certificates=certificates,
836
- )
837
- log(INFO, "Starting Flower ClientAppIo gRPC server on %s", address)
838
- clientappio_grpc_server.start()
839
- return clientappio_grpc_server, clientappio_servicer
flwr/proto/fleet_pb2.py CHANGED
@@ -19,15 +19,21 @@ from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
19
19
  from flwr.proto import message_pb2 as flwr_dot_proto_dot_message__pb2
20
20
 
21
21
 
22
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66lwr/proto/fleet.proto\x12\nflwr.proto\x1a\x1a\x66lwr/proto/heartbeat.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x18\x66lwr/proto/message.proto\"/\n\x11\x43reateNodeRequest\x12\x1a\n\x12heartbeat_interval\x18\x01 \x01(\x01\"4\n\x12\x43reateNodeResponse\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"3\n\x11\x44\x65leteNodeRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"\x14\n\x12\x44\x65leteNodeResponse\"J\n\x13PullMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x13\n\x0bmessage_ids\x18\x02 \x03(\t\"l\n\x14PullMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\"a\n\x13PushMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\"\xb0\x01\n\x14PushMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12>\n\x07results\x18\x02 \x03(\x0b\x32-.flwr.proto.PushMessagesResponse.ResultsEntry\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x1e\n\tReconnect\x12\x11\n\treconnect\x18\x01 \x01(\x04\x32\xd7\x05\n\x05\x46leet\x12M\n\nCreateNode\x12\x1d.flwr.proto.CreateNodeRequest\x1a\x1e.flwr.proto.CreateNodeResponse\"\x00\x12M\n\nDeleteNode\x12\x1d.flwr.proto.DeleteNodeRequest\x1a\x1e.flwr.proto.DeleteNodeResponse\"\x00\x12\x62\n\x11SendNodeHeartbeat\x12$.flwr.proto.SendNodeHeartbeatRequest\x1a%.flwr.proto.SendNodeHeartbeatResponse\"\x00\x12S\n\x0cPullMessages\x12\x1f.flwr.proto.PullMessagesRequest\x1a .flwr.proto.PullMessagesResponse\"\x00\x12S\n\x0cPushMessages\x12\x1f.flwr.proto.PushMessagesRequest\x1a .flwr.proto.PushMessagesResponse\"\x00\x12\x41\n\x06GetRun\x12\x19.flwr.proto.GetRunRequest\x1a\x1a.flwr.proto.GetRunResponse\"\x00\x12\x41\n\x06GetFab\x12\x19.flwr.proto.GetFabRequest\x1a\x1a.flwr.proto.GetFabResponse\"\x00\x12M\n\nPushObject\x12\x1d.flwr.proto.PushObjectRequest\x1a\x1e.flwr.proto.PushObjectResponse\"\x00\x12M\n\nPullObject\x12\x1d.flwr.proto.PullObjectRequest\x1a\x1e.flwr.proto.PullObjectResponse\"\x00\x62\x06proto3')
22
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66lwr/proto/fleet.proto\x12\nflwr.proto\x1a\x1a\x66lwr/proto/heartbeat.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x18\x66lwr/proto/message.proto\"/\n\x11\x43reateNodeRequest\x12\x1a\n\x12heartbeat_interval\x18\x01 \x01(\x01\"4\n\x12\x43reateNodeResponse\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"3\n\x11\x44\x65leteNodeRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"\x14\n\x12\x44\x65leteNodeResponse\"J\n\x13PullMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x13\n\x0bmessage_ids\x18\x02 \x03(\t\"\x87\x02\n\x14PullMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\x12L\n\x0fobjects_to_pull\x18\x03 \x03(\x0b\x32\x33.flwr.proto.PullMessagesResponse.ObjectsToPullEntry\x1aK\n\x12ObjectsToPullEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.flwr.proto.ObjectIDs:\x02\x38\x01\"\x91\x02\n\x13PushMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\x12Z\n\x17msg_to_children_mapping\x18\x03 \x03(\x0b\x32\x39.flwr.proto.PushMessagesRequest.MsgToChildrenMappingEntry\x1aR\n\x19MsgToChildrenMappingEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.flwr.proto.ObjectIDs:\x02\x38\x01\"\xcb\x02\n\x14PushMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12>\n\x07results\x18\x02 \x03(\x0b\x32-.flwr.proto.PushMessagesResponse.ResultsEntry\x12L\n\x0fobjects_to_push\x18\x03 \x03(\x0b\x32\x33.flwr.proto.PushMessagesResponse.ObjectsToPushEntry\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\x1aK\n\x12ObjectsToPushEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.flwr.proto.ObjectIDs:\x02\x38\x01\"\x1e\n\tReconnect\x12\x11\n\treconnect\x18\x01 \x01(\x04\x32\xd7\x05\n\x05\x46leet\x12M\n\nCreateNode\x12\x1d.flwr.proto.CreateNodeRequest\x1a\x1e.flwr.proto.CreateNodeResponse\"\x00\x12M\n\nDeleteNode\x12\x1d.flwr.proto.DeleteNodeRequest\x1a\x1e.flwr.proto.DeleteNodeResponse\"\x00\x12\x62\n\x11SendNodeHeartbeat\x12$.flwr.proto.SendNodeHeartbeatRequest\x1a%.flwr.proto.SendNodeHeartbeatResponse\"\x00\x12S\n\x0cPullMessages\x12\x1f.flwr.proto.PullMessagesRequest\x1a .flwr.proto.PullMessagesResponse\"\x00\x12S\n\x0cPushMessages\x12\x1f.flwr.proto.PushMessagesRequest\x1a .flwr.proto.PushMessagesResponse\"\x00\x12\x41\n\x06GetRun\x12\x19.flwr.proto.GetRunRequest\x1a\x1a.flwr.proto.GetRunResponse\"\x00\x12\x41\n\x06GetFab\x12\x19.flwr.proto.GetFabRequest\x1a\x1a.flwr.proto.GetFabResponse\"\x00\x12M\n\nPushObject\x12\x1d.flwr.proto.PushObjectRequest\x1a\x1e.flwr.proto.PushObjectResponse\"\x00\x12M\n\nPullObject\x12\x1d.flwr.proto.PullObjectRequest\x1a\x1e.flwr.proto.PullObjectResponse\"\x00\x62\x06proto3')
23
23
 
24
24
  _globals = globals()
25
25
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
26
26
  _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.fleet_pb2', _globals)
27
27
  if _descriptor._USE_C_DESCRIPTORS == False:
28
28
  DESCRIPTOR._options = None
29
+ _globals['_PULLMESSAGESRESPONSE_OBJECTSTOPULLENTRY']._options = None
30
+ _globals['_PULLMESSAGESRESPONSE_OBJECTSTOPULLENTRY']._serialized_options = b'8\001'
31
+ _globals['_PUSHMESSAGESREQUEST_MSGTOCHILDRENMAPPINGENTRY']._options = None
32
+ _globals['_PUSHMESSAGESREQUEST_MSGTOCHILDRENMAPPINGENTRY']._serialized_options = b'8\001'
29
33
  _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._options = None
30
34
  _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_options = b'8\001'
35
+ _globals['_PUSHMESSAGESRESPONSE_OBJECTSTOPUSHENTRY']._options = None
36
+ _globals['_PUSHMESSAGESRESPONSE_OBJECTSTOPUSHENTRY']._serialized_options = b'8\001'
31
37
  _globals['_CREATENODEREQUEST']._serialized_start=159
32
38
  _globals['_CREATENODEREQUEST']._serialized_end=206
33
39
  _globals['_CREATENODERESPONSE']._serialized_start=208
@@ -38,16 +44,22 @@ if _descriptor._USE_C_DESCRIPTORS == False:
38
44
  _globals['_DELETENODERESPONSE']._serialized_end=335
39
45
  _globals['_PULLMESSAGESREQUEST']._serialized_start=337
40
46
  _globals['_PULLMESSAGESREQUEST']._serialized_end=411
41
- _globals['_PULLMESSAGESRESPONSE']._serialized_start=413
42
- _globals['_PULLMESSAGESRESPONSE']._serialized_end=521
43
- _globals['_PUSHMESSAGESREQUEST']._serialized_start=523
44
- _globals['_PUSHMESSAGESREQUEST']._serialized_end=620
45
- _globals['_PUSHMESSAGESRESPONSE']._serialized_start=623
46
- _globals['_PUSHMESSAGESRESPONSE']._serialized_end=799
47
- _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_start=753
48
- _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_end=799
49
- _globals['_RECONNECT']._serialized_start=801
50
- _globals['_RECONNECT']._serialized_end=831
51
- _globals['_FLEET']._serialized_start=834
52
- _globals['_FLEET']._serialized_end=1561
47
+ _globals['_PULLMESSAGESRESPONSE']._serialized_start=414
48
+ _globals['_PULLMESSAGESRESPONSE']._serialized_end=677
49
+ _globals['_PULLMESSAGESRESPONSE_OBJECTSTOPULLENTRY']._serialized_start=602
50
+ _globals['_PULLMESSAGESRESPONSE_OBJECTSTOPULLENTRY']._serialized_end=677
51
+ _globals['_PUSHMESSAGESREQUEST']._serialized_start=680
52
+ _globals['_PUSHMESSAGESREQUEST']._serialized_end=953
53
+ _globals['_PUSHMESSAGESREQUEST_MSGTOCHILDRENMAPPINGENTRY']._serialized_start=871
54
+ _globals['_PUSHMESSAGESREQUEST_MSGTOCHILDRENMAPPINGENTRY']._serialized_end=953
55
+ _globals['_PUSHMESSAGESRESPONSE']._serialized_start=956
56
+ _globals['_PUSHMESSAGESRESPONSE']._serialized_end=1287
57
+ _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_start=1164
58
+ _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_end=1210
59
+ _globals['_PUSHMESSAGESRESPONSE_OBJECTSTOPUSHENTRY']._serialized_start=1212
60
+ _globals['_PUSHMESSAGESRESPONSE_OBJECTSTOPUSHENTRY']._serialized_end=1287
61
+ _globals['_RECONNECT']._serialized_start=1289
62
+ _globals['_RECONNECT']._serialized_end=1319
63
+ _globals['_FLEET']._serialized_start=1322
64
+ _globals['_FLEET']._serialized_end=2049
53
65
  # @@protoc_insertion_point(module_scope)
flwr/proto/fleet_pb2.pyi CHANGED
@@ -78,37 +78,75 @@ global___PullMessagesRequest = PullMessagesRequest
78
78
 
79
79
  class PullMessagesResponse(google.protobuf.message.Message):
80
80
  DESCRIPTOR: google.protobuf.descriptor.Descriptor
81
+ class ObjectsToPullEntry(google.protobuf.message.Message):
82
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
83
+ KEY_FIELD_NUMBER: builtins.int
84
+ VALUE_FIELD_NUMBER: builtins.int
85
+ key: typing.Text
86
+ @property
87
+ def value(self) -> flwr.proto.message_pb2.ObjectIDs: ...
88
+ def __init__(self,
89
+ *,
90
+ key: typing.Text = ...,
91
+ value: typing.Optional[flwr.proto.message_pb2.ObjectIDs] = ...,
92
+ ) -> None: ...
93
+ def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ...
94
+ def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
95
+
81
96
  RECONNECT_FIELD_NUMBER: builtins.int
82
97
  MESSAGES_LIST_FIELD_NUMBER: builtins.int
98
+ OBJECTS_TO_PULL_FIELD_NUMBER: builtins.int
83
99
  @property
84
100
  def reconnect(self) -> global___Reconnect: ...
85
101
  @property
86
102
  def messages_list(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[flwr.proto.message_pb2.Message]: ...
103
+ @property
104
+ def objects_to_pull(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.message_pb2.ObjectIDs]: ...
87
105
  def __init__(self,
88
106
  *,
89
107
  reconnect: typing.Optional[global___Reconnect] = ...,
90
108
  messages_list: typing.Optional[typing.Iterable[flwr.proto.message_pb2.Message]] = ...,
109
+ objects_to_pull: typing.Optional[typing.Mapping[typing.Text, flwr.proto.message_pb2.ObjectIDs]] = ...,
91
110
  ) -> None: ...
92
111
  def HasField(self, field_name: typing_extensions.Literal["reconnect",b"reconnect"]) -> builtins.bool: ...
93
- def ClearField(self, field_name: typing_extensions.Literal["messages_list",b"messages_list","reconnect",b"reconnect"]) -> None: ...
112
+ def ClearField(self, field_name: typing_extensions.Literal["messages_list",b"messages_list","objects_to_pull",b"objects_to_pull","reconnect",b"reconnect"]) -> None: ...
94
113
  global___PullMessagesResponse = PullMessagesResponse
95
114
 
96
115
  class PushMessagesRequest(google.protobuf.message.Message):
97
116
  """PushMessages messages"""
98
117
  DESCRIPTOR: google.protobuf.descriptor.Descriptor
118
+ class MsgToChildrenMappingEntry(google.protobuf.message.Message):
119
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
120
+ KEY_FIELD_NUMBER: builtins.int
121
+ VALUE_FIELD_NUMBER: builtins.int
122
+ key: typing.Text
123
+ @property
124
+ def value(self) -> flwr.proto.message_pb2.ObjectIDs: ...
125
+ def __init__(self,
126
+ *,
127
+ key: typing.Text = ...,
128
+ value: typing.Optional[flwr.proto.message_pb2.ObjectIDs] = ...,
129
+ ) -> None: ...
130
+ def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ...
131
+ def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
132
+
99
133
  NODE_FIELD_NUMBER: builtins.int
100
134
  MESSAGES_LIST_FIELD_NUMBER: builtins.int
135
+ MSG_TO_CHILDREN_MAPPING_FIELD_NUMBER: builtins.int
101
136
  @property
102
137
  def node(self) -> flwr.proto.node_pb2.Node: ...
103
138
  @property
104
139
  def messages_list(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[flwr.proto.message_pb2.Message]: ...
140
+ @property
141
+ def msg_to_children_mapping(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.message_pb2.ObjectIDs]: ...
105
142
  def __init__(self,
106
143
  *,
107
144
  node: typing.Optional[flwr.proto.node_pb2.Node] = ...,
108
145
  messages_list: typing.Optional[typing.Iterable[flwr.proto.message_pb2.Message]] = ...,
146
+ msg_to_children_mapping: typing.Optional[typing.Mapping[typing.Text, flwr.proto.message_pb2.ObjectIDs]] = ...,
109
147
  ) -> None: ...
110
148
  def HasField(self, field_name: typing_extensions.Literal["node",b"node"]) -> builtins.bool: ...
111
- def ClearField(self, field_name: typing_extensions.Literal["messages_list",b"messages_list","node",b"node"]) -> None: ...
149
+ def ClearField(self, field_name: typing_extensions.Literal["messages_list",b"messages_list","msg_to_children_mapping",b"msg_to_children_mapping","node",b"node"]) -> None: ...
112
150
  global___PushMessagesRequest = PushMessagesRequest
113
151
 
114
152
  class PushMessagesResponse(google.protobuf.message.Message):
@@ -126,19 +164,38 @@ class PushMessagesResponse(google.protobuf.message.Message):
126
164
  ) -> None: ...
127
165
  def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
128
166
 
167
+ class ObjectsToPushEntry(google.protobuf.message.Message):
168
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
169
+ KEY_FIELD_NUMBER: builtins.int
170
+ VALUE_FIELD_NUMBER: builtins.int
171
+ key: typing.Text
172
+ @property
173
+ def value(self) -> flwr.proto.message_pb2.ObjectIDs: ...
174
+ def __init__(self,
175
+ *,
176
+ key: typing.Text = ...,
177
+ value: typing.Optional[flwr.proto.message_pb2.ObjectIDs] = ...,
178
+ ) -> None: ...
179
+ def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ...
180
+ def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
181
+
129
182
  RECONNECT_FIELD_NUMBER: builtins.int
130
183
  RESULTS_FIELD_NUMBER: builtins.int
184
+ OBJECTS_TO_PUSH_FIELD_NUMBER: builtins.int
131
185
  @property
132
186
  def reconnect(self) -> global___Reconnect: ...
133
187
  @property
134
188
  def results(self) -> google.protobuf.internal.containers.ScalarMap[typing.Text, builtins.int]: ...
189
+ @property
190
+ def objects_to_push(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.message_pb2.ObjectIDs]: ...
135
191
  def __init__(self,
136
192
  *,
137
193
  reconnect: typing.Optional[global___Reconnect] = ...,
138
194
  results: typing.Optional[typing.Mapping[typing.Text, builtins.int]] = ...,
195
+ objects_to_push: typing.Optional[typing.Mapping[typing.Text, flwr.proto.message_pb2.ObjectIDs]] = ...,
139
196
  ) -> None: ...
140
197
  def HasField(self, field_name: typing_extensions.Literal["reconnect",b"reconnect"]) -> builtins.bool: ...
141
- def ClearField(self, field_name: typing_extensions.Literal["reconnect",b"reconnect","results",b"results"]) -> None: ...
198
+ def ClearField(self, field_name: typing_extensions.Literal["objects_to_push",b"objects_to_push","reconnect",b"reconnect","results",b"results"]) -> None: ...
142
199
  global___PushMessagesResponse = PushMessagesResponse
143
200
 
144
201
  class Reconnect(google.protobuf.message.Message):
flwr/proto/message_pb2.py CHANGED
@@ -15,9 +15,10 @@ _sym_db = _symbol_database.Default()
15
15
  from flwr.proto import error_pb2 as flwr_dot_proto_dot_error__pb2
16
16
  from flwr.proto import recorddict_pb2 as flwr_dot_proto_dot_recorddict__pb2
17
17
  from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2
18
+ from flwr.proto import node_pb2 as flwr_dot_proto_dot_node__pb2
18
19
 
19
20
 
20
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x66lwr/proto/message.proto\x12\nflwr.proto\x1a\x16\x66lwr/proto/error.proto\x1a\x1b\x66lwr/proto/recorddict.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\x16.flwr.proto.RecordDict\x12 \n\x05\x65rror\x18\x03 \x01(\x0b\x32\x11.flwr.proto.Error\"\xd0\x02\n\x07\x43ontext\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12\x0f\n\x07node_id\x18\x02 \x01(\x04\x12\x38\n\x0bnode_config\x18\x03 \x03(\x0b\x32#.flwr.proto.Context.NodeConfigEntry\x12%\n\x05state\x18\x04 \x01(\x0b\x32\x16.flwr.proto.RecordDict\x12\x36\n\nrun_config\x18\x05 \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\"\xbe\x01\n\x08Metadata\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12\x12\n\nmessage_id\x18\x02 \x01(\t\x12\x13\n\x0bsrc_node_id\x18\x03 \x01(\x04\x12\x13\n\x0b\x64st_node_id\x18\x04 \x01(\x04\x12\x1b\n\x13reply_to_message_id\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(\t\x12\x12\n\ncreated_at\x18\t \x01(\x01\">\n\x11PushObjectRequest\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x16\n\x0eobject_content\x18\x02 \x01(\x0c\"\x14\n\x12PushObjectResponse\"&\n\x11PullObjectRequest\x12\x11\n\tobject_id\x18\x01 \x01(\t\",\n\x12PullObjectResponse\x12\x16\n\x0eobject_content\x18\x01 \x01(\x0c\x62\x06proto3')
21
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x66lwr/proto/message.proto\x12\nflwr.proto\x1a\x16\x66lwr/proto/error.proto\x1a\x1b\x66lwr/proto/recorddict.proto\x1a\x1a\x66lwr/proto/transport.proto\x1a\x15\x66lwr/proto/node.proto\"|\n\x07Message\x12&\n\x08metadata\x18\x01 \x01(\x0b\x32\x14.flwr.proto.Metadata\x12\'\n\x07\x63ontent\x18\x02 \x01(\x0b\x32\x16.flwr.proto.RecordDict\x12 \n\x05\x65rror\x18\x03 \x01(\x0b\x32\x11.flwr.proto.Error\"\xd0\x02\n\x07\x43ontext\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12\x0f\n\x07node_id\x18\x02 \x01(\x04\x12\x38\n\x0bnode_config\x18\x03 \x03(\x0b\x32#.flwr.proto.Context.NodeConfigEntry\x12%\n\x05state\x18\x04 \x01(\x0b\x32\x16.flwr.proto.RecordDict\x12\x36\n\nrun_config\x18\x05 \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\"\xbe\x01\n\x08Metadata\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12\x12\n\nmessage_id\x18\x02 \x01(\t\x12\x13\n\x0bsrc_node_id\x18\x03 \x01(\x04\x12\x13\n\x0b\x64st_node_id\x18\x04 \x01(\x04\x12\x1b\n\x13reply_to_message_id\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(\t\x12\x12\n\ncreated_at\x18\t \x01(\x01\"\x1e\n\tObjectIDs\x12\x11\n\tobject_id\x18\x01 \x03(\t\"^\n\x11PushObjectRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x11\n\tobject_id\x18\x02 \x01(\t\x12\x16\n\x0eobject_content\x18\x03 \x01(\x0c\"\x14\n\x12PushObjectResponse\"F\n\x11PullObjectRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x11\n\tobject_id\x18\x02 \x01(\t\",\n\x12PullObjectResponse\x12\x16\n\x0eobject_content\x18\x01 \x01(\x0c\x62\x06proto3')
21
22
 
22
23
  _globals = globals()
23
24
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -28,22 +29,24 @@ if _descriptor._USE_C_DESCRIPTORS == False:
28
29
  _globals['_CONTEXT_NODECONFIGENTRY']._serialized_options = b'8\001'
29
30
  _globals['_CONTEXT_RUNCONFIGENTRY']._options = None
30
31
  _globals['_CONTEXT_RUNCONFIGENTRY']._serialized_options = b'8\001'
31
- _globals['_MESSAGE']._serialized_start=121
32
- _globals['_MESSAGE']._serialized_end=245
33
- _globals['_CONTEXT']._serialized_start=248
34
- _globals['_CONTEXT']._serialized_end=584
35
- _globals['_CONTEXT_NODECONFIGENTRY']._serialized_start=445
36
- _globals['_CONTEXT_NODECONFIGENTRY']._serialized_end=514
37
- _globals['_CONTEXT_RUNCONFIGENTRY']._serialized_start=516
38
- _globals['_CONTEXT_RUNCONFIGENTRY']._serialized_end=584
39
- _globals['_METADATA']._serialized_start=587
40
- _globals['_METADATA']._serialized_end=777
41
- _globals['_PUSHOBJECTREQUEST']._serialized_start=779
42
- _globals['_PUSHOBJECTREQUEST']._serialized_end=841
43
- _globals['_PUSHOBJECTRESPONSE']._serialized_start=843
44
- _globals['_PUSHOBJECTRESPONSE']._serialized_end=863
45
- _globals['_PULLOBJECTREQUEST']._serialized_start=865
46
- _globals['_PULLOBJECTREQUEST']._serialized_end=903
47
- _globals['_PULLOBJECTRESPONSE']._serialized_start=905
48
- _globals['_PULLOBJECTRESPONSE']._serialized_end=949
32
+ _globals['_MESSAGE']._serialized_start=144
33
+ _globals['_MESSAGE']._serialized_end=268
34
+ _globals['_CONTEXT']._serialized_start=271
35
+ _globals['_CONTEXT']._serialized_end=607
36
+ _globals['_CONTEXT_NODECONFIGENTRY']._serialized_start=468
37
+ _globals['_CONTEXT_NODECONFIGENTRY']._serialized_end=537
38
+ _globals['_CONTEXT_RUNCONFIGENTRY']._serialized_start=539
39
+ _globals['_CONTEXT_RUNCONFIGENTRY']._serialized_end=607
40
+ _globals['_METADATA']._serialized_start=610
41
+ _globals['_METADATA']._serialized_end=800
42
+ _globals['_OBJECTIDS']._serialized_start=802
43
+ _globals['_OBJECTIDS']._serialized_end=832
44
+ _globals['_PUSHOBJECTREQUEST']._serialized_start=834
45
+ _globals['_PUSHOBJECTREQUEST']._serialized_end=928
46
+ _globals['_PUSHOBJECTRESPONSE']._serialized_start=930
47
+ _globals['_PUSHOBJECTRESPONSE']._serialized_end=950
48
+ _globals['_PULLOBJECTREQUEST']._serialized_start=952
49
+ _globals['_PULLOBJECTREQUEST']._serialized_end=1022
50
+ _globals['_PULLOBJECTRESPONSE']._serialized_start=1024
51
+ _globals['_PULLOBJECTRESPONSE']._serialized_end=1068
49
52
  # @@protoc_insertion_point(module_scope)
@@ -4,6 +4,7 @@ isort:skip_file
4
4
  """
5
5
  import builtins
6
6
  import flwr.proto.error_pb2
7
+ import flwr.proto.node_pb2
7
8
  import flwr.proto.recorddict_pb2
8
9
  import flwr.proto.transport_pb2
9
10
  import google.protobuf.descriptor
@@ -127,19 +128,36 @@ class Metadata(google.protobuf.message.Message):
127
128
  def ClearField(self, field_name: typing_extensions.Literal["created_at",b"created_at","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_id",b"reply_to_message_id","run_id",b"run_id","src_node_id",b"src_node_id","ttl",b"ttl"]) -> None: ...
128
129
  global___Metadata = Metadata
129
130
 
131
+ class ObjectIDs(google.protobuf.message.Message):
132
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
133
+ OBJECT_ID_FIELD_NUMBER: builtins.int
134
+ @property
135
+ def object_id(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: ...
136
+ def __init__(self,
137
+ *,
138
+ object_id: typing.Optional[typing.Iterable[typing.Text]] = ...,
139
+ ) -> None: ...
140
+ def ClearField(self, field_name: typing_extensions.Literal["object_id",b"object_id"]) -> None: ...
141
+ global___ObjectIDs = ObjectIDs
142
+
130
143
  class PushObjectRequest(google.protobuf.message.Message):
131
144
  """PushObject messages"""
132
145
  DESCRIPTOR: google.protobuf.descriptor.Descriptor
146
+ NODE_FIELD_NUMBER: builtins.int
133
147
  OBJECT_ID_FIELD_NUMBER: builtins.int
134
148
  OBJECT_CONTENT_FIELD_NUMBER: builtins.int
149
+ @property
150
+ def node(self) -> flwr.proto.node_pb2.Node: ...
135
151
  object_id: typing.Text
136
152
  object_content: builtins.bytes
137
153
  def __init__(self,
138
154
  *,
155
+ node: typing.Optional[flwr.proto.node_pb2.Node] = ...,
139
156
  object_id: typing.Text = ...,
140
157
  object_content: builtins.bytes = ...,
141
158
  ) -> None: ...
142
- def ClearField(self, field_name: typing_extensions.Literal["object_content",b"object_content","object_id",b"object_id"]) -> None: ...
159
+ def HasField(self, field_name: typing_extensions.Literal["node",b"node"]) -> builtins.bool: ...
160
+ def ClearField(self, field_name: typing_extensions.Literal["node",b"node","object_content",b"object_content","object_id",b"object_id"]) -> None: ...
143
161
  global___PushObjectRequest = PushObjectRequest
144
162
 
145
163
  class PushObjectResponse(google.protobuf.message.Message):
@@ -151,13 +169,18 @@ global___PushObjectResponse = PushObjectResponse
151
169
  class PullObjectRequest(google.protobuf.message.Message):
152
170
  """PullObject messages"""
153
171
  DESCRIPTOR: google.protobuf.descriptor.Descriptor
172
+ NODE_FIELD_NUMBER: builtins.int
154
173
  OBJECT_ID_FIELD_NUMBER: builtins.int
174
+ @property
175
+ def node(self) -> flwr.proto.node_pb2.Node: ...
155
176
  object_id: typing.Text
156
177
  def __init__(self,
157
178
  *,
179
+ node: typing.Optional[flwr.proto.node_pb2.Node] = ...,
158
180
  object_id: typing.Text = ...,
159
181
  ) -> None: ...
160
- def ClearField(self, field_name: typing_extensions.Literal["object_id",b"object_id"]) -> None: ...
182
+ def HasField(self, field_name: typing_extensions.Literal["node",b"node"]) -> builtins.bool: ...
183
+ def ClearField(self, field_name: typing_extensions.Literal["node",b"node","object_id",b"object_id"]) -> None: ...
161
184
  global___PullObjectRequest = PullObjectRequest
162
185
 
163
186
  class PullObjectResponse(google.protobuf.message.Message):
@@ -20,33 +20,45 @@ from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2
20
20
  from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
21
21
 
22
22
 
23
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x66lwr/proto/serverappio.proto\x12\nflwr.proto\x1a\x1a\x66lwr/proto/heartbeat.proto\x1a\x14\x66lwr/proto/log.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x18\x66lwr/proto/message.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\"!\n\x0fGetNodesRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\"3\n\x10GetNodesResponse\x12\x1f\n\x05nodes\x18\x01 \x03(\x0b\x32\x10.flwr.proto.Node\"T\n\x16PushInsMessagesRequest\x12*\n\rmessages_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.Message\x12\x0e\n\x06run_id\x18\x02 \x01(\x04\".\n\x17PushInsMessagesResponse\x12\x13\n\x0bmessage_ids\x18\x01 \x03(\t\"=\n\x16PullResMessagesRequest\x12\x13\n\x0bmessage_ids\x18\x01 \x03(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\x04\"E\n\x17PullResMessagesResponse\x12*\n\rmessages_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.Message\"\x1c\n\x1aPullServerAppInputsRequest\"\x7f\n\x1bPullServerAppInputsResponse\x12$\n\x07\x63ontext\x18\x01 \x01(\x0b\x32\x13.flwr.proto.Context\x12\x1c\n\x03run\x18\x02 \x01(\x0b\x32\x0f.flwr.proto.Run\x12\x1c\n\x03\x66\x61\x62\x18\x03 \x01(\x0b\x32\x0f.flwr.proto.Fab\"S\n\x1bPushServerAppOutputsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12$\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x13.flwr.proto.Context\"\x1e\n\x1cPushServerAppOutputsResponse2\xe4\x08\n\x0bServerAppIo\x12G\n\x08GetNodes\x12\x1b.flwr.proto.GetNodesRequest\x1a\x1c.flwr.proto.GetNodesResponse\"\x00\x12Y\n\x0cPushMessages\x12\".flwr.proto.PushInsMessagesRequest\x1a#.flwr.proto.PushInsMessagesResponse\"\x00\x12Y\n\x0cPullMessages\x12\".flwr.proto.PullResMessagesRequest\x1a#.flwr.proto.PullResMessagesResponse\"\x00\x12\x41\n\x06GetRun\x12\x19.flwr.proto.GetRunRequest\x1a\x1a.flwr.proto.GetRunResponse\"\x00\x12\x41\n\x06GetFab\x12\x19.flwr.proto.GetFabRequest\x1a\x1a.flwr.proto.GetFabResponse\"\x00\x12h\n\x13PullServerAppInputs\x12&.flwr.proto.PullServerAppInputsRequest\x1a\'.flwr.proto.PullServerAppInputsResponse\"\x00\x12k\n\x14PushServerAppOutputs\x12\'.flwr.proto.PushServerAppOutputsRequest\x1a(.flwr.proto.PushServerAppOutputsResponse\"\x00\x12\\\n\x0fUpdateRunStatus\x12\".flwr.proto.UpdateRunStatusRequest\x1a#.flwr.proto.UpdateRunStatusResponse\"\x00\x12S\n\x0cGetRunStatus\x12\x1f.flwr.proto.GetRunStatusRequest\x1a .flwr.proto.GetRunStatusResponse\"\x00\x12G\n\x08PushLogs\x12\x1b.flwr.proto.PushLogsRequest\x1a\x1c.flwr.proto.PushLogsResponse\"\x00\x12_\n\x10SendAppHeartbeat\x12#.flwr.proto.SendAppHeartbeatRequest\x1a$.flwr.proto.SendAppHeartbeatResponse\"\x00\x12M\n\nPushObject\x12\x1d.flwr.proto.PushObjectRequest\x1a\x1e.flwr.proto.PushObjectResponse\"\x00\x12M\n\nPullObject\x12\x1d.flwr.proto.PullObjectRequest\x1a\x1e.flwr.proto.PullObjectResponse\"\x00\x62\x06proto3')
23
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x66lwr/proto/serverappio.proto\x12\nflwr.proto\x1a\x1a\x66lwr/proto/heartbeat.proto\x1a\x14\x66lwr/proto/log.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x18\x66lwr/proto/message.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\"!\n\x0fGetNodesRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\"3\n\x10GetNodesResponse\x12\x1f\n\x05nodes\x18\x01 \x03(\x0b\x32\x10.flwr.proto.Node\"\x87\x02\n\x16PushInsMessagesRequest\x12*\n\rmessages_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.Message\x12\x0e\n\x06run_id\x18\x02 \x01(\x04\x12]\n\x17msg_to_children_mapping\x18\x03 \x03(\x0b\x32<.flwr.proto.PushInsMessagesRequest.MsgToChildrenMappingEntry\x1aR\n\x19MsgToChildrenMappingEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.flwr.proto.ObjectIDs:\x02\x38\x01\"\xcc\x01\n\x17PushInsMessagesResponse\x12\x13\n\x0bmessage_ids\x18\x01 \x03(\t\x12O\n\x0fobjects_to_push\x18\x02 \x03(\x0b\x32\x36.flwr.proto.PushInsMessagesResponse.ObjectsToPushEntry\x1aK\n\x12ObjectsToPushEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.flwr.proto.ObjectIDs:\x02\x38\x01\"=\n\x16PullResMessagesRequest\x12\x13\n\x0bmessage_ids\x18\x01 \x03(\t\x12\x0e\n\x06run_id\x18\x02 \x01(\x04\"\xe3\x01\n\x17PullResMessagesResponse\x12*\n\rmessages_list\x18\x01 \x03(\x0b\x32\x13.flwr.proto.Message\x12O\n\x0fobjects_to_pull\x18\x02 \x03(\x0b\x32\x36.flwr.proto.PullResMessagesResponse.ObjectsToPullEntry\x1aK\n\x12ObjectsToPullEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.flwr.proto.ObjectIDs:\x02\x38\x01\"\x1c\n\x1aPullServerAppInputsRequest\"\x7f\n\x1bPullServerAppInputsResponse\x12$\n\x07\x63ontext\x18\x01 \x01(\x0b\x32\x13.flwr.proto.Context\x12\x1c\n\x03run\x18\x02 \x01(\x0b\x32\x0f.flwr.proto.Run\x12\x1c\n\x03\x66\x61\x62\x18\x03 \x01(\x0b\x32\x0f.flwr.proto.Fab\"S\n\x1bPushServerAppOutputsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12$\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x13.flwr.proto.Context\"\x1e\n\x1cPushServerAppOutputsResponse2\xe4\x08\n\x0bServerAppIo\x12G\n\x08GetNodes\x12\x1b.flwr.proto.GetNodesRequest\x1a\x1c.flwr.proto.GetNodesResponse\"\x00\x12Y\n\x0cPushMessages\x12\".flwr.proto.PushInsMessagesRequest\x1a#.flwr.proto.PushInsMessagesResponse\"\x00\x12Y\n\x0cPullMessages\x12\".flwr.proto.PullResMessagesRequest\x1a#.flwr.proto.PullResMessagesResponse\"\x00\x12\x41\n\x06GetRun\x12\x19.flwr.proto.GetRunRequest\x1a\x1a.flwr.proto.GetRunResponse\"\x00\x12\x41\n\x06GetFab\x12\x19.flwr.proto.GetFabRequest\x1a\x1a.flwr.proto.GetFabResponse\"\x00\x12h\n\x13PullServerAppInputs\x12&.flwr.proto.PullServerAppInputsRequest\x1a\'.flwr.proto.PullServerAppInputsResponse\"\x00\x12k\n\x14PushServerAppOutputs\x12\'.flwr.proto.PushServerAppOutputsRequest\x1a(.flwr.proto.PushServerAppOutputsResponse\"\x00\x12\\\n\x0fUpdateRunStatus\x12\".flwr.proto.UpdateRunStatusRequest\x1a#.flwr.proto.UpdateRunStatusResponse\"\x00\x12S\n\x0cGetRunStatus\x12\x1f.flwr.proto.GetRunStatusRequest\x1a .flwr.proto.GetRunStatusResponse\"\x00\x12G\n\x08PushLogs\x12\x1b.flwr.proto.PushLogsRequest\x1a\x1c.flwr.proto.PushLogsResponse\"\x00\x12_\n\x10SendAppHeartbeat\x12#.flwr.proto.SendAppHeartbeatRequest\x1a$.flwr.proto.SendAppHeartbeatResponse\"\x00\x12M\n\nPushObject\x12\x1d.flwr.proto.PushObjectRequest\x1a\x1e.flwr.proto.PushObjectResponse\"\x00\x12M\n\nPullObject\x12\x1d.flwr.proto.PullObjectRequest\x1a\x1e.flwr.proto.PullObjectResponse\"\x00\x62\x06proto3')
24
24
 
25
25
  _globals = globals()
26
26
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
27
27
  _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.serverappio_pb2', _globals)
28
28
  if _descriptor._USE_C_DESCRIPTORS == False:
29
29
  DESCRIPTOR._options = None
30
+ _globals['_PUSHINSMESSAGESREQUEST_MSGTOCHILDRENMAPPINGENTRY']._options = None
31
+ _globals['_PUSHINSMESSAGESREQUEST_MSGTOCHILDRENMAPPINGENTRY']._serialized_options = b'8\001'
32
+ _globals['_PUSHINSMESSAGESRESPONSE_OBJECTSTOPUSHENTRY']._options = None
33
+ _globals['_PUSHINSMESSAGESRESPONSE_OBJECTSTOPUSHENTRY']._serialized_options = b'8\001'
34
+ _globals['_PULLRESMESSAGESRESPONSE_OBJECTSTOPULLENTRY']._options = None
35
+ _globals['_PULLRESMESSAGESRESPONSE_OBJECTSTOPULLENTRY']._serialized_options = b'8\001'
30
36
  _globals['_GETNODESREQUEST']._serialized_start=187
31
37
  _globals['_GETNODESREQUEST']._serialized_end=220
32
38
  _globals['_GETNODESRESPONSE']._serialized_start=222
33
39
  _globals['_GETNODESRESPONSE']._serialized_end=273
34
- _globals['_PUSHINSMESSAGESREQUEST']._serialized_start=275
35
- _globals['_PUSHINSMESSAGESREQUEST']._serialized_end=359
36
- _globals['_PUSHINSMESSAGESRESPONSE']._serialized_start=361
37
- _globals['_PUSHINSMESSAGESRESPONSE']._serialized_end=407
38
- _globals['_PULLRESMESSAGESREQUEST']._serialized_start=409
39
- _globals['_PULLRESMESSAGESREQUEST']._serialized_end=470
40
- _globals['_PULLRESMESSAGESRESPONSE']._serialized_start=472
41
- _globals['_PULLRESMESSAGESRESPONSE']._serialized_end=541
42
- _globals['_PULLSERVERAPPINPUTSREQUEST']._serialized_start=543
43
- _globals['_PULLSERVERAPPINPUTSREQUEST']._serialized_end=571
44
- _globals['_PULLSERVERAPPINPUTSRESPONSE']._serialized_start=573
45
- _globals['_PULLSERVERAPPINPUTSRESPONSE']._serialized_end=700
46
- _globals['_PUSHSERVERAPPOUTPUTSREQUEST']._serialized_start=702
47
- _globals['_PUSHSERVERAPPOUTPUTSREQUEST']._serialized_end=785
48
- _globals['_PUSHSERVERAPPOUTPUTSRESPONSE']._serialized_start=787
49
- _globals['_PUSHSERVERAPPOUTPUTSRESPONSE']._serialized_end=817
50
- _globals['_SERVERAPPIO']._serialized_start=820
51
- _globals['_SERVERAPPIO']._serialized_end=1944
40
+ _globals['_PUSHINSMESSAGESREQUEST']._serialized_start=276
41
+ _globals['_PUSHINSMESSAGESREQUEST']._serialized_end=539
42
+ _globals['_PUSHINSMESSAGESREQUEST_MSGTOCHILDRENMAPPINGENTRY']._serialized_start=457
43
+ _globals['_PUSHINSMESSAGESREQUEST_MSGTOCHILDRENMAPPINGENTRY']._serialized_end=539
44
+ _globals['_PUSHINSMESSAGESRESPONSE']._serialized_start=542
45
+ _globals['_PUSHINSMESSAGESRESPONSE']._serialized_end=746
46
+ _globals['_PUSHINSMESSAGESRESPONSE_OBJECTSTOPUSHENTRY']._serialized_start=671
47
+ _globals['_PUSHINSMESSAGESRESPONSE_OBJECTSTOPUSHENTRY']._serialized_end=746
48
+ _globals['_PULLRESMESSAGESREQUEST']._serialized_start=748
49
+ _globals['_PULLRESMESSAGESREQUEST']._serialized_end=809
50
+ _globals['_PULLRESMESSAGESRESPONSE']._serialized_start=812
51
+ _globals['_PULLRESMESSAGESRESPONSE']._serialized_end=1039
52
+ _globals['_PULLRESMESSAGESRESPONSE_OBJECTSTOPULLENTRY']._serialized_start=964
53
+ _globals['_PULLRESMESSAGESRESPONSE_OBJECTSTOPULLENTRY']._serialized_end=1039
54
+ _globals['_PULLSERVERAPPINPUTSREQUEST']._serialized_start=1041
55
+ _globals['_PULLSERVERAPPINPUTSREQUEST']._serialized_end=1069
56
+ _globals['_PULLSERVERAPPINPUTSRESPONSE']._serialized_start=1071
57
+ _globals['_PULLSERVERAPPINPUTSRESPONSE']._serialized_end=1198
58
+ _globals['_PUSHSERVERAPPOUTPUTSREQUEST']._serialized_start=1200
59
+ _globals['_PUSHSERVERAPPOUTPUTSREQUEST']._serialized_end=1283
60
+ _globals['_PUSHSERVERAPPOUTPUTSRESPONSE']._serialized_start=1285
61
+ _globals['_PUSHSERVERAPPOUTPUTSRESPONSE']._serialized_end=1315
62
+ _globals['_SERVERAPPIO']._serialized_start=1318
63
+ _globals['_SERVERAPPIO']._serialized_end=2442
52
64
  # @@protoc_insertion_point(module_scope)
@@ -42,29 +42,67 @@ global___GetNodesResponse = GetNodesResponse
42
42
  class PushInsMessagesRequest(google.protobuf.message.Message):
43
43
  """PushMessages messages"""
44
44
  DESCRIPTOR: google.protobuf.descriptor.Descriptor
45
+ class MsgToChildrenMappingEntry(google.protobuf.message.Message):
46
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
47
+ KEY_FIELD_NUMBER: builtins.int
48
+ VALUE_FIELD_NUMBER: builtins.int
49
+ key: typing.Text
50
+ @property
51
+ def value(self) -> flwr.proto.message_pb2.ObjectIDs: ...
52
+ def __init__(self,
53
+ *,
54
+ key: typing.Text = ...,
55
+ value: typing.Optional[flwr.proto.message_pb2.ObjectIDs] = ...,
56
+ ) -> None: ...
57
+ def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ...
58
+ def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
59
+
45
60
  MESSAGES_LIST_FIELD_NUMBER: builtins.int
46
61
  RUN_ID_FIELD_NUMBER: builtins.int
62
+ MSG_TO_CHILDREN_MAPPING_FIELD_NUMBER: builtins.int
47
63
  @property
48
64
  def messages_list(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[flwr.proto.message_pb2.Message]: ...
49
65
  run_id: builtins.int
66
+ @property
67
+ def msg_to_children_mapping(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.message_pb2.ObjectIDs]: ...
50
68
  def __init__(self,
51
69
  *,
52
70
  messages_list: typing.Optional[typing.Iterable[flwr.proto.message_pb2.Message]] = ...,
53
71
  run_id: builtins.int = ...,
72
+ msg_to_children_mapping: typing.Optional[typing.Mapping[typing.Text, flwr.proto.message_pb2.ObjectIDs]] = ...,
54
73
  ) -> None: ...
55
- def ClearField(self, field_name: typing_extensions.Literal["messages_list",b"messages_list","run_id",b"run_id"]) -> None: ...
74
+ def ClearField(self, field_name: typing_extensions.Literal["messages_list",b"messages_list","msg_to_children_mapping",b"msg_to_children_mapping","run_id",b"run_id"]) -> None: ...
56
75
  global___PushInsMessagesRequest = PushInsMessagesRequest
57
76
 
58
77
  class PushInsMessagesResponse(google.protobuf.message.Message):
59
78
  DESCRIPTOR: google.protobuf.descriptor.Descriptor
79
+ class ObjectsToPushEntry(google.protobuf.message.Message):
80
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
81
+ KEY_FIELD_NUMBER: builtins.int
82
+ VALUE_FIELD_NUMBER: builtins.int
83
+ key: typing.Text
84
+ @property
85
+ def value(self) -> flwr.proto.message_pb2.ObjectIDs: ...
86
+ def __init__(self,
87
+ *,
88
+ key: typing.Text = ...,
89
+ value: typing.Optional[flwr.proto.message_pb2.ObjectIDs] = ...,
90
+ ) -> None: ...
91
+ def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ...
92
+ def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
93
+
60
94
  MESSAGE_IDS_FIELD_NUMBER: builtins.int
95
+ OBJECTS_TO_PUSH_FIELD_NUMBER: builtins.int
61
96
  @property
62
97
  def message_ids(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[typing.Text]: ...
98
+ @property
99
+ def objects_to_push(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.message_pb2.ObjectIDs]: ...
63
100
  def __init__(self,
64
101
  *,
65
102
  message_ids: typing.Optional[typing.Iterable[typing.Text]] = ...,
103
+ objects_to_push: typing.Optional[typing.Mapping[typing.Text, flwr.proto.message_pb2.ObjectIDs]] = ...,
66
104
  ) -> None: ...
67
- def ClearField(self, field_name: typing_extensions.Literal["message_ids",b"message_ids"]) -> None: ...
105
+ def ClearField(self, field_name: typing_extensions.Literal["message_ids",b"message_ids","objects_to_push",b"objects_to_push"]) -> None: ...
68
106
  global___PushInsMessagesResponse = PushInsMessagesResponse
69
107
 
70
108
  class PullResMessagesRequest(google.protobuf.message.Message):
@@ -85,14 +123,33 @@ global___PullResMessagesRequest = PullResMessagesRequest
85
123
 
86
124
  class PullResMessagesResponse(google.protobuf.message.Message):
87
125
  DESCRIPTOR: google.protobuf.descriptor.Descriptor
126
+ class ObjectsToPullEntry(google.protobuf.message.Message):
127
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
128
+ KEY_FIELD_NUMBER: builtins.int
129
+ VALUE_FIELD_NUMBER: builtins.int
130
+ key: typing.Text
131
+ @property
132
+ def value(self) -> flwr.proto.message_pb2.ObjectIDs: ...
133
+ def __init__(self,
134
+ *,
135
+ key: typing.Text = ...,
136
+ value: typing.Optional[flwr.proto.message_pb2.ObjectIDs] = ...,
137
+ ) -> None: ...
138
+ def HasField(self, field_name: typing_extensions.Literal["value",b"value"]) -> builtins.bool: ...
139
+ def ClearField(self, field_name: typing_extensions.Literal["key",b"key","value",b"value"]) -> None: ...
140
+
88
141
  MESSAGES_LIST_FIELD_NUMBER: builtins.int
142
+ OBJECTS_TO_PULL_FIELD_NUMBER: builtins.int
89
143
  @property
90
144
  def messages_list(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[flwr.proto.message_pb2.Message]: ...
145
+ @property
146
+ def objects_to_pull(self) -> google.protobuf.internal.containers.MessageMap[typing.Text, flwr.proto.message_pb2.ObjectIDs]: ...
91
147
  def __init__(self,
92
148
  *,
93
149
  messages_list: typing.Optional[typing.Iterable[flwr.proto.message_pb2.Message]] = ...,
150
+ objects_to_pull: typing.Optional[typing.Mapping[typing.Text, flwr.proto.message_pb2.ObjectIDs]] = ...,
94
151
  ) -> None: ...
95
- def ClearField(self, field_name: typing_extensions.Literal["messages_list",b"messages_list"]) -> None: ...
152
+ def ClearField(self, field_name: typing_extensions.Literal["messages_list",b"messages_list","objects_to_pull",b"objects_to_pull"]) -> None: ...
96
153
  global___PullResMessagesResponse = PullResMessagesResponse
97
154
 
98
155
  class PullServerAppInputsRequest(google.protobuf.message.Message):
flwr/server/app.py CHANGED
@@ -37,10 +37,11 @@ from cryptography.hazmat.primitives.serialization import load_ssh_public_key
37
37
  from flwr.common import GRPC_MAX_MESSAGE_LENGTH, EventType, event
38
38
  from flwr.common.address import parse_address
39
39
  from flwr.common.args import try_obtain_server_certificates
40
- from flwr.common.auth_plugin import ExecAuthPlugin
40
+ from flwr.common.auth_plugin import ExecAuthPlugin, ExecAuthzPlugin
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
+ AUTHZ_TYPE_YAML_KEY,
44
45
  CLIENT_OCTET,
45
46
  EXEC_API_DEFAULT_SERVER_ADDRESS,
46
47
  FLEET_API_GRPC_RERE_DEFAULT_ADDRESS,
@@ -91,6 +92,7 @@ try:
91
92
  add_ee_args_superlink,
92
93
  get_dashboard_server,
93
94
  get_exec_auth_plugins,
95
+ get_exec_authz_plugins,
94
96
  get_exec_event_log_writer_plugins,
95
97
  get_fleet_event_log_writer_plugins,
96
98
  )
@@ -104,6 +106,10 @@ except ImportError:
104
106
  """Return all Exec API authentication plugins."""
105
107
  raise NotImplementedError("No authentication plugins are currently supported.")
106
108
 
109
+ def get_exec_authz_plugins() -> dict[str, type[ExecAuthzPlugin]]:
110
+ """Return all Exec API authorization plugins."""
111
+ raise NotImplementedError("No authorization plugins are currently supported.")
112
+
107
113
  def get_exec_event_log_writer_plugins() -> dict[str, type[EventLogWriterPlugin]]:
108
114
  """Return all Exec API event log writer plugins."""
109
115
  raise NotImplementedError(
@@ -145,6 +151,7 @@ def run_superlink() -> None:
145
151
  verify_tls_cert = not getattr(args, "disable_oidc_tls_cert_verification", None)
146
152
 
147
153
  auth_plugin: Optional[ExecAuthPlugin] = None
154
+ authz_plugin: Optional[ExecAuthzPlugin] = None # pylint: disable=unused-variable
148
155
  event_log_plugin: Optional[EventLogWriterPlugin] = None
149
156
  # Load the auth plugin if the args.user_auth_config is provided
150
157
  if cfg_path := getattr(args, "user_auth_config", None):
@@ -152,6 +159,13 @@ def run_superlink() -> None:
152
159
  # Enable event logging if the args.enable_event_log is True
153
160
  if args.enable_event_log:
154
161
  event_log_plugin = _try_obtain_exec_event_log_writer_plugin()
162
+ # Enable authorization if the args.enable_authorization is True
163
+ if args.enable_authorization:
164
+ # pylint: disable=unused-variable
165
+ authz_plugin = _try_obtain_exec_authz_plugin( # noqa: F841
166
+ Path(cfg_path), verify_tls_cert
167
+ )
168
+ # pylint: enable=unused-variable
155
169
 
156
170
  # Initialize StateFactory
157
171
  state_factory = LinkStateFactory(args.database)
@@ -498,6 +512,35 @@ def _try_obtain_exec_auth_plugin(
498
512
  sys.exit("No authentication plugins are currently supported.")
499
513
 
500
514
 
515
+ def _try_obtain_exec_authz_plugin(
516
+ config_path: Path, verify_tls_cert: bool
517
+ ) -> Optional[ExecAuthzPlugin]:
518
+ # Load YAML file
519
+ with config_path.open("r", encoding="utf-8") as file:
520
+ config: dict[str, Any] = yaml.safe_load(file)
521
+
522
+ # Load authentication configuration
523
+ authz_config: dict[str, Any] = config.get("authorization", {})
524
+ authz_type: str = authz_config.get(AUTHZ_TYPE_YAML_KEY, "")
525
+
526
+ # Load authorization plugin
527
+ try:
528
+ all_plugins: dict[str, type[ExecAuthzPlugin]] = get_exec_authz_plugins()
529
+ authz_plugin_class = all_plugins[authz_type]
530
+ return authz_plugin_class(
531
+ user_authz_config_path=config_path, verify_tls_cert=verify_tls_cert
532
+ )
533
+ except KeyError:
534
+ if authz_type != "":
535
+ sys.exit(
536
+ f'Authentication type "{authz_type}" is not supported. '
537
+ "Please provide a valid authorization type in the configuration."
538
+ )
539
+ sys.exit("No authorization type is provided in the configuration.")
540
+ except NotImplementedError:
541
+ sys.exit("No authorization plugins are currently supported.")
542
+
543
+
501
544
  def _try_obtain_exec_event_log_writer_plugin() -> Optional[EventLogWriterPlugin]:
502
545
  """Return an instance of the event log writer plugin."""
503
546
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: flwr-nightly
3
- Version: 1.19.0.dev20250524
3
+ Version: 1.19.0.dev20250527
4
4
  Summary: Flower: A Friendly Federated AI Framework
5
5
  License: Apache-2.0
6
6
  Keywords: Artificial Intelligence,Federated AI,Federated Analytics,Federated Evaluation,Federated Learning,Flower,Machine Learning
@@ -107,10 +107,10 @@ flwr/clientapp/__init__.py,sha256=zGW4z49Ojzoi1hDiRC7kyhLjijUilc6fqHhtM_ATRVA,71
107
107
  flwr/common/__init__.py,sha256=5GCLVk399Az_rTJHNticRlL0Sl_oPw_j5_LuFKfX7-M,4171
108
108
  flwr/common/address.py,sha256=9JucdTwlc-jpeJkRKeUboZoacUtErwSVtnDR9kAtLqE,4119
109
109
  flwr/common/args.py,sha256=-aX_jVnSaDrJR2KZ8Wq0Y3dQHII4R4MJtJOIXzVUA0c,5417
110
- flwr/common/auth_plugin/__init__.py,sha256=m271m9YjK2QfKDOuIIhcTvGmv1GWh1PL97QB05NTSHs,887
111
- flwr/common/auth_plugin/auth_plugin.py,sha256=GaXw4IiU2DkVNkp5S9ue821sbkU9zWSu6HSVZetEdjs,3938
110
+ flwr/common/auth_plugin/__init__.py,sha256=3rzPkVLn9WyB5n7HLk1XGDw3SLCqRWAU1_CnglcWPfw,970
111
+ flwr/common/auth_plugin/auth_plugin.py,sha256=lds7y8sDIzd4ZYuNEVUevXcPmCK93t-tvPqiKvq6eYQ,4499
112
112
  flwr/common/config.py,sha256=glcZDjco-amw1YfQcYTFJ4S1pt9APoexT-mf1QscuHs,13960
113
- flwr/common/constant.py,sha256=FeS_KqX2T3GtzMjR_lm1R1FcV9q0SIUvzdexzcq_bjs,7372
113
+ flwr/common/constant.py,sha256=lQCel7YanrEdFzy7pHBejhrQ7ZIylJrhBD9pXY02qv0,7472
114
114
  flwr/common/context.py,sha256=Be8obQR_OvEDy1OmshuUKxGRQ7Qx89mf5F4xlhkR10s,2407
115
115
  flwr/common/date.py,sha256=1ZT2cRSpC2DJqprOVTLXYCR_O2_OZR0zXO_brJ3LqWc,1554
116
116
  flwr/common/differential_privacy.py,sha256=FdlpdpPl_H_2HJa8CQM1iCUGBBQ5Dc8CzxmHERM-EoE,6148
@@ -127,7 +127,7 @@ flwr/common/heartbeat.py,sha256=SyEpNDnmJ0lni0cWO67rcoJVKasCLmkNHm3dKLeNrLU,5749
127
127
  flwr/common/inflatable.py,sha256=i7tYRS5ql4630wN7O0YLCoWZMXk3iNQwOnnrZs4dlDE,5813
128
128
  flwr/common/inflatable_grpc_utils.py,sha256=On_RT8cYChwE3-1MlY21s_cVXgYCGeKTONRafm-rmEk,3432
129
129
  flwr/common/logger.py,sha256=JbRf6E2vQxXzpDBq1T8IDUJo_usu3gjWEBPQ6uKcmdg,13049
130
- flwr/common/message.py,sha256=dfct6ZGizK2zSj2JLiQTRbOfDNu79KzwUplpQaxFg40,18997
130
+ flwr/common/message.py,sha256=onc0stpXk26P9d__AfSTde1BUVN0Z9Ofw85m0kyS9pY,19225
131
131
  flwr/common/object_ref.py,sha256=p3SfTeqo3Aj16SkB-vsnNn01zswOPdGNBitcbRnqmUk,9134
132
132
  flwr/common/parameter.py,sha256=UVw6sOgehEFhFs4uUCMl2kfVq1PD6ncmWgPLMsZPKPE,2095
133
133
  flwr/common/pyproject.py,sha256=2SU6yJW7059SbMXgzjOdK1GZRWO6AixDH7BmdxbMvHI,1386
@@ -156,7 +156,7 @@ flwr/common/typing.py,sha256=97QRfRRS7sQnjkAI5FDZ01-38oQUSz4i1qqewQmBWRg,6886
156
156
  flwr/common/version.py,sha256=7GAGzPn73Mkh09qhrjbmjZQtcqVhBuzhFBaK4Mk4VRk,1325
157
157
  flwr/compat/__init__.py,sha256=gbfDQKKKMZzi3GswyVRgyLdDlHiWj3wU6dg7y6m5O_s,752
158
158
  flwr/compat/client/__init__.py,sha256=qpbo0lcxdNL4qy5KHqiGm8OLxSxkYgI_-dLh5rwhtcI,746
159
- flwr/compat/client/app.py,sha256=49novX4eW9uZiU4zxIPNWzThcs0TuihygLtsT_T8Zjs,34397
159
+ flwr/compat/client/app.py,sha256=OlLB8ME9YWlmbN9aC65EElgje69IoUL0yzwEGqQQhpg,28092
160
160
  flwr/compat/client/grpc_client/__init__.py,sha256=MDOckOODn-FJnkkFEfb2JO-2G97wrBr_TTqht-LhOcY,735
161
161
  flwr/compat/client/grpc_client/connection.py,sha256=xAyvcTVr7bkwUfR5P3D_LKlZYiyySpt5sEwORA1h8Gc,9189
162
162
  flwr/compat/common/__init__.py,sha256=OMnKw4ad0qYMSIA9LZRa2gOkhSOXwAZCpAHnBQE_hFc,746
@@ -180,8 +180,8 @@ flwr/proto/fab_pb2.py,sha256=2Nu0WaWxDZ8TbutMtctjdcGM7OtXiyP4kmCgg5o7Jjw,1627
180
180
  flwr/proto/fab_pb2.pyi,sha256=AMXpiDK0fo3nZWjxsC2E4otSaVjyQbU7iiWKrsSZavs,2395
181
181
  flwr/proto/fab_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
182
182
  flwr/proto/fab_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
183
- flwr/proto/fleet_pb2.py,sha256=FB-FnqNi0f5A8t8vycG_frOx9l9EzN3jtmwiDPcKuP0,4792
184
- flwr/proto/fleet_pb2.pyi,sha256=ugXXUx2K6mbeWqOxBzoa2B1Uc2d2d03T2z8wS56vLD0,6777
183
+ flwr/proto/fleet_pb2.py,sha256=bg9Jp2h0_9zzL_Tvk7aIpoab4F0-7kl8OmKZYB5R_SE,6509
184
+ flwr/proto/fleet_pb2.pyi,sha256=tVEh2ffDZ_VnL53fk-wC8xk_TZYRWerjAwnPM-obuEk,9974
185
185
  flwr/proto/fleet_pb2_grpc.py,sha256=pYQwwZ8KUZFmbYaJKJ8YJ06QCilhLqI_9vc0bBFXrNI,15779
186
186
  flwr/proto/fleet_pb2_grpc.pyi,sha256=F--4QaDeoCHFuyOB506wHoMlQ4fPHvf8MoiVei_9jr8,4214
187
187
  flwr/proto/grpcadapter_pb2.py,sha256=PJ8DtfeV29g_y4Z3aNZlSZocLqSxeLmTsYCdOZDYCiE,1843
@@ -196,8 +196,8 @@ flwr/proto/log_pb2.py,sha256=iKaS3MVn1BS4xHu8uGPFCOi1KWtvVx-H9V4jCUIJghs,1393
196
196
  flwr/proto/log_pb2.pyi,sha256=ipuhgo40sAHTcRzCsGI1HwIstr5q0THPNk_cf62YyME,1448
197
197
  flwr/proto/log_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
198
198
  flwr/proto/log_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
199
- flwr/proto/message_pb2.py,sha256=m0RTI5J69FEOFeKJsdyb0fUfaY-5x7s8_omBI-BRAtw,3909
200
- flwr/proto/message_pb2.pyi,sha256=zFxk7VQL7iACanaIluVGF1mzImzHvpggRt4aWOIJb4c,7502
199
+ flwr/proto/message_pb2.py,sha256=b5hNBRRABH4sIUVo0G1iTOGjCFd4M68yiAPlJBeda_g,4276
200
+ flwr/proto/message_pb2.pyi,sha256=lRzQ5rvriqWDde-TX8K6jYEQhsl6TZZdmamtc8wf5O4,8622
201
201
  flwr/proto/message_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
202
202
  flwr/proto/message_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
203
203
  flwr/proto/node_pb2.py,sha256=BzZfAWIX7lV62bZr9f7x16lUZcpg-EImxnwxQXgCbYg,1045
@@ -212,8 +212,8 @@ flwr/proto/run_pb2.py,sha256=SWpc2yDTprm7DaabMQne43q_7_NWQN3I66y-d_PpcGg,4727
212
212
  flwr/proto/run_pb2.pyi,sha256=g87sUXdUA3cPmlYG03EoUisVIxOtWft3OR6nznzXeDo,9416
213
213
  flwr/proto/run_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
214
214
  flwr/proto/run_pb2_grpc.pyi,sha256=ff2TSiLVnG6IVQcTGzb2DIH3XRSoAvAo_RMcvbMFyc0,76
215
- flwr/proto/serverappio_pb2.py,sha256=JvIoTp15o7og5saAuAPPEHS2-qoxOI4y1t6pD78GBf4,5236
216
- flwr/proto/serverappio_pb2.pyi,sha256=8Q81UXbBCArSXnma6-rXUE_vKneCowZjY4W4JmLaH0c,6450
215
+ flwr/proto/serverappio_pb2.py,sha256=5TgzU5_KCVtNohLrBUsM7hed0nl0TQqjVjEp0T0cpOY,7005
216
+ flwr/proto/serverappio_pb2.pyi,sha256=tuz3TyMmlSbwR1nQSP2842V4gCwW5YRo_KwSd73u4eI,9647
217
217
  flwr/proto/serverappio_pb2_grpc.py,sha256=An5cPfO_1-MjvP8FaVymRfAFpes_pASDLUoxonZ1vrs,22602
218
218
  flwr/proto/serverappio_pb2_grpc.pyi,sha256=GI6b8aH2H7yPnqeE7q9lF6RUMtohuucYYxTjtHXzLsA,6204
219
219
  flwr/proto/simulationio_pb2.py,sha256=sAJX72z-IttVGxyU3PFnG8AFuA-pV7itvBoxz-hOudE,3342
@@ -226,7 +226,7 @@ flwr/proto/transport_pb2_grpc.py,sha256=vLN3EHtx2aEEMCO4f1Upu-l27BPzd3-5pV-u8wPc
226
226
  flwr/proto/transport_pb2_grpc.pyi,sha256=AGXf8RiIiW2J5IKMlm_3qT3AzcDa4F3P5IqUjve_esA,766
227
227
  flwr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
228
228
  flwr/server/__init__.py,sha256=LQQHiuL2jy7TpNaKastRdGsexlxSt5ZWAQNVqitDnrY,1598
229
- flwr/server/app.py,sha256=VLvatu0jNb7FvgnUt_kc21jzdvdVfBAwpXolwI2jINQ,28737
229
+ flwr/server/app.py,sha256=iSv0CI9RjnOqJIyNzoL_1jBP7NEwVGXCdikElA_5fZo,30586
230
230
  flwr/server/client_manager.py,sha256=5jCGavVli7XdupvWWo7ru3PdFTlRU8IGvHFSSoUVLRs,6227
231
231
  flwr/server/client_proxy.py,sha256=sv0E9AldBYOvc3pusqFh-GnyreeMfsXQ1cuTtxTq_wY,2399
232
232
  flwr/server/compat/__init__.py,sha256=0IsttWvY15qO98_1GyzVC-vR1e_ZPXOdu2qUlOkYMPE,886
@@ -353,7 +353,7 @@ flwr/supernode/nodestate/in_memory_nodestate.py,sha256=brV7TMMzS93tXk6ntpoYjtPK5
353
353
  flwr/supernode/nodestate/nodestate.py,sha256=-LAjZOnS7VyHC05ll3b31cYDjwAt6l4WmYt7duVLRKk,1024
354
354
  flwr/supernode/nodestate/nodestate_factory.py,sha256=UYTDCcwK_baHUmkzkJDxL0UEqvtTfOMlQRrROMCd0Xo,1430
355
355
  flwr/supernode/start_client_internal.py,sha256=4z9qtwT7ZwNwahpX1SRfuaoYw1HCICPFUvjPBLHgsA0,18806
356
- flwr_nightly-1.19.0.dev20250524.dist-info/METADATA,sha256=wciHfcEhok_S6e8SueDdMCIL-QcOhUZGUI46AyGWPak,15910
357
- flwr_nightly-1.19.0.dev20250524.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
358
- flwr_nightly-1.19.0.dev20250524.dist-info/entry_points.txt,sha256=08k99PaHg3Wr6W49rFXYtjmgcfIdpFLNeu6O0bXDYnU,370
359
- flwr_nightly-1.19.0.dev20250524.dist-info/RECORD,,
356
+ flwr_nightly-1.19.0.dev20250527.dist-info/METADATA,sha256=aJpg79RidiZ2zArLNcebjMunaH9p-xmUV5kPgzIKq1M,15910
357
+ flwr_nightly-1.19.0.dev20250527.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
358
+ flwr_nightly-1.19.0.dev20250527.dist-info/entry_points.txt,sha256=08k99PaHg3Wr6W49rFXYtjmgcfIdpFLNeu6O0bXDYnU,370
359
+ flwr_nightly-1.19.0.dev20250527.dist-info/RECORD,,