flwr 1.25.0__tar.gz → 1.26.0__tar.gz
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-1.25.0 → flwr-1.26.0}/PKG-INFO +7 -5
- {flwr-1.25.0 → flwr-1.26.0}/README.md +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/__init__.py +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/app/__init__.py +4 -1
- flwr-1.26.0/py/flwr/app/message_type.py +29 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/app/metadata.py +5 -2
- flwr-1.26.0/py/flwr/app/user_config.py +19 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/app.py +37 -19
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/app_cmd/publish.py +25 -75
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/app_cmd/review.py +18 -69
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/auth_plugin/auth_plugin.py +5 -10
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/auth_plugin/noop_auth_plugin.py +1 -2
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/auth_plugin/oidc_cli_plugin.py +38 -38
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/build.py +15 -28
- flwr-1.26.0/py/flwr/cli/config/__init__.py +21 -0
- flwr-1.26.0/py/flwr/cli/config/ls.py +71 -0
- flwr-1.26.0/py/flwr/cli/config_migration.py +297 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/config_utils.py +63 -156
- flwr-1.26.0/py/flwr/cli/constant.py +115 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/federation/__init__.py +0 -2
- flwr-1.25.0/py/flwr/cli/federation/show.py → flwr-1.26.0/py/flwr/cli/federation/ls.py +135 -121
- flwr-1.26.0/py/flwr/cli/flower_config.py +429 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/install.py +23 -62
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/log.py +23 -37
- flwr-1.26.0/py/flwr/cli/login/login.py +103 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/ls.py +28 -58
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/new/new.py +9 -29
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/pull.py +19 -37
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/run/run.py +85 -93
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/run_utils.py +1 -1
- flwr-1.26.0/py/flwr/cli/stop.py +119 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/supernode/ls.py +25 -57
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/supernode/register.py +31 -80
- flwr-1.26.0/py/flwr/cli/supernode/unregister.py +94 -0
- flwr-1.26.0/py/flwr/cli/typing.py +200 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/utils.py +160 -275
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/grpc_rere_client/connection.py +3 -3
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/grpc_rere_client/grpc_adapter.py +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/message_handler/message_handler.py +2 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/mod/centraldp_mods.py +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/mod/localdp_mod.py +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/run_info_store.py +2 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/clientapp/client_app.py +2 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/__init__.py +3 -2
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/args.py +5 -5
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/config.py +12 -17
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/constant.py +3 -16
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/context.py +2 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/exit/exit.py +4 -4
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/exit/exit_code.py +6 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/grpc.py +2 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/logger.py +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/message.py +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/retry_invoker.py +13 -5
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py +5 -2
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/serde.py +7 -5
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/telemetry.py +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/typing.py +4 -3
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/compat/client/app.py +6 -9
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/compat/client/grpc_client/connection.py +2 -1
- flwr-1.26.0/py/flwr/compat/common/constant.py +29 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/compat/server/app.py +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/clientappio_pb2.py +2 -2
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/clientappio_pb2_grpc.py +104 -88
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/clientappio_pb2_grpc.pyi +140 -80
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/federation_pb2.py +5 -3
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/federation_pb2.pyi +32 -2
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/run_pb2.py +5 -13
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/run_pb2.pyi +0 -57
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/serverappio_pb2.py +2 -2
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/serverappio_pb2_grpc.py +138 -207
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/serverappio_pb2_grpc.pyi +189 -155
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/simulationio_pb2.py +2 -2
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/simulationio_pb2_grpc.py +62 -90
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/simulationio_pb2_grpc.pyi +95 -55
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/app.py +6 -13
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/compat/grid_client_proxy.py +2 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/grid/grpc_grid.py +5 -5
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/serverapp/app.py +11 -4
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/grpc_rere/node_auth_server_interceptor.py +13 -12
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/message_handler/message_handler.py +6 -5
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/linkstate/__init__.py +2 -2
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/linkstate/in_memory_linkstate.py +2 -10
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/linkstate/linkstate.py +2 -21
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/linkstate/linkstate_factory.py +16 -8
- flwr-1.25.0/py/flwr/server/superlink/linkstate/sqlite_linkstate.py → flwr-1.26.0/py/flwr/server/superlink/linkstate/sql_linkstate.py +432 -534
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/linkstate/utils.py +49 -2
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/serverappio/serverappio_servicer.py +1 -33
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/simulation/simulationio_servicer.py +0 -19
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/utils/validator.py +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/workflow/default_workflows.py +2 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/bulyan.py +7 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/dp_fixed_clipping.py +9 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/fedavg.py +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/fedxgb_cyclic.py +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/simulation/ray_transport/ray_client_proxy.py +2 -6
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/simulation/run_simulation.py +3 -12
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/simulation/simulationio_connection.py +3 -3
- {flwr-1.25.0/py/flwr/common → flwr-1.26.0/py/flwr/supercore}/address.py +7 -33
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/app_utils.py +2 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/constant.py +24 -2
- flwr-1.25.0/py/flwr/supercore/corestate/sqlite_corestate.py → flwr-1.26.0/py/flwr/supercore/corestate/sql_corestate.py +19 -23
- flwr-1.26.0/py/flwr/supercore/credential_store/__init__.py +33 -0
- flwr-1.26.0/py/flwr/supercore/credential_store/credential_store.py +34 -0
- flwr-1.26.0/py/flwr/supercore/credential_store/file_credential_store.py +76 -0
- {flwr-1.25.0/py/flwr/common → flwr-1.26.0/py/flwr/supercore}/date.py +0 -11
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/ffs/disk_ffs.py +1 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/object_store/object_store_factory.py +14 -6
- flwr-1.25.0/py/flwr/supercore/object_store/sqlite_object_store.py → flwr-1.26.0/py/flwr/supercore/object_store/sql_object_store.py +115 -117
- flwr-1.26.0/py/flwr/supercore/sql_mixin.py +315 -0
- flwr-1.26.0/py/flwr/supercore/state/__init__.py +15 -0
- flwr-1.26.0/py/flwr/supercore/state/alembic/__init__.py +15 -0
- flwr-1.26.0/py/flwr/supercore/state/alembic/env.py +103 -0
- flwr-1.26.0/py/flwr/supercore/state/alembic/script.py.mako +43 -0
- flwr-1.26.0/py/flwr/supercore/state/alembic/utils.py +239 -0
- flwr-1.26.0/py/flwr/supercore/state/alembic/versions/__init__.py +15 -0
- flwr-1.26.0/py/flwr/supercore/state/alembic/versions/rev_2026_01_28_initialize_migration_of_state_tables.py +200 -0
- flwr-1.26.0/py/flwr/supercore/state/schema/README.md +121 -0
- flwr-1.26.0/py/flwr/supercore/state/schema/__init__.py +15 -0
- flwr-1.26.0/py/flwr/supercore/state/schema/corestate_tables.py +36 -0
- flwr-1.26.0/py/flwr/supercore/state/schema/linkstate_tables.py +152 -0
- flwr-1.26.0/py/flwr/supercore/state/schema/objectstore_tables.py +90 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/superexec/run_superexec.py +2 -2
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/utils.py +36 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/federation/federation_manager.py +2 -2
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/federation/noop_federation_manager.py +8 -6
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/servicer/control/control_servicer.py +19 -17
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supernode/cli/flower_supernode.py +2 -1
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supernode/runtime/run_clientapp.py +14 -14
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supernode/servicer/clientappio/clientappio_servicer.py +10 -8
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supernode/start_client_internal.py +10 -6
- {flwr-1.25.0 → flwr-1.26.0}/pyproject.toml +8 -6
- flwr-1.25.0/py/flwr/cli/constant.py +0 -44
- flwr-1.25.0/py/flwr/cli/federation/ls.py +0 -140
- flwr-1.25.0/py/flwr/cli/login/login.py +0 -137
- flwr-1.25.0/py/flwr/cli/stop.py +0 -160
- flwr-1.25.0/py/flwr/cli/supernode/unregister.py +0 -140
- flwr-1.25.0/py/flwr/common/pyproject.py +0 -42
- flwr-1.25.0/py/flwr/supercore/sqlite_mixin.py +0 -159
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/app/error.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/app/exception.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/app_cmd/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/auth_plugin/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/cli_account_auth_interceptor.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/example.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/login/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/new/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/run/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/cli/supernode/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/client.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/dpfedavg_numpy_client.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/grpc_adapter_client/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/grpc_adapter_client/connection.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/grpc_rere_client/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/grpc_rere_client/node_auth_client_interceptor.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/message_handler/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/mod/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/mod/comms_mods.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/mod/secure_aggregation/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/mod/secure_aggregation/secagg_mod.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/mod/utils.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/numpy_client.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/rest_client/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/rest_client/connection.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/client/typing.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/clientapp/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/clientapp/mod/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/clientapp/mod/centraldp_mods.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/clientapp/mod/localdp_mod.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/clientapp/typing.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/clientapp/utils.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/differential_privacy.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/differential_privacy_constants.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/dp.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/event_log_plugin/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/event_log_plugin/event_log_plugin.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/exit/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/exit/exit_handler.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/exit/signal_handler.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/inflatable.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/inflatable_protobuf_utils.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/inflatable_utils.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/object_ref.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/parameter.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/record/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/record/array.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/record/arraychunk.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/record/arrayrecord.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/record/configrecord.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/record/conversion_utils.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/record/metricrecord.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/record/recorddict.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/record/typeddict.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/recorddict_compat.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/secure_aggregation/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/secure_aggregation/crypto/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/secure_aggregation/crypto/shamir.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/secure_aggregation/quantization.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/secure_aggregation/secaggplus_constants.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/secure_aggregation/secaggplus_utils.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/common/serde_utils.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/compat/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/compat/client/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/compat/client/grpc_client/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/compat/common/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/compat/server/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/compat/simulation/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/appio_pb2.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/appio_pb2.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/appio_pb2_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/appio_pb2_grpc.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/clientappio_pb2.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/control_pb2.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/control_pb2.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/control_pb2_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/control_pb2_grpc.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/error_pb2.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/error_pb2.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/error_pb2_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/error_pb2_grpc.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/fab_pb2.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/fab_pb2.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/fab_pb2_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/fab_pb2_grpc.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/federation_pb2_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/federation_pb2_grpc.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/fleet_pb2.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/fleet_pb2.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/fleet_pb2_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/fleet_pb2_grpc.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/grpcadapter_pb2.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/grpcadapter_pb2.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/grpcadapter_pb2_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/grpcadapter_pb2_grpc.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/heartbeat_pb2.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/heartbeat_pb2.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/heartbeat_pb2_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/heartbeat_pb2_grpc.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/log_pb2.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/log_pb2.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/log_pb2_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/log_pb2_grpc.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/message_pb2.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/message_pb2.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/message_pb2_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/message_pb2_grpc.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/node_pb2.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/node_pb2.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/node_pb2_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/node_pb2_grpc.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/recorddict_pb2.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/recorddict_pb2.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/recorddict_pb2_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/recorddict_pb2_grpc.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/run_pb2_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/run_pb2_grpc.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/serverappio_pb2.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/simulationio_pb2.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/transport_pb2.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/transport_pb2.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/transport_pb2_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/proto/transport_pb2_grpc.pyi +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/py.typed +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/client_manager.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/client_proxy.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/compat/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/compat/app.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/compat/app_utils.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/compat/legacy_context.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/criterion.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/fleet_event_log_interceptor.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/grid/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/grid/grid.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/grid/inmemory_grid.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/history.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/run_serverapp.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/server.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/server_app.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/server_config.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/serverapp/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/serverapp_components.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/aggregate.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/bulyan.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/dp_adaptive_clipping.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/dp_fixed_clipping.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/dpfedavg_adaptive.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/dpfedavg_fixed.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/fault_tolerant_fedavg.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/fedadagrad.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/fedadam.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/fedavg.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/fedavg_android.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/fedavgm.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/fedmedian.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/fedopt.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/fedprox.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/fedtrimmedavg.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/fedxgb_bagging.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/fedxgb_cyclic.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/fedxgb_nn_avg.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/fedyogi.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/krum.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/qfedavg.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/strategy/strategy.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/grpc_adapter/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/grpc_rere/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/message_handler/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/rest_rere/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/rest_rere/rest_api.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/vce/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/vce/backend/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/vce/backend/backend.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/vce/backend/raybackend.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/fleet/vce/vce_api.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/serverappio/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/serverappio/serverappio_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/simulation/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/simulation/simulationio_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/superlink/utils.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/typing.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/utils/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/utils/tensorboard.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/workflow/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/workflow/constant.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/workflow/secure_aggregation/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/server/workflow/secure_aggregation/secagg_workflow.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/exception.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/dp_adaptive_clipping.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/fedadagrad.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/fedadam.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/fedavgm.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/fedmedian.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/fedopt.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/fedprox.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/fedtrimmedavg.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/fedxgb_bagging.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/fedyogi.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/krum.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/multikrum.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/qfedavg.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/result.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/strategy.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/serverapp/strategy/strategy_utils.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/simulation/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/simulation/app.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/simulation/legacy_app.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/simulation/ray_transport/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/simulation/ray_transport/ray_actor.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/simulation/ray_transport/utils.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/cli/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/cli/flower_superexec.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/corestate/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/corestate/corestate.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/corestate/in_memory_corestate.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/ffs/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/ffs/ffs.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/ffs/ffs_factory.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/grpc_health/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/grpc_health/health_server.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/grpc_health/simple_health_servicer.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/heartbeat.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/license_plugin/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/license_plugin/license_plugin.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/object_store/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/object_store/in_memory_object_store.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/object_store/object_store.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/primitives/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/primitives/asymmetric.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/primitives/asymmetric_ed25519.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/superexec/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/superexec/plugin/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/superexec/plugin/base_exec_plugin.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/superexec/plugin/clientapp_exec_plugin.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/superexec/plugin/exec_plugin.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/superexec/plugin/serverapp_exec_plugin.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supercore/superexec/plugin/simulation_exec_plugin.py +0 -0
- {flwr-1.25.0/py/flwr/common → flwr-1.26.0/py/flwr/supercore}/version.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/artifact_provider/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/artifact_provider/artifact_provider.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/auth_plugin/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/auth_plugin/auth_plugin.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/auth_plugin/noop_auth_plugin.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/federation/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/servicer/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/servicer/control/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/servicer/control/control_account_auth_interceptor.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/servicer/control/control_event_log_interceptor.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/servicer/control/control_grpc.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/superlink/servicer/control/control_license_interceptor.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supernode/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supernode/cli/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supernode/cli/flwr_clientapp.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supernode/nodestate/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supernode/nodestate/in_memory_nodestate.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supernode/nodestate/nodestate.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supernode/nodestate/nodestate_factory.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supernode/runtime/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supernode/servicer/__init__.py +0 -0
- {flwr-1.25.0 → flwr-1.26.0}/py/flwr/supernode/servicer/clientappio/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: flwr
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.26.0
|
|
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
|
|
@@ -30,7 +30,9 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
30
30
|
Classifier: Typing :: Typed
|
|
31
31
|
Provides-Extra: rest
|
|
32
32
|
Provides-Extra: simulation
|
|
33
|
-
Requires-Dist:
|
|
33
|
+
Requires-Dist: SQLAlchemy (>=2.0.45,<3.0.0)
|
|
34
|
+
Requires-Dist: alembic (>=1.18.1,<2.0.0)
|
|
35
|
+
Requires-Dist: click (>=8.0.0,<9.0.0)
|
|
34
36
|
Requires-Dist: cryptography (>=44.0.1,<45.0.0)
|
|
35
37
|
Requires-Dist: grpcio (>=1.70.0,<2.0.0)
|
|
36
38
|
Requires-Dist: grpcio-health-checking (>=1.70.0,<2.0.0)
|
|
@@ -44,11 +46,11 @@ Requires-Dist: ray (==2.51.1) ; (python_version >= "3.10" and python_version < "
|
|
|
44
46
|
Requires-Dist: ray (==2.51.1) ; (sys_platform != "win32" and python_version == "3.13") and (extra == "simulation")
|
|
45
47
|
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
|
46
48
|
Requires-Dist: rich (>=13.5.0,<14.0.0)
|
|
47
|
-
Requires-Dist: starlette (>=0.
|
|
49
|
+
Requires-Dist: starlette (>=0.50.0,<0.51.0) ; extra == "rest"
|
|
48
50
|
Requires-Dist: tomli (>=2.0.1,<3.0.0)
|
|
49
51
|
Requires-Dist: tomli-w (>=1.0.0,<2.0.0)
|
|
50
52
|
Requires-Dist: typer (>=0.12.5,<0.21.0)
|
|
51
|
-
Requires-Dist: uvicorn[standard] (>=0.
|
|
53
|
+
Requires-Dist: uvicorn[standard] (>=0.40.0,<0.41.0) ; extra == "rest"
|
|
52
54
|
Project-URL: Documentation, https://flower.ai
|
|
53
55
|
Project-URL: Homepage, https://flower.ai
|
|
54
56
|
Project-URL: Repository, https://github.com/adap/flower
|
|
@@ -65,7 +67,7 @@ Description-Content-Type: text/markdown
|
|
|
65
67
|
<a href="https://flower.ai/">Website</a> |
|
|
66
68
|
<a href="https://flower.ai/blog">Blog</a> |
|
|
67
69
|
<a href="https://flower.ai/docs/">Docs</a> |
|
|
68
|
-
<a href="https://flower.ai/events/flower-ai-summit-
|
|
70
|
+
<a href="https://flower.ai/events/flower-ai-summit-2026">Summit</a> |
|
|
69
71
|
<a href="https://flower.ai/join-slack">Slack</a>
|
|
70
72
|
<br /><br />
|
|
71
73
|
</p>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<a href="https://flower.ai/">Website</a> |
|
|
10
10
|
<a href="https://flower.ai/blog">Blog</a> |
|
|
11
11
|
<a href="https://flower.ai/docs/">Docs</a> |
|
|
12
|
-
<a href="https://flower.ai/events/flower-ai-summit-
|
|
12
|
+
<a href="https://flower.ai/events/flower-ai-summit-2026">Summit</a> |
|
|
13
13
|
<a href="https://flower.ai/join-slack">Slack</a>
|
|
14
14
|
<br /><br />
|
|
15
15
|
</p>
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
"""Public Flower App APIs."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from flwr.common.constant import MessageType
|
|
19
18
|
from flwr.common.context import Context
|
|
20
19
|
from flwr.common.message import Message
|
|
21
20
|
from flwr.common.record import (
|
|
@@ -27,7 +26,9 @@ from flwr.common.record import (
|
|
|
27
26
|
)
|
|
28
27
|
|
|
29
28
|
from .error import Error
|
|
29
|
+
from .message_type import MessageType
|
|
30
30
|
from .metadata import Metadata
|
|
31
|
+
from .user_config import UserConfig, UserConfigValue
|
|
31
32
|
|
|
32
33
|
__all__ = [
|
|
33
34
|
"Array",
|
|
@@ -40,4 +41,6 @@ __all__ = [
|
|
|
40
41
|
"Metadata",
|
|
41
42
|
"MetricRecord",
|
|
42
43
|
"RecordDict",
|
|
44
|
+
"UserConfig",
|
|
45
|
+
"UserConfigValue",
|
|
43
46
|
]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Copyright 2026 Flower Labs GmbH. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
# ==============================================================================
|
|
15
|
+
"""MessageType constants."""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MessageType:
|
|
21
|
+
"""Message type."""
|
|
22
|
+
|
|
23
|
+
TRAIN = "train"
|
|
24
|
+
EVALUATE = "evaluate"
|
|
25
|
+
QUERY = "query"
|
|
26
|
+
|
|
27
|
+
def __new__(cls) -> MessageType:
|
|
28
|
+
"""Prevent instantiation."""
|
|
29
|
+
raise TypeError(f"{cls.__name__} cannot be instantiated.")
|
|
@@ -19,7 +19,10 @@ from __future__ import annotations
|
|
|
19
19
|
|
|
20
20
|
from typing import cast
|
|
21
21
|
|
|
22
|
-
from
|
|
22
|
+
from flwr.app.message_type import MessageType
|
|
23
|
+
from flwr.supercore.constant import SYSTEM_MESSAGE_TYPE
|
|
24
|
+
|
|
25
|
+
from ..common.constant import MessageTypeLegacy
|
|
23
26
|
|
|
24
27
|
|
|
25
28
|
class Metadata: # pylint: disable=too-many-instance-attributes
|
|
@@ -194,7 +197,7 @@ def validate_message_type(message_type: str) -> bool:
|
|
|
194
197
|
MessageType.TRAIN,
|
|
195
198
|
MessageType.EVALUATE,
|
|
196
199
|
MessageType.QUERY,
|
|
197
|
-
|
|
200
|
+
SYSTEM_MESSAGE_TYPE,
|
|
198
201
|
}
|
|
199
202
|
if message_type in valid_types:
|
|
200
203
|
return True
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Copyright 2026 Flower Labs GmbH. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
# ==============================================================================
|
|
15
|
+
"""UserConfig type definition."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
UserConfigValue = bool | float | int | str
|
|
19
|
+
UserConfig = dict[str, UserConfigValue]
|
|
@@ -14,16 +14,19 @@
|
|
|
14
14
|
# ==============================================================================
|
|
15
15
|
"""Flower command line interface."""
|
|
16
16
|
|
|
17
|
+
|
|
18
|
+
from typing import Any, TypedDict
|
|
19
|
+
|
|
17
20
|
import typer
|
|
18
21
|
from typer.main import get_command
|
|
19
22
|
|
|
20
|
-
from flwr.
|
|
23
|
+
from flwr.supercore.version import package_version
|
|
21
24
|
|
|
22
25
|
from .app_cmd import publish as app_publish
|
|
23
26
|
from .app_cmd import review as app_review
|
|
24
27
|
from .build import build
|
|
28
|
+
from .config import ls as config_list
|
|
25
29
|
from .federation import ls as federation_list
|
|
26
|
-
from .federation import show as federation_show
|
|
27
30
|
from .install import install
|
|
28
31
|
from .log import log
|
|
29
32
|
from .login import login
|
|
@@ -36,6 +39,15 @@ from .supernode import ls as supernode_list
|
|
|
36
39
|
from .supernode import register as supernode_register
|
|
37
40
|
from .supernode import unregister as supernode_unregister
|
|
38
41
|
|
|
42
|
+
|
|
43
|
+
class CommandKwargs(TypedDict):
|
|
44
|
+
"""Keywords for typer command to make mypy happy."""
|
|
45
|
+
|
|
46
|
+
context_settings: dict[str, Any]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
ALLOW_EXTRAS: CommandKwargs = {"context_settings": {"allow_extra_args": True}}
|
|
50
|
+
|
|
39
51
|
app = typer.Typer(
|
|
40
52
|
help=typer.style(
|
|
41
53
|
"flwr is the Flower command line interface.",
|
|
@@ -50,21 +62,21 @@ app.command()(new)
|
|
|
50
62
|
app.command()(run)
|
|
51
63
|
app.command()(build)
|
|
52
64
|
app.command()(install)
|
|
53
|
-
app.command()(log)
|
|
54
|
-
app.command("list")(ls)
|
|
55
|
-
app.command(hidden=True)(ls)
|
|
56
|
-
app.command()(stop)
|
|
57
|
-
app.command()(login)
|
|
58
|
-
app.command()(pull)
|
|
65
|
+
app.command(**ALLOW_EXTRAS)(log)
|
|
66
|
+
app.command("list", **ALLOW_EXTRAS)(ls)
|
|
67
|
+
app.command(hidden=True, **ALLOW_EXTRAS)(ls)
|
|
68
|
+
app.command(**ALLOW_EXTRAS)(stop)
|
|
69
|
+
app.command(**ALLOW_EXTRAS)(login)
|
|
70
|
+
app.command(**ALLOW_EXTRAS)(pull)
|
|
59
71
|
|
|
60
72
|
# Create supernode command group
|
|
61
73
|
supernode_app = typer.Typer(help="Manage SuperNodes")
|
|
62
|
-
supernode_app.command()(supernode_register)
|
|
63
|
-
supernode_app.command()(supernode_unregister)
|
|
74
|
+
supernode_app.command(**ALLOW_EXTRAS)(supernode_register)
|
|
75
|
+
supernode_app.command(**ALLOW_EXTRAS)(supernode_unregister)
|
|
64
76
|
# Make it appear as "list"
|
|
65
|
-
supernode_app.command("list")(supernode_list)
|
|
77
|
+
supernode_app.command("list", **ALLOW_EXTRAS)(supernode_list)
|
|
66
78
|
# Hide "ls" command (left as alias)
|
|
67
|
-
supernode_app.command(hidden=True)(supernode_list)
|
|
79
|
+
supernode_app.command(hidden=True, **ALLOW_EXTRAS)(supernode_list)
|
|
68
80
|
app.add_typer(supernode_app, name="supernode")
|
|
69
81
|
|
|
70
82
|
# Create app command group
|
|
@@ -76,18 +88,24 @@ app.add_typer(app_app, name="app")
|
|
|
76
88
|
# Create federation command group
|
|
77
89
|
federation_app = typer.Typer(help="Manage Federations")
|
|
78
90
|
# Make it appear as "list"
|
|
79
|
-
federation_app.command("list")(federation_list)
|
|
91
|
+
federation_app.command("list", **ALLOW_EXTRAS)(federation_list)
|
|
80
92
|
# Hide "ls" command (left as alias)
|
|
81
|
-
federation_app.command(hidden=True)(federation_list)
|
|
93
|
+
federation_app.command(hidden=True, **ALLOW_EXTRAS)(federation_list)
|
|
82
94
|
app.add_typer(federation_app, name="federation")
|
|
83
|
-
|
|
95
|
+
|
|
96
|
+
# Create config command group
|
|
97
|
+
config_app = typer.Typer(help="Manage Configuration")
|
|
98
|
+
config_app.command("list")(config_list)
|
|
99
|
+
# Hide "ls" command (left as alias)
|
|
100
|
+
config_app.command(hidden=True)(config_list)
|
|
101
|
+
app.add_typer(config_app, name="config")
|
|
84
102
|
|
|
85
103
|
typer_click_object = get_command(app)
|
|
86
104
|
|
|
87
105
|
|
|
88
106
|
@app.callback(invoke_without_command=True)
|
|
89
|
-
def
|
|
90
|
-
|
|
107
|
+
def main(
|
|
108
|
+
version: bool = typer.Option(
|
|
91
109
|
None,
|
|
92
110
|
"-V",
|
|
93
111
|
"--version",
|
|
@@ -95,8 +113,8 @@ def version_callback(
|
|
|
95
113
|
help="Show the version and exit.",
|
|
96
114
|
),
|
|
97
115
|
) -> None:
|
|
98
|
-
"""
|
|
99
|
-
if
|
|
116
|
+
"""Flower CLI."""
|
|
117
|
+
if version:
|
|
100
118
|
typer.secho(f"Flower version: {package_version}", fg="blue")
|
|
101
119
|
raise typer.Exit()
|
|
102
120
|
|
|
@@ -19,12 +19,11 @@ from contextlib import ExitStack
|
|
|
19
19
|
from pathlib import Path
|
|
20
20
|
from typing import IO, Annotated
|
|
21
21
|
|
|
22
|
+
import click
|
|
22
23
|
import requests
|
|
23
24
|
import typer
|
|
24
25
|
from requests import Response
|
|
25
26
|
|
|
26
|
-
from flwr.common.constant import FAB_CONFIG_FILE
|
|
27
|
-
from flwr.common.version import package_version as flwr_version
|
|
28
27
|
from flwr.supercore.constant import (
|
|
29
28
|
APP_PUBLISH_EXCLUDE_PATTERNS,
|
|
30
29
|
APP_PUBLISH_INCLUDE_PATTERNS,
|
|
@@ -34,17 +33,17 @@ from flwr.supercore.constant import (
|
|
|
34
33
|
MAX_TOTAL_BYTES,
|
|
35
34
|
MIME_MAP,
|
|
36
35
|
PLATFORM_API_URL,
|
|
36
|
+
SUPERGRID_ADDRESS,
|
|
37
37
|
UTF8,
|
|
38
38
|
)
|
|
39
|
+
from flwr.supercore.version import package_version as flwr_version
|
|
39
40
|
|
|
40
41
|
from ..auth_plugin.oidc_cli_plugin import OidcCliPlugin
|
|
41
|
-
from ..
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
from ..utils import (
|
|
43
|
+
build_pathspec,
|
|
44
|
+
load_cli_auth_plugin_from_connection,
|
|
45
|
+
load_gitignore_patterns,
|
|
45
46
|
)
|
|
46
|
-
from ..constant import FEDERATION_CONFIG_HELP_MESSAGE
|
|
47
|
-
from ..utils import build_pathspec, load_cli_auth_plugin, load_gitignore_patterns
|
|
48
47
|
|
|
49
48
|
|
|
50
49
|
# pylint: disable=too-many-locals
|
|
@@ -55,43 +54,16 @@ def publish(
|
|
|
55
54
|
help="Project directory to upload (defaults to current directory)."
|
|
56
55
|
),
|
|
57
56
|
] = Path("."),
|
|
58
|
-
federation: Annotated[
|
|
59
|
-
str | None,
|
|
60
|
-
typer.Argument(
|
|
61
|
-
help="Name of the federation used for login before publishing app."
|
|
62
|
-
),
|
|
63
|
-
] = None,
|
|
64
|
-
federation_config_overrides: Annotated[
|
|
65
|
-
list[str] | None,
|
|
66
|
-
typer.Option(
|
|
67
|
-
"--federation-config",
|
|
68
|
-
help=FEDERATION_CONFIG_HELP_MESSAGE,
|
|
69
|
-
),
|
|
70
|
-
] = None,
|
|
71
57
|
) -> None:
|
|
72
58
|
"""Publish a Flower App to the Flower Platform.
|
|
73
59
|
|
|
74
60
|
This command uploads your app project to the Flower Platform. Files are filtered
|
|
75
61
|
based on .gitignore patterns and allowed file extensions.
|
|
76
62
|
"""
|
|
77
|
-
|
|
78
|
-
pyproject_path = app / FAB_CONFIG_FILE if app else None
|
|
79
|
-
config, errors, warnings = load_and_validate(pyproject_path, check_module=False)
|
|
80
|
-
config = process_loaded_project_config(config, errors, warnings)
|
|
81
|
-
federation, federation_config = validate_federation_in_project_config(
|
|
82
|
-
federation, config, federation_config_overrides
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
# Load the authentication plugin
|
|
86
|
-
auth_plugin = load_cli_auth_plugin(app, federation, federation_config)
|
|
63
|
+
auth_plugin = load_cli_auth_plugin_from_connection(SUPERGRID_ADDRESS)
|
|
87
64
|
auth_plugin.load_tokens()
|
|
88
65
|
if not isinstance(auth_plugin, OidcCliPlugin) or not auth_plugin.access_token:
|
|
89
|
-
|
|
90
|
-
"❌ Please log in before publishing app.",
|
|
91
|
-
fg=typer.colors.RED,
|
|
92
|
-
err=True,
|
|
93
|
-
)
|
|
94
|
-
raise typer.Exit(code=1)
|
|
66
|
+
raise click.ClickException("Please log in before publishing app.")
|
|
95
67
|
|
|
96
68
|
# Load token from the plugin
|
|
97
69
|
token = auth_plugin.access_token
|
|
@@ -106,19 +78,17 @@ def publish(
|
|
|
106
78
|
try:
|
|
107
79
|
resp = _post_files(files_param, token)
|
|
108
80
|
except requests.RequestException as err:
|
|
109
|
-
|
|
110
|
-
raise typer.Exit(code=1) from err
|
|
81
|
+
raise click.ClickException(f"Network error: {err}") from err
|
|
111
82
|
|
|
112
83
|
if resp.ok:
|
|
113
84
|
typer.secho("🎊 Upload successful", fg=typer.colors.GREEN, bold=True)
|
|
114
85
|
return # success
|
|
115
86
|
|
|
116
87
|
# Error path:
|
|
117
|
-
msg = f"
|
|
88
|
+
msg = f"Upload failed with status {resp.status_code}"
|
|
118
89
|
if resp.text:
|
|
119
90
|
msg += f": {resp.text}"
|
|
120
|
-
|
|
121
|
-
raise typer.Exit(code=1)
|
|
91
|
+
raise click.ClickException(msg)
|
|
122
92
|
|
|
123
93
|
|
|
124
94
|
def _depth_of(relative_path_to_root: Path) -> int:
|
|
@@ -162,14 +132,9 @@ def _collect_file_paths(root: Path) -> list[Path]:
|
|
|
162
132
|
|
|
163
133
|
# Check max depth
|
|
164
134
|
if _depth_of(relative_path) > MAX_DIR_DEPTH:
|
|
165
|
-
|
|
166
|
-
f"
|
|
167
|
-
f"exceeds the maximum directory depth "
|
|
168
|
-
f"of {MAX_DIR_DEPTH}.",
|
|
169
|
-
fg=typer.colors.RED,
|
|
170
|
-
err=True,
|
|
135
|
+
raise click.ClickException(
|
|
136
|
+
f"'{path}' exceeds the maximum directory depth of {MAX_DIR_DEPTH}."
|
|
171
137
|
)
|
|
172
|
-
raise typer.Exit(code=2)
|
|
173
138
|
|
|
174
139
|
file_paths.append(path)
|
|
175
140
|
|
|
@@ -184,21 +149,15 @@ def _validate_files(file_paths: list[Path]) -> None:
|
|
|
184
149
|
Checks file count, individual file size, total size, and UTF-8 encoding.
|
|
185
150
|
"""
|
|
186
151
|
if len(file_paths) == 0:
|
|
187
|
-
|
|
152
|
+
raise click.ClickException(
|
|
188
153
|
"Nothing to upload: no files matched after applying .gitignore and "
|
|
189
|
-
"allowed extensions."
|
|
190
|
-
fg=typer.colors.RED,
|
|
191
|
-
err=True,
|
|
154
|
+
"allowed extensions."
|
|
192
155
|
)
|
|
193
|
-
raise typer.Exit(code=2)
|
|
194
156
|
|
|
195
157
|
if len(file_paths) > MAX_FILE_COUNT:
|
|
196
|
-
|
|
197
|
-
f"Too many files: {len(file_paths)} > allowed maximum of {MAX_FILE_COUNT}."
|
|
198
|
-
fg=typer.colors.RED,
|
|
199
|
-
err=True,
|
|
158
|
+
raise click.ClickException(
|
|
159
|
+
f"Too many files: {len(file_paths)} > allowed maximum of {MAX_FILE_COUNT}."
|
|
200
160
|
)
|
|
201
|
-
raise typer.Exit(code=2)
|
|
202
161
|
|
|
203
162
|
# Calculate files size
|
|
204
163
|
total_size = 0
|
|
@@ -208,34 +167,25 @@ def _validate_files(file_paths: list[Path]) -> None:
|
|
|
208
167
|
|
|
209
168
|
# Check single file size
|
|
210
169
|
if file_size > MAX_FILE_BYTES:
|
|
211
|
-
|
|
170
|
+
raise click.ClickException(
|
|
212
171
|
f"File too large: '{path.as_posix()}' is {file_size:,} bytes, "
|
|
213
|
-
f"exceeding the per-file limit of {MAX_FILE_BYTES:,} bytes."
|
|
214
|
-
fg=typer.colors.RED,
|
|
215
|
-
err=True,
|
|
172
|
+
f"exceeding the per-file limit of {MAX_FILE_BYTES:,} bytes."
|
|
216
173
|
)
|
|
217
|
-
raise typer.Exit(code=2)
|
|
218
174
|
|
|
219
175
|
# Ensure we can decode as UTF-8.
|
|
220
176
|
try:
|
|
221
177
|
path.read_text(encoding=UTF8)
|
|
222
178
|
except UnicodeDecodeError as err:
|
|
223
|
-
|
|
224
|
-
f"Encoding error: '{path}' is not UTF-8 encoded."
|
|
225
|
-
|
|
226
|
-
err=True,
|
|
227
|
-
)
|
|
228
|
-
raise typer.Exit(code=2) from err
|
|
179
|
+
raise click.ClickException(
|
|
180
|
+
f"Encoding error: '{path}' is not UTF-8 encoded."
|
|
181
|
+
) from err
|
|
229
182
|
|
|
230
183
|
# Check total files size
|
|
231
184
|
if total_size > MAX_TOTAL_BYTES:
|
|
232
|
-
|
|
185
|
+
raise click.ClickException(
|
|
233
186
|
"Total size of all files is too large: "
|
|
234
|
-
f"{total_size:,} bytes > {MAX_TOTAL_BYTES:,} bytes."
|
|
235
|
-
fg=typer.colors.RED,
|
|
236
|
-
err=True,
|
|
187
|
+
f"{total_size:,} bytes > {MAX_TOTAL_BYTES:,} bytes."
|
|
237
188
|
)
|
|
238
|
-
raise typer.Exit(code=2)
|
|
239
189
|
|
|
240
190
|
# Print validation passed prompt
|
|
241
191
|
typer.echo(typer.style("✅ Validation passed", fg=typer.colors.GREEN, bold=True))
|
|
@@ -21,6 +21,7 @@ import re
|
|
|
21
21
|
from pathlib import Path
|
|
22
22
|
from typing import Annotated
|
|
23
23
|
|
|
24
|
+
import click
|
|
24
25
|
import requests
|
|
25
26
|
import typer
|
|
26
27
|
from cryptography.exceptions import UnsupportedAlgorithm
|
|
@@ -28,25 +29,18 @@ from cryptography.hazmat.primitives.asymmetric import ed25519
|
|
|
28
29
|
|
|
29
30
|
from flwr.common import now
|
|
30
31
|
from flwr.common.config import get_flwr_dir
|
|
31
|
-
from flwr.
|
|
32
|
-
from flwr.common.version import package_version as flwr_version
|
|
33
|
-
from flwr.supercore.constant import PLATFORM_API_URL
|
|
32
|
+
from flwr.supercore.constant import PLATFORM_API_URL, SUPERGRID_ADDRESS
|
|
34
33
|
from flwr.supercore.primitives.asymmetric_ed25519 import (
|
|
35
34
|
create_message_to_sign,
|
|
36
35
|
load_private_key,
|
|
37
36
|
sign_message,
|
|
38
37
|
)
|
|
39
38
|
from flwr.supercore.utils import parse_app_spec, request_download_link
|
|
39
|
+
from flwr.supercore.version import package_version as flwr_version
|
|
40
40
|
|
|
41
41
|
from ..auth_plugin.oidc_cli_plugin import OidcCliPlugin
|
|
42
|
-
from ..config_utils import (
|
|
43
|
-
load_and_validate,
|
|
44
|
-
process_loaded_project_config,
|
|
45
|
-
validate_federation_in_project_config,
|
|
46
|
-
)
|
|
47
|
-
from ..constant import FEDERATION_CONFIG_HELP_MESSAGE
|
|
48
42
|
from ..install import install_from_fab
|
|
49
|
-
from ..utils import
|
|
43
|
+
from ..utils import load_cli_auth_plugin_from_connection
|
|
50
44
|
|
|
51
45
|
TRY_AGAIN_MESSAGE = "Please try again or press CTRL+C to abort.\n"
|
|
52
46
|
|
|
@@ -60,46 +54,14 @@ def review(
|
|
|
60
54
|
"Version is optional; defaults to the latest."
|
|
61
55
|
),
|
|
62
56
|
],
|
|
63
|
-
app_dir_login: Annotated[
|
|
64
|
-
Path,
|
|
65
|
-
typer.Argument(
|
|
66
|
-
help="Project directory to used for login before reviewing app."
|
|
67
|
-
),
|
|
68
|
-
] = Path("."),
|
|
69
|
-
federation: Annotated[
|
|
70
|
-
str | None,
|
|
71
|
-
typer.Argument(
|
|
72
|
-
help="Name of the federation used for login before reviewing app."
|
|
73
|
-
),
|
|
74
|
-
] = None,
|
|
75
|
-
federation_config_overrides: Annotated[
|
|
76
|
-
list[str] | None,
|
|
77
|
-
typer.Option(
|
|
78
|
-
"--federation-config",
|
|
79
|
-
help=FEDERATION_CONFIG_HELP_MESSAGE,
|
|
80
|
-
),
|
|
81
|
-
] = None,
|
|
82
57
|
) -> None:
|
|
83
58
|
"""Download a FAB for <APP-ID>, unpack it for manual review, and upon confirmation
|
|
84
59
|
sign & submit the review to the Platform."""
|
|
85
|
-
|
|
86
|
-
pyproject_path = app_dir_login / FAB_CONFIG_FILE if app_dir_login else None
|
|
87
|
-
config, errors, warnings = load_and_validate(pyproject_path, check_module=False)
|
|
88
|
-
config = process_loaded_project_config(config, errors, warnings)
|
|
89
|
-
federation, federation_config = validate_federation_in_project_config(
|
|
90
|
-
federation, config, federation_config_overrides
|
|
91
|
-
)
|
|
60
|
+
auth_plugin = load_cli_auth_plugin_from_connection(SUPERGRID_ADDRESS)
|
|
92
61
|
|
|
93
|
-
# Load the authentication plugin
|
|
94
|
-
auth_plugin = load_cli_auth_plugin(app_dir_login, federation, federation_config)
|
|
95
62
|
auth_plugin.load_tokens()
|
|
96
63
|
if not isinstance(auth_plugin, OidcCliPlugin) or not auth_plugin.access_token:
|
|
97
|
-
|
|
98
|
-
"❌ Please log in before reviewing app.",
|
|
99
|
-
fg=typer.colors.RED,
|
|
100
|
-
err=True,
|
|
101
|
-
)
|
|
102
|
-
raise typer.Exit(code=1)
|
|
64
|
+
raise click.ClickException("Please log in before reviewing app.")
|
|
103
65
|
|
|
104
66
|
# Load token from the plugin
|
|
105
67
|
token = auth_plugin.access_token
|
|
@@ -108,24 +70,22 @@ def review(
|
|
|
108
70
|
try:
|
|
109
71
|
app_id, app_version = parse_app_spec(app_spec)
|
|
110
72
|
except ValueError as e:
|
|
111
|
-
|
|
112
|
-
raise typer.Exit(code=1) from e
|
|
73
|
+
raise click.ClickException(str(e)) from e
|
|
113
74
|
|
|
114
75
|
# Download FAB
|
|
115
76
|
typer.secho("Downloading FAB... ", fg=typer.colors.BLUE)
|
|
116
77
|
url = f"{PLATFORM_API_URL}/hub/fetch-fab"
|
|
117
78
|
try:
|
|
118
79
|
presigned_url, _ = request_download_link(app_id, app_version, url, "fab_url")
|
|
119
|
-
except ValueError as e:
|
|
120
|
-
typer.secho(f"❌ {e}", fg=typer.colors.RED, err=True)
|
|
121
|
-
raise typer.Exit(code=1) from e
|
|
122
80
|
|
|
123
|
-
|
|
81
|
+
fab_bytes = _download_fab(presigned_url)
|
|
124
82
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
83
|
+
# Unpack FAB
|
|
84
|
+
typer.secho("Unpacking FAB... ", fg=typer.colors.BLUE)
|
|
85
|
+
review_dir = _create_review_dir()
|
|
86
|
+
review_app_path = install_from_fab(fab_bytes, review_dir)
|
|
87
|
+
except ValueError as e:
|
|
88
|
+
raise click.ClickException(str(e)) from e
|
|
129
89
|
|
|
130
90
|
# Extract app version
|
|
131
91
|
version_pattern = re.compile(r"\b(\d+\.\d+\.\d+)\b")
|
|
@@ -204,12 +164,7 @@ def _download_fab(url: str) -> bytes:
|
|
|
204
164
|
r = requests.get(url, timeout=60)
|
|
205
165
|
r.raise_for_status()
|
|
206
166
|
except requests.RequestException as e:
|
|
207
|
-
|
|
208
|
-
f"❌ FAB download failed: {e}",
|
|
209
|
-
fg=typer.colors.RED,
|
|
210
|
-
err=True,
|
|
211
|
-
)
|
|
212
|
-
raise typer.Exit(code=1) from e
|
|
167
|
+
raise click.ClickException(f"FAB download failed: {e}") from e
|
|
213
168
|
return r.content
|
|
214
169
|
|
|
215
170
|
|
|
@@ -243,20 +198,14 @@ def _submit_review(
|
|
|
243
198
|
try:
|
|
244
199
|
resp = requests.post(url, headers=headers, json=payload, timeout=120)
|
|
245
200
|
except requests.RequestException as e:
|
|
246
|
-
|
|
247
|
-
f"❌ Network error while submitting review: {e}",
|
|
248
|
-
fg=typer.colors.RED,
|
|
249
|
-
err=True,
|
|
250
|
-
)
|
|
251
|
-
raise typer.Exit(code=1) from e
|
|
201
|
+
raise click.ClickException(f"Network error while submitting review: {e}") from e
|
|
252
202
|
|
|
253
203
|
if resp.ok:
|
|
254
204
|
typer.secho("🎊 Review submitted", fg=typer.colors.GREEN, bold=True)
|
|
255
205
|
return
|
|
256
206
|
|
|
257
207
|
# Error path:
|
|
258
|
-
msg = f"
|
|
208
|
+
msg = f"Review submission failed (HTTP {resp.status_code})"
|
|
259
209
|
if resp.text:
|
|
260
210
|
msg += f": {resp.text}"
|
|
261
|
-
|
|
262
|
-
raise typer.Exit(code=1)
|
|
211
|
+
raise click.ClickException(msg)
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
|
|
18
18
|
from abc import ABC, abstractmethod
|
|
19
19
|
from collections.abc import Sequence
|
|
20
|
-
from pathlib import Path
|
|
21
20
|
|
|
22
21
|
from flwr.common.typing import AccountAuthCredentials, AccountAuthLoginDetails
|
|
23
22
|
from flwr.proto.control_pb2_grpc import ControlStub
|
|
@@ -35,8 +34,8 @@ class CliAuthPlugin(ABC):
|
|
|
35
34
|
|
|
36
35
|
Parameters
|
|
37
36
|
----------
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
host : str
|
|
38
|
+
The address of the SuperLink Control API server.
|
|
40
39
|
"""
|
|
41
40
|
|
|
42
41
|
@staticmethod
|
|
@@ -66,20 +65,16 @@ class CliAuthPlugin(ABC):
|
|
|
66
65
|
"""
|
|
67
66
|
|
|
68
67
|
@abstractmethod
|
|
69
|
-
def __init__(self,
|
|
68
|
+
def __init__(self, host: str):
|
|
70
69
|
"""Abstract constructor."""
|
|
71
70
|
|
|
72
71
|
@abstractmethod
|
|
73
72
|
def store_tokens(self, credentials: AccountAuthCredentials) -> None:
|
|
74
|
-
"""Store authentication tokens to the
|
|
75
|
-
|
|
76
|
-
The credentials, including tokens, will be saved as a JSON file
|
|
77
|
-
at `credentials_path`.
|
|
78
|
-
"""
|
|
73
|
+
"""Store authentication tokens to the credential store."""
|
|
79
74
|
|
|
80
75
|
@abstractmethod
|
|
81
76
|
def load_tokens(self) -> None:
|
|
82
|
-
"""Load authentication tokens from the
|
|
77
|
+
"""Load authentication tokens from the credential store."""
|
|
83
78
|
|
|
84
79
|
@abstractmethod
|
|
85
80
|
def write_tokens_to_metadata(
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
from collections.abc import Sequence
|
|
19
|
-
from pathlib import Path
|
|
20
19
|
|
|
21
20
|
from flwr.common.typing import AccountAuthCredentials, AccountAuthLoginDetails
|
|
22
21
|
from flwr.proto.control_pb2_grpc import ControlStub
|
|
@@ -57,7 +56,7 @@ class NoOpCliAuthPlugin(CliAuthPlugin):
|
|
|
57
56
|
"""
|
|
58
57
|
raise LoginError("Account authentication is not enabled on this SuperLink.")
|
|
59
58
|
|
|
60
|
-
def __init__(self,
|
|
59
|
+
def __init__(self, host: str = "") -> None:
|
|
61
60
|
pass
|
|
62
61
|
|
|
63
62
|
def store_tokens(self, credentials: AccountAuthCredentials) -> None:
|