flwr-nightly 1.9.0.dev20240420__tar.gz → 1.9.0.dev20240507__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.
Potentially problematic release.
This version of flwr-nightly might be problematic. Click here for more details.
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/PKG-INFO +3 -2
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/README.md +1 -1
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/pyproject.toml +4 -9
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/app.py +2 -0
- flwr_nightly-1.9.0.dev20240507/src/py/flwr/cli/build.py +151 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/config_utils.py +18 -46
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/new.py +42 -18
- flwr_nightly-1.9.0.dev20240507/src/py/flwr/cli/new/templates/app/code/client.mlx.py.tpl +70 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/templates/app/code/client.pytorch.py.tpl +1 -1
- flwr_nightly-1.9.0.dev20240507/src/py/flwr/cli/new/templates/app/code/client.sklearn.py.tpl +94 -0
- flwr_nightly-1.9.0.dev20240507/src/py/flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +43 -0
- flwr_nightly-1.9.0.dev20240507/src/py/flwr/cli/new/templates/app/code/server.mlx.py.tpl +15 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/templates/app/code/server.pytorch.py.tpl +1 -1
- flwr_nightly-1.9.0.dev20240420/src/py/flwr/cli/new/templates/app/code/server.tensorflow.py.tpl → flwr_nightly-1.9.0.dev20240507/src/py/flwr/cli/new/templates/app/code/server.sklearn.py.tpl +3 -5
- flwr_nightly-1.9.0.dev20240507/src/py/flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +27 -0
- flwr_nightly-1.9.0.dev20240507/src/py/flwr/cli/new/templates/app/code/task.mlx.py.tpl +89 -0
- flwr_nightly-1.9.0.dev20240507/src/py/flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +29 -0
- flwr_nightly-1.9.0.dev20240507/src/py/flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +28 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +7 -4
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +7 -4
- flwr_nightly-1.9.0.dev20240507/src/py/flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +27 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +7 -4
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/run/run.py +1 -1
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/utils.py +18 -17
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/__init__.py +1 -1
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/app.py +17 -93
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/grpc_client/connection.py +6 -1
- flwr_nightly-1.9.0.dev20240507/src/py/flwr/client/grpc_rere_client/client_interceptor.py +158 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/grpc_rere_client/connection.py +17 -2
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/mod/centraldp_mods.py +4 -2
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/mod/localdp_mod.py +9 -3
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/rest_client/connection.py +5 -1
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/supernode/__init__.py +2 -0
- flwr_nightly-1.9.0.dev20240507/src/py/flwr/client/supernode/app.py +281 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/grpc.py +5 -1
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/logger.py +37 -4
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/message.py +105 -86
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/record/parametersrecord.py +0 -1
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/record/recordset.py +17 -5
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py +35 -1
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/app.py +111 -1
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/compat/app.py +2 -2
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/compat/app_utils.py +1 -1
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/compat/driver_client_proxy.py +27 -72
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/driver/__init__.py +3 -0
- flwr_nightly-1.9.0.dev20240420/src/py/flwr/server/driver/driver.py → flwr_nightly-1.9.0.dev20240507/src/py/flwr/server/driver/grpc_driver.py +25 -80
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/run_serverapp.py +18 -4
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/dp_adaptive_clipping.py +5 -3
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/dp_fixed_clipping.py +6 -3
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/driver/driver_servicer.py +1 -1
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +3 -1
- flwr_nightly-1.9.0.dev20240507/src/py/flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +215 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/vce/backend/raybackend.py +5 -5
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/vce/vce_api.py +1 -1
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/state/in_memory_state.py +76 -8
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/state/sqlite_state.py +116 -11
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/state/state.py +35 -3
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/simulation/__init__.py +2 -2
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/simulation/app.py +16 -1
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/simulation/run_simulation.py +10 -7
- flwr_nightly-1.9.0.dev20240420/src/py/flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -57
- flwr_nightly-1.9.0.dev20240420/src/py/flwr/client/supernode/app.py +0 -107
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/LICENSE +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/example.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/templates/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/templates/app/.gitignore.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/templates/app/README.md.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/templates/app/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/templates/app/code/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/templates/app/code/__init__.py.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/run/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/client.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/client_app.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/dpfedavg_numpy_client.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/grpc_client/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/grpc_rere_client/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/heartbeat.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/message_handler/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/message_handler/message_handler.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/message_handler/task_handler.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/mod/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/mod/comms_mods.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/mod/secure_aggregation/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/mod/secure_aggregation/secagg_mod.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/mod/utils.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/node_state.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/node_state_tests.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/numpy_client.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/rest_client/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/client/typing.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/address.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/constant.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/context.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/date.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/differential_privacy.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/differential_privacy_constants.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/dp.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/exit_handlers.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/object_ref.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/parameter.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/pyproject.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/record/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/record/configsrecord.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/record/conversion_utils.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/record/metricsrecord.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/record/typeddict.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/recordset_compat.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/retry_invoker.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/secure_aggregation/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/secure_aggregation/crypto/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/secure_aggregation/crypto/shamir.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/secure_aggregation/quantization.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/secure_aggregation/secaggplus_constants.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/secure_aggregation/secaggplus_utils.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/serde.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/telemetry.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/typing.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/common/version.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/driver_pb2.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/driver_pb2.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/driver_pb2_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/driver_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/error_pb2.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/error_pb2.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/error_pb2_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/error_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/fleet_pb2.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/fleet_pb2.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/fleet_pb2_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/fleet_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/node_pb2.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/node_pb2.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/node_pb2_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/node_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/recordset_pb2.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/recordset_pb2.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/recordset_pb2_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/recordset_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/task_pb2.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/task_pb2.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/task_pb2_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/task_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/transport_pb2.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/transport_pb2.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/transport_pb2_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/proto/transport_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/py.typed +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/client_manager.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/client_proxy.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/compat/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/compat/legacy_context.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/criterion.py +0 -0
- /flwr_nightly-1.9.0.dev20240420/src/py/flwr/server/driver/abc_driver.py → /flwr_nightly-1.9.0.dev20240507/src/py/flwr/server/driver/driver.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/history.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/server.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/server_app.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/server_config.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/aggregate.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/bulyan.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/dpfedavg_adaptive.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/dpfedavg_fixed.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/fault_tolerant_fedavg.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/fedadagrad.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/fedadam.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/fedavg.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/fedavg_android.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/fedavgm.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/fedmedian.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/fedopt.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/fedprox.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/fedtrimmedavg.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/fedxgb_bagging.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/fedxgb_cyclic.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/fedxgb_nn_avg.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/fedyogi.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/krum.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/qfedavg.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/strategy/strategy.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/driver/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/driver/driver_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/grpc_rere/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/message_handler/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/rest_rere/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/vce/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/vce/backend/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/fleet/vce/backend/backend.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/state/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/state/state_factory.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/superlink/state/utils.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/typing.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/utils/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/utils/tensorboard.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/utils/validator.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/workflow/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/workflow/constant.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/workflow/default_workflows.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/workflow/secure_aggregation/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/workflow/secure_aggregation/secagg_workflow.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/simulation/ray_transport/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/simulation/ray_transport/ray_actor.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/simulation/ray_transport/ray_client_proxy.py +0 -0
- {flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/simulation/ray_transport/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: flwr-nightly
|
|
3
|
-
Version: 1.9.0.
|
|
3
|
+
Version: 1.9.0.dev20240507
|
|
4
4
|
Summary: Flower: A Friendly Federated Learning Framework
|
|
5
5
|
Home-page: https://flower.ai
|
|
6
6
|
License: Apache-2.0
|
|
@@ -36,6 +36,7 @@ Requires-Dist: cryptography (>=42.0.4,<43.0.0)
|
|
|
36
36
|
Requires-Dist: grpcio (>=1.60.0,<2.0.0)
|
|
37
37
|
Requires-Dist: iterators (>=0.0.2,<0.0.3)
|
|
38
38
|
Requires-Dist: numpy (>=1.21.0,<2.0.0)
|
|
39
|
+
Requires-Dist: pathspec (>=0.12.1,<0.13.0)
|
|
39
40
|
Requires-Dist: protobuf (>=4.25.2,<5.0.0)
|
|
40
41
|
Requires-Dist: pycryptodome (>=3.18.0,<4.0.0)
|
|
41
42
|
Requires-Dist: ray (==2.6.3) ; (python_version >= "3.8" and python_version < "3.12") and (extra == "simulation")
|
|
@@ -193,7 +194,7 @@ Other [examples](https://github.com/adap/flower/tree/main/examples):
|
|
|
193
194
|
- [PyTorch: From Centralized to Federated](https://github.com/adap/flower/tree/main/examples/pytorch-from-centralized-to-federated)
|
|
194
195
|
- [Vertical FL](https://github.com/adap/flower/tree/main/examples/vertical-fl)
|
|
195
196
|
- [Federated Finetuning of OpenAI's Whisper](https://github.com/adap/flower/tree/main/examples/whisper-federated-finetuning)
|
|
196
|
-
- [Federated Finetuning of Large Language Model](https://github.com/adap/flower/tree/main/examples/
|
|
197
|
+
- [Federated Finetuning of Large Language Model](https://github.com/adap/flower/tree/main/examples/llm-flowertune)
|
|
197
198
|
- [Federated Finetuning of a Vision Transformer](https://github.com/adap/flower/tree/main/examples/vit-finetune)
|
|
198
199
|
- [Advanced Flower with TensorFlow/Keras](https://github.com/adap/flower/tree/main/examples/advanced-tensorflow)
|
|
199
200
|
- [Advanced Flower with PyTorch](https://github.com/adap/flower/tree/main/examples/advanced-pytorch)
|
|
@@ -143,7 +143,7 @@ Other [examples](https://github.com/adap/flower/tree/main/examples):
|
|
|
143
143
|
- [PyTorch: From Centralized to Federated](https://github.com/adap/flower/tree/main/examples/pytorch-from-centralized-to-federated)
|
|
144
144
|
- [Vertical FL](https://github.com/adap/flower/tree/main/examples/vertical-fl)
|
|
145
145
|
- [Federated Finetuning of OpenAI's Whisper](https://github.com/adap/flower/tree/main/examples/whisper-federated-finetuning)
|
|
146
|
-
- [Federated Finetuning of Large Language Model](https://github.com/adap/flower/tree/main/examples/
|
|
146
|
+
- [Federated Finetuning of Large Language Model](https://github.com/adap/flower/tree/main/examples/llm-flowertune)
|
|
147
147
|
- [Federated Finetuning of a Vision Transformer](https://github.com/adap/flower/tree/main/examples/vit-finetune)
|
|
148
148
|
- [Advanced Flower with TensorFlow/Keras](https://github.com/adap/flower/tree/main/examples/advanced-tensorflow)
|
|
149
149
|
- [Advanced Flower with PyTorch](https://github.com/adap/flower/tree/main/examples/advanced-pytorch)
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "flwr-nightly"
|
|
7
|
-
version = "1.9.0.
|
|
7
|
+
version = "1.9.0.dev20240507"
|
|
8
8
|
description = "Flower: A Friendly Federated Learning Framework"
|
|
9
9
|
license = "Apache-2.0"
|
|
10
10
|
authors = ["The Flower Authors <hello@flower.ai>"]
|
|
@@ -59,7 +59,7 @@ flower-superlink = "flwr.server:run_superlink"
|
|
|
59
59
|
flower-supernode = "flwr.client:run_supernode"
|
|
60
60
|
flower-client-app = "flwr.client:run_client_app"
|
|
61
61
|
flower-server-app = "flwr.server:run_server_app"
|
|
62
|
-
flower-simulation = "flwr.simulation:run_simulation_from_cli"
|
|
62
|
+
flower-simulation = "flwr.simulation.run_simulation:run_simulation_from_cli"
|
|
63
63
|
|
|
64
64
|
[tool.poetry.dependencies]
|
|
65
65
|
python = "^3.8"
|
|
@@ -72,6 +72,7 @@ pycryptodome = "^3.18.0"
|
|
|
72
72
|
iterators = "^0.0.2"
|
|
73
73
|
typer = { version = "^0.9.0", extras=["all"] }
|
|
74
74
|
tomli = "^2.0.1"
|
|
75
|
+
pathspec = "^0.12.1"
|
|
75
76
|
# Optional dependencies (Simulation Engine)
|
|
76
77
|
ray = { version = "==2.6.3", optional = true, python = ">=3.8,<3.12" }
|
|
77
78
|
# Optional dependencies (REST transport layer)
|
|
@@ -136,7 +137,7 @@ multi_line_output = 3
|
|
|
136
137
|
include_trailing_comma = true
|
|
137
138
|
force_grid_wrap = 0
|
|
138
139
|
use_parentheses = true
|
|
139
|
-
known_first_party = ["flwr", "
|
|
140
|
+
known_first_party = ["flwr", "flwr_tool"]
|
|
140
141
|
|
|
141
142
|
[tool.black]
|
|
142
143
|
line-length = 88
|
|
@@ -170,12 +171,6 @@ plugins = [
|
|
|
170
171
|
ignore_missing_imports = true
|
|
171
172
|
strict = true
|
|
172
173
|
|
|
173
|
-
[[tool.mypy.overrides]]
|
|
174
|
-
module = [
|
|
175
|
-
"flwr_experimental.*",
|
|
176
|
-
]
|
|
177
|
-
ignore_errors = true
|
|
178
|
-
|
|
179
174
|
[[tool.mypy.overrides]]
|
|
180
175
|
module = [
|
|
181
176
|
"importlib.metadata.*",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import typer
|
|
18
18
|
|
|
19
|
+
from .build import build
|
|
19
20
|
from .example import example
|
|
20
21
|
from .new import new
|
|
21
22
|
from .run import run
|
|
@@ -32,6 +33,7 @@ app = typer.Typer(
|
|
|
32
33
|
app.command()(new)
|
|
33
34
|
app.command()(example)
|
|
34
35
|
app.command()(run)
|
|
36
|
+
app.command()(build)
|
|
35
37
|
|
|
36
38
|
if __name__ == "__main__":
|
|
37
39
|
app()
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
"""Flower command line interface `build` command."""
|
|
16
|
+
|
|
17
|
+
import hashlib
|
|
18
|
+
import os
|
|
19
|
+
import zipfile
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Optional
|
|
22
|
+
|
|
23
|
+
import pathspec
|
|
24
|
+
import typer
|
|
25
|
+
from typing_extensions import Annotated
|
|
26
|
+
|
|
27
|
+
from .config_utils import load_and_validate_with_defaults
|
|
28
|
+
from .utils import is_valid_project_name
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# pylint: disable=too-many-locals
|
|
32
|
+
def build(
|
|
33
|
+
directory: Annotated[
|
|
34
|
+
Optional[Path],
|
|
35
|
+
typer.Option(help="The Flower project directory to bundle into a FAB"),
|
|
36
|
+
] = None,
|
|
37
|
+
) -> None:
|
|
38
|
+
"""Build a Flower project into a Flower App Bundle (FAB).
|
|
39
|
+
|
|
40
|
+
You can run `flwr build` without any argument to bundle the current directory:
|
|
41
|
+
|
|
42
|
+
`flwr build`
|
|
43
|
+
|
|
44
|
+
You can also build a specific directory:
|
|
45
|
+
|
|
46
|
+
`flwr build --directory ./projects/flower-hello-world`
|
|
47
|
+
"""
|
|
48
|
+
if directory is None:
|
|
49
|
+
directory = Path.cwd()
|
|
50
|
+
|
|
51
|
+
directory = directory.resolve()
|
|
52
|
+
if not directory.is_dir():
|
|
53
|
+
typer.secho(
|
|
54
|
+
f"❌ The path {directory} is not a valid directory.",
|
|
55
|
+
fg=typer.colors.RED,
|
|
56
|
+
bold=True,
|
|
57
|
+
)
|
|
58
|
+
raise typer.Exit(code=1)
|
|
59
|
+
|
|
60
|
+
if not is_valid_project_name(directory.name):
|
|
61
|
+
typer.secho(
|
|
62
|
+
f"❌ The project name {directory.name} is invalid, "
|
|
63
|
+
"a valid project name must start with a letter or an underscore, "
|
|
64
|
+
"and can only contain letters, digits, and underscores.",
|
|
65
|
+
fg=typer.colors.RED,
|
|
66
|
+
bold=True,
|
|
67
|
+
)
|
|
68
|
+
raise typer.Exit(code=1)
|
|
69
|
+
|
|
70
|
+
conf, errors, warnings = load_and_validate_with_defaults(
|
|
71
|
+
directory / "pyproject.toml"
|
|
72
|
+
)
|
|
73
|
+
if conf is None:
|
|
74
|
+
typer.secho(
|
|
75
|
+
"Project configuration could not be loaded.\npyproject.toml is invalid:\n"
|
|
76
|
+
+ "\n".join([f"- {line}" for line in errors]),
|
|
77
|
+
fg=typer.colors.RED,
|
|
78
|
+
bold=True,
|
|
79
|
+
)
|
|
80
|
+
raise typer.Exit(code=1)
|
|
81
|
+
|
|
82
|
+
if warnings:
|
|
83
|
+
typer.secho(
|
|
84
|
+
"Project configuration is missing the following "
|
|
85
|
+
"recommended properties:\n" + "\n".join([f"- {line}" for line in warnings]),
|
|
86
|
+
fg=typer.colors.RED,
|
|
87
|
+
bold=True,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Load .gitignore rules if present
|
|
91
|
+
ignore_spec = _load_gitignore(directory)
|
|
92
|
+
|
|
93
|
+
# Set the name of the zip file
|
|
94
|
+
fab_filename = (
|
|
95
|
+
f"{conf['flower']['publisher']}"
|
|
96
|
+
f".{directory.name}"
|
|
97
|
+
f".{conf['project']['version'].replace('.', '-')}.fab"
|
|
98
|
+
)
|
|
99
|
+
list_file_content = ""
|
|
100
|
+
|
|
101
|
+
allowed_extensions = {".py", ".toml", ".md"}
|
|
102
|
+
|
|
103
|
+
with zipfile.ZipFile(fab_filename, "w", zipfile.ZIP_DEFLATED) as fab_file:
|
|
104
|
+
for root, _, files in os.walk(directory, topdown=True):
|
|
105
|
+
# Filter directories and files based on .gitignore
|
|
106
|
+
files = [
|
|
107
|
+
f
|
|
108
|
+
for f in files
|
|
109
|
+
if not ignore_spec.match_file(Path(root) / f)
|
|
110
|
+
and f != fab_filename
|
|
111
|
+
and Path(f).suffix in allowed_extensions
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
for file in files:
|
|
115
|
+
file_path = Path(root) / file
|
|
116
|
+
archive_path = file_path.relative_to(directory)
|
|
117
|
+
fab_file.write(file_path, archive_path)
|
|
118
|
+
|
|
119
|
+
# Calculate file info
|
|
120
|
+
sha256_hash = _get_sha256_hash(file_path)
|
|
121
|
+
file_size_bits = os.path.getsize(file_path) * 8 # size in bits
|
|
122
|
+
list_file_content += f"{archive_path},{sha256_hash},{file_size_bits}\n"
|
|
123
|
+
|
|
124
|
+
# Add CONTENT and CONTENT.jwt to the zip file
|
|
125
|
+
fab_file.writestr(".info/CONTENT", list_file_content)
|
|
126
|
+
|
|
127
|
+
typer.secho(
|
|
128
|
+
f"🎊 Successfully built {fab_filename}.", fg=typer.colors.GREEN, bold=True
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _get_sha256_hash(file_path: Path) -> str:
|
|
133
|
+
"""Calculate the SHA-256 hash of a file."""
|
|
134
|
+
sha256 = hashlib.sha256()
|
|
135
|
+
with open(file_path, "rb") as f:
|
|
136
|
+
while True:
|
|
137
|
+
data = f.read(65536) # Read in 64kB blocks
|
|
138
|
+
if not data:
|
|
139
|
+
break
|
|
140
|
+
sha256.update(data)
|
|
141
|
+
return sha256.hexdigest()
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _load_gitignore(directory: Path) -> pathspec.PathSpec:
|
|
145
|
+
"""Load and parse .gitignore file, returning a pathspec."""
|
|
146
|
+
gitignore_path = directory / ".gitignore"
|
|
147
|
+
patterns = ["__pycache__/"] # Default pattern
|
|
148
|
+
if gitignore_path.exists():
|
|
149
|
+
with open(gitignore_path, encoding="UTF-8") as file:
|
|
150
|
+
patterns.extend(file.readlines())
|
|
151
|
+
return pathspec.PathSpec.from_lines("gitwildmatch", patterns)
|
{flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/config_utils.py
RENAMED
|
@@ -14,49 +14,16 @@
|
|
|
14
14
|
# ==============================================================================
|
|
15
15
|
"""Utility to validate the `pyproject.toml` file."""
|
|
16
16
|
|
|
17
|
-
import os
|
|
18
17
|
from pathlib import Path
|
|
19
18
|
from typing import Any, Dict, List, Optional, Tuple
|
|
20
19
|
|
|
21
20
|
import tomli
|
|
22
|
-
import typer
|
|
23
21
|
|
|
24
22
|
from flwr.common import object_ref
|
|
25
23
|
|
|
26
24
|
|
|
27
|
-
def validate_project_dir(project_dir: Path) -> Optional[Dict[str, Any]]:
|
|
28
|
-
"""Check if a Flower App directory is valid."""
|
|
29
|
-
config = load(str(project_dir / "pyproject.toml"))
|
|
30
|
-
if config is None:
|
|
31
|
-
typer.secho(
|
|
32
|
-
"❌ Project configuration could not be loaded. "
|
|
33
|
-
"`pyproject.toml` does not exist.",
|
|
34
|
-
fg=typer.colors.RED,
|
|
35
|
-
bold=True,
|
|
36
|
-
)
|
|
37
|
-
return None
|
|
38
|
-
|
|
39
|
-
if not validate(config):
|
|
40
|
-
typer.secho(
|
|
41
|
-
"❌ Project configuration is invalid.",
|
|
42
|
-
fg=typer.colors.RED,
|
|
43
|
-
bold=True,
|
|
44
|
-
)
|
|
45
|
-
return None
|
|
46
|
-
|
|
47
|
-
if "publisher" not in config["flower"]:
|
|
48
|
-
typer.secho(
|
|
49
|
-
"❌ Project configuration is missing required `publisher` field.",
|
|
50
|
-
fg=typer.colors.RED,
|
|
51
|
-
bold=True,
|
|
52
|
-
)
|
|
53
|
-
return None
|
|
54
|
-
|
|
55
|
-
return config
|
|
56
|
-
|
|
57
|
-
|
|
58
25
|
def load_and_validate_with_defaults(
|
|
59
|
-
path: Optional[
|
|
26
|
+
path: Optional[Path] = None,
|
|
60
27
|
) -> Tuple[Optional[Dict[str, Any]], List[str], List[str]]:
|
|
61
28
|
"""Load and validate pyproject.toml as dict.
|
|
62
29
|
|
|
@@ -70,7 +37,8 @@ def load_and_validate_with_defaults(
|
|
|
70
37
|
|
|
71
38
|
if config is None:
|
|
72
39
|
errors = [
|
|
73
|
-
"Project configuration could not be loaded.
|
|
40
|
+
"Project configuration could not be loaded. "
|
|
41
|
+
"`pyproject.toml` does not exist."
|
|
74
42
|
]
|
|
75
43
|
return (None, errors, [])
|
|
76
44
|
|
|
@@ -90,22 +58,23 @@ def load_and_validate_with_defaults(
|
|
|
90
58
|
return (config, errors, warnings)
|
|
91
59
|
|
|
92
60
|
|
|
93
|
-
def load(path: Optional[
|
|
61
|
+
def load(path: Optional[Path] = None) -> Optional[Dict[str, Any]]:
|
|
94
62
|
"""Load pyproject.toml and return as dict."""
|
|
95
63
|
if path is None:
|
|
96
|
-
cur_dir =
|
|
97
|
-
toml_path =
|
|
64
|
+
cur_dir = Path.cwd()
|
|
65
|
+
toml_path = cur_dir / "pyproject.toml"
|
|
98
66
|
else:
|
|
99
67
|
toml_path = path
|
|
100
68
|
|
|
101
|
-
if not
|
|
69
|
+
if not toml_path.is_file():
|
|
102
70
|
return None
|
|
103
71
|
|
|
104
|
-
with open(
|
|
72
|
+
with toml_path.open(encoding="utf-8") as toml_file:
|
|
105
73
|
data = tomli.loads(toml_file.read())
|
|
106
74
|
return data
|
|
107
75
|
|
|
108
76
|
|
|
77
|
+
# pylint: disable=too-many-branches
|
|
109
78
|
def validate_fields(config: Dict[str, Any]) -> Tuple[bool, List[str], List[str]]:
|
|
110
79
|
"""Validate pyproject.toml fields."""
|
|
111
80
|
errors = []
|
|
@@ -127,13 +96,16 @@ def validate_fields(config: Dict[str, Any]) -> Tuple[bool, List[str], List[str]]
|
|
|
127
96
|
|
|
128
97
|
if "flower" not in config:
|
|
129
98
|
errors.append("Missing [flower] section")
|
|
130
|
-
elif "components" not in config["flower"]:
|
|
131
|
-
errors.append("Missing [flower.components] section")
|
|
132
99
|
else:
|
|
133
|
-
if "
|
|
134
|
-
errors.append('Property "
|
|
135
|
-
if "
|
|
136
|
-
errors.append(
|
|
100
|
+
if "publisher" not in config["flower"]:
|
|
101
|
+
errors.append('Property "publisher" missing in [flower]')
|
|
102
|
+
if "components" not in config["flower"]:
|
|
103
|
+
errors.append("Missing [flower.components] section")
|
|
104
|
+
else:
|
|
105
|
+
if "serverapp" not in config["flower"]["components"]:
|
|
106
|
+
errors.append('Property "serverapp" missing in [flower.components]')
|
|
107
|
+
if "clientapp" not in config["flower"]["components"]:
|
|
108
|
+
errors.append('Property "clientapp" missing in [flower.components]')
|
|
137
109
|
|
|
138
110
|
return len(errors) == 0, errors, warnings
|
|
139
111
|
|
{flwr_nightly-1.9.0.dev20240420 → flwr_nightly-1.9.0.dev20240507}/src/py/flwr/cli/new/new.py
RENAMED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"""Flower command line interface `new` command."""
|
|
16
16
|
|
|
17
17
|
import os
|
|
18
|
+
import re
|
|
18
19
|
from enum import Enum
|
|
19
20
|
from string import Template
|
|
20
21
|
from typing import Dict, Optional
|
|
@@ -36,6 +37,8 @@ class MlFramework(str, Enum):
|
|
|
36
37
|
NUMPY = "NumPy"
|
|
37
38
|
PYTORCH = "PyTorch"
|
|
38
39
|
TENSORFLOW = "TensorFlow"
|
|
40
|
+
MLX = "MLX"
|
|
41
|
+
SKLEARN = "sklearn"
|
|
39
42
|
|
|
40
43
|
|
|
41
44
|
class TemplateNotFound(Exception):
|
|
@@ -85,32 +88,31 @@ def new(
|
|
|
85
88
|
Optional[MlFramework],
|
|
86
89
|
typer.Option(case_sensitive=False, help="The ML framework to use"),
|
|
87
90
|
] = None,
|
|
91
|
+
username: Annotated[
|
|
92
|
+
Optional[str],
|
|
93
|
+
typer.Option(case_sensitive=False, help="The Flower username of the author"),
|
|
94
|
+
] = None,
|
|
88
95
|
) -> None:
|
|
89
96
|
"""Create new Flower project."""
|
|
90
97
|
if project_name is None:
|
|
91
|
-
project_name = prompt_text("Please provide project name")
|
|
98
|
+
project_name = prompt_text("Please provide the project name")
|
|
92
99
|
if not is_valid_project_name(project_name):
|
|
93
100
|
project_name = prompt_text(
|
|
94
101
|
"Please provide a name that only contains "
|
|
95
|
-
"characters in {'
|
|
102
|
+
"characters in {'-', a-zA-Z', '0-9'}",
|
|
96
103
|
predicate=is_valid_project_name,
|
|
97
104
|
default=sanitize_project_name(project_name),
|
|
98
105
|
)
|
|
99
106
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
f"🔨 Creating Flower project {project_name}...",
|
|
103
|
-
fg=typer.colors.GREEN,
|
|
104
|
-
bold=True,
|
|
105
|
-
)
|
|
106
|
-
)
|
|
107
|
+
if username is None:
|
|
108
|
+
username = prompt_text("Please provide your Flower username")
|
|
107
109
|
|
|
108
110
|
if framework is not None:
|
|
109
111
|
framework_str = str(framework.value)
|
|
110
112
|
else:
|
|
111
113
|
framework_value = prompt_options(
|
|
112
114
|
"Please select ML framework by typing in the number",
|
|
113
|
-
[mlf.value for mlf in MlFramework],
|
|
115
|
+
sorted([mlf.value for mlf in MlFramework]),
|
|
114
116
|
)
|
|
115
117
|
selected_value = [
|
|
116
118
|
name
|
|
@@ -121,29 +123,51 @@ def new(
|
|
|
121
123
|
|
|
122
124
|
framework_str = framework_str.lower()
|
|
123
125
|
|
|
126
|
+
print(
|
|
127
|
+
typer.style(
|
|
128
|
+
f"\n🔨 Creating Flower project {project_name}...",
|
|
129
|
+
fg=typer.colors.GREEN,
|
|
130
|
+
bold=True,
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
|
|
124
134
|
# Set project directory path
|
|
125
135
|
cwd = os.getcwd()
|
|
126
|
-
|
|
127
|
-
|
|
136
|
+
package_name = re.sub(r"[-_.]+", "-", project_name).lower()
|
|
137
|
+
import_name = package_name.replace("-", "_")
|
|
138
|
+
project_dir = os.path.join(cwd, package_name)
|
|
128
139
|
|
|
129
140
|
# List of files to render
|
|
130
141
|
files = {
|
|
131
142
|
".gitignore": {"template": "app/.gitignore.tpl"},
|
|
132
143
|
"README.md": {"template": "app/README.md.tpl"},
|
|
133
144
|
"pyproject.toml": {"template": f"app/pyproject.{framework_str}.toml.tpl"},
|
|
134
|
-
f"{
|
|
135
|
-
f"{
|
|
136
|
-
|
|
145
|
+
f"{import_name}/__init__.py": {"template": "app/code/__init__.py.tpl"},
|
|
146
|
+
f"{import_name}/server.py": {
|
|
147
|
+
"template": f"app/code/server.{framework_str}.py.tpl"
|
|
148
|
+
},
|
|
149
|
+
f"{import_name}/client.py": {
|
|
150
|
+
"template": f"app/code/client.{framework_str}.py.tpl"
|
|
151
|
+
},
|
|
137
152
|
}
|
|
138
153
|
|
|
139
154
|
# Depending on the framework, generate task.py file
|
|
140
155
|
frameworks_with_tasks = [
|
|
141
156
|
MlFramework.PYTORCH.value.lower(),
|
|
157
|
+
MlFramework.MLX.value.lower(),
|
|
158
|
+
MlFramework.TENSORFLOW.value.lower(),
|
|
142
159
|
]
|
|
143
160
|
if framework_str in frameworks_with_tasks:
|
|
144
|
-
files[f"{
|
|
145
|
-
|
|
146
|
-
|
|
161
|
+
files[f"{import_name}/task.py"] = {
|
|
162
|
+
"template": f"app/code/task.{framework_str}.py.tpl"
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
context = {
|
|
166
|
+
"project_name": project_name,
|
|
167
|
+
"package_name": package_name,
|
|
168
|
+
"import_name": import_name.replace("-", "_"),
|
|
169
|
+
"username": username,
|
|
170
|
+
}
|
|
147
171
|
|
|
148
172
|
for file_path, value in files.items():
|
|
149
173
|
render_and_create(
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""$project_name: A Flower / MLX app."""
|
|
2
|
+
|
|
3
|
+
import mlx.core as mx
|
|
4
|
+
import mlx.nn as nn
|
|
5
|
+
import mlx.optimizers as optim
|
|
6
|
+
from flwr.client import NumPyClient, ClientApp
|
|
7
|
+
|
|
8
|
+
from $import_name.task import (
|
|
9
|
+
batch_iterate,
|
|
10
|
+
eval_fn,
|
|
11
|
+
get_params,
|
|
12
|
+
load_data,
|
|
13
|
+
loss_fn,
|
|
14
|
+
set_params,
|
|
15
|
+
MLP,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Define Flower Client and client_fn
|
|
20
|
+
class FlowerClient(NumPyClient):
|
|
21
|
+
def __init__(self, data):
|
|
22
|
+
num_layers = 2
|
|
23
|
+
hidden_dim = 32
|
|
24
|
+
num_classes = 10
|
|
25
|
+
batch_size = 256
|
|
26
|
+
num_epochs = 1
|
|
27
|
+
learning_rate = 1e-1
|
|
28
|
+
|
|
29
|
+
self.train_images, self.train_labels, self.test_images, self.test_labels = data
|
|
30
|
+
self.model = MLP(num_layers, self.train_images.shape[-1], hidden_dim, num_classes)
|
|
31
|
+
self.optimizer = optim.SGD(learning_rate=learning_rate)
|
|
32
|
+
self.loss_and_grad_fn = nn.value_and_grad(self.model, loss_fn)
|
|
33
|
+
self.num_epochs = num_epochs
|
|
34
|
+
self.batch_size = batch_size
|
|
35
|
+
|
|
36
|
+
def get_parameters(self, config):
|
|
37
|
+
return get_params(self.model)
|
|
38
|
+
|
|
39
|
+
def set_parameters(self, parameters):
|
|
40
|
+
set_params(self.model, parameters)
|
|
41
|
+
|
|
42
|
+
def fit(self, parameters, config):
|
|
43
|
+
self.set_parameters(parameters)
|
|
44
|
+
for _ in range(self.num_epochs):
|
|
45
|
+
for X, y in batch_iterate(
|
|
46
|
+
self.batch_size, self.train_images, self.train_labels
|
|
47
|
+
):
|
|
48
|
+
_, grads = self.loss_and_grad_fn(self.model, X, y)
|
|
49
|
+
self.optimizer.update(self.model, grads)
|
|
50
|
+
mx.eval(self.model.parameters(), self.optimizer.state)
|
|
51
|
+
return self.get_parameters(config={}), len(self.train_images), {}
|
|
52
|
+
|
|
53
|
+
def evaluate(self, parameters, config):
|
|
54
|
+
self.set_parameters(parameters)
|
|
55
|
+
accuracy = eval_fn(self.model, self.test_images, self.test_labels)
|
|
56
|
+
loss = loss_fn(self.model, self.test_images, self.test_labels)
|
|
57
|
+
return loss.item(), len(self.test_images), {"accuracy": accuracy.item()}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def client_fn(cid):
|
|
61
|
+
data = load_data(int(cid), 2)
|
|
62
|
+
|
|
63
|
+
# Return Client instance
|
|
64
|
+
return FlowerClient(data).to_client()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# Flower ClientApp
|
|
68
|
+
app = ClientApp(
|
|
69
|
+
client_fn,
|
|
70
|
+
)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""$project_name: A Flower / Scikit-Learn app."""
|
|
2
|
+
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from flwr.client import NumPyClient, ClientApp
|
|
7
|
+
from flwr_datasets import FederatedDataset
|
|
8
|
+
from sklearn.linear_model import LogisticRegression
|
|
9
|
+
from sklearn.metrics import log_loss
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_model_parameters(model):
|
|
13
|
+
if model.fit_intercept:
|
|
14
|
+
params = [
|
|
15
|
+
model.coef_,
|
|
16
|
+
model.intercept_,
|
|
17
|
+
]
|
|
18
|
+
else:
|
|
19
|
+
params = [model.coef_]
|
|
20
|
+
return params
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def set_model_params(model, params):
|
|
24
|
+
model.coef_ = params[0]
|
|
25
|
+
if model.fit_intercept:
|
|
26
|
+
model.intercept_ = params[1]
|
|
27
|
+
return model
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def set_initial_params(model):
|
|
31
|
+
n_classes = 10 # MNIST has 10 classes
|
|
32
|
+
n_features = 784 # Number of features in dataset
|
|
33
|
+
model.classes_ = np.array([i for i in range(10)])
|
|
34
|
+
|
|
35
|
+
model.coef_ = np.zeros((n_classes, n_features))
|
|
36
|
+
if model.fit_intercept:
|
|
37
|
+
model.intercept_ = np.zeros((n_classes,))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class FlowerClient(NumPyClient):
|
|
41
|
+
def __init__(self, model, X_train, X_test, y_train, y_test):
|
|
42
|
+
self.model = model
|
|
43
|
+
self.X_train = X_train
|
|
44
|
+
self.X_test = X_test
|
|
45
|
+
self.y_train = y_train
|
|
46
|
+
self.y_test = y_test
|
|
47
|
+
|
|
48
|
+
def get_parameters(self, config):
|
|
49
|
+
return get_model_parameters(self.model)
|
|
50
|
+
|
|
51
|
+
def fit(self, parameters, config):
|
|
52
|
+
set_model_params(self.model, parameters)
|
|
53
|
+
|
|
54
|
+
# Ignore convergence failure due to low local epochs
|
|
55
|
+
with warnings.catch_warnings():
|
|
56
|
+
warnings.simplefilter("ignore")
|
|
57
|
+
self.model.fit(self.X_train, self.y_train)
|
|
58
|
+
|
|
59
|
+
return get_model_parameters(self.model), len(self.X_train), {}
|
|
60
|
+
|
|
61
|
+
def evaluate(self, parameters, config):
|
|
62
|
+
set_model_params(self.model, parameters)
|
|
63
|
+
|
|
64
|
+
loss = log_loss(self.y_test, self.model.predict_proba(self.X_test))
|
|
65
|
+
accuracy = self.model.score(self.X_test, self.y_test)
|
|
66
|
+
|
|
67
|
+
return loss, len(self.X_test), {"accuracy": accuracy}
|
|
68
|
+
|
|
69
|
+
fds = FederatedDataset(dataset="mnist", partitioners={"train": 2})
|
|
70
|
+
|
|
71
|
+
def client_fn(cid: str):
|
|
72
|
+
dataset = fds.load_partition(int(cid), "train").with_format("numpy")
|
|
73
|
+
|
|
74
|
+
X, y = dataset["image"].reshape((len(dataset), -1)), dataset["label"]
|
|
75
|
+
|
|
76
|
+
# Split the on edge data: 80% train, 20% test
|
|
77
|
+
X_train, X_test = X[: int(0.8 * len(X))], X[int(0.8 * len(X)) :]
|
|
78
|
+
y_train, y_test = y[: int(0.8 * len(y))], y[int(0.8 * len(y)) :]
|
|
79
|
+
|
|
80
|
+
# Create LogisticRegression Model
|
|
81
|
+
model = LogisticRegression(
|
|
82
|
+
penalty="l2",
|
|
83
|
+
max_iter=1, # local epoch
|
|
84
|
+
warm_start=True, # prevent refreshing weights when fitting
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
# Setting initial parameters, akin to model.compile for keras models
|
|
88
|
+
set_initial_params(model)
|
|
89
|
+
|
|
90
|
+
return FlowerClient(model, X_train, X_test, y_train, y_test).to_client()
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
# Flower ClientApp
|
|
94
|
+
app = ClientApp(client_fn=client_fn)
|