From 17b46ec34dfc4c8145faa04d98830a6f3489e7f3 Mon Sep 17 00:00:00 2001 From: Chong Shen Ng Date: Mon, 4 Nov 2024 16:40:15 +0000 Subject: [PATCH 1/3] refactor(framework:skip) Remove unnecessary `print` (#4423) --- src/py/flwr/cli/config_utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/py/flwr/cli/config_utils.py b/src/py/flwr/cli/config_utils.py index 6b646e50255f..40fa1e0d3b98 100644 --- a/src/py/flwr/cli/config_utils.py +++ b/src/py/flwr/cli/config_utils.py @@ -275,7 +275,6 @@ def validate_federation_in_project_config( # Validate the federation exists in the configuration federation_config = config["tool"]["flwr"]["federations"].get(federation) - print(federation_config) if federation_config is None: available_feds = { fed for fed in config["tool"]["flwr"]["federations"] if fed != "default" From 64fd9bd40702c89643b0d04319a86093c43cbb00 Mon Sep 17 00:00:00 2001 From: Robert Steiner Date: Mon, 4 Nov 2024 17:47:55 +0100 Subject: [PATCH 2/3] feat(framework:skip) Update docker/build-push-action to v6.9.0 (#4424) Signed-off-by: Robert Steiner --- .github/workflows/_docker-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/_docker-build.yml b/.github/workflows/_docker-build.yml index 9c58e882cf0b..febff9f9ee7d 100644 --- a/.github/workflows/_docker-build.yml +++ b/.github/workflows/_docker-build.yml @@ -96,7 +96,7 @@ jobs: uses: Wandalen/wretry.action@f8754f79743ba113fedbba4499593f7d73b458eb # v3.7.0 id: build with: - action: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 # v6.7.0 + action: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0 attempt_limit: 60 # 60 attempts * (9 secs delay + 1 sec retry) = ~10 mins attempt_delay: 9000 # 9 secs with: | From 8f92a3d78bf596e356f927a8a82fb6c2c2b99592 Mon Sep 17 00:00:00 2001 From: Javier Date: Mon, 4 Nov 2024 16:55:33 +0000 Subject: [PATCH 3/3] feat(framework) Introduce `simulationio.proto` (#4421) --- src/proto/flwr/proto/simulationio.proto | 55 +++++++ src/py/flwr/proto/simulationio_pb2.py | 38 +++++ src/py/flwr/proto/simulationio_pb2.pyi | 65 ++++++++ src/py/flwr/proto/simulationio_pb2_grpc.py | 171 ++++++++++++++++++++ src/py/flwr/proto/simulationio_pb2_grpc.pyi | 68 ++++++++ src/py/flwr_tool/protoc_test.py | 2 +- 6 files changed, 398 insertions(+), 1 deletion(-) create mode 100644 src/proto/flwr/proto/simulationio.proto create mode 100644 src/py/flwr/proto/simulationio_pb2.py create mode 100644 src/py/flwr/proto/simulationio_pb2.pyi create mode 100644 src/py/flwr/proto/simulationio_pb2_grpc.py create mode 100644 src/py/flwr/proto/simulationio_pb2_grpc.pyi diff --git a/src/proto/flwr/proto/simulationio.proto b/src/proto/flwr/proto/simulationio.proto new file mode 100644 index 000000000000..e5ed289e80c1 --- /dev/null +++ b/src/proto/flwr/proto/simulationio.proto @@ -0,0 +1,55 @@ +// Copyright 2024 Flower Labs GmbH. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================== + +syntax = "proto3"; + +package flwr.proto; + +import "flwr/proto/log.proto"; +import "flwr/proto/message.proto"; +import "flwr/proto/run.proto"; +import "flwr/proto/fab.proto"; + +service SimulationIo { + // Pull Simulation inputs + rpc PullSimulationInputs(PullSimulationInputsRequest) + returns (PullSimulationInputsResponse) {} + + // Push Simulation outputs + rpc PushSimulationOutputs(PushSimulationOutputsRequest) + returns (PushSimulationOutputsResponse) {} + + // Update the status of a given run + rpc UpdateRunStatus(UpdateRunStatusRequest) + returns (UpdateRunStatusResponse) {} + + // Push ServerApp logs + rpc PushLogs(PushLogsRequest) returns (PushLogsResponse) {} +} + +// PullSimulationInputs messages +message PullSimulationInputsRequest {} +message PullSimulationInputsResponse { + Context context = 1; + Run run = 2; + Fab fab = 3; +} + +// PushSimulationOutputs messages +message PushSimulationOutputsRequest { + uint64 run_id = 1; + Context context = 2; +} +message PushSimulationOutputsResponse {} diff --git a/src/py/flwr/proto/simulationio_pb2.py b/src/py/flwr/proto/simulationio_pb2.py new file mode 100644 index 000000000000..679fda1b3bf2 --- /dev/null +++ b/src/py/flwr/proto/simulationio_pb2.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: flwr/proto/simulationio.proto +# Protobuf Python Version: 4.25.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from flwr.proto import log_pb2 as flwr_dot_proto_dot_log__pb2 +from flwr.proto import message_pb2 as flwr_dot_proto_dot_message__pb2 +from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2 +from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x66lwr/proto/simulationio.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/log.proto\x1a\x18\x66lwr/proto/message.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\"\x1d\n\x1bPullSimulationInputsRequest\"\x80\x01\n\x1cPullSimulationInputsResponse\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\"T\n\x1cPushSimulationOutputsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x04\x12$\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x13.flwr.proto.Context\"\x1f\n\x1dPushSimulationOutputsResponse2\x92\x03\n\x0cSimulationIo\x12k\n\x14PullSimulationInputs\x12\'.flwr.proto.PullSimulationInputsRequest\x1a(.flwr.proto.PullSimulationInputsResponse\"\x00\x12n\n\x15PushSimulationOutputs\x12(.flwr.proto.PushSimulationOutputsRequest\x1a).flwr.proto.PushSimulationOutputsResponse\"\x00\x12\\\n\x0fUpdateRunStatus\x12\".flwr.proto.UpdateRunStatusRequest\x1a#.flwr.proto.UpdateRunStatusResponse\"\x00\x12G\n\x08PushLogs\x12\x1b.flwr.proto.PushLogsRequest\x1a\x1c.flwr.proto.PushLogsResponse\"\x00\x62\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.simulationio_pb2', _globals) +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + _globals['_PULLSIMULATIONINPUTSREQUEST']._serialized_start=137 + _globals['_PULLSIMULATIONINPUTSREQUEST']._serialized_end=166 + _globals['_PULLSIMULATIONINPUTSRESPONSE']._serialized_start=169 + _globals['_PULLSIMULATIONINPUTSRESPONSE']._serialized_end=297 + _globals['_PUSHSIMULATIONOUTPUTSREQUEST']._serialized_start=299 + _globals['_PUSHSIMULATIONOUTPUTSREQUEST']._serialized_end=383 + _globals['_PUSHSIMULATIONOUTPUTSRESPONSE']._serialized_start=385 + _globals['_PUSHSIMULATIONOUTPUTSRESPONSE']._serialized_end=416 + _globals['_SIMULATIONIO']._serialized_start=419 + _globals['_SIMULATIONIO']._serialized_end=821 +# @@protoc_insertion_point(module_scope) diff --git a/src/py/flwr/proto/simulationio_pb2.pyi b/src/py/flwr/proto/simulationio_pb2.pyi new file mode 100644 index 000000000000..648bd0b71f21 --- /dev/null +++ b/src/py/flwr/proto/simulationio_pb2.pyi @@ -0,0 +1,65 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" +import builtins +import flwr.proto.fab_pb2 +import flwr.proto.message_pb2 +import flwr.proto.run_pb2 +import google.protobuf.descriptor +import google.protobuf.message +import typing +import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class PullSimulationInputsRequest(google.protobuf.message.Message): + """PullSimulationInputs messages""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor + def __init__(self, + ) -> None: ... +global___PullSimulationInputsRequest = PullSimulationInputsRequest + +class PullSimulationInputsResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + CONTEXT_FIELD_NUMBER: builtins.int + RUN_FIELD_NUMBER: builtins.int + FAB_FIELD_NUMBER: builtins.int + @property + def context(self) -> flwr.proto.message_pb2.Context: ... + @property + def run(self) -> flwr.proto.run_pb2.Run: ... + @property + def fab(self) -> flwr.proto.fab_pb2.Fab: ... + def __init__(self, + *, + context: typing.Optional[flwr.proto.message_pb2.Context] = ..., + run: typing.Optional[flwr.proto.run_pb2.Run] = ..., + fab: typing.Optional[flwr.proto.fab_pb2.Fab] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["context",b"context","fab",b"fab","run",b"run"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["context",b"context","fab",b"fab","run",b"run"]) -> None: ... +global___PullSimulationInputsResponse = PullSimulationInputsResponse + +class PushSimulationOutputsRequest(google.protobuf.message.Message): + """PushSimulationOutputs messages""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor + RUN_ID_FIELD_NUMBER: builtins.int + CONTEXT_FIELD_NUMBER: builtins.int + run_id: builtins.int + @property + def context(self) -> flwr.proto.message_pb2.Context: ... + def __init__(self, + *, + run_id: builtins.int = ..., + context: typing.Optional[flwr.proto.message_pb2.Context] = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["context",b"context"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["context",b"context","run_id",b"run_id"]) -> None: ... +global___PushSimulationOutputsRequest = PushSimulationOutputsRequest + +class PushSimulationOutputsResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + def __init__(self, + ) -> None: ... +global___PushSimulationOutputsResponse = PushSimulationOutputsResponse diff --git a/src/py/flwr/proto/simulationio_pb2_grpc.py b/src/py/flwr/proto/simulationio_pb2_grpc.py new file mode 100644 index 000000000000..7ba619735cb7 --- /dev/null +++ b/src/py/flwr/proto/simulationio_pb2_grpc.py @@ -0,0 +1,171 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + +from flwr.proto import log_pb2 as flwr_dot_proto_dot_log__pb2 +from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2 +from flwr.proto import simulationio_pb2 as flwr_dot_proto_dot_simulationio__pb2 + + +class SimulationIoStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.PullSimulationInputs = channel.unary_unary( + '/flwr.proto.SimulationIo/PullSimulationInputs', + request_serializer=flwr_dot_proto_dot_simulationio__pb2.PullSimulationInputsRequest.SerializeToString, + response_deserializer=flwr_dot_proto_dot_simulationio__pb2.PullSimulationInputsResponse.FromString, + ) + self.PushSimulationOutputs = channel.unary_unary( + '/flwr.proto.SimulationIo/PushSimulationOutputs', + request_serializer=flwr_dot_proto_dot_simulationio__pb2.PushSimulationOutputsRequest.SerializeToString, + response_deserializer=flwr_dot_proto_dot_simulationio__pb2.PushSimulationOutputsResponse.FromString, + ) + self.UpdateRunStatus = channel.unary_unary( + '/flwr.proto.SimulationIo/UpdateRunStatus', + request_serializer=flwr_dot_proto_dot_run__pb2.UpdateRunStatusRequest.SerializeToString, + response_deserializer=flwr_dot_proto_dot_run__pb2.UpdateRunStatusResponse.FromString, + ) + self.PushLogs = channel.unary_unary( + '/flwr.proto.SimulationIo/PushLogs', + request_serializer=flwr_dot_proto_dot_log__pb2.PushLogsRequest.SerializeToString, + response_deserializer=flwr_dot_proto_dot_log__pb2.PushLogsResponse.FromString, + ) + + +class SimulationIoServicer(object): + """Missing associated documentation comment in .proto file.""" + + def PullSimulationInputs(self, request, context): + """Pull Simulation inputs + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def PushSimulationOutputs(self, request, context): + """Push Simulation outputs + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def UpdateRunStatus(self, request, context): + """Update the status of a given run + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def PushLogs(self, request, context): + """Push ServerApp logs + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_SimulationIoServicer_to_server(servicer, server): + rpc_method_handlers = { + 'PullSimulationInputs': grpc.unary_unary_rpc_method_handler( + servicer.PullSimulationInputs, + request_deserializer=flwr_dot_proto_dot_simulationio__pb2.PullSimulationInputsRequest.FromString, + response_serializer=flwr_dot_proto_dot_simulationio__pb2.PullSimulationInputsResponse.SerializeToString, + ), + 'PushSimulationOutputs': grpc.unary_unary_rpc_method_handler( + servicer.PushSimulationOutputs, + request_deserializer=flwr_dot_proto_dot_simulationio__pb2.PushSimulationOutputsRequest.FromString, + response_serializer=flwr_dot_proto_dot_simulationio__pb2.PushSimulationOutputsResponse.SerializeToString, + ), + 'UpdateRunStatus': grpc.unary_unary_rpc_method_handler( + servicer.UpdateRunStatus, + request_deserializer=flwr_dot_proto_dot_run__pb2.UpdateRunStatusRequest.FromString, + response_serializer=flwr_dot_proto_dot_run__pb2.UpdateRunStatusResponse.SerializeToString, + ), + 'PushLogs': grpc.unary_unary_rpc_method_handler( + servicer.PushLogs, + request_deserializer=flwr_dot_proto_dot_log__pb2.PushLogsRequest.FromString, + response_serializer=flwr_dot_proto_dot_log__pb2.PushLogsResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'flwr.proto.SimulationIo', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + + + # This class is part of an EXPERIMENTAL API. +class SimulationIo(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def PullSimulationInputs(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/flwr.proto.SimulationIo/PullSimulationInputs', + flwr_dot_proto_dot_simulationio__pb2.PullSimulationInputsRequest.SerializeToString, + flwr_dot_proto_dot_simulationio__pb2.PullSimulationInputsResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def PushSimulationOutputs(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/flwr.proto.SimulationIo/PushSimulationOutputs', + flwr_dot_proto_dot_simulationio__pb2.PushSimulationOutputsRequest.SerializeToString, + flwr_dot_proto_dot_simulationio__pb2.PushSimulationOutputsResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def UpdateRunStatus(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/flwr.proto.SimulationIo/UpdateRunStatus', + flwr_dot_proto_dot_run__pb2.UpdateRunStatusRequest.SerializeToString, + flwr_dot_proto_dot_run__pb2.UpdateRunStatusResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def PushLogs(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/flwr.proto.SimulationIo/PushLogs', + flwr_dot_proto_dot_log__pb2.PushLogsRequest.SerializeToString, + flwr_dot_proto_dot_log__pb2.PushLogsResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/src/py/flwr/proto/simulationio_pb2_grpc.pyi b/src/py/flwr/proto/simulationio_pb2_grpc.pyi new file mode 100644 index 000000000000..778a05429664 --- /dev/null +++ b/src/py/flwr/proto/simulationio_pb2_grpc.pyi @@ -0,0 +1,68 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" +import abc +import flwr.proto.log_pb2 +import flwr.proto.run_pb2 +import flwr.proto.simulationio_pb2 +import grpc + +class SimulationIoStub: + def __init__(self, channel: grpc.Channel) -> None: ... + PullSimulationInputs: grpc.UnaryUnaryMultiCallable[ + flwr.proto.simulationio_pb2.PullSimulationInputsRequest, + flwr.proto.simulationio_pb2.PullSimulationInputsResponse] + """Pull Simulation inputs""" + + PushSimulationOutputs: grpc.UnaryUnaryMultiCallable[ + flwr.proto.simulationio_pb2.PushSimulationOutputsRequest, + flwr.proto.simulationio_pb2.PushSimulationOutputsResponse] + """Push Simulation outputs""" + + UpdateRunStatus: grpc.UnaryUnaryMultiCallable[ + flwr.proto.run_pb2.UpdateRunStatusRequest, + flwr.proto.run_pb2.UpdateRunStatusResponse] + """Update the status of a given run""" + + PushLogs: grpc.UnaryUnaryMultiCallable[ + flwr.proto.log_pb2.PushLogsRequest, + flwr.proto.log_pb2.PushLogsResponse] + """Push ServerApp logs""" + + +class SimulationIoServicer(metaclass=abc.ABCMeta): + @abc.abstractmethod + def PullSimulationInputs(self, + request: flwr.proto.simulationio_pb2.PullSimulationInputsRequest, + context: grpc.ServicerContext, + ) -> flwr.proto.simulationio_pb2.PullSimulationInputsResponse: + """Pull Simulation inputs""" + pass + + @abc.abstractmethod + def PushSimulationOutputs(self, + request: flwr.proto.simulationio_pb2.PushSimulationOutputsRequest, + context: grpc.ServicerContext, + ) -> flwr.proto.simulationio_pb2.PushSimulationOutputsResponse: + """Push Simulation outputs""" + pass + + @abc.abstractmethod + def UpdateRunStatus(self, + request: flwr.proto.run_pb2.UpdateRunStatusRequest, + context: grpc.ServicerContext, + ) -> flwr.proto.run_pb2.UpdateRunStatusResponse: + """Update the status of a given run""" + pass + + @abc.abstractmethod + def PushLogs(self, + request: flwr.proto.log_pb2.PushLogsRequest, + context: grpc.ServicerContext, + ) -> flwr.proto.log_pb2.PushLogsResponse: + """Push ServerApp logs""" + pass + + +def add_SimulationIoServicer_to_server(servicer: SimulationIoServicer, server: grpc.Server) -> None: ... diff --git a/src/py/flwr_tool/protoc_test.py b/src/py/flwr_tool/protoc_test.py index 9b85aeb5ac7a..e2e14858174c 100644 --- a/src/py/flwr_tool/protoc_test.py +++ b/src/py/flwr_tool/protoc_test.py @@ -28,4 +28,4 @@ def test_directories() -> None: def test_proto_file_count() -> None: """Test if the correct number of proto files were captured by the glob.""" - assert len(PROTO_FILES) == 15 + assert len(PROTO_FILES) == 16