flwr-nightly 1.23.0.dev20250930__py3-none-any.whl → 1.26.0.dev20260121__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/__init__.py +17 -6
- flwr/app/__init__.py +4 -1
- flwr/app/error.py +2 -2
- flwr/app/exception.py +3 -3
- flwr/app/message_type.py +29 -0
- flwr/app/metadata.py +5 -2
- flwr/app/user_config.py +19 -0
- flwr/cli/app.py +62 -9
- flwr/cli/{new/templates/app/code → app_cmd}/__init__.py +9 -1
- flwr/cli/app_cmd/publish.py +285 -0
- flwr/cli/app_cmd/review.py +262 -0
- flwr/cli/auth_plugin/__init__.py +13 -6
- flwr/cli/auth_plugin/auth_plugin.py +26 -15
- flwr/cli/auth_plugin/noop_auth_plugin.py +101 -0
- flwr/cli/auth_plugin/oidc_cli_plugin.py +52 -32
- flwr/cli/build.py +166 -53
- flwr/cli/{cli_user_auth_interceptor.py → cli_account_auth_interceptor.py} +27 -10
- flwr/cli/config/__init__.py +21 -0
- flwr/cli/config/ls.py +104 -0
- flwr/cli/config_migration.py +300 -0
- flwr/cli/config_utils.py +154 -13
- flwr/cli/constant.py +67 -0
- flwr/cli/{new/templates/app/code/flwr_tune → federation}/__init__.py +8 -1
- flwr/cli/federation/ls.py +361 -0
- flwr/cli/flower_config.py +447 -0
- flwr/cli/install.py +91 -13
- flwr/cli/log.py +65 -36
- flwr/cli/login/login.py +41 -27
- flwr/cli/ls.py +232 -158
- flwr/cli/new/new.py +188 -244
- flwr/cli/pull.py +25 -34
- flwr/cli/run/run.py +106 -74
- flwr/cli/run_utils.py +148 -0
- flwr/cli/stop.py +46 -37
- flwr/cli/supernode/__init__.py +25 -0
- flwr/cli/supernode/ls.py +273 -0
- flwr/cli/supernode/register.py +190 -0
- flwr/cli/supernode/unregister.py +140 -0
- flwr/cli/typing.py +211 -0
- flwr/cli/utils.py +428 -80
- flwr/client/__init__.py +2 -1
- flwr/client/dpfedavg_numpy_client.py +4 -1
- flwr/client/grpc_adapter_client/connection.py +14 -17
- flwr/client/grpc_rere_client/connection.py +73 -43
- flwr/client/grpc_rere_client/grpc_adapter.py +35 -15
- flwr/client/grpc_rere_client/{client_interceptor.py → node_auth_client_interceptor.py} +5 -7
- flwr/client/message_handler/message_handler.py +4 -3
- flwr/client/mod/centraldp_mods.py +1 -1
- flwr/client/mod/localdp_mod.py +1 -1
- flwr/client/mod/secure_aggregation/secaggplus_mod.py +11 -9
- flwr/client/numpy_client.py +1 -1
- flwr/client/rest_client/connection.py +99 -54
- flwr/client/run_info_store.py +6 -6
- flwr/client/typing.py +1 -1
- flwr/clientapp/__init__.py +1 -2
- flwr/{client → clientapp}/client_app.py +11 -11
- flwr/clientapp/mod/centraldp_mods.py +16 -17
- flwr/clientapp/mod/localdp_mod.py +8 -9
- flwr/clientapp/typing.py +1 -1
- flwr/{client/clientapp → clientapp}/utils.py +4 -4
- flwr/common/__init__.py +3 -2
- flwr/common/args.py +3 -4
- flwr/common/config.py +15 -17
- flwr/common/constant.py +56 -28
- flwr/common/context.py +2 -1
- flwr/common/differential_privacy.py +3 -4
- flwr/common/event_log_plugin/event_log_plugin.py +3 -4
- flwr/common/exit/exit.py +16 -3
- flwr/common/exit/exit_code.py +39 -10
- flwr/common/exit/exit_handler.py +6 -2
- flwr/common/exit/signal_handler.py +5 -5
- flwr/common/grpc.py +8 -7
- flwr/common/inflatable_protobuf_utils.py +1 -1
- flwr/common/inflatable_utils.py +48 -31
- flwr/common/logger.py +19 -19
- flwr/common/message.py +5 -5
- flwr/common/object_ref.py +7 -7
- flwr/common/record/array.py +6 -6
- flwr/common/record/arrayrecord.py +18 -21
- flwr/common/record/configrecord.py +3 -3
- flwr/common/record/recorddict.py +5 -5
- flwr/common/record/typeddict.py +9 -2
- flwr/common/recorddict_compat.py +7 -10
- flwr/common/retry_invoker.py +20 -20
- flwr/common/secure_aggregation/crypto/symmetric_encryption.py +1 -89
- flwr/common/secure_aggregation/ndarrays_arithmetic.py +8 -5
- flwr/common/serde.py +22 -11
- flwr/common/serde_utils.py +2 -2
- flwr/common/telemetry.py +10 -6
- flwr/common/typing.py +65 -44
- flwr/compat/client/app.py +45 -47
- flwr/compat/client/grpc_client/connection.py +15 -14
- flwr/compat/common/constant.py +29 -0
- flwr/compat/server/app.py +6 -7
- flwr/proto/appio_pb2.py +13 -3
- flwr/proto/appio_pb2.pyi +134 -65
- flwr/proto/appio_pb2_grpc.py +20 -0
- flwr/proto/appio_pb2_grpc.pyi +27 -0
- flwr/proto/clientappio_pb2.py +17 -7
- flwr/proto/clientappio_pb2.pyi +15 -0
- flwr/proto/clientappio_pb2_grpc.py +206 -40
- flwr/proto/clientappio_pb2_grpc.pyi +168 -53
- flwr/proto/control_pb2.py +72 -40
- flwr/proto/control_pb2.pyi +319 -87
- flwr/proto/control_pb2_grpc.py +339 -28
- flwr/proto/control_pb2_grpc.pyi +209 -37
- flwr/proto/error_pb2.py +13 -3
- flwr/proto/error_pb2.pyi +24 -6
- flwr/proto/error_pb2_grpc.py +20 -0
- flwr/proto/error_pb2_grpc.pyi +27 -0
- flwr/proto/fab_pb2.py +24 -10
- flwr/proto/fab_pb2.pyi +68 -20
- flwr/proto/fab_pb2_grpc.py +20 -0
- flwr/proto/fab_pb2_grpc.pyi +27 -0
- flwr/proto/federation_pb2.py +38 -0
- flwr/proto/federation_pb2.pyi +56 -0
- flwr/proto/federation_pb2_grpc.py +24 -0
- flwr/proto/federation_pb2_grpc.pyi +31 -0
- flwr/proto/fleet_pb2.py +45 -27
- flwr/proto/fleet_pb2.pyi +190 -70
- flwr/proto/fleet_pb2_grpc.py +277 -66
- flwr/proto/fleet_pb2_grpc.pyi +201 -55
- flwr/proto/grpcadapter_pb2.py +14 -4
- flwr/proto/grpcadapter_pb2.pyi +38 -16
- flwr/proto/grpcadapter_pb2_grpc.py +35 -4
- flwr/proto/grpcadapter_pb2_grpc.pyi +38 -7
- flwr/proto/heartbeat_pb2.py +17 -7
- flwr/proto/heartbeat_pb2.pyi +51 -22
- flwr/proto/heartbeat_pb2_grpc.py +20 -0
- flwr/proto/heartbeat_pb2_grpc.pyi +27 -0
- flwr/proto/log_pb2.py +13 -3
- flwr/proto/log_pb2.pyi +34 -11
- flwr/proto/log_pb2_grpc.py +20 -0
- flwr/proto/log_pb2_grpc.pyi +27 -0
- flwr/proto/message_pb2.py +15 -5
- flwr/proto/message_pb2.pyi +154 -86
- flwr/proto/message_pb2_grpc.py +20 -0
- flwr/proto/message_pb2_grpc.pyi +27 -0
- flwr/proto/node_pb2.py +16 -4
- flwr/proto/node_pb2.pyi +77 -4
- flwr/proto/node_pb2_grpc.py +20 -0
- flwr/proto/node_pb2_grpc.pyi +27 -0
- flwr/proto/recorddict_pb2.py +13 -3
- flwr/proto/recorddict_pb2.pyi +184 -107
- flwr/proto/recorddict_pb2_grpc.py +20 -0
- flwr/proto/recorddict_pb2_grpc.pyi +27 -0
- flwr/proto/run_pb2.py +40 -31
- flwr/proto/run_pb2.pyi +158 -84
- flwr/proto/run_pb2_grpc.py +20 -0
- flwr/proto/run_pb2_grpc.pyi +27 -0
- flwr/proto/serverappio_pb2.py +13 -3
- flwr/proto/serverappio_pb2.pyi +32 -8
- flwr/proto/serverappio_pb2_grpc.py +246 -65
- flwr/proto/serverappio_pb2_grpc.pyi +221 -85
- flwr/proto/simulationio_pb2.py +16 -8
- flwr/proto/simulationio_pb2.pyi +15 -0
- flwr/proto/simulationio_pb2_grpc.py +162 -41
- flwr/proto/simulationio_pb2_grpc.pyi +149 -55
- flwr/proto/transport_pb2.py +20 -10
- flwr/proto/transport_pb2.pyi +249 -160
- flwr/proto/transport_pb2_grpc.py +35 -4
- flwr/proto/transport_pb2_grpc.pyi +38 -8
- flwr/server/app.py +175 -128
- flwr/server/client_manager.py +4 -5
- flwr/server/client_proxy.py +10 -11
- flwr/server/compat/app.py +4 -5
- flwr/server/compat/app_utils.py +2 -1
- flwr/server/compat/grid_client_proxy.py +12 -13
- flwr/server/compat/legacy_context.py +3 -4
- flwr/server/fleet_event_log_interceptor.py +2 -1
- flwr/server/grid/grid.py +2 -3
- flwr/server/grid/grpc_grid.py +12 -10
- flwr/server/grid/inmemory_grid.py +4 -4
- flwr/server/run_serverapp.py +2 -3
- flwr/server/server.py +34 -39
- flwr/server/server_app.py +7 -8
- flwr/server/server_config.py +1 -2
- flwr/server/serverapp/app.py +34 -28
- flwr/server/serverapp_components.py +4 -5
- flwr/server/strategy/aggregate.py +9 -8
- flwr/server/strategy/bulyan.py +13 -11
- flwr/server/strategy/dp_adaptive_clipping.py +16 -20
- flwr/server/strategy/dp_fixed_clipping.py +12 -17
- flwr/server/strategy/dpfedavg_adaptive.py +3 -4
- flwr/server/strategy/dpfedavg_fixed.py +6 -10
- flwr/server/strategy/fault_tolerant_fedavg.py +14 -13
- flwr/server/strategy/fedadagrad.py +18 -14
- flwr/server/strategy/fedadam.py +16 -14
- flwr/server/strategy/fedavg.py +16 -17
- flwr/server/strategy/fedavg_android.py +15 -15
- flwr/server/strategy/fedavgm.py +21 -18
- flwr/server/strategy/fedmedian.py +2 -3
- flwr/server/strategy/fedopt.py +11 -10
- flwr/server/strategy/fedprox.py +10 -9
- flwr/server/strategy/fedtrimmedavg.py +12 -11
- flwr/server/strategy/fedxgb_bagging.py +13 -11
- flwr/server/strategy/fedxgb_cyclic.py +6 -6
- flwr/server/strategy/fedxgb_nn_avg.py +4 -4
- flwr/server/strategy/fedyogi.py +16 -14
- flwr/server/strategy/krum.py +12 -11
- flwr/server/strategy/qfedavg.py +16 -15
- flwr/server/strategy/strategy.py +6 -9
- flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +20 -9
- flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +1 -2
- flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +3 -4
- flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +10 -12
- flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +1 -3
- flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +136 -42
- flwr/server/superlink/fleet/grpc_rere/{server_interceptor.py → node_auth_server_interceptor.py} +28 -50
- flwr/server/superlink/fleet/message_handler/message_handler.py +141 -51
- flwr/server/superlink/fleet/rest_rere/rest_api.py +54 -33
- flwr/server/superlink/fleet/vce/backend/backend.py +2 -2
- flwr/server/superlink/fleet/vce/backend/raybackend.py +6 -6
- flwr/server/superlink/fleet/vce/vce_api.py +32 -13
- flwr/server/superlink/linkstate/__init__.py +2 -0
- flwr/server/superlink/linkstate/in_memory_linkstate.py +293 -208
- flwr/server/superlink/linkstate/linkstate.py +176 -64
- flwr/server/superlink/linkstate/linkstate_factory.py +24 -6
- flwr/server/superlink/linkstate/sql_linkstate.py +221 -0
- flwr/server/superlink/linkstate/sqlite_linkstate.py +743 -648
- flwr/server/superlink/linkstate/utils.py +11 -62
- flwr/server/superlink/serverappio/serverappio_grpc.py +1 -2
- flwr/server/superlink/serverappio/serverappio_servicer.py +28 -23
- flwr/server/superlink/simulation/simulationio_grpc.py +1 -2
- flwr/server/superlink/simulation/simulationio_servicer.py +19 -14
- flwr/server/superlink/utils.py +4 -6
- flwr/server/typing.py +1 -1
- flwr/server/utils/tensorboard.py +15 -8
- flwr/server/utils/validator.py +2 -3
- flwr/server/workflow/default_workflows.py +7 -6
- flwr/server/workflow/secure_aggregation/secagg_workflow.py +2 -4
- flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +13 -11
- flwr/serverapp/strategy/bulyan.py +16 -15
- flwr/serverapp/strategy/dp_adaptive_clipping.py +12 -11
- flwr/serverapp/strategy/dp_fixed_clipping.py +11 -14
- flwr/serverapp/strategy/fedadagrad.py +10 -11
- flwr/serverapp/strategy/fedadam.py +10 -11
- flwr/serverapp/strategy/fedavg.py +10 -11
- flwr/serverapp/strategy/fedavgm.py +17 -16
- flwr/serverapp/strategy/fedmedian.py +2 -2
- flwr/serverapp/strategy/fedopt.py +10 -11
- flwr/serverapp/strategy/fedprox.py +7 -8
- flwr/serverapp/strategy/fedtrimmedavg.py +9 -9
- flwr/serverapp/strategy/fedxgb_bagging.py +3 -3
- flwr/serverapp/strategy/fedxgb_cyclic.py +10 -10
- flwr/serverapp/strategy/fedyogi.py +9 -11
- flwr/serverapp/strategy/krum.py +7 -7
- flwr/serverapp/strategy/multikrum.py +9 -9
- flwr/serverapp/strategy/qfedavg.py +17 -16
- flwr/serverapp/strategy/strategy.py +6 -9
- flwr/serverapp/strategy/strategy_utils.py +7 -8
- flwr/simulation/app.py +46 -42
- flwr/simulation/legacy_app.py +12 -12
- flwr/simulation/ray_transport/ray_actor.py +11 -12
- flwr/simulation/ray_transport/ray_client_proxy.py +14 -19
- flwr/simulation/run_simulation.py +46 -44
- flwr/simulation/simulationio_connection.py +4 -4
- flwr/{common → supercore}/address.py +1 -37
- flwr/supercore/cli/flower_superexec.py +3 -4
- flwr/supercore/constant.py +69 -0
- flwr/supercore/corestate/corestate.py +24 -3
- flwr/supercore/corestate/in_memory_corestate.py +138 -0
- flwr/supercore/corestate/sql_corestate.py +153 -0
- flwr/supercore/corestate/sqlite_corestate.py +157 -0
- flwr/supercore/credential_store/__init__.py +33 -0
- flwr/supercore/credential_store/credential_store.py +34 -0
- flwr/supercore/credential_store/file_credential_store.py +76 -0
- flwr/{common → supercore}/date.py +0 -11
- flwr/supercore/ffs/disk_ffs.py +1 -2
- flwr/supercore/ffs/ffs.py +1 -2
- flwr/supercore/ffs/ffs_factory.py +1 -2
- flwr/{common → supercore}/heartbeat.py +20 -25
- flwr/supercore/object_store/in_memory_object_store.py +1 -6
- flwr/supercore/object_store/object_store.py +1 -2
- flwr/supercore/object_store/object_store_factory.py +27 -8
- flwr/supercore/object_store/sqlite_object_store.py +253 -0
- flwr/{cli/new/templates/app → supercore/primitives}/__init__.py +1 -1
- flwr/supercore/primitives/asymmetric.py +117 -0
- flwr/supercore/primitives/asymmetric_ed25519.py +175 -0
- flwr/supercore/sql_mixin.py +292 -0
- flwr/supercore/sqlite_mixin.py +156 -0
- flwr/{client/clientapp → supercore/state}/__init__.py +2 -2
- flwr/supercore/state/schema/README.md +125 -0
- flwr/{cli/new/templates → supercore/state/schema}/__init__.py +2 -2
- flwr/supercore/state/schema/corestate_tables.py +36 -0
- flwr/supercore/state/schema/linkstate_tables.py +152 -0
- flwr/supercore/state/schema/objectstore_tables.py +90 -0
- flwr/supercore/superexec/plugin/base_exec_plugin.py +1 -2
- flwr/supercore/superexec/plugin/exec_plugin.py +3 -3
- flwr/supercore/superexec/run_superexec.py +9 -13
- flwr/supercore/utils.py +224 -0
- flwr/superlink/artifact_provider/artifact_provider.py +1 -2
- flwr/superlink/auth_plugin/__init__.py +5 -2
- flwr/superlink/auth_plugin/auth_plugin.py +20 -19
- flwr/superlink/auth_plugin/noop_auth_plugin.py +84 -0
- flwr/superlink/federation/__init__.py +24 -0
- flwr/superlink/federation/federation_manager.py +64 -0
- flwr/superlink/federation/noop_federation_manager.py +71 -0
- flwr/superlink/servicer/control/{control_user_auth_interceptor.py → control_account_auth_interceptor.py} +41 -32
- flwr/superlink/servicer/control/control_event_log_interceptor.py +7 -7
- flwr/superlink/servicer/control/control_grpc.py +20 -17
- flwr/superlink/servicer/control/control_license_interceptor.py +3 -3
- flwr/superlink/servicer/control/control_servicer.py +328 -68
- flwr/supernode/cli/flower_supernode.py +74 -26
- flwr/supernode/nodestate/in_memory_nodestate.py +121 -49
- flwr/supernode/nodestate/nodestate.py +52 -8
- flwr/supernode/nodestate/nodestate_factory.py +7 -4
- flwr/supernode/runtime/run_clientapp.py +43 -24
- flwr/supernode/servicer/clientappio/clientappio_servicer.py +48 -10
- flwr/supernode/start_client_internal.py +185 -57
- {flwr_nightly-1.23.0.dev20250930.dist-info → flwr_nightly-1.26.0.dev20260121.dist-info}/METADATA +10 -11
- flwr_nightly-1.26.0.dev20260121.dist-info/RECORD +411 -0
- flwr/cli/new/templates/app/.gitignore.tpl +0 -163
- flwr/cli/new/templates/app/LICENSE.tpl +0 -202
- flwr/cli/new/templates/app/README.baseline.md.tpl +0 -127
- flwr/cli/new/templates/app/README.flowertune.md.tpl +0 -68
- flwr/cli/new/templates/app/README.md.tpl +0 -37
- flwr/cli/new/templates/app/code/__init__.baseline.py.tpl +0 -1
- flwr/cli/new/templates/app/code/__init__.py.tpl +0 -1
- flwr/cli/new/templates/app/code/__init__.pytorch_legacy_api.py.tpl +0 -1
- flwr/cli/new/templates/app/code/client.baseline.py.tpl +0 -75
- flwr/cli/new/templates/app/code/client.huggingface.py.tpl +0 -93
- flwr/cli/new/templates/app/code/client.jax.py.tpl +0 -71
- flwr/cli/new/templates/app/code/client.mlx.py.tpl +0 -102
- flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -46
- flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -80
- flwr/cli/new/templates/app/code/client.pytorch_legacy_api.py.tpl +0 -55
- flwr/cli/new/templates/app/code/client.sklearn.py.tpl +0 -108
- flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -82
- flwr/cli/new/templates/app/code/client.xgboost.py.tpl +0 -110
- flwr/cli/new/templates/app/code/dataset.baseline.py.tpl +0 -36
- flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +0 -92
- flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +0 -87
- flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +0 -56
- flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +0 -73
- flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +0 -78
- flwr/cli/new/templates/app/code/model.baseline.py.tpl +0 -66
- flwr/cli/new/templates/app/code/server.baseline.py.tpl +0 -43
- flwr/cli/new/templates/app/code/server.huggingface.py.tpl +0 -42
- flwr/cli/new/templates/app/code/server.jax.py.tpl +0 -39
- flwr/cli/new/templates/app/code/server.mlx.py.tpl +0 -41
- flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -38
- flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -41
- flwr/cli/new/templates/app/code/server.pytorch_legacy_api.py.tpl +0 -31
- flwr/cli/new/templates/app/code/server.sklearn.py.tpl +0 -44
- flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -38
- flwr/cli/new/templates/app/code/server.xgboost.py.tpl +0 -56
- flwr/cli/new/templates/app/code/strategy.baseline.py.tpl +0 -1
- flwr/cli/new/templates/app/code/task.huggingface.py.tpl +0 -98
- flwr/cli/new/templates/app/code/task.jax.py.tpl +0 -57
- flwr/cli/new/templates/app/code/task.mlx.py.tpl +0 -102
- flwr/cli/new/templates/app/code/task.numpy.py.tpl +0 -7
- flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -98
- flwr/cli/new/templates/app/code/task.pytorch_legacy_api.py.tpl +0 -111
- flwr/cli/new/templates/app/code/task.sklearn.py.tpl +0 -67
- flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +0 -52
- flwr/cli/new/templates/app/code/task.xgboost.py.tpl +0 -67
- flwr/cli/new/templates/app/code/utils.baseline.py.tpl +0 -1
- flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +0 -146
- flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +0 -80
- flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +0 -65
- flwr/cli/new/templates/app/pyproject.jax.toml.tpl +0 -52
- flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +0 -56
- flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +0 -49
- flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +0 -53
- flwr/cli/new/templates/app/pyproject.pytorch_legacy_api.toml.tpl +0 -53
- flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +0 -52
- flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +0 -53
- flwr/cli/new/templates/app/pyproject.xgboost.toml.tpl +0 -61
- flwr/common/pyproject.py +0 -42
- flwr/supercore/object_store/utils.py +0 -43
- flwr_nightly-1.23.0.dev20250930.dist-info/RECORD +0 -429
- /flwr/{common → supercore}/version.py +0 -0
- {flwr_nightly-1.23.0.dev20250930.dist-info → flwr_nightly-1.26.0.dev20260121.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.23.0.dev20250930.dist-info → flwr_nightly-1.26.0.dev20260121.dist-info}/entry_points.txt +0 -0
flwr/common/recorddict_compat.py
CHANGED
|
@@ -15,9 +15,8 @@
|
|
|
15
15
|
"""RecordDict utilities."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from collections import OrderedDict
|
|
19
18
|
from collections.abc import Mapping
|
|
20
|
-
from typing import
|
|
19
|
+
from typing import cast, get_args
|
|
21
20
|
|
|
22
21
|
from . import Array, ArrayRecord, ConfigRecord, MetricRecord, RecordDict
|
|
23
22
|
from .typing import (
|
|
@@ -104,25 +103,23 @@ def parameters_to_arrayrecord(parameters: Parameters, keep_input: bool) -> Array
|
|
|
104
103
|
tensor_type = parameters.tensor_type
|
|
105
104
|
|
|
106
105
|
num_arrays = len(parameters.tensors)
|
|
107
|
-
|
|
106
|
+
array_dict = {}
|
|
108
107
|
for idx in range(num_arrays):
|
|
109
108
|
if keep_input:
|
|
110
109
|
tensor = parameters.tensors[idx]
|
|
111
110
|
else:
|
|
112
111
|
tensor = parameters.tensors.pop(0)
|
|
113
|
-
|
|
114
|
-
data=tensor, dtype="", stype=tensor_type, shape=()
|
|
115
|
-
)
|
|
112
|
+
array_dict[str(idx)] = Array(data=tensor, dtype="", stype=tensor_type, shape=())
|
|
116
113
|
|
|
117
114
|
if num_arrays == 0:
|
|
118
|
-
|
|
115
|
+
array_dict[EMPTY_TENSOR_KEY] = Array(
|
|
119
116
|
data=b"", dtype="", stype=tensor_type, shape=()
|
|
120
117
|
)
|
|
121
|
-
return ArrayRecord(
|
|
118
|
+
return ArrayRecord(array_dict, keep_input=keep_input)
|
|
122
119
|
|
|
123
120
|
|
|
124
121
|
def _check_mapping_from_recordscalartype_to_scalar(
|
|
125
|
-
record_data: Mapping[str,
|
|
122
|
+
record_data: Mapping[str, ConfigRecordValues | MetricRecordValues],
|
|
126
123
|
) -> dict[str, Scalar]:
|
|
127
124
|
"""Check mapping `common.*RecordValues` into `common.Scalar` is possible."""
|
|
128
125
|
for value in record_data.values():
|
|
@@ -157,7 +154,7 @@ def _recorddict_to_fit_or_evaluate_ins_components(
|
|
|
157
154
|
|
|
158
155
|
|
|
159
156
|
def _fit_or_evaluate_ins_to_recorddict(
|
|
160
|
-
ins:
|
|
157
|
+
ins: FitIns | EvaluateIns, keep_input: bool
|
|
161
158
|
) -> RecordDict:
|
|
162
159
|
recorddict = RecordDict()
|
|
163
160
|
|
flwr/common/retry_invoker.py
CHANGED
|
@@ -19,10 +19,10 @@ import itertools
|
|
|
19
19
|
import random
|
|
20
20
|
import threading
|
|
21
21
|
import time
|
|
22
|
-
from collections.abc import Generator, Iterable
|
|
22
|
+
from collections.abc import Callable, Generator, Iterable
|
|
23
23
|
from dataclasses import dataclass
|
|
24
24
|
from logging import INFO, WARN
|
|
25
|
-
from typing import Any,
|
|
25
|
+
from typing import Any, cast
|
|
26
26
|
|
|
27
27
|
import grpc
|
|
28
28
|
|
|
@@ -39,7 +39,7 @@ from flwr.proto.simulationio_pb2_grpc import SimulationIoStub
|
|
|
39
39
|
def exponential(
|
|
40
40
|
base_delay: float = 1,
|
|
41
41
|
multiplier: float = 2,
|
|
42
|
-
max_delay:
|
|
42
|
+
max_delay: int | None = None,
|
|
43
43
|
) -> Generator[float, None, None]:
|
|
44
44
|
"""Wait time generator for exponential backoff strategy.
|
|
45
45
|
|
|
@@ -66,7 +66,7 @@ def exponential(
|
|
|
66
66
|
|
|
67
67
|
|
|
68
68
|
def constant(
|
|
69
|
-
interval:
|
|
69
|
+
interval: float | Iterable[float] = 1,
|
|
70
70
|
) -> Generator[float, None, None]:
|
|
71
71
|
"""Wait time generator for specified intervals.
|
|
72
72
|
|
|
@@ -114,8 +114,8 @@ class RetryState:
|
|
|
114
114
|
kwargs: dict[str, Any]
|
|
115
115
|
tries: int
|
|
116
116
|
elapsed_time: float
|
|
117
|
-
exception:
|
|
118
|
-
actual_wait:
|
|
117
|
+
exception: Exception | None = None
|
|
118
|
+
actual_wait: float | None = None
|
|
119
119
|
|
|
120
120
|
|
|
121
121
|
# pylint: disable-next=too-many-instance-attributes
|
|
@@ -184,16 +184,16 @@ class RetryInvoker:
|
|
|
184
184
|
def __init__(
|
|
185
185
|
self,
|
|
186
186
|
wait_gen_factory: Callable[[], Generator[float, None, None]],
|
|
187
|
-
recoverable_exceptions:
|
|
188
|
-
max_tries:
|
|
189
|
-
max_time:
|
|
187
|
+
recoverable_exceptions: type[Exception] | tuple[type[Exception], ...],
|
|
188
|
+
max_tries: int | None,
|
|
189
|
+
max_time: float | None,
|
|
190
190
|
*,
|
|
191
|
-
on_success:
|
|
192
|
-
on_backoff:
|
|
193
|
-
on_giveup:
|
|
194
|
-
jitter:
|
|
195
|
-
should_giveup:
|
|
196
|
-
wait_function:
|
|
191
|
+
on_success: Callable[[RetryState], None] | None = None,
|
|
192
|
+
on_backoff: Callable[[RetryState], None] | None = None,
|
|
193
|
+
on_giveup: Callable[[RetryState], None] | None = None,
|
|
194
|
+
jitter: Callable[[float], float] | None = full_jitter,
|
|
195
|
+
should_giveup: Callable[[Exception], bool] | None = None,
|
|
196
|
+
wait_function: Callable[[float], None] | None = None,
|
|
197
197
|
) -> None:
|
|
198
198
|
self.wait_gen_factory = wait_gen_factory
|
|
199
199
|
self.recoverable_exceptions = recoverable_exceptions
|
|
@@ -253,7 +253,7 @@ class RetryInvoker:
|
|
|
253
253
|
"""
|
|
254
254
|
|
|
255
255
|
def try_call_event_handler(
|
|
256
|
-
handler:
|
|
256
|
+
handler: Callable[[RetryState], None] | None,
|
|
257
257
|
) -> None:
|
|
258
258
|
if handler is not None:
|
|
259
259
|
handler(cast(RetryState, ref_state[0]))
|
|
@@ -261,7 +261,7 @@ class RetryInvoker:
|
|
|
261
261
|
try_cnt = 0
|
|
262
262
|
wait_generator = self.wait_gen_factory()
|
|
263
263
|
start = time.monotonic()
|
|
264
|
-
ref_state: list[
|
|
264
|
+
ref_state: list[RetryState | None] = [None]
|
|
265
265
|
|
|
266
266
|
while True:
|
|
267
267
|
try_cnt += 1
|
|
@@ -387,9 +387,9 @@ def _make_simple_grpc_retry_invoker() -> RetryInvoker:
|
|
|
387
387
|
|
|
388
388
|
|
|
389
389
|
def _wrap_stub(
|
|
390
|
-
stub:
|
|
391
|
-
ServerAppIoStub
|
|
392
|
-
|
|
390
|
+
stub: (
|
|
391
|
+
ServerAppIoStub | ClientAppIoStub | SimulationIoStub | FleetStub | GrpcAdapter
|
|
392
|
+
),
|
|
393
393
|
retry_invoker: RetryInvoker,
|
|
394
394
|
) -> None:
|
|
395
395
|
"""Wrap a gRPC stub with a retry invoker."""
|
|
@@ -16,57 +16,14 @@
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
import base64
|
|
19
|
-
from typing import cast
|
|
20
19
|
|
|
21
20
|
from cryptography.exceptions import InvalidSignature
|
|
22
21
|
from cryptography.fernet import Fernet
|
|
23
|
-
from cryptography.hazmat.primitives import hashes, hmac
|
|
22
|
+
from cryptography.hazmat.primitives import hashes, hmac
|
|
24
23
|
from cryptography.hazmat.primitives.asymmetric import ec
|
|
25
24
|
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
|
|
26
25
|
|
|
27
26
|
|
|
28
|
-
def generate_key_pairs() -> (
|
|
29
|
-
tuple[ec.EllipticCurvePrivateKey, ec.EllipticCurvePublicKey]
|
|
30
|
-
):
|
|
31
|
-
"""Generate private and public key pairs with Cryptography."""
|
|
32
|
-
private_key = ec.generate_private_key(ec.SECP384R1())
|
|
33
|
-
public_key = private_key.public_key()
|
|
34
|
-
return private_key, public_key
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def private_key_to_bytes(private_key: ec.EllipticCurvePrivateKey) -> bytes:
|
|
38
|
-
"""Serialize private key to bytes."""
|
|
39
|
-
return private_key.private_bytes(
|
|
40
|
-
encoding=serialization.Encoding.PEM,
|
|
41
|
-
format=serialization.PrivateFormat.PKCS8,
|
|
42
|
-
encryption_algorithm=serialization.NoEncryption(),
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def bytes_to_private_key(private_key_bytes: bytes) -> ec.EllipticCurvePrivateKey:
|
|
47
|
-
"""Deserialize private key from bytes."""
|
|
48
|
-
return cast(
|
|
49
|
-
ec.EllipticCurvePrivateKey,
|
|
50
|
-
serialization.load_pem_private_key(data=private_key_bytes, password=None),
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def public_key_to_bytes(public_key: ec.EllipticCurvePublicKey) -> bytes:
|
|
55
|
-
"""Serialize public key to bytes."""
|
|
56
|
-
return public_key.public_bytes(
|
|
57
|
-
encoding=serialization.Encoding.PEM,
|
|
58
|
-
format=serialization.PublicFormat.SubjectPublicKeyInfo,
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def bytes_to_public_key(public_key_bytes: bytes) -> ec.EllipticCurvePublicKey:
|
|
63
|
-
"""Deserialize public key from bytes."""
|
|
64
|
-
return cast(
|
|
65
|
-
ec.EllipticCurvePublicKey,
|
|
66
|
-
serialization.load_pem_public_key(data=public_key_bytes),
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
27
|
def generate_shared_key(
|
|
71
28
|
private_key: ec.EllipticCurvePrivateKey, public_key: ec.EllipticCurvePublicKey
|
|
72
29
|
) -> bytes:
|
|
@@ -117,48 +74,3 @@ def verify_hmac(key: bytes, message: bytes, hmac_value: bytes) -> bool:
|
|
|
117
74
|
return True
|
|
118
75
|
except InvalidSignature:
|
|
119
76
|
return False
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def sign_message(private_key: ec.EllipticCurvePrivateKey, message: bytes) -> bytes:
|
|
123
|
-
"""Sign a message using the provided EC private key.
|
|
124
|
-
|
|
125
|
-
Parameters
|
|
126
|
-
----------
|
|
127
|
-
private_key : ec.EllipticCurvePrivateKey
|
|
128
|
-
The EC private key to sign the message with.
|
|
129
|
-
message : bytes
|
|
130
|
-
The message to be signed.
|
|
131
|
-
|
|
132
|
-
Returns
|
|
133
|
-
-------
|
|
134
|
-
bytes
|
|
135
|
-
The signature of the message.
|
|
136
|
-
"""
|
|
137
|
-
signature = private_key.sign(message, ec.ECDSA(hashes.SHA256()))
|
|
138
|
-
return signature
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
def verify_signature(
|
|
142
|
-
public_key: ec.EllipticCurvePublicKey, message: bytes, signature: bytes
|
|
143
|
-
) -> bool:
|
|
144
|
-
"""Verify a signature against a message using the provided EC public key.
|
|
145
|
-
|
|
146
|
-
Parameters
|
|
147
|
-
----------
|
|
148
|
-
public_key : ec.EllipticCurvePublicKey
|
|
149
|
-
The EC public key to verify the signature.
|
|
150
|
-
message : bytes
|
|
151
|
-
The original message.
|
|
152
|
-
signature : bytes
|
|
153
|
-
The signature to verify.
|
|
154
|
-
|
|
155
|
-
Returns
|
|
156
|
-
-------
|
|
157
|
-
bool
|
|
158
|
-
True if the signature is valid, False otherwise.
|
|
159
|
-
"""
|
|
160
|
-
try:
|
|
161
|
-
public_key.verify(signature, message, ec.ECDSA(hashes.SHA256()))
|
|
162
|
-
return True
|
|
163
|
-
except InvalidSignature:
|
|
164
|
-
return False
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
"""Utility functions for performing operations on Numpy NDArrays."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from typing import Any
|
|
18
|
+
from typing import Any
|
|
19
19
|
|
|
20
20
|
import numpy as np
|
|
21
|
-
from numpy.typing import
|
|
21
|
+
from numpy.typing import NDArray
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
def factor_combine(factor: int, parameters: list[NDArray[Any]]) -> list[NDArray[Any]]:
|
|
@@ -38,8 +38,11 @@ def get_parameters_shape(parameters: list[NDArray[Any]]) -> list[tuple[int, ...]
|
|
|
38
38
|
return [arr.shape for arr in parameters]
|
|
39
39
|
|
|
40
40
|
|
|
41
|
+
default_numpy_dtype = np.dtype(np.int64)
|
|
42
|
+
|
|
43
|
+
|
|
41
44
|
def get_zero_parameters(
|
|
42
|
-
dimensions_list: list[tuple[int, ...]], dtype:
|
|
45
|
+
dimensions_list: list[tuple[int, ...]], dtype: np.dtype[Any] = default_numpy_dtype
|
|
43
46
|
) -> list[NDArray[Any]]:
|
|
44
47
|
"""Generate zero parameters based on the dimensions list."""
|
|
45
48
|
return [np.zeros(dimensions, dtype=dtype) for dimensions in dimensions_list]
|
|
@@ -68,14 +71,14 @@ def parameters_mod(parameters: list[NDArray[Any]], divisor: int) -> list[NDArray
|
|
|
68
71
|
|
|
69
72
|
|
|
70
73
|
def parameters_multiply(
|
|
71
|
-
parameters: list[NDArray[Any]], multiplier:
|
|
74
|
+
parameters: list[NDArray[Any]], multiplier: int | float
|
|
72
75
|
) -> list[NDArray[Any]]:
|
|
73
76
|
"""Multiply parameters by an integer/float multiplier."""
|
|
74
77
|
return [parameters[idx] * multiplier for idx in range(len(parameters))]
|
|
75
78
|
|
|
76
79
|
|
|
77
80
|
def parameters_divide(
|
|
78
|
-
parameters: list[NDArray[Any]], divisor:
|
|
81
|
+
parameters: list[NDArray[Any]], divisor: int | float
|
|
79
82
|
) -> list[NDArray[Any]]:
|
|
80
83
|
"""Divide weight by an integer/float divisor."""
|
|
81
84
|
return [parameters[idx] / divisor for idx in range(len(parameters))]
|
flwr/common/serde.py
CHANGED
|
@@ -15,9 +15,10 @@
|
|
|
15
15
|
"""ProtoBuf serialization and deserialization."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from collections import OrderedDict
|
|
19
18
|
from typing import Any, cast
|
|
20
19
|
|
|
20
|
+
from flwr.app.user_config import UserConfig, UserConfigValue
|
|
21
|
+
|
|
21
22
|
# pylint: disable=E0611
|
|
22
23
|
from flwr.proto.fab_pb2 import Fab as ProtoFab
|
|
23
24
|
from flwr.proto.message_pb2 import Context as ProtoContext
|
|
@@ -410,9 +411,9 @@ def array_record_from_proto(
|
|
|
410
411
|
) -> ArrayRecord:
|
|
411
412
|
"""Deserialize ArrayRecord from ProtoBuf."""
|
|
412
413
|
return ArrayRecord(
|
|
413
|
-
array_dict=
|
|
414
|
-
|
|
415
|
-
|
|
414
|
+
array_dict={
|
|
415
|
+
item.key: array_from_proto(item.value) for item in record_proto.items
|
|
416
|
+
},
|
|
416
417
|
keep_input=False,
|
|
417
418
|
)
|
|
418
419
|
|
|
@@ -501,18 +502,20 @@ def recorddict_from_proto(recorddict_proto: ProtoRecordDict) -> RecordDict:
|
|
|
501
502
|
|
|
502
503
|
def fab_to_proto(fab: typing.Fab) -> ProtoFab:
|
|
503
504
|
"""Create a proto Fab object from a Python Fab."""
|
|
504
|
-
return ProtoFab(
|
|
505
|
+
return ProtoFab(
|
|
506
|
+
hash_str=fab.hash_str, content=fab.content, verifications=fab.verifications
|
|
507
|
+
)
|
|
505
508
|
|
|
506
509
|
|
|
507
510
|
def fab_from_proto(fab: ProtoFab) -> typing.Fab:
|
|
508
511
|
"""Create a Python Fab object from a proto Fab."""
|
|
509
|
-
return typing.Fab(fab.hash_str, fab.content)
|
|
512
|
+
return typing.Fab(fab.hash_str, fab.content, dict(fab.verifications))
|
|
510
513
|
|
|
511
514
|
|
|
512
515
|
# === User configs ===
|
|
513
516
|
|
|
514
517
|
|
|
515
|
-
def user_config_to_proto(user_config:
|
|
518
|
+
def user_config_to_proto(user_config: UserConfig) -> Any:
|
|
516
519
|
"""Serialize `UserConfig` to ProtoBuf."""
|
|
517
520
|
proto = {}
|
|
518
521
|
for key, value in user_config.items():
|
|
@@ -520,7 +523,7 @@ def user_config_to_proto(user_config: typing.UserConfig) -> Any:
|
|
|
520
523
|
return proto
|
|
521
524
|
|
|
522
525
|
|
|
523
|
-
def user_config_from_proto(proto: Any) ->
|
|
526
|
+
def user_config_from_proto(proto: Any) -> UserConfig:
|
|
524
527
|
"""Deserialize `UserConfig` from ProtoBuf."""
|
|
525
528
|
metrics = {}
|
|
526
529
|
for key, value in proto.items():
|
|
@@ -528,7 +531,7 @@ def user_config_from_proto(proto: Any) -> typing.UserConfig:
|
|
|
528
531
|
return metrics
|
|
529
532
|
|
|
530
533
|
|
|
531
|
-
def user_config_value_to_proto(user_config_value:
|
|
534
|
+
def user_config_value_to_proto(user_config_value: UserConfigValue) -> Scalar:
|
|
532
535
|
"""Serialize `UserConfigValue` to ProtoBuf."""
|
|
533
536
|
if isinstance(user_config_value, bool):
|
|
534
537
|
return Scalar(bool=user_config_value)
|
|
@@ -547,11 +550,11 @@ def user_config_value_to_proto(user_config_value: typing.UserConfigValue) -> Sca
|
|
|
547
550
|
)
|
|
548
551
|
|
|
549
552
|
|
|
550
|
-
def user_config_value_from_proto(scalar_msg: Scalar) ->
|
|
553
|
+
def user_config_value_from_proto(scalar_msg: Scalar) -> UserConfigValue:
|
|
551
554
|
"""Deserialize `UserConfigValue` from ProtoBuf."""
|
|
552
555
|
scalar_field = scalar_msg.WhichOneof("scalar")
|
|
553
556
|
scalar = getattr(scalar_msg, cast(str, scalar_field))
|
|
554
|
-
return cast(
|
|
557
|
+
return cast(UserConfigValue, scalar)
|
|
555
558
|
|
|
556
559
|
|
|
557
560
|
# === Message messages ===
|
|
@@ -630,6 +633,10 @@ def run_to_proto(run: typing.Run) -> ProtoRun:
|
|
|
630
633
|
finished_at=run.finished_at,
|
|
631
634
|
status=run_status_to_proto(run.status),
|
|
632
635
|
flwr_aid=run.flwr_aid,
|
|
636
|
+
federation=run.federation,
|
|
637
|
+
bytes_sent=run.bytes_sent,
|
|
638
|
+
bytes_recv=run.bytes_recv,
|
|
639
|
+
clientapp_runtime=run.clientapp_runtime,
|
|
633
640
|
)
|
|
634
641
|
return proto
|
|
635
642
|
|
|
@@ -648,6 +655,10 @@ def run_from_proto(run_proto: ProtoRun) -> typing.Run:
|
|
|
648
655
|
finished_at=run_proto.finished_at,
|
|
649
656
|
status=run_status_from_proto(run_proto.status),
|
|
650
657
|
flwr_aid=run_proto.flwr_aid,
|
|
658
|
+
federation=run_proto.federation,
|
|
659
|
+
bytes_sent=run_proto.bytes_sent,
|
|
660
|
+
bytes_recv=run_proto.bytes_recv,
|
|
661
|
+
clientapp_runtime=run_proto.clientapp_runtime,
|
|
651
662
|
)
|
|
652
663
|
return run
|
|
653
664
|
|
flwr/common/serde_utils.py
CHANGED
|
@@ -114,7 +114,7 @@ def record_value_dict_to_proto(
|
|
|
114
114
|
Note: `bool` MUST be put in the front of allowd_types if it exists.
|
|
115
115
|
"""
|
|
116
116
|
# Move bool to the front
|
|
117
|
-
if bool in allowed_types and allowed_types[0]
|
|
117
|
+
if bool in allowed_types and allowed_types[0] is not bool:
|
|
118
118
|
allowed_types.remove(bool)
|
|
119
119
|
allowed_types.insert(0, bool)
|
|
120
120
|
|
|
@@ -125,7 +125,7 @@ def record_value_dict_to_proto(
|
|
|
125
125
|
|
|
126
126
|
|
|
127
127
|
def record_value_dict_from_proto(
|
|
128
|
-
value_dict_proto: MutableMapping[str, Any]
|
|
128
|
+
value_dict_proto: MutableMapping[str, Any],
|
|
129
129
|
) -> dict[str, Any]:
|
|
130
130
|
"""Deserialize the record value dict from ProtoBuf."""
|
|
131
131
|
return {k: _record_value_from_proto(v) for k, v in value_dict_proto.items()}
|
flwr/common/telemetry.py
CHANGED
|
@@ -25,10 +25,10 @@ import uuid
|
|
|
25
25
|
from concurrent.futures import Future, ThreadPoolExecutor
|
|
26
26
|
from enum import Enum, auto
|
|
27
27
|
from pathlib import Path
|
|
28
|
-
from typing import Any,
|
|
28
|
+
from typing import Any, cast
|
|
29
29
|
|
|
30
30
|
from flwr.common.constant import FLWR_DIR
|
|
31
|
-
from flwr.
|
|
31
|
+
from flwr.supercore.version import package_name, package_version
|
|
32
32
|
|
|
33
33
|
FLWR_TELEMETRY_ENABLED = os.getenv("FLWR_TELEMETRY_ENABLED", "1")
|
|
34
34
|
FLWR_TELEMETRY_LOGGING = os.getenv("FLWR_TELEMETRY_LOGGING", "0")
|
|
@@ -56,7 +56,7 @@ def _configure_logger(log_level: int) -> None:
|
|
|
56
56
|
_configure_logger(LOGGER_LEVEL)
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
def log(msg:
|
|
59
|
+
def log(msg: str | Exception) -> None:
|
|
60
60
|
"""Log message using logger at DEBUG level."""
|
|
61
61
|
logging.getLogger(LOGGER_NAME).log(LOGGER_LEVEL, msg)
|
|
62
62
|
|
|
@@ -161,6 +161,10 @@ class EventType(str, Enum):
|
|
|
161
161
|
FLWR_SERVERAPP_RUN_ENTER = auto()
|
|
162
162
|
FLWR_SERVERAPP_RUN_LEAVE = auto()
|
|
163
163
|
|
|
164
|
+
# CLI: flwr-clientapp
|
|
165
|
+
FLWR_CLIENTAPP_RUN_ENTER = auto()
|
|
166
|
+
FLWR_CLIENTAPP_RUN_LEAVE = auto()
|
|
167
|
+
|
|
164
168
|
# --- Simulation Engine ------------------------------------------------------------
|
|
165
169
|
|
|
166
170
|
# CLI: flower-simulation
|
|
@@ -188,7 +192,7 @@ class EventType(str, Enum):
|
|
|
188
192
|
|
|
189
193
|
# Use the ThreadPoolExecutor with max_workers=1 to have a queue
|
|
190
194
|
# and also ensure that telemetry calls are not blocking.
|
|
191
|
-
state: dict[str,
|
|
195
|
+
state: dict[str, str | None | ThreadPoolExecutor | None] = {
|
|
192
196
|
# Will be assigned ThreadPoolExecutor(max_workers=1)
|
|
193
197
|
# in event() the first time it's required
|
|
194
198
|
"executor": None,
|
|
@@ -200,7 +204,7 @@ state: dict[str, Union[Optional[str], Optional[ThreadPoolExecutor]]] = {
|
|
|
200
204
|
|
|
201
205
|
def event(
|
|
202
206
|
event_type: EventType,
|
|
203
|
-
event_details:
|
|
207
|
+
event_details: dict[str, Any] | None = None,
|
|
204
208
|
) -> Future: # type: ignore
|
|
205
209
|
"""Submit create_event to ThreadPoolExecutor to avoid blocking."""
|
|
206
210
|
if state["executor"] is None:
|
|
@@ -212,7 +216,7 @@ def event(
|
|
|
212
216
|
return result
|
|
213
217
|
|
|
214
218
|
|
|
215
|
-
def create_event(event_type: EventType, event_details:
|
|
219
|
+
def create_event(event_type: EventType, event_details: dict[str, Any] | None) -> str:
|
|
216
220
|
"""Create telemetry event."""
|
|
217
221
|
if state["source"] is None:
|
|
218
222
|
state["source"] = _get_source_id()
|