flwr-nightly 1.9.0.dev20240424__tar.gz → 1.9.0.dev20240426__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 (215) hide show
  1. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/PKG-INFO +1 -1
  2. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/pyproject.toml +1 -1
  3. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/config_utils.py +18 -46
  4. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/new.py +37 -17
  5. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/README.md.tpl +1 -1
  6. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/code/client.pytorch.py.tpl +1 -1
  7. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/code/server.pytorch.py.tpl +1 -1
  8. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +6 -3
  9. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +6 -3
  10. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +6 -3
  11. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +6 -3
  12. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/run/run.py +1 -1
  13. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/utils.py +18 -17
  14. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/compat/app_utils.py +1 -1
  15. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/compat/driver_client_proxy.py +27 -72
  16. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/driver/grpc_driver.py +17 -8
  17. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/run_serverapp.py +14 -0
  18. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/LICENSE +0 -0
  19. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/README.md +0 -0
  20. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/__init__.py +0 -0
  21. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/__init__.py +0 -0
  22. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/app.py +0 -0
  23. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/example.py +0 -0
  24. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/__init__.py +0 -0
  25. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/__init__.py +0 -0
  26. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/.gitignore.tpl +0 -0
  27. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/__init__.py +0 -0
  28. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/code/__init__.py +0 -0
  29. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/code/__init__.py.tpl +0 -0
  30. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -0
  31. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/code/client.sklearn.py.tpl +0 -0
  32. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -0
  33. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -0
  34. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/code/server.sklearn.py.tpl +0 -0
  35. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -0
  36. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -0
  37. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/cli/run/__init__.py +0 -0
  38. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/__init__.py +0 -0
  39. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/app.py +0 -0
  40. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/client.py +0 -0
  41. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/client_app.py +0 -0
  42. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/dpfedavg_numpy_client.py +0 -0
  43. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/grpc_client/__init__.py +0 -0
  44. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/grpc_client/connection.py +0 -0
  45. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/grpc_rere_client/__init__.py +0 -0
  46. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/grpc_rere_client/client_interceptor.py +0 -0
  47. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/grpc_rere_client/connection.py +0 -0
  48. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/heartbeat.py +0 -0
  49. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/message_handler/__init__.py +0 -0
  50. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/message_handler/message_handler.py +0 -0
  51. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/message_handler/task_handler.py +0 -0
  52. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/mod/__init__.py +0 -0
  53. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/mod/centraldp_mods.py +0 -0
  54. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/mod/comms_mods.py +0 -0
  55. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/mod/localdp_mod.py +0 -0
  56. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/mod/secure_aggregation/__init__.py +0 -0
  57. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/mod/secure_aggregation/secagg_mod.py +0 -0
  58. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +0 -0
  59. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/mod/utils.py +0 -0
  60. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/node_state.py +0 -0
  61. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/node_state_tests.py +0 -0
  62. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/numpy_client.py +0 -0
  63. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/rest_client/__init__.py +0 -0
  64. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/rest_client/connection.py +0 -0
  65. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/supernode/__init__.py +0 -0
  66. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/supernode/app.py +0 -0
  67. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/client/typing.py +0 -0
  68. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/__init__.py +0 -0
  69. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/address.py +0 -0
  70. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/constant.py +0 -0
  71. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/context.py +0 -0
  72. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/date.py +0 -0
  73. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/differential_privacy.py +0 -0
  74. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/differential_privacy_constants.py +0 -0
  75. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/dp.py +0 -0
  76. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/exit_handlers.py +0 -0
  77. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/grpc.py +0 -0
  78. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/logger.py +0 -0
  79. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/message.py +0 -0
  80. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/object_ref.py +0 -0
  81. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/parameter.py +0 -0
  82. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/pyproject.py +0 -0
  83. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/record/__init__.py +0 -0
  84. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/record/configsrecord.py +0 -0
  85. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/record/conversion_utils.py +0 -0
  86. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/record/metricsrecord.py +0 -0
  87. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/record/parametersrecord.py +0 -0
  88. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/record/recordset.py +0 -0
  89. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/record/typeddict.py +0 -0
  90. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/recordset_compat.py +0 -0
  91. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/retry_invoker.py +0 -0
  92. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/secure_aggregation/__init__.py +0 -0
  93. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/secure_aggregation/crypto/__init__.py +0 -0
  94. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/secure_aggregation/crypto/shamir.py +0 -0
  95. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py +0 -0
  96. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py +0 -0
  97. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/secure_aggregation/quantization.py +0 -0
  98. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/secure_aggregation/secaggplus_constants.py +0 -0
  99. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/secure_aggregation/secaggplus_utils.py +0 -0
  100. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/serde.py +0 -0
  101. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/telemetry.py +0 -0
  102. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/typing.py +0 -0
  103. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/common/version.py +0 -0
  104. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/__init__.py +0 -0
  105. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/driver_pb2.py +0 -0
  106. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/driver_pb2.pyi +0 -0
  107. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/driver_pb2_grpc.py +0 -0
  108. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/driver_pb2_grpc.pyi +0 -0
  109. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/error_pb2.py +0 -0
  110. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/error_pb2.pyi +0 -0
  111. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/error_pb2_grpc.py +0 -0
  112. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/error_pb2_grpc.pyi +0 -0
  113. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/fleet_pb2.py +0 -0
  114. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/fleet_pb2.pyi +0 -0
  115. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/fleet_pb2_grpc.py +0 -0
  116. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/fleet_pb2_grpc.pyi +0 -0
  117. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/node_pb2.py +0 -0
  118. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/node_pb2.pyi +0 -0
  119. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/node_pb2_grpc.py +0 -0
  120. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/node_pb2_grpc.pyi +0 -0
  121. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/recordset_pb2.py +0 -0
  122. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/recordset_pb2.pyi +0 -0
  123. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/recordset_pb2_grpc.py +0 -0
  124. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/recordset_pb2_grpc.pyi +0 -0
  125. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/task_pb2.py +0 -0
  126. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/task_pb2.pyi +0 -0
  127. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/task_pb2_grpc.py +0 -0
  128. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/task_pb2_grpc.pyi +0 -0
  129. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/transport_pb2.py +0 -0
  130. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/transport_pb2.pyi +0 -0
  131. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/transport_pb2_grpc.py +0 -0
  132. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/proto/transport_pb2_grpc.pyi +0 -0
  133. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/py.typed +0 -0
  134. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/__init__.py +0 -0
  135. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/app.py +0 -0
  136. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/client_manager.py +0 -0
  137. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/client_proxy.py +0 -0
  138. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/compat/__init__.py +0 -0
  139. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/compat/app.py +0 -0
  140. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/compat/legacy_context.py +0 -0
  141. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/criterion.py +0 -0
  142. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/driver/__init__.py +0 -0
  143. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/driver/driver.py +0 -0
  144. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/history.py +0 -0
  145. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/server.py +0 -0
  146. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/server_app.py +0 -0
  147. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/server_config.py +0 -0
  148. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/__init__.py +0 -0
  149. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/aggregate.py +0 -0
  150. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/bulyan.py +0 -0
  151. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/dp_adaptive_clipping.py +0 -0
  152. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/dp_fixed_clipping.py +0 -0
  153. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/dpfedavg_adaptive.py +0 -0
  154. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/dpfedavg_fixed.py +0 -0
  155. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/fault_tolerant_fedavg.py +0 -0
  156. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/fedadagrad.py +0 -0
  157. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/fedadam.py +0 -0
  158. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/fedavg.py +0 -0
  159. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/fedavg_android.py +0 -0
  160. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/fedavgm.py +0 -0
  161. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/fedmedian.py +0 -0
  162. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/fedopt.py +0 -0
  163. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/fedprox.py +0 -0
  164. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/fedtrimmedavg.py +0 -0
  165. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/fedxgb_bagging.py +0 -0
  166. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/fedxgb_cyclic.py +0 -0
  167. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/fedxgb_nn_avg.py +0 -0
  168. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/fedyogi.py +0 -0
  169. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/krum.py +0 -0
  170. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/qfedavg.py +0 -0
  171. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/strategy/strategy.py +0 -0
  172. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/__init__.py +0 -0
  173. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/driver/__init__.py +0 -0
  174. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/driver/driver_grpc.py +0 -0
  175. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/driver/driver_servicer.py +0 -0
  176. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/__init__.py +0 -0
  177. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py +0 -0
  178. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +0 -0
  179. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +0 -0
  180. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +0 -0
  181. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +0 -0
  182. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/grpc_rere/__init__.py +0 -0
  183. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +0 -0
  184. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/message_handler/__init__.py +0 -0
  185. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py +0 -0
  186. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/rest_rere/__init__.py +0 -0
  187. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py +0 -0
  188. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/vce/__init__.py +0 -0
  189. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/vce/backend/__init__.py +0 -0
  190. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/vce/backend/backend.py +0 -0
  191. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/vce/backend/raybackend.py +0 -0
  192. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/fleet/vce/vce_api.py +0 -0
  193. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/state/__init__.py +0 -0
  194. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/state/in_memory_state.py +0 -0
  195. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/state/sqlite_state.py +0 -0
  196. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/state/state.py +0 -0
  197. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/state/state_factory.py +0 -0
  198. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/superlink/state/utils.py +0 -0
  199. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/typing.py +0 -0
  200. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/utils/__init__.py +0 -0
  201. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/utils/tensorboard.py +0 -0
  202. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/utils/validator.py +0 -0
  203. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/workflow/__init__.py +0 -0
  204. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/workflow/constant.py +0 -0
  205. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/workflow/default_workflows.py +0 -0
  206. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/workflow/secure_aggregation/__init__.py +0 -0
  207. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/workflow/secure_aggregation/secagg_workflow.py +0 -0
  208. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +0 -0
  209. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/simulation/__init__.py +0 -0
  210. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/simulation/app.py +0 -0
  211. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/simulation/ray_transport/__init__.py +0 -0
  212. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/simulation/ray_transport/ray_actor.py +0 -0
  213. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/simulation/ray_transport/ray_client_proxy.py +0 -0
  214. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/src/py/flwr/simulation/ray_transport/utils.py +0 -0
  215. {flwr_nightly-1.9.0.dev20240424 → flwr_nightly-1.9.0.dev20240426}/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.9.0.dev20240424
3
+ Version: 1.9.0.dev20240426
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.9.0.dev20240424"
7
+ version = "1.9.0.dev20240426"
8
8
  description = "Flower: A Friendly Federated Learning Framework"
9
9
  license = "Apache-2.0"
10
10
  authors = ["The Flower Authors <hello@flower.ai>"]
@@ -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[str] = None,
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. pyproject.toml does not exist."
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[str] = None) -> Optional[Dict[str, Any]]:
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 = os.getcwd()
97
- toml_path = os.path.join(cur_dir, "pyproject.toml")
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 os.path.isfile(toml_path):
69
+ if not toml_path.is_file():
102
70
  return None
103
71
 
104
- with open(toml_path, encoding="utf-8") as toml_file:
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 "serverapp" not in config["flower"]["components"]:
134
- errors.append('Property "serverapp" missing in [flower.components]')
135
- if "clientapp" not in config["flower"]["components"]:
136
- errors.append('Property "clientapp" missing in [flower.components]')
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
 
@@ -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
@@ -86,25 +87,24 @@ def new(
86
87
  Optional[MlFramework],
87
88
  typer.Option(case_sensitive=False, help="The ML framework to use"),
88
89
  ] = None,
90
+ username: Annotated[
91
+ Optional[str],
92
+ typer.Option(case_sensitive=False, help="The Flower username of the author"),
93
+ ] = None,
89
94
  ) -> None:
90
95
  """Create new Flower project."""
91
96
  if project_name is None:
92
- project_name = prompt_text("Please provide project name")
97
+ project_name = prompt_text("Please provide the project name")
93
98
  if not is_valid_project_name(project_name):
94
99
  project_name = prompt_text(
95
100
  "Please provide a name that only contains "
96
- "characters in {'_', 'a-zA-Z', '0-9'}",
101
+ "characters in {'-', a-zA-Z', '0-9'}",
97
102
  predicate=is_valid_project_name,
98
103
  default=sanitize_project_name(project_name),
99
104
  )
100
105
 
101
- print(
102
- typer.style(
103
- f"🔨 Creating Flower project {project_name}...",
104
- fg=typer.colors.GREEN,
105
- bold=True,
106
- )
107
- )
106
+ if username is None:
107
+ username = prompt_text("Please provide your Flower username")
108
108
 
109
109
  if framework is not None:
110
110
  framework_str = str(framework.value)
@@ -122,19 +122,32 @@ def new(
122
122
 
123
123
  framework_str = framework_str.lower()
124
124
 
125
+ print(
126
+ typer.style(
127
+ f"\n🔨 Creating Flower project {project_name}...",
128
+ fg=typer.colors.GREEN,
129
+ bold=True,
130
+ )
131
+ )
132
+
125
133
  # Set project directory path
126
134
  cwd = os.getcwd()
127
- pnl = project_name.lower()
128
- project_dir = os.path.join(cwd, pnl)
135
+ package_name = re.sub(r"[-_.]+", "-", project_name).lower()
136
+ import_name = package_name.replace("-", "_")
137
+ project_dir = os.path.join(cwd, package_name)
129
138
 
130
139
  # List of files to render
131
140
  files = {
132
141
  ".gitignore": {"template": "app/.gitignore.tpl"},
133
142
  "README.md": {"template": "app/README.md.tpl"},
134
143
  "pyproject.toml": {"template": f"app/pyproject.{framework_str}.toml.tpl"},
135
- f"{pnl}/__init__.py": {"template": "app/code/__init__.py.tpl"},
136
- f"{pnl}/server.py": {"template": f"app/code/server.{framework_str}.py.tpl"},
137
- f"{pnl}/client.py": {"template": f"app/code/client.{framework_str}.py.tpl"},
144
+ f"{import_name}/__init__.py": {"template": "app/code/__init__.py.tpl"},
145
+ f"{import_name}/server.py": {
146
+ "template": f"app/code/server.{framework_str}.py.tpl"
147
+ },
148
+ f"{import_name}/client.py": {
149
+ "template": f"app/code/client.{framework_str}.py.tpl"
150
+ },
138
151
  }
139
152
 
140
153
  # Depending on the framework, generate task.py file
@@ -142,9 +155,16 @@ def new(
142
155
  MlFramework.PYTORCH.value.lower(),
143
156
  ]
144
157
  if framework_str in frameworks_with_tasks:
145
- files[f"{pnl}/task.py"] = {"template": f"app/code/task.{framework_str}.py.tpl"}
146
-
147
- context = {"project_name": project_name}
158
+ files[f"{import_name}/task.py"] = {
159
+ "template": f"app/code/task.{framework_str}.py.tpl"
160
+ }
161
+
162
+ context = {
163
+ "project_name": project_name,
164
+ "package_name": package_name,
165
+ "import_name": import_name.replace("-", "_"),
166
+ "username": username,
167
+ }
148
168
 
149
169
  for file_path, value in files.items():
150
170
  render_and_create(
@@ -8,7 +8,7 @@ pip install .
8
8
 
9
9
  ## Run (Simulation Engine)
10
10
 
11
- In the `$project_name` directory, use `flwr run` to run a local simulation:
11
+ In the `$import_name` directory, use `flwr run` to run a local simulation:
12
12
 
13
13
  ```bash
14
14
  flwr run
@@ -2,7 +2,7 @@
2
2
 
3
3
  from flwr.client import NumPyClient, ClientApp
4
4
 
5
- from $project_name.task import (
5
+ from $import_name.task import (
6
6
  Net,
7
7
  DEVICE,
8
8
  load_data,
@@ -4,7 +4,7 @@ from flwr.common import ndarrays_to_parameters
4
4
  from flwr.server import ServerApp, ServerConfig
5
5
  from flwr.server.strategy import FedAvg
6
6
 
7
- from $project_name.task import Net, get_weights
7
+ from $import_name.task import Net, get_weights
8
8
 
9
9
 
10
10
  # Initialize model parameters
@@ -3,7 +3,7 @@ requires = ["hatchling"]
3
3
  build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
- name = "$project_name"
6
+ name = "$package_name"
7
7
  version = "1.0.0"
8
8
  description = ""
9
9
  authors = [
@@ -18,6 +18,9 @@ dependencies = [
18
18
  [tool.hatch.build.targets.wheel]
19
19
  packages = ["."]
20
20
 
21
+ [flower]
22
+ publisher = "$username"
23
+
21
24
  [flower.components]
22
- serverapp = "$project_name.server:app"
23
- clientapp = "$project_name.client:app"
25
+ serverapp = "$import_name.server:app"
26
+ clientapp = "$import_name.client:app"
@@ -3,7 +3,7 @@ requires = ["hatchling"]
3
3
  build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
- name = "$project_name"
6
+ name = "$package_name"
7
7
  version = "1.0.0"
8
8
  description = ""
9
9
  authors = [
@@ -20,6 +20,9 @@ dependencies = [
20
20
  [tool.hatch.build.targets.wheel]
21
21
  packages = ["."]
22
22
 
23
+ [flower]
24
+ publisher = "$username"
25
+
23
26
  [flower.components]
24
- serverapp = "$project_name.server:app"
25
- clientapp = "$project_name.client:app"
27
+ serverapp = "$import_name.server:app"
28
+ clientapp = "$import_name.client:app"
@@ -3,7 +3,7 @@ requires = ["hatchling"]
3
3
  build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
- name = "$project_name"
6
+ name = "$package_name"
7
7
  version = "1.0.0"
8
8
  description = ""
9
9
  authors = [
@@ -19,6 +19,9 @@ dependencies = [
19
19
  [tool.hatch.build.targets.wheel]
20
20
  packages = ["."]
21
21
 
22
+ [flower]
23
+ publisher = "$username"
24
+
22
25
  [flower.components]
23
- serverapp = "$project_name.server:app"
24
- clientapp = "$project_name.client:app"
26
+ serverapp = "$import_name.server:app"
27
+ clientapp = "$import_name.client:app"
@@ -3,7 +3,7 @@ requires = ["hatchling"]
3
3
  build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
- name = "$project_name"
6
+ name = "$package_name"
7
7
  version = "1.0.0"
8
8
  description = ""
9
9
  authors = [
@@ -19,6 +19,9 @@ dependencies = [
19
19
  [tool.hatch.build.targets.wheel]
20
20
  packages = ["."]
21
21
 
22
+ [flower]
23
+ publisher = "$username"
24
+
22
25
  [flower.components]
23
- serverapp = "$project_name.server:app"
24
- clientapp = "$project_name.client:app"
26
+ serverapp = "$import_name.server:app"
27
+ clientapp = "$import_name.client:app"
@@ -30,7 +30,7 @@ def run() -> None:
30
30
 
31
31
  if config is None:
32
32
  typer.secho(
33
- "Project configuration could not be loaded.\nflower.toml is invalid:\n"
33
+ "Project configuration could not be loaded.\npyproject.toml is invalid:\n"
34
34
  + "\n".join([f"- {line}" for line in errors]),
35
35
  fg=typer.colors.RED,
36
36
  bold=True,
@@ -14,6 +14,7 @@
14
14
  # ==============================================================================
15
15
  """Flower command line interface utils."""
16
16
 
17
+ import re
17
18
  from typing import Callable, List, Optional, cast
18
19
 
19
20
  import typer
@@ -73,51 +74,51 @@ def prompt_options(text: str, options: List[str]) -> str:
73
74
 
74
75
 
75
76
  def is_valid_project_name(name: str) -> bool:
76
- """Check if the given string is a valid Python module name.
77
+ """Check if the given string is a valid Python project name.
77
78
 
78
- A valid module name must start with a letter or an underscore, and can only contain
79
- letters, digits, and underscores.
79
+ A valid project name must start with a letter and can only contain letters, digits,
80
+ and hyphens.
80
81
  """
81
82
  if not name:
82
83
  return False
83
84
 
84
- # Check if the first character is a letter or underscore
85
- if not (name[0].isalpha() or name[0] == "_"):
85
+ # Check if the first character is a letter
86
+ if not name[0].isalpha():
86
87
  return False
87
88
 
88
- # Check if the rest of the characters are valid (letter, digit, or underscore)
89
+ # Check if the rest of the characters are valid (letter, digit, or dash)
89
90
  for char in name[1:]:
90
- if not (char.isalnum() or char == "_"):
91
+ if not (char.isalnum() or char in "-"):
91
92
  return False
92
93
 
93
94
  return True
94
95
 
95
96
 
96
97
  def sanitize_project_name(name: str) -> str:
97
- """Sanitize the given string to make it a valid Python module name.
98
+ """Sanitize the given string to make it a valid Python project name.
98
99
 
99
- This version replaces hyphens with underscores, removes any characters not allowed
100
- in Python module names, makes the string lowercase, and ensures it starts with a
101
- valid character.
100
+ This version replaces spaces, dots, slashes, and underscores with dashes, removes
101
+ any characters not allowed in Python project names, makes the string lowercase, and
102
+ ensures it starts with a valid character.
102
103
  """
103
- # Replace '-' with '_'
104
- name_with_underscores = name.replace("-", "_").replace(" ", "_")
104
+ # Replace whitespace with '_'
105
+ name_with_hyphens = re.sub(r"[ ./_]", "-", name)
105
106
 
106
107
  # Allowed characters in a module name: letters, digits, underscore
107
108
  allowed_chars = set(
108
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
109
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-"
109
110
  )
110
111
 
111
112
  # Make the string lowercase
112
- sanitized_name = name_with_underscores.lower()
113
+ sanitized_name = name_with_hyphens.lower()
113
114
 
114
115
  # Remove any characters not allowed in Python module names
115
116
  sanitized_name = "".join(c for c in sanitized_name if c in allowed_chars)
116
117
 
117
118
  # Ensure the first character is a letter or underscore
118
- if sanitized_name and (
119
+ while sanitized_name and (
119
120
  sanitized_name[0].isdigit() or sanitized_name[0] not in allowed_chars
120
121
  ):
121
- sanitized_name = "_" + sanitized_name
122
+ sanitized_name = sanitized_name[1:]
122
123
 
123
124
  return sanitized_name
@@ -89,7 +89,7 @@ def _update_client_manager(
89
89
  for node_id in new_nodes:
90
90
  client_proxy = DriverClientProxy(
91
91
  node_id=node_id,
92
- driver=driver.grpc_driver_helper, # type: ignore
92
+ driver=driver,
93
93
  anonymous=False,
94
94
  run_id=driver.run_id, # type: ignore
95
95
  )
@@ -16,16 +16,14 @@
16
16
 
17
17
 
18
18
  import time
19
- from typing import List, Optional
19
+ from typing import Optional
20
20
 
21
21
  from flwr import common
22
- from flwr.common import DEFAULT_TTL, MessageType, MessageTypeLegacy, RecordSet
22
+ from flwr.common import Message, MessageType, MessageTypeLegacy, RecordSet
23
23
  from flwr.common import recordset_compat as compat
24
- from flwr.common import serde
25
- from flwr.proto import driver_pb2, node_pb2, task_pb2 # pylint: disable=E0611
26
24
  from flwr.server.client_proxy import ClientProxy
27
25
 
28
- from ..driver.grpc_driver import GrpcDriverHelper
26
+ from ..driver.driver import Driver
29
27
 
30
28
  SLEEP_TIME = 1
31
29
 
@@ -33,9 +31,7 @@ SLEEP_TIME = 1
33
31
  class DriverClientProxy(ClientProxy):
34
32
  """Flower client proxy which delegates work using the Driver API."""
35
33
 
36
- def __init__(
37
- self, node_id: int, driver: GrpcDriverHelper, anonymous: bool, run_id: int
38
- ):
34
+ def __init__(self, node_id: int, driver: Driver, anonymous: bool, run_id: int):
39
35
  super().__init__(str(node_id))
40
36
  self.node_id = node_id
41
37
  self.driver = driver
@@ -116,80 +112,39 @@ class DriverClientProxy(ClientProxy):
116
112
  timeout: Optional[float],
117
113
  group_id: Optional[int],
118
114
  ) -> RecordSet:
119
- task_ins = task_pb2.TaskIns( # pylint: disable=E1101
120
- task_id="",
121
- group_id=str(group_id) if group_id is not None else "",
122
- run_id=self.run_id,
123
- task=task_pb2.Task( # pylint: disable=E1101
124
- producer=node_pb2.Node( # pylint: disable=E1101
125
- node_id=0,
126
- anonymous=True,
127
- ),
128
- consumer=node_pb2.Node( # pylint: disable=E1101
129
- node_id=self.node_id,
130
- anonymous=self.anonymous,
131
- ),
132
- task_type=task_type,
133
- recordset=serde.recordset_to_proto(recordset),
134
- ttl=DEFAULT_TTL,
135
- ),
136
- )
137
-
138
- # This would normally be recorded upon common.Message creation
139
- # but this compatibility stack doesn't create Messages,
140
- # so we need to inject `created_at` manually (needed for
141
- # taskins validation by server.utils.validator)
142
- task_ins.task.created_at = time.time()
143
115
 
144
- push_task_ins_req = driver_pb2.PushTaskInsRequest( # pylint: disable=E1101
145
- task_ins_list=[task_ins]
116
+ # Create message
117
+ message = self.driver.create_message(
118
+ content=recordset,
119
+ message_type=task_type,
120
+ dst_node_id=self.node_id,
121
+ group_id=str(group_id) if group_id else "",
122
+ ttl=timeout,
146
123
  )
147
124
 
148
- # Send TaskIns to Driver API
149
- push_task_ins_res = self.driver.push_task_ins(req=push_task_ins_req)
150
-
151
- if len(push_task_ins_res.task_ids) != 1:
152
- raise ValueError("Unexpected number of task_ids")
125
+ # Push message
126
+ message_ids = list(self.driver.push_messages(messages=[message]))
127
+ if len(message_ids) != 1:
128
+ raise ValueError("Unexpected number of message_ids")
153
129
 
154
- task_id = push_task_ins_res.task_ids[0]
155
- if task_id == "":
156
- raise ValueError(f"Failed to schedule task for node {self.node_id}")
130
+ message_id = message_ids[0]
131
+ if message_id == "":
132
+ raise ValueError(f"Failed to send message to node {self.node_id}")
157
133
 
158
134
  if timeout:
159
135
  start_time = time.time()
160
136
 
161
137
  while True:
162
- pull_task_res_req = driver_pb2.PullTaskResRequest( # pylint: disable=E1101
163
- node=node_pb2.Node(node_id=0, anonymous=True), # pylint: disable=E1101
164
- task_ids=[task_id],
165
- )
166
-
167
- # Ask Driver API for TaskRes
168
- pull_task_res_res = self.driver.pull_task_res(req=pull_task_res_req)
169
-
170
- task_res_list: List[task_pb2.TaskRes] = list( # pylint: disable=E1101
171
- pull_task_res_res.task_res_list
172
- )
173
- if len(task_res_list) == 1:
174
- task_res = task_res_list[0]
175
-
176
- # This will raise an Exception if task_res carries an `error`
177
- validate_task_res(task_res=task_res)
178
-
179
- return serde.recordset_from_proto(task_res.task.recordset)
138
+ messages = list(self.driver.pull_messages(message_ids))
139
+ if len(messages) == 1:
140
+ msg: Message = messages[0]
141
+ if msg.has_error():
142
+ raise ValueError(
143
+ f"Message contains an Error (reason: {msg.error.reason}). "
144
+ "It originated during client-side execution of a message."
145
+ )
146
+ return msg.content
180
147
 
181
148
  if timeout is not None and time.time() > start_time + timeout:
182
149
  raise RuntimeError("Timeout reached")
183
150
  time.sleep(SLEEP_TIME)
184
-
185
-
186
- def validate_task_res(
187
- task_res: task_pb2.TaskRes, # pylint: disable=E1101
188
- ) -> None:
189
- """Validate if a TaskRes is empty or not."""
190
- if not task_res.HasField("task"):
191
- raise ValueError("Invalid TaskRes, field `task` missing")
192
- if task_res.task.HasField("error"):
193
- raise ValueError("Exception during client-side task execution")
194
- if not task_res.task.HasField("recordset"):
195
- raise ValueError("Invalid TaskRes, both `recordset` and `error` are missing")
@@ -151,31 +151,40 @@ class GrpcDriver(Driver):
151
151
  * CA certificate.
152
152
  * server certificate.
153
153
  * server private key.
154
+ fab_id : str (default: None)
155
+ The identifier of the FAB used in the run.
156
+ fab_version : str (default: None)
157
+ The version of the FAB used in the run.
154
158
  """
155
159
 
156
160
  def __init__(
157
161
  self,
158
162
  driver_service_address: str = DEFAULT_SERVER_ADDRESS_DRIVER,
159
163
  root_certificates: Optional[bytes] = None,
164
+ fab_id: Optional[str] = None,
165
+ fab_version: Optional[str] = None,
160
166
  ) -> None:
161
167
  self.addr = driver_service_address
162
168
  self.root_certificates = root_certificates
163
- self.grpc_driver_helper: Optional[GrpcDriverHelper] = None
169
+ self.driver_helper: Optional[GrpcDriverHelper] = None
164
170
  self.run_id: Optional[int] = None
171
+ self.fab_id = fab_id if fab_id is not None else ""
172
+ self.fab_version = fab_version if fab_version is not None else ""
165
173
  self.node = Node(node_id=0, anonymous=True)
166
174
 
167
175
  def _get_grpc_driver_helper_and_run_id(self) -> Tuple[GrpcDriverHelper, int]:
168
176
  # Check if the GrpcDriverHelper is initialized
169
- if self.grpc_driver_helper is None or self.run_id is None:
177
+ if self.driver_helper is None or self.run_id is None:
170
178
  # Connect and create run
171
- self.grpc_driver_helper = GrpcDriverHelper(
179
+ self.driver_helper = GrpcDriverHelper(
172
180
  driver_service_address=self.addr,
173
181
  root_certificates=self.root_certificates,
174
182
  )
175
- self.grpc_driver_helper.connect()
176
- res = self.grpc_driver_helper.create_run(CreateRunRequest())
183
+ self.driver_helper.connect()
184
+ req = CreateRunRequest(fab_id=self.fab_id, fab_version=self.fab_version)
185
+ res = self.driver_helper.create_run(req)
177
186
  self.run_id = res.run_id
178
- return self.grpc_driver_helper, self.run_id
187
+ return self.driver_helper, self.run_id
179
188
 
180
189
  def _check_message(self, message: Message) -> None:
181
190
  # Check if the message is valid
@@ -300,7 +309,7 @@ class GrpcDriver(Driver):
300
309
  def close(self) -> None:
301
310
  """Disconnect from the SuperLink if connected."""
302
311
  # Check if GrpcDriverHelper is initialized
303
- if self.grpc_driver_helper is None:
312
+ if self.driver_helper is None:
304
313
  return
305
314
  # Disconnect
306
- self.grpc_driver_helper.disconnect()
315
+ self.driver_helper.disconnect()
@@ -132,6 +132,8 @@ def run_server_app() -> None:
132
132
  driver = GrpcDriver(
133
133
  driver_service_address=args.server,
134
134
  root_certificates=root_certificates,
135
+ fab_id=args.fab_id,
136
+ fab_version=args.fab_version,
135
137
  )
136
138
 
137
139
  # Run the ServerApp with the Driver
@@ -183,5 +185,17 @@ def _parse_args_run_server_app() -> argparse.ArgumentParser:
183
185
  "app from there."
184
186
  " Default: current working directory.",
185
187
  )
188
+ parser.add_argument(
189
+ "--fab-id",
190
+ default=None,
191
+ type=str,
192
+ help="The identifier of the FAB used in the run.",
193
+ )
194
+ parser.add_argument(
195
+ "--fab-version",
196
+ default=None,
197
+ type=str,
198
+ help="The version of the FAB used in the run.",
199
+ )
186
200
 
187
201
  return parser