flwr-nightly 1.10.0.dev20240611__tar.gz → 1.10.0.dev20240613__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.

Files changed (248) hide show
  1. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/PKG-INFO +1 -1
  2. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/pyproject.toml +2 -3
  3. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/app.py +2 -0
  4. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/build.py +4 -15
  5. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/config_utils.py +64 -7
  6. flwr_nightly-1.10.0.dev20240613/src/py/flwr/cli/install.py +211 -0
  7. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/utils.py +14 -0
  8. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/app.py +18 -10
  9. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/grpc_rere_client/client_interceptor.py +1 -1
  10. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/grpc_rere_client/connection.py +1 -2
  11. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/rest_client/connection.py +1 -2
  12. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/supernode/app.py +141 -38
  13. flwr_nightly-1.10.0.dev20240613/src/py/flwr/common/config.py +28 -0
  14. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/constant.py +2 -0
  15. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/object_ref.py +13 -9
  16. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/telemetry.py +4 -0
  17. flwr_nightly-1.10.0.dev20240613/src/py/flwr/proto/driver_pb2.py +45 -0
  18. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/driver_pb2_grpc.py +35 -0
  19. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/driver_pb2_grpc.pyi +14 -0
  20. flwr_nightly-1.10.0.dev20240613/src/py/flwr/proto/exec_pb2.py +30 -0
  21. flwr_nightly-1.10.0.dev20240613/src/py/flwr/proto/exec_pb2.pyi +32 -0
  22. flwr_nightly-1.10.0.dev20240613/src/py/flwr/proto/exec_pb2_grpc.py +67 -0
  23. flwr_nightly-1.10.0.dev20240613/src/py/flwr/proto/exec_pb2_grpc.pyi +27 -0
  24. flwr_nightly-1.10.0.dev20240613/src/py/flwr/proto/fleet_pb2.py +55 -0
  25. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/fleet_pb2.pyi +0 -42
  26. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/fleet_pb2_grpc.py +7 -6
  27. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/fleet_pb2_grpc.pyi +5 -4
  28. flwr_nightly-1.10.0.dev20240613/src/py/flwr/proto/run_pb2.py +30 -0
  29. flwr_nightly-1.10.0.dev20240613/src/py/flwr/proto/run_pb2.pyi +52 -0
  30. flwr_nightly-1.10.0.dev20240613/src/py/flwr/proto/task_pb2_grpc.py +4 -0
  31. flwr_nightly-1.10.0.dev20240613/src/py/flwr/proto/task_pb2_grpc.pyi +4 -0
  32. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/__init__.py +0 -4
  33. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/app.py +16 -186
  34. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/driver/driver_servicer.py +7 -0
  35. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +1 -2
  36. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +1 -2
  37. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py +5 -3
  38. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py +1 -1
  39. flwr_nightly-1.10.0.dev20240613/src/py/flwr/superexec/__init__.py +19 -0
  40. flwr_nightly-1.10.0.dev20240611/src/py/flwr/proto/driver_pb2.py +0 -44
  41. flwr_nightly-1.10.0.dev20240611/src/py/flwr/proto/fleet_pb2.py +0 -60
  42. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/LICENSE +0 -0
  43. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/README.md +0 -0
  44. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/__init__.py +0 -0
  45. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/__init__.py +0 -0
  46. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/example.py +0 -0
  47. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/__init__.py +0 -0
  48. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/new.py +0 -0
  49. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/__init__.py +0 -0
  50. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/.gitignore.tpl +0 -0
  51. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/README.md.tpl +0 -0
  52. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/__init__.py +0 -0
  53. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/__init__.py +0 -0
  54. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/__init__.py.tpl +0 -0
  55. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/client.hf.py.tpl +0 -0
  56. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/client.jax.py.tpl +0 -0
  57. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/client.mlx.py.tpl +0 -0
  58. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -0
  59. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -0
  60. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/client.sklearn.py.tpl +0 -0
  61. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -0
  62. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/server.hf.py.tpl +0 -0
  63. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/server.jax.py.tpl +0 -0
  64. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/server.mlx.py.tpl +0 -0
  65. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -0
  66. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -0
  67. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/server.sklearn.py.tpl +0 -0
  68. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -0
  69. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/task.hf.py.tpl +0 -0
  70. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/task.jax.py.tpl +0 -0
  71. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/task.mlx.py.tpl +0 -0
  72. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -0
  73. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +0 -0
  74. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/pyproject.hf.toml.tpl +0 -0
  75. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/pyproject.jax.toml.tpl +0 -0
  76. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +0 -0
  77. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +0 -0
  78. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +0 -0
  79. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +0 -0
  80. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +0 -0
  81. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/run/__init__.py +0 -0
  82. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/cli/run/run.py +0 -0
  83. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/__init__.py +0 -0
  84. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/client.py +0 -0
  85. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/client_app.py +0 -0
  86. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/dpfedavg_numpy_client.py +0 -0
  87. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/grpc_client/__init__.py +0 -0
  88. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/grpc_client/connection.py +0 -0
  89. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/grpc_rere_client/__init__.py +0 -0
  90. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/heartbeat.py +0 -0
  91. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/message_handler/__init__.py +0 -0
  92. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/message_handler/message_handler.py +0 -0
  93. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/message_handler/task_handler.py +0 -0
  94. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/mod/__init__.py +0 -0
  95. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/mod/centraldp_mods.py +0 -0
  96. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/mod/comms_mods.py +0 -0
  97. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/mod/localdp_mod.py +0 -0
  98. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/mod/secure_aggregation/__init__.py +0 -0
  99. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/mod/secure_aggregation/secagg_mod.py +0 -0
  100. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +0 -0
  101. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/mod/utils.py +0 -0
  102. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/node_state.py +0 -0
  103. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/node_state_tests.py +0 -0
  104. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/numpy_client.py +0 -0
  105. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/rest_client/__init__.py +0 -0
  106. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/supernode/__init__.py +0 -0
  107. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/client/typing.py +0 -0
  108. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/__init__.py +0 -0
  109. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/address.py +0 -0
  110. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/context.py +0 -0
  111. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/date.py +0 -0
  112. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/differential_privacy.py +0 -0
  113. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/differential_privacy_constants.py +0 -0
  114. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/dp.py +0 -0
  115. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/exit_handlers.py +0 -0
  116. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/grpc.py +0 -0
  117. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/logger.py +0 -0
  118. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/message.py +0 -0
  119. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/parameter.py +0 -0
  120. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/pyproject.py +0 -0
  121. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/record/__init__.py +0 -0
  122. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/record/configsrecord.py +0 -0
  123. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/record/conversion_utils.py +0 -0
  124. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/record/metricsrecord.py +0 -0
  125. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/record/parametersrecord.py +0 -0
  126. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/record/recordset.py +0 -0
  127. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/record/typeddict.py +0 -0
  128. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/recordset_compat.py +0 -0
  129. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/retry_invoker.py +0 -0
  130. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/secure_aggregation/__init__.py +0 -0
  131. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/secure_aggregation/crypto/__init__.py +0 -0
  132. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/secure_aggregation/crypto/shamir.py +0 -0
  133. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py +0 -0
  134. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py +0 -0
  135. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/secure_aggregation/quantization.py +0 -0
  136. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/secure_aggregation/secaggplus_constants.py +0 -0
  137. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/secure_aggregation/secaggplus_utils.py +0 -0
  138. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/serde.py +0 -0
  139. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/typing.py +0 -0
  140. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/common/version.py +0 -0
  141. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/__init__.py +0 -0
  142. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/driver_pb2.pyi +0 -0
  143. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/error_pb2.py +0 -0
  144. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/error_pb2.pyi +0 -0
  145. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/error_pb2_grpc.py +0 -0
  146. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/error_pb2_grpc.pyi +0 -0
  147. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/grpcadapter_pb2.py +0 -0
  148. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/grpcadapter_pb2.pyi +0 -0
  149. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/grpcadapter_pb2_grpc.py +0 -0
  150. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/grpcadapter_pb2_grpc.pyi +0 -0
  151. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/node_pb2.py +0 -0
  152. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/node_pb2.pyi +0 -0
  153. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/node_pb2_grpc.py +0 -0
  154. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/node_pb2_grpc.pyi +0 -0
  155. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/recordset_pb2.py +0 -0
  156. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/recordset_pb2.pyi +0 -0
  157. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/recordset_pb2_grpc.py +0 -0
  158. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/recordset_pb2_grpc.pyi +0 -0
  159. /flwr_nightly-1.10.0.dev20240611/src/py/flwr/proto/task_pb2_grpc.py → /flwr_nightly-1.10.0.dev20240613/src/py/flwr/proto/run_pb2_grpc.py +0 -0
  160. /flwr_nightly-1.10.0.dev20240611/src/py/flwr/proto/task_pb2_grpc.pyi → /flwr_nightly-1.10.0.dev20240613/src/py/flwr/proto/run_pb2_grpc.pyi +0 -0
  161. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/task_pb2.py +0 -0
  162. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/task_pb2.pyi +0 -0
  163. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/transport_pb2.py +0 -0
  164. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/transport_pb2.pyi +0 -0
  165. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/transport_pb2_grpc.py +0 -0
  166. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/proto/transport_pb2_grpc.pyi +0 -0
  167. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/py.typed +0 -0
  168. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/client_manager.py +0 -0
  169. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/client_proxy.py +0 -0
  170. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/compat/__init__.py +0 -0
  171. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/compat/app.py +0 -0
  172. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/compat/app_utils.py +0 -0
  173. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/compat/driver_client_proxy.py +0 -0
  174. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/compat/legacy_context.py +0 -0
  175. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/criterion.py +0 -0
  176. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/driver/__init__.py +0 -0
  177. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/driver/driver.py +0 -0
  178. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/driver/grpc_driver.py +0 -0
  179. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/driver/inmemory_driver.py +0 -0
  180. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/history.py +0 -0
  181. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/run_serverapp.py +0 -0
  182. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/server.py +0 -0
  183. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/server_app.py +0 -0
  184. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/server_config.py +0 -0
  185. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/__init__.py +0 -0
  186. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/aggregate.py +0 -0
  187. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/bulyan.py +0 -0
  188. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/dp_adaptive_clipping.py +0 -0
  189. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/dp_fixed_clipping.py +0 -0
  190. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/dpfedavg_adaptive.py +0 -0
  191. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/dpfedavg_fixed.py +0 -0
  192. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/fault_tolerant_fedavg.py +0 -0
  193. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/fedadagrad.py +0 -0
  194. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/fedadam.py +0 -0
  195. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/fedavg.py +0 -0
  196. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/fedavg_android.py +0 -0
  197. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/fedavgm.py +0 -0
  198. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/fedmedian.py +0 -0
  199. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/fedopt.py +0 -0
  200. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/fedprox.py +0 -0
  201. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/fedtrimmedavg.py +0 -0
  202. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/fedxgb_bagging.py +0 -0
  203. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/fedxgb_cyclic.py +0 -0
  204. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/fedxgb_nn_avg.py +0 -0
  205. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/fedyogi.py +0 -0
  206. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/krum.py +0 -0
  207. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/qfedavg.py +0 -0
  208. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/strategy/strategy.py +0 -0
  209. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/__init__.py +0 -0
  210. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/driver/__init__.py +0 -0
  211. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/driver/driver_grpc.py +0 -0
  212. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/__init__.py +0 -0
  213. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py +0 -0
  214. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +0 -0
  215. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +0 -0
  216. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +0 -0
  217. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +0 -0
  218. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/grpc_rere/__init__.py +0 -0
  219. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/message_handler/__init__.py +0 -0
  220. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/rest_rere/__init__.py +0 -0
  221. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/vce/__init__.py +0 -0
  222. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/vce/backend/__init__.py +0 -0
  223. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/vce/backend/backend.py +0 -0
  224. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/vce/backend/raybackend.py +0 -0
  225. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/fleet/vce/vce_api.py +0 -0
  226. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/state/__init__.py +0 -0
  227. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/state/in_memory_state.py +0 -0
  228. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/state/sqlite_state.py +0 -0
  229. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/state/state.py +0 -0
  230. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/state/state_factory.py +0 -0
  231. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/superlink/state/utils.py +0 -0
  232. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/typing.py +0 -0
  233. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/utils/__init__.py +0 -0
  234. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/utils/tensorboard.py +0 -0
  235. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/utils/validator.py +0 -0
  236. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/workflow/__init__.py +0 -0
  237. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/workflow/constant.py +0 -0
  238. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/workflow/default_workflows.py +0 -0
  239. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/workflow/secure_aggregation/__init__.py +0 -0
  240. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/workflow/secure_aggregation/secagg_workflow.py +0 -0
  241. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +0 -0
  242. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/simulation/__init__.py +0 -0
  243. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/simulation/app.py +0 -0
  244. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/simulation/ray_transport/__init__.py +0 -0
  245. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/simulation/ray_transport/ray_actor.py +0 -0
  246. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/simulation/ray_transport/ray_client_proxy.py +0 -0
  247. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/simulation/ray_transport/utils.py +0 -0
  248. {flwr_nightly-1.10.0.dev20240611 → flwr_nightly-1.10.0.dev20240613}/src/py/flwr/simulation/run_simulation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flwr-nightly
3
- Version: 1.10.0.dev20240611
3
+ Version: 1.10.0.dev20240613
4
4
  Summary: Flower: A Friendly Federated Learning Framework
5
5
  Home-page: https://flower.ai
6
6
  License: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "flwr-nightly"
7
- version = "1.10.0.dev20240611"
7
+ version = "1.10.0.dev20240613"
8
8
  description = "Flower: A Friendly Federated Learning Framework"
9
9
  license = "Apache-2.0"
10
10
  authors = ["The Flower Authors <hello@flower.ai>"]
@@ -53,9 +53,8 @@ exclude = [
53
53
 
54
54
  [tool.poetry.scripts]
55
55
  flwr = "flwr.cli.app:app"
56
- flower-driver-api = "flwr.server:run_driver_api"
57
- flower-fleet-api = "flwr.server:run_fleet_api"
58
56
  flower-superlink = "flwr.server:run_superlink"
57
+ flower-superexec = "flwr.superexec:run_superexec"
59
58
  flower-supernode = "flwr.client:run_supernode"
60
59
  flower-client-app = "flwr.client:run_client_app"
61
60
  flower-server-app = "flwr.server:run_server_app"
@@ -18,6 +18,7 @@ import typer
18
18
 
19
19
  from .build import build
20
20
  from .example import example
21
+ from .install import install
21
22
  from .new import new
22
23
  from .run import run
23
24
 
@@ -34,6 +35,7 @@ app.command()(new)
34
35
  app.command()(example)
35
36
  app.command()(run)
36
37
  app.command()(build)
38
+ app.command()(install)
37
39
 
38
40
  if __name__ == "__main__":
39
41
  app()
@@ -14,7 +14,6 @@
14
14
  # ==============================================================================
15
15
  """Flower command line interface `build` command."""
16
16
 
17
- import hashlib
18
17
  import os
19
18
  import zipfile
20
19
  from pathlib import Path
@@ -25,7 +24,7 @@ import typer
25
24
  from typing_extensions import Annotated
26
25
 
27
26
  from .config_utils import load_and_validate
28
- from .utils import is_valid_project_name
27
+ from .utils import get_sha256_hash, is_valid_project_name
29
28
 
30
29
 
31
30
  # pylint: disable=too-many-locals
@@ -34,7 +33,7 @@ def build(
34
33
  Optional[Path],
35
34
  typer.Option(help="The Flower project directory to bundle into a FAB"),
36
35
  ] = None,
37
- ) -> None:
36
+ ) -> str:
38
37
  """Build a Flower project into a Flower App Bundle (FAB).
39
38
 
40
39
  You can run `flwr build` without any argument to bundle the current directory:
@@ -115,7 +114,7 @@ def build(
115
114
  fab_file.write(file_path, archive_path)
116
115
 
117
116
  # Calculate file info
118
- sha256_hash = _get_sha256_hash(file_path)
117
+ sha256_hash = get_sha256_hash(file_path)
119
118
  file_size_bits = os.path.getsize(file_path) * 8 # size in bits
120
119
  list_file_content += f"{archive_path},{sha256_hash},{file_size_bits}\n"
121
120
 
@@ -126,17 +125,7 @@ def build(
126
125
  f"🎊 Successfully built {fab_filename}.", fg=typer.colors.GREEN, bold=True
127
126
  )
128
127
 
129
-
130
- def _get_sha256_hash(file_path: Path) -> str:
131
- """Calculate the SHA-256 hash of a file."""
132
- sha256 = hashlib.sha256()
133
- with open(file_path, "rb") as f:
134
- while True:
135
- data = f.read(65536) # Read in 64kB blocks
136
- if not data:
137
- break
138
- sha256.update(data)
139
- return sha256.hexdigest()
128
+ return fab_filename
140
129
 
141
130
 
142
131
  def _load_gitignore(directory: Path) -> pathspec.PathSpec:
@@ -14,16 +14,59 @@
14
14
  # ==============================================================================
15
15
  """Utility to validate the `pyproject.toml` file."""
16
16
 
17
+ import zipfile
18
+ from io import BytesIO
17
19
  from pathlib import Path
18
- from typing import Any, Dict, List, Optional, Tuple
20
+ from typing import IO, Any, Dict, List, Optional, Tuple, Union
19
21
 
20
22
  import tomli
21
23
 
22
24
  from flwr.common import object_ref
23
25
 
24
26
 
27
+ def get_fab_metadata(fab_file: Union[Path, bytes]) -> Tuple[str, str]:
28
+ """Extract the fab_id and the fab_version from a FAB file or path.
29
+
30
+ Parameters
31
+ ----------
32
+ fab_file : Union[Path, bytes]
33
+ The Flower App Bundle file to validate and extract the metadata from.
34
+ It can either be a path to the file or the file itself as bytes.
35
+
36
+ Returns
37
+ -------
38
+ Tuple[str, str]
39
+ The `fab_version` and `fab_id` of the given Flower App Bundle.
40
+ """
41
+ fab_file_archive: Union[Path, IO[bytes]]
42
+ if isinstance(fab_file, bytes):
43
+ fab_file_archive = BytesIO(fab_file)
44
+ elif isinstance(fab_file, Path):
45
+ fab_file_archive = fab_file
46
+ else:
47
+ raise ValueError("fab_file must be either a Path or bytes")
48
+
49
+ with zipfile.ZipFile(fab_file_archive, "r") as zipf:
50
+ with zipf.open("pyproject.toml") as file:
51
+ toml_content = file.read().decode("utf-8")
52
+
53
+ conf = load_from_string(toml_content)
54
+ if conf is None:
55
+ raise ValueError("Invalid TOML content in pyproject.toml")
56
+
57
+ is_valid, errors, _ = validate(conf)
58
+ if not is_valid:
59
+ raise ValueError(errors)
60
+
61
+ return (
62
+ conf["project"]["version"],
63
+ f"{conf['flower']['publisher']}/{conf['project']['name']}",
64
+ )
65
+
66
+
25
67
  def load_and_validate(
26
68
  path: Optional[Path] = None,
69
+ check_module: bool = True,
27
70
  ) -> Tuple[Optional[Dict[str, Any]], List[str], List[str]]:
28
71
  """Load and validate pyproject.toml as dict.
29
72
 
@@ -42,7 +85,7 @@ def load_and_validate(
42
85
  ]
43
86
  return (None, errors, [])
44
87
 
45
- is_valid, errors, warnings = validate(config)
88
+ is_valid, errors, warnings = validate(config, check_module)
46
89
 
47
90
  if not is_valid:
48
91
  return (None, errors, warnings)
@@ -62,8 +105,7 @@ def load(path: Optional[Path] = None) -> Optional[Dict[str, Any]]:
62
105
  return None
63
106
 
64
107
  with toml_path.open(encoding="utf-8") as toml_file:
65
- data = tomli.loads(toml_file.read())
66
- return data
108
+ return load_from_string(toml_file.read())
67
109
 
68
110
 
69
111
  # pylint: disable=too-many-branches
@@ -102,7 +144,9 @@ def validate_fields(config: Dict[str, Any]) -> Tuple[bool, List[str], List[str]]
102
144
  return len(errors) == 0, errors, warnings
103
145
 
104
146
 
105
- def validate(config: Dict[str, Any]) -> Tuple[bool, List[str], List[str]]:
147
+ def validate(
148
+ config: Dict[str, Any], check_module: bool = True
149
+ ) -> Tuple[bool, List[str], List[str]]:
106
150
  """Validate pyproject.toml."""
107
151
  is_valid, errors, warnings = validate_fields(config)
108
152
 
@@ -110,14 +154,27 @@ def validate(config: Dict[str, Any]) -> Tuple[bool, List[str], List[str]]:
110
154
  return False, errors, warnings
111
155
 
112
156
  # Validate serverapp
113
- is_valid, reason = object_ref.validate(config["flower"]["components"]["serverapp"])
157
+ is_valid, reason = object_ref.validate(
158
+ config["flower"]["components"]["serverapp"], check_module
159
+ )
114
160
  if not is_valid and isinstance(reason, str):
115
161
  return False, [reason], []
116
162
 
117
163
  # Validate clientapp
118
- is_valid, reason = object_ref.validate(config["flower"]["components"]["clientapp"])
164
+ is_valid, reason = object_ref.validate(
165
+ config["flower"]["components"]["clientapp"], check_module
166
+ )
119
167
 
120
168
  if not is_valid and isinstance(reason, str):
121
169
  return False, [reason], []
122
170
 
123
171
  return True, [], []
172
+
173
+
174
+ def load_from_string(toml_content: str) -> Optional[Dict[str, Any]]:
175
+ """Load TOML content from a string and return as dict."""
176
+ try:
177
+ data = tomli.loads(toml_content)
178
+ return data
179
+ except tomli.TOMLDecodeError:
180
+ return None
@@ -0,0 +1,211 @@
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 `install` command."""
16
+
17
+
18
+ import shutil
19
+ import tempfile
20
+ import zipfile
21
+ from io import BytesIO
22
+ from pathlib import Path
23
+ from typing import IO, Optional, Union
24
+
25
+ import typer
26
+ from typing_extensions import Annotated
27
+
28
+ from flwr.common.config import get_flwr_dir
29
+
30
+ from .config_utils import load_and_validate
31
+ from .utils import get_sha256_hash
32
+
33
+
34
+ def install(
35
+ source: Annotated[
36
+ Optional[Path],
37
+ typer.Argument(metavar="source", help="The source FAB file to install."),
38
+ ] = None,
39
+ flwr_dir: Annotated[
40
+ Optional[Path],
41
+ typer.Option(help="The desired install path."),
42
+ ] = None,
43
+ ) -> None:
44
+ """Install a Flower App Bundle.
45
+
46
+ It can be ran with a single FAB file argument:
47
+
48
+ ``flwr install ./target_project.fab``
49
+
50
+ The target install directory can be specified with ``--flwr-dir``:
51
+
52
+ ``flwr install ./target_project.fab --flwr-dir ./docs/flwr``
53
+
54
+ This will install ``target_project`` to ``./docs/flwr/``. By default,
55
+ ``flwr-dir`` is equal to:
56
+
57
+ - ``$FLWR_HOME/`` if ``$FLWR_HOME`` is defined
58
+ - ``$XDG_DATA_HOME/.flwr/`` if ``$XDG_DATA_HOME`` is defined
59
+ - ``$HOME/.flwr/`` in all other cases
60
+ """
61
+ if source is None:
62
+ source = Path(typer.prompt("Enter the source FAB file"))
63
+
64
+ source = source.resolve()
65
+ if not source.exists() or not source.is_file():
66
+ typer.secho(
67
+ f"❌ The source {source} does not exist or is not a file.",
68
+ fg=typer.colors.RED,
69
+ bold=True,
70
+ )
71
+ raise typer.Exit(code=1)
72
+
73
+ if source.suffix != ".fab":
74
+ typer.secho(
75
+ f"❌ The source {source} is not a `.fab` file.",
76
+ fg=typer.colors.RED,
77
+ bold=True,
78
+ )
79
+ raise typer.Exit(code=1)
80
+
81
+ install_from_fab(source, flwr_dir)
82
+
83
+
84
+ def install_from_fab(
85
+ fab_file: Union[Path, bytes],
86
+ flwr_dir: Optional[Path],
87
+ skip_prompt: bool = False,
88
+ ) -> Path:
89
+ """Install from a FAB file after extracting and validating."""
90
+ fab_file_archive: Union[Path, IO[bytes]]
91
+ fab_name: Optional[str]
92
+ if isinstance(fab_file, bytes):
93
+ fab_file_archive = BytesIO(fab_file)
94
+ fab_name = None
95
+ elif isinstance(fab_file, Path):
96
+ fab_file_archive = fab_file
97
+ fab_name = fab_file.stem
98
+ else:
99
+ raise ValueError("fab_file must be either a Path or bytes")
100
+
101
+ with tempfile.TemporaryDirectory() as tmpdir:
102
+ with zipfile.ZipFile(fab_file_archive, "r") as zipf:
103
+ zipf.extractall(tmpdir)
104
+ tmpdir_path = Path(tmpdir)
105
+ info_dir = tmpdir_path / ".info"
106
+ if not info_dir.exists():
107
+ typer.secho(
108
+ "❌ FAB file has incorrect format.",
109
+ fg=typer.colors.RED,
110
+ bold=True,
111
+ )
112
+ raise typer.Exit(code=1)
113
+
114
+ content_file = info_dir / "CONTENT"
115
+
116
+ if not content_file.exists() or not _verify_hashes(
117
+ content_file.read_text(), tmpdir_path
118
+ ):
119
+ typer.secho(
120
+ "❌ File hashes couldn't be verified.",
121
+ fg=typer.colors.RED,
122
+ bold=True,
123
+ )
124
+ raise typer.Exit(code=1)
125
+
126
+ shutil.rmtree(info_dir)
127
+
128
+ installed_path = validate_and_install(
129
+ tmpdir_path, fab_name, flwr_dir, skip_prompt
130
+ )
131
+
132
+ return installed_path
133
+
134
+
135
+ def validate_and_install(
136
+ project_dir: Path,
137
+ fab_name: Optional[str],
138
+ flwr_dir: Optional[Path],
139
+ skip_prompt: bool = False,
140
+ ) -> Path:
141
+ """Validate TOML files and install the project to the desired directory."""
142
+ config, _, _ = load_and_validate(project_dir / "pyproject.toml", check_module=False)
143
+
144
+ if config is None:
145
+ typer.secho(
146
+ "❌ Invalid config inside FAB file.",
147
+ fg=typer.colors.RED,
148
+ bold=True,
149
+ )
150
+ raise typer.Exit(code=1)
151
+
152
+ publisher = config["flower"]["publisher"]
153
+ project_name = config["project"]["name"]
154
+ version = config["project"]["version"]
155
+
156
+ if (
157
+ fab_name
158
+ and fab_name != f"{publisher}.{project_name}.{version.replace('.', '-')}"
159
+ ):
160
+ typer.secho(
161
+ "❌ FAB file has incorrect name. The file name must follow the format "
162
+ "`<publisher>.<project_name>.<version>.fab`.",
163
+ fg=typer.colors.RED,
164
+ bold=True,
165
+ )
166
+ raise typer.Exit(code=1)
167
+
168
+ install_dir: Path = (
169
+ (get_flwr_dir() if not flwr_dir else flwr_dir)
170
+ / "apps"
171
+ / publisher
172
+ / project_name
173
+ / version
174
+ )
175
+ if install_dir.exists() and not skip_prompt:
176
+ if not typer.confirm(
177
+ typer.style(
178
+ f"\n💬 {project_name} version {version} is already installed, "
179
+ "do you want to reinstall it?",
180
+ fg=typer.colors.MAGENTA,
181
+ bold=True,
182
+ )
183
+ ):
184
+ return install_dir
185
+
186
+ install_dir.mkdir(parents=True, exist_ok=True)
187
+
188
+ # Move contents from source directory
189
+ for item in project_dir.iterdir():
190
+ if item.is_dir():
191
+ shutil.copytree(item, install_dir / item.name, dirs_exist_ok=True)
192
+ else:
193
+ shutil.copy2(item, install_dir / item.name)
194
+
195
+ typer.secho(
196
+ f"🎊 Successfully installed {project_name} to {install_dir}.",
197
+ fg=typer.colors.GREEN,
198
+ bold=True,
199
+ )
200
+
201
+ return install_dir
202
+
203
+
204
+ def _verify_hashes(list_content: str, tmpdir: Path) -> bool:
205
+ """Verify file hashes based on the LIST content."""
206
+ for line in list_content.strip().split("\n"):
207
+ rel_path, hash_expected, _ = line.split(",")
208
+ file_path = tmpdir / rel_path
209
+ if not file_path.exists() or get_sha256_hash(file_path) != hash_expected:
210
+ return False
211
+ return True
@@ -14,7 +14,9 @@
14
14
  # ==============================================================================
15
15
  """Flower command line interface utils."""
16
16
 
17
+ import hashlib
17
18
  import re
19
+ from pathlib import Path
18
20
  from typing import Callable, List, Optional, cast
19
21
 
20
22
  import typer
@@ -122,3 +124,15 @@ def sanitize_project_name(name: str) -> str:
122
124
  sanitized_name = sanitized_name[1:]
123
125
 
124
126
  return sanitized_name
127
+
128
+
129
+ def get_sha256_hash(file_path: Path) -> str:
130
+ """Calculate the SHA-256 hash of a file."""
131
+ sha256 = hashlib.sha256()
132
+ with open(file_path, "rb") as f:
133
+ while True:
134
+ data = f.read(65536) # Read in 64kB blocks
135
+ if not data:
136
+ break
137
+ sha256.update(data)
138
+ return sha256.hexdigest()
@@ -19,7 +19,7 @@ import sys
19
19
  import time
20
20
  from dataclasses import dataclass
21
21
  from logging import DEBUG, ERROR, INFO, WARN
22
- from typing import Callable, ContextManager, Optional, Tuple, Type, Union
22
+ from typing import Callable, ContextManager, Dict, Optional, Tuple, Type, Union
23
23
 
24
24
  from cryptography.hazmat.primitives.asymmetric import ec
25
25
  from grpc import RpcError
@@ -177,7 +177,7 @@ def start_client(
177
177
  def _start_client_internal(
178
178
  *,
179
179
  server_address: str,
180
- load_client_app_fn: Optional[Callable[[], ClientApp]] = None,
180
+ load_client_app_fn: Optional[Callable[[str, str], ClientApp]] = None,
181
181
  client_fn: Optional[ClientFn] = None,
182
182
  client: Optional[Client] = None,
183
183
  grpc_max_message_length: int = GRPC_MAX_MESSAGE_LENGTH,
@@ -252,7 +252,7 @@ def _start_client_internal(
252
252
 
253
253
  client_fn = single_client_factory
254
254
 
255
- def _load_client_app() -> ClientApp:
255
+ def _load_client_app(_1: str, _2: str) -> ClientApp:
256
256
  return ClientApp(client_fn=client_fn)
257
257
 
258
258
  load_client_app_fn = _load_client_app
@@ -308,6 +308,8 @@ def _start_client_internal(
308
308
  )
309
309
 
310
310
  node_state = NodeState()
311
+ # run_id -> (fab_id, fab_version)
312
+ run_info: Dict[int, Tuple[str, str]] = {}
311
313
 
312
314
  while not app_state_tracker.interrupt:
313
315
  sleep_duration: int = 0
@@ -319,7 +321,6 @@ def _start_client_internal(
319
321
  root_certificates,
320
322
  authentication_keys,
321
323
  ) as conn:
322
- # pylint: disable-next=W0612
323
324
  receive, send, create_node, delete_node, get_run = conn
324
325
 
325
326
  # Register node
@@ -356,13 +357,20 @@ def _start_client_internal(
356
357
  send(out_message)
357
358
  break
358
359
 
360
+ # Get run info
361
+ run_id = message.metadata.run_id
362
+ if run_id not in run_info:
363
+ if get_run is not None:
364
+ run_info[run_id] = get_run(run_id)
365
+ # If get_run is None, i.e., in grpc-bidi mode
366
+ else:
367
+ run_info[run_id] = ("", "")
368
+
359
369
  # Register context for this run
360
- node_state.register_context(run_id=message.metadata.run_id)
370
+ node_state.register_context(run_id=run_id)
361
371
 
362
372
  # Retrieve context for this run
363
- context = node_state.retrieve_context(
364
- run_id=message.metadata.run_id
365
- )
373
+ context = node_state.retrieve_context(run_id=run_id)
366
374
 
367
375
  # Create an error reply message that will never be used to prevent
368
376
  # the used-before-assignment linting error
@@ -373,7 +381,7 @@ def _start_client_internal(
373
381
  # Handle app loading and task message
374
382
  try:
375
383
  # Load ClientApp instance
376
- client_app: ClientApp = load_client_app_fn()
384
+ client_app: ClientApp = load_client_app_fn(*run_info[run_id])
377
385
 
378
386
  # Execute ClientApp
379
387
  reply_message = client_app(message=message, context=context)
@@ -411,7 +419,7 @@ def _start_client_internal(
411
419
  else:
412
420
  # No exception, update node state
413
421
  node_state.update_context(
414
- run_id=message.metadata.run_id,
422
+ run_id=run_id,
415
423
  context=context,
416
424
  )
417
425
 
@@ -31,11 +31,11 @@ from flwr.common.secure_aggregation.crypto.symmetric_encryption import (
31
31
  from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
32
32
  CreateNodeRequest,
33
33
  DeleteNodeRequest,
34
- GetRunRequest,
35
34
  PingRequest,
36
35
  PullTaskInsRequest,
37
36
  PushTaskResRequest,
38
37
  )
38
+ from flwr.proto.run_pb2 import GetRunRequest # pylint: disable=E0611
39
39
 
40
40
  _PUBLIC_KEY_HEADER = "public-key"
41
41
  _AUTH_TOKEN_HEADER = "auth-token"
@@ -44,8 +44,6 @@ from flwr.common.serde import message_from_taskins, message_to_taskres
44
44
  from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
45
45
  CreateNodeRequest,
46
46
  DeleteNodeRequest,
47
- GetRunRequest,
48
- GetRunResponse,
49
47
  PingRequest,
50
48
  PingResponse,
51
49
  PullTaskInsRequest,
@@ -53,6 +51,7 @@ from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
53
51
  )
54
52
  from flwr.proto.fleet_pb2_grpc import FleetStub # pylint: disable=E0611
55
53
  from flwr.proto.node_pb2 import Node # pylint: disable=E0611
54
+ from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611
56
55
  from flwr.proto.task_pb2 import TaskIns # pylint: disable=E0611
57
56
 
58
57
  from .client_interceptor import AuthenticateClientInterceptor
@@ -46,8 +46,6 @@ from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
46
46
  CreateNodeResponse,
47
47
  DeleteNodeRequest,
48
48
  DeleteNodeResponse,
49
- GetRunRequest,
50
- GetRunResponse,
51
49
  PingRequest,
52
50
  PingResponse,
53
51
  PullTaskInsRequest,
@@ -56,6 +54,7 @@ from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
56
54
  PushTaskResResponse,
57
55
  )
58
56
  from flwr.proto.node_pb2 import Node # pylint: disable=E0611
57
+ from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611
59
58
  from flwr.proto.task_pb2 import TaskIns # pylint: disable=E0611
60
59
 
61
60
  try: