flwr-nightly 1.9.0.dev20240417__tar.gz → 1.9.0.dev20240418__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 (211) hide show
  1. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/PKG-INFO +1 -1
  2. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/pyproject.toml +1 -1
  3. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/new.py +9 -4
  4. flwr_nightly-1.9.0.dev20240418/src/py/flwr/cli/new/templates/app/.gitignore.tpl +160 -0
  5. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/rest_client/connection.py +6 -6
  6. flwr_nightly-1.9.0.dev20240418/src/py/flwr/common/record/recordset.py +118 -0
  7. flwr_nightly-1.9.0.dev20240418/src/py/flwr/server/driver/abc_driver.py +140 -0
  8. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/driver/driver_servicer.py +1 -1
  9. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/state/in_memory_state.py +13 -4
  10. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/state/sqlite_state.py +17 -5
  11. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/state/state.py +21 -3
  12. flwr_nightly-1.9.0.dev20240417/src/py/flwr/common/record/recordset.py +0 -79
  13. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/LICENSE +0 -0
  14. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/README.md +0 -0
  15. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/__init__.py +0 -0
  16. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/__init__.py +0 -0
  17. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/app.py +0 -0
  18. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/config_utils.py +0 -0
  19. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/example.py +0 -0
  20. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/__init__.py +0 -0
  21. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/templates/__init__.py +0 -0
  22. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/templates/app/README.md.tpl +0 -0
  23. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/templates/app/__init__.py +0 -0
  24. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/templates/app/code/__init__.py +0 -0
  25. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/templates/app/code/__init__.py.tpl +0 -0
  26. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -0
  27. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -0
  28. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -0
  29. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -0
  30. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -0
  31. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -0
  32. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -0
  33. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +0 -0
  34. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +0 -0
  35. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +0 -0
  36. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/run/__init__.py +0 -0
  37. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/run/run.py +0 -0
  38. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/cli/utils.py +0 -0
  39. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/__init__.py +0 -0
  40. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/app.py +0 -0
  41. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/client.py +0 -0
  42. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/client_app.py +0 -0
  43. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/dpfedavg_numpy_client.py +0 -0
  44. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/grpc_client/__init__.py +0 -0
  45. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/grpc_client/connection.py +0 -0
  46. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/grpc_rere_client/__init__.py +0 -0
  47. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/grpc_rere_client/connection.py +0 -0
  48. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/heartbeat.py +0 -0
  49. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/message_handler/__init__.py +0 -0
  50. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/message_handler/message_handler.py +0 -0
  51. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/message_handler/task_handler.py +0 -0
  52. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/mod/__init__.py +0 -0
  53. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/mod/centraldp_mods.py +0 -0
  54. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/mod/comms_mods.py +0 -0
  55. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/mod/localdp_mod.py +0 -0
  56. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/mod/secure_aggregation/__init__.py +0 -0
  57. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/mod/secure_aggregation/secagg_mod.py +0 -0
  58. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +0 -0
  59. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/mod/utils.py +0 -0
  60. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/node_state.py +0 -0
  61. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/node_state_tests.py +0 -0
  62. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/numpy_client.py +0 -0
  63. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/rest_client/__init__.py +0 -0
  64. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/client/typing.py +0 -0
  65. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/__init__.py +0 -0
  66. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/address.py +0 -0
  67. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/constant.py +0 -0
  68. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/context.py +0 -0
  69. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/date.py +0 -0
  70. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/differential_privacy.py +0 -0
  71. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/differential_privacy_constants.py +0 -0
  72. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/dp.py +0 -0
  73. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/exit_handlers.py +0 -0
  74. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/grpc.py +0 -0
  75. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/logger.py +0 -0
  76. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/message.py +0 -0
  77. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/object_ref.py +0 -0
  78. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/parameter.py +0 -0
  79. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/pyproject.py +0 -0
  80. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/record/__init__.py +0 -0
  81. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/record/configsrecord.py +0 -0
  82. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/record/conversion_utils.py +0 -0
  83. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/record/metricsrecord.py +0 -0
  84. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/record/parametersrecord.py +0 -0
  85. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/record/typeddict.py +0 -0
  86. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/recordset_compat.py +0 -0
  87. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/retry_invoker.py +0 -0
  88. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/secure_aggregation/__init__.py +0 -0
  89. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/secure_aggregation/crypto/__init__.py +0 -0
  90. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/secure_aggregation/crypto/shamir.py +0 -0
  91. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py +0 -0
  92. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py +0 -0
  93. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/secure_aggregation/quantization.py +0 -0
  94. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/secure_aggregation/secaggplus_constants.py +0 -0
  95. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/secure_aggregation/secaggplus_utils.py +0 -0
  96. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/serde.py +0 -0
  97. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/telemetry.py +0 -0
  98. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/typing.py +0 -0
  99. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/common/version.py +0 -0
  100. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/__init__.py +0 -0
  101. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/driver_pb2.py +0 -0
  102. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/driver_pb2.pyi +0 -0
  103. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/driver_pb2_grpc.py +0 -0
  104. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/driver_pb2_grpc.pyi +0 -0
  105. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/error_pb2.py +0 -0
  106. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/error_pb2.pyi +0 -0
  107. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/error_pb2_grpc.py +0 -0
  108. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/error_pb2_grpc.pyi +0 -0
  109. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/fleet_pb2.py +0 -0
  110. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/fleet_pb2.pyi +0 -0
  111. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/fleet_pb2_grpc.py +0 -0
  112. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/fleet_pb2_grpc.pyi +0 -0
  113. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/node_pb2.py +0 -0
  114. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/node_pb2.pyi +0 -0
  115. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/node_pb2_grpc.py +0 -0
  116. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/node_pb2_grpc.pyi +0 -0
  117. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/recordset_pb2.py +0 -0
  118. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/recordset_pb2.pyi +0 -0
  119. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/recordset_pb2_grpc.py +0 -0
  120. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/recordset_pb2_grpc.pyi +0 -0
  121. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/task_pb2.py +0 -0
  122. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/task_pb2.pyi +0 -0
  123. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/task_pb2_grpc.py +0 -0
  124. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/task_pb2_grpc.pyi +0 -0
  125. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/transport_pb2.py +0 -0
  126. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/transport_pb2.pyi +0 -0
  127. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/transport_pb2_grpc.py +0 -0
  128. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/proto/transport_pb2_grpc.pyi +0 -0
  129. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/py.typed +0 -0
  130. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/__init__.py +0 -0
  131. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/app.py +0 -0
  132. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/client_manager.py +0 -0
  133. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/client_proxy.py +0 -0
  134. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/compat/__init__.py +0 -0
  135. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/compat/app.py +0 -0
  136. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/compat/app_utils.py +0 -0
  137. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/compat/driver_client_proxy.py +0 -0
  138. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/compat/legacy_context.py +0 -0
  139. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/criterion.py +0 -0
  140. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/driver/__init__.py +0 -0
  141. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/driver/driver.py +0 -0
  142. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/driver/grpc_driver.py +0 -0
  143. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/history.py +0 -0
  144. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/run_serverapp.py +0 -0
  145. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/server.py +0 -0
  146. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/server_app.py +0 -0
  147. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/server_config.py +0 -0
  148. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/__init__.py +0 -0
  149. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/aggregate.py +0 -0
  150. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/bulyan.py +0 -0
  151. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/dp_adaptive_clipping.py +0 -0
  152. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/dp_fixed_clipping.py +0 -0
  153. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/dpfedavg_adaptive.py +0 -0
  154. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/dpfedavg_fixed.py +0 -0
  155. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/fault_tolerant_fedavg.py +0 -0
  156. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/fedadagrad.py +0 -0
  157. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/fedadam.py +0 -0
  158. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/fedavg.py +0 -0
  159. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/fedavg_android.py +0 -0
  160. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/fedavgm.py +0 -0
  161. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/fedmedian.py +0 -0
  162. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/fedopt.py +0 -0
  163. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/fedprox.py +0 -0
  164. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/fedtrimmedavg.py +0 -0
  165. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/fedxgb_bagging.py +0 -0
  166. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/fedxgb_cyclic.py +0 -0
  167. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/fedxgb_nn_avg.py +0 -0
  168. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/fedyogi.py +0 -0
  169. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/krum.py +0 -0
  170. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/qfedavg.py +0 -0
  171. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/strategy/strategy.py +0 -0
  172. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/__init__.py +0 -0
  173. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/driver/__init__.py +0 -0
  174. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/driver/driver_grpc.py +0 -0
  175. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/__init__.py +0 -0
  176. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py +0 -0
  177. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +0 -0
  178. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +0 -0
  179. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +0 -0
  180. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +0 -0
  181. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/grpc_rere/__init__.py +0 -0
  182. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +0 -0
  183. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/message_handler/__init__.py +0 -0
  184. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py +0 -0
  185. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/rest_rere/__init__.py +0 -0
  186. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py +0 -0
  187. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/vce/__init__.py +0 -0
  188. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/vce/backend/__init__.py +0 -0
  189. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/vce/backend/backend.py +0 -0
  190. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/vce/backend/raybackend.py +0 -0
  191. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/fleet/vce/vce_api.py +0 -0
  192. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/state/__init__.py +0 -0
  193. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/state/state_factory.py +0 -0
  194. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/superlink/state/utils.py +0 -0
  195. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/typing.py +0 -0
  196. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/utils/__init__.py +0 -0
  197. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/utils/tensorboard.py +0 -0
  198. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/utils/validator.py +0 -0
  199. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/workflow/__init__.py +0 -0
  200. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/workflow/constant.py +0 -0
  201. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/workflow/default_workflows.py +0 -0
  202. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/workflow/secure_aggregation/__init__.py +0 -0
  203. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/workflow/secure_aggregation/secagg_workflow.py +0 -0
  204. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +0 -0
  205. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/simulation/__init__.py +0 -0
  206. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/simulation/app.py +0 -0
  207. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/simulation/ray_transport/__init__.py +0 -0
  208. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/simulation/ray_transport/ray_actor.py +0 -0
  209. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/simulation/ray_transport/ray_client_proxy.py +0 -0
  210. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/src/py/flwr/simulation/ray_transport/utils.py +0 -0
  211. {flwr_nightly-1.9.0.dev20240417 → flwr_nightly-1.9.0.dev20240418}/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.dev20240417
3
+ Version: 1.9.0.dev20240418
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.dev20240417"
7
+ version = "1.9.0.dev20240418"
8
8
  description = "Flower: A Friendly Federated Learning Framework"
9
9
  license = "Apache-2.0"
10
10
  authors = ["The Flower Authors <hello@flower.ai>"]
@@ -58,8 +58,9 @@ def render_template(template: str, data: Dict[str, str]) -> str:
58
58
  """Render template."""
59
59
  tpl_file = load_template(template)
60
60
  tpl = Template(tpl_file)
61
- result = tpl.substitute(data)
62
- return result
61
+ if ".gitignore" not in template:
62
+ return tpl.substitute(data)
63
+ return tpl.template
63
64
 
64
65
 
65
66
  def create_file(file_path: str, content: str) -> None:
@@ -127,6 +128,7 @@ def new(
127
128
 
128
129
  # List of files to render
129
130
  files = {
131
+ ".gitignore": {"template": "app/.gitignore.tpl"},
130
132
  "README.md": {"template": "app/README.md.tpl"},
131
133
  "pyproject.toml": {"template": f"app/pyproject.{framework_str}.toml.tpl"},
132
134
  f"{pnl}/__init__.py": {"template": "app/code/__init__.py.tpl"},
@@ -134,8 +136,11 @@ def new(
134
136
  f"{pnl}/client.py": {"template": f"app/code/client.{framework_str}.py.tpl"},
135
137
  }
136
138
 
137
- # In case framework is MlFramework.PYTORCH generate additionally the task.py file
138
- if framework_str == MlFramework.PYTORCH.value.lower():
139
+ # Depending on the framework, generate task.py file
140
+ frameworks_with_tasks = [
141
+ MlFramework.PYTORCH.value.lower(),
142
+ ]
143
+ if framework_str in frameworks_with_tasks:
139
144
  files[f"{pnl}/task.py"] = {"template": f"app/code/task.{framework_str}.py.tpl"}
140
145
 
141
146
  context = {"project_name": project_name}
@@ -0,0 +1,160 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # poetry
98
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102
+ #poetry.lock
103
+
104
+ # pdm
105
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106
+ #pdm.lock
107
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108
+ # in version control.
109
+ # https://pdm.fming.dev/#use-with-ide
110
+ .pdm.toml
111
+
112
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113
+ __pypackages__/
114
+
115
+ # Celery stuff
116
+ celerybeat-schedule
117
+ celerybeat.pid
118
+
119
+ # SageMath parsed files
120
+ *.sage.py
121
+
122
+ # Environments
123
+ .env
124
+ .venv
125
+ env/
126
+ venv/
127
+ ENV/
128
+ env.bak/
129
+ venv.bak/
130
+
131
+ # Spyder project settings
132
+ .spyderproject
133
+ .spyproject
134
+
135
+ # Rope project settings
136
+ .ropeproject
137
+
138
+ # mkdocs documentation
139
+ /site
140
+
141
+ # mypy
142
+ .mypy_cache/
143
+ .dmypy.json
144
+ dmypy.json
145
+
146
+ # Pyre type checker
147
+ .pyre/
148
+
149
+ # pytype static type analyzer
150
+ .pytype/
151
+
152
+ # Cython debug symbols
153
+ cython_debug/
154
+
155
+ # PyCharm
156
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
159
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160
+ #.idea/
@@ -173,14 +173,14 @@ def http_request_response( # pylint: disable=R0914, R0915
173
173
  log(
174
174
  WARN,
175
175
  "[Node] POST /%s: missing header `Content-Type`",
176
- PATH_PULL_TASK_INS,
176
+ PATH_PING,
177
177
  )
178
178
  return
179
179
  if res.headers["content-type"] != "application/protobuf":
180
180
  log(
181
181
  WARN,
182
182
  "[Node] POST /%s: header `Content-Type` has wrong value",
183
- PATH_PULL_TASK_INS,
183
+ PATH_PING,
184
184
  )
185
185
  return
186
186
 
@@ -223,14 +223,14 @@ def http_request_response( # pylint: disable=R0914, R0915
223
223
  log(
224
224
  WARN,
225
225
  "[Node] POST /%s: missing header `Content-Type`",
226
- PATH_PULL_TASK_INS,
226
+ PATH_CREATE_NODE,
227
227
  )
228
228
  return
229
229
  if res.headers["content-type"] != "application/protobuf":
230
230
  log(
231
231
  WARN,
232
232
  "[Node] POST /%s: header `Content-Type` has wrong value",
233
- PATH_PULL_TASK_INS,
233
+ PATH_CREATE_NODE,
234
234
  )
235
235
  return
236
236
 
@@ -277,14 +277,14 @@ def http_request_response( # pylint: disable=R0914, R0915
277
277
  log(
278
278
  WARN,
279
279
  "[Node] POST /%s: missing header `Content-Type`",
280
- PATH_PULL_TASK_INS,
280
+ PATH_DELETE_NODE,
281
281
  )
282
282
  return
283
283
  if res.headers["content-type"] != "application/protobuf":
284
284
  log(
285
285
  WARN,
286
286
  "[Node] POST /%s: header `Content-Type` has wrong value",
287
- PATH_PULL_TASK_INS,
287
+ PATH_DELETE_NODE,
288
288
  )
289
289
 
290
290
  # Cleanup
@@ -0,0 +1,118 @@
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
+ """RecordSet."""
16
+
17
+
18
+ from dataclasses import dataclass
19
+ from typing import Dict, Optional, cast
20
+
21
+ from .configsrecord import ConfigsRecord
22
+ from .metricsrecord import MetricsRecord
23
+ from .parametersrecord import ParametersRecord
24
+ from .typeddict import TypedDict
25
+
26
+
27
+ class RecordSetData:
28
+ """Inner data container for the RecordSet class."""
29
+
30
+ parameters_records: TypedDict[str, ParametersRecord]
31
+ metrics_records: TypedDict[str, MetricsRecord]
32
+ configs_records: TypedDict[str, ConfigsRecord]
33
+
34
+ def __init__(
35
+ self,
36
+ parameters_records: Optional[Dict[str, ParametersRecord]] = None,
37
+ metrics_records: Optional[Dict[str, MetricsRecord]] = None,
38
+ configs_records: Optional[Dict[str, ConfigsRecord]] = None,
39
+ ) -> None:
40
+ self.parameters_records = TypedDict[str, ParametersRecord](
41
+ self._check_fn_str, self._check_fn_params
42
+ )
43
+ self.metrics_records = TypedDict[str, MetricsRecord](
44
+ self._check_fn_str, self._check_fn_metrics
45
+ )
46
+ self.configs_records = TypedDict[str, ConfigsRecord](
47
+ self._check_fn_str, self._check_fn_configs
48
+ )
49
+ if parameters_records is not None:
50
+ self.parameters_records.update(parameters_records)
51
+ if metrics_records is not None:
52
+ self.metrics_records.update(metrics_records)
53
+ if configs_records is not None:
54
+ self.configs_records.update(configs_records)
55
+
56
+ def _check_fn_str(self, key: str) -> None:
57
+ if not isinstance(key, str):
58
+ raise TypeError(
59
+ f"Expected `{str.__name__}`, but "
60
+ f"received `{type(key).__name__}` for the key."
61
+ )
62
+
63
+ def _check_fn_params(self, record: ParametersRecord) -> None:
64
+ if not isinstance(record, ParametersRecord):
65
+ raise TypeError(
66
+ f"Expected `{ParametersRecord.__name__}`, but "
67
+ f"received `{type(record).__name__}` for the value."
68
+ )
69
+
70
+ def _check_fn_metrics(self, record: MetricsRecord) -> None:
71
+ if not isinstance(record, MetricsRecord):
72
+ raise TypeError(
73
+ f"Expected `{MetricsRecord.__name__}`, but "
74
+ f"received `{type(record).__name__}` for the value."
75
+ )
76
+
77
+ def _check_fn_configs(self, record: ConfigsRecord) -> None:
78
+ if not isinstance(record, ConfigsRecord):
79
+ raise TypeError(
80
+ f"Expected `{ConfigsRecord.__name__}`, but "
81
+ f"received `{type(record).__name__}` for the value."
82
+ )
83
+
84
+
85
+ @dataclass
86
+ class RecordSet:
87
+ """RecordSet stores groups of parameters, metrics and configs."""
88
+
89
+ def __init__(
90
+ self,
91
+ parameters_records: Optional[Dict[str, ParametersRecord]] = None,
92
+ metrics_records: Optional[Dict[str, MetricsRecord]] = None,
93
+ configs_records: Optional[Dict[str, ConfigsRecord]] = None,
94
+ ) -> None:
95
+ data = RecordSetData(
96
+ parameters_records=parameters_records,
97
+ metrics_records=metrics_records,
98
+ configs_records=configs_records,
99
+ )
100
+ setattr(self, "_data", data) # noqa
101
+
102
+ @property
103
+ def parameters_records(self) -> TypedDict[str, ParametersRecord]:
104
+ """Dictionary holding ParametersRecord instances."""
105
+ data = cast(RecordSetData, getattr(self, "_data")) # noqa
106
+ return data.parameters_records
107
+
108
+ @property
109
+ def metrics_records(self) -> TypedDict[str, MetricsRecord]:
110
+ """Dictionary holding MetricsRecord instances."""
111
+ data = cast(RecordSetData, getattr(self, "_data")) # noqa
112
+ return data.metrics_records
113
+
114
+ @property
115
+ def configs_records(self) -> TypedDict[str, ConfigsRecord]:
116
+ """Dictionary holding ConfigsRecord instances."""
117
+ data = cast(RecordSetData, getattr(self, "_data")) # noqa
118
+ return data.configs_records
@@ -0,0 +1,140 @@
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
+ """Driver (abstract base class)."""
16
+
17
+
18
+ from abc import ABC, abstractmethod
19
+ from typing import Iterable, List, Optional
20
+
21
+ from flwr.common import Message, RecordSet
22
+
23
+
24
+ class Driver(ABC):
25
+ """Abstract base Driver class for the Driver API."""
26
+
27
+ @abstractmethod
28
+ def create_message( # pylint: disable=too-many-arguments
29
+ self,
30
+ content: RecordSet,
31
+ message_type: str,
32
+ dst_node_id: int,
33
+ group_id: str,
34
+ ttl: Optional[float] = None,
35
+ ) -> Message:
36
+ """Create a new message with specified parameters.
37
+
38
+ This method constructs a new `Message` with given content and metadata.
39
+ The `run_id` and `src_node_id` will be set automatically.
40
+
41
+ Parameters
42
+ ----------
43
+ content : RecordSet
44
+ The content for the new message. This holds records that are to be sent
45
+ to the destination node.
46
+ message_type : str
47
+ The type of the message, defining the action to be executed on
48
+ the receiving end.
49
+ dst_node_id : int
50
+ The ID of the destination node to which the message is being sent.
51
+ group_id : str
52
+ The ID of the group to which this message is associated. In some settings,
53
+ this is used as the FL round.
54
+ ttl : Optional[float] (default: None)
55
+ Time-to-live for the round trip of this message, i.e., the time from sending
56
+ this message to receiving a reply. It specifies in seconds the duration for
57
+ which the message and its potential reply are considered valid. If unset,
58
+ the default TTL (i.e., `common.DEFAULT_TTL`) will be used.
59
+
60
+ Returns
61
+ -------
62
+ message : Message
63
+ A new `Message` instance with the specified content and metadata.
64
+ """
65
+
66
+ @abstractmethod
67
+ def get_node_ids(self) -> List[int]:
68
+ """Get node IDs."""
69
+
70
+ @abstractmethod
71
+ def push_messages(self, messages: Iterable[Message]) -> Iterable[str]:
72
+ """Push messages to specified node IDs.
73
+
74
+ This method takes an iterable of messages and sends each message
75
+ to the node specified in `dst_node_id`.
76
+
77
+ Parameters
78
+ ----------
79
+ messages : Iterable[Message]
80
+ An iterable of messages to be sent.
81
+
82
+ Returns
83
+ -------
84
+ message_ids : Iterable[str]
85
+ An iterable of IDs for the messages that were sent, which can be used
86
+ to pull replies.
87
+ """
88
+
89
+ @abstractmethod
90
+ def pull_messages(self, message_ids: Iterable[str]) -> Iterable[Message]:
91
+ """Pull messages based on message IDs.
92
+
93
+ This method is used to collect messages from the SuperLink
94
+ that correspond to a set of given message IDs.
95
+
96
+ Parameters
97
+ ----------
98
+ message_ids : Iterable[str]
99
+ An iterable of message IDs for which reply messages are to be retrieved.
100
+
101
+ Returns
102
+ -------
103
+ messages : Iterable[Message]
104
+ An iterable of messages received.
105
+ """
106
+
107
+ @abstractmethod
108
+ def send_and_receive(
109
+ self,
110
+ messages: Iterable[Message],
111
+ *,
112
+ timeout: Optional[float] = None,
113
+ ) -> Iterable[Message]:
114
+ """Push messages to specified node IDs and pull the reply messages.
115
+
116
+ This method sends a list of messages to their destination node IDs and then
117
+ waits for the replies. It continues to pull replies until either all
118
+ replies are received or the specified timeout duration is exceeded.
119
+
120
+ Parameters
121
+ ----------
122
+ messages : Iterable[Message]
123
+ An iterable of messages to be sent.
124
+ timeout : Optional[float] (default: None)
125
+ The timeout duration in seconds. If specified, the method will wait for
126
+ replies for this duration. If `None`, there is no time limit and the method
127
+ will wait until replies for all messages are received.
128
+
129
+ Returns
130
+ -------
131
+ replies : Iterable[Message]
132
+ An iterable of reply messages received from the SuperLink.
133
+
134
+ Notes
135
+ -----
136
+ This method uses `push_messages` to send the messages and `pull_messages`
137
+ to collect the replies. If `timeout` is set, the method may not return
138
+ replies for all sent messages. A message remains valid until its TTL,
139
+ which is not affected by `timeout`.
140
+ """
@@ -64,7 +64,7 @@ class DriverServicer(driver_pb2_grpc.DriverServicer):
64
64
  """Create run ID."""
65
65
  log(INFO, "DriverServicer.CreateRun")
66
66
  state: State = self.state_factory.state()
67
- run_id = state.create_run()
67
+ run_id = state.create_run("None/None", "None")
68
68
  return CreateRunResponse(run_id=run_id)
69
69
 
70
70
  def PushTaskIns(
@@ -36,7 +36,8 @@ class InMemoryState(State):
36
36
  def __init__(self) -> None:
37
37
  # Map node_id to (online_until, ping_interval)
38
38
  self.node_ids: Dict[int, Tuple[float, float]] = {}
39
- self.run_ids: Set[int] = set()
39
+ # Map run_id to (fab_id, fab_version)
40
+ self.run_ids: Dict[int, Tuple[str, str]] = {}
40
41
  self.task_ins_store: Dict[UUID, TaskIns] = {}
41
42
  self.task_res_store: Dict[UUID, TaskRes] = {}
42
43
  self.lock = threading.Lock()
@@ -238,18 +239,26 @@ class InMemoryState(State):
238
239
  if online_until > current_time
239
240
  }
240
241
 
241
- def create_run(self) -> int:
242
- """Create one run."""
242
+ def create_run(self, fab_id: str, fab_version: str) -> int:
243
+ """Create a new run for the specified `fab_id` and `fab_version`."""
243
244
  # Sample a random int64 as run_id
244
245
  with self.lock:
245
246
  run_id: int = int.from_bytes(os.urandom(8), "little", signed=True)
246
247
 
247
248
  if run_id not in self.run_ids:
248
- self.run_ids.add(run_id)
249
+ self.run_ids[run_id] = (fab_id, fab_version)
249
250
  return run_id
250
251
  log(ERROR, "Unexpected run creation failure.")
251
252
  return 0
252
253
 
254
+ def get_run(self, run_id: int) -> Tuple[int, str, str]:
255
+ """Retrieve information about the run with the specified `run_id`."""
256
+ with self.lock:
257
+ if run_id not in self.run_ids:
258
+ log(ERROR, "`run_id` is invalid")
259
+ return 0, "", ""
260
+ return run_id, *self.run_ids[run_id]
261
+
253
262
  def acknowledge_ping(self, node_id: int, ping_interval: float) -> bool:
254
263
  """Acknowledge a ping received from a node, serving as a heartbeat."""
255
264
  with self.lock:
@@ -46,7 +46,9 @@ CREATE INDEX IF NOT EXISTS idx_online_until ON node (online_until);
46
46
 
47
47
  SQL_CREATE_TABLE_RUN = """
48
48
  CREATE TABLE IF NOT EXISTS run(
49
- run_id INTEGER UNIQUE
49
+ run_id INTEGER UNIQUE,
50
+ fab_id TEXT,
51
+ fab_version TEXT
50
52
  );
51
53
  """
52
54
 
@@ -558,8 +560,8 @@ class SqliteState(State):
558
560
  result: Set[int] = {row["node_id"] for row in rows}
559
561
  return result
560
562
 
561
- def create_run(self) -> int:
562
- """Create one run and store it in state."""
563
+ def create_run(self, fab_id: str, fab_version: str) -> int:
564
+ """Create a new run for the specified `fab_id` and `fab_version`."""
563
565
  # Sample a random int64 as run_id
564
566
  run_id: int = int.from_bytes(os.urandom(8), "little", signed=True)
565
567
 
@@ -567,12 +569,22 @@ class SqliteState(State):
567
569
  query = "SELECT COUNT(*) FROM run WHERE run_id = ?;"
568
570
  # If run_id does not exist
569
571
  if self.query(query, (run_id,))[0]["COUNT(*)"] == 0:
570
- query = "INSERT INTO run VALUES(:run_id);"
571
- self.query(query, {"run_id": run_id})
572
+ query = "INSERT INTO run (run_id, fab_id, fab_version) VALUES (?, ?, ?);"
573
+ self.query(query, (run_id, fab_id, fab_version))
572
574
  return run_id
573
575
  log(ERROR, "Unexpected run creation failure.")
574
576
  return 0
575
577
 
578
+ def get_run(self, run_id: int) -> Tuple[int, str, str]:
579
+ """Retrieve information about the run with the specified `run_id`."""
580
+ query = "SELECT * FROM run WHERE run_id = ?;"
581
+ try:
582
+ row = self.query(query, (run_id,))[0]
583
+ return run_id, row["fab_id"], row["fab_version"]
584
+ except sqlite3.IntegrityError:
585
+ log(ERROR, "`run_id` does not exist.")
586
+ return 0, "", ""
587
+
576
588
  def acknowledge_ping(self, node_id: int, ping_interval: float) -> bool:
577
589
  """Acknowledge a ping received from a node, serving as a heartbeat."""
578
590
  # Update `online_until` and `ping_interval` for the given `node_id`
@@ -16,7 +16,7 @@
16
16
 
17
17
 
18
18
  import abc
19
- from typing import List, Optional, Set
19
+ from typing import List, Optional, Set, Tuple
20
20
  from uuid import UUID
21
21
 
22
22
  from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611
@@ -150,8 +150,26 @@ class State(abc.ABC):
150
150
  """
151
151
 
152
152
  @abc.abstractmethod
153
- def create_run(self) -> int:
154
- """Create one run."""
153
+ def create_run(self, fab_id: str, fab_version: str) -> int:
154
+ """Create a new run for the specified `fab_id` and `fab_version`."""
155
+
156
+ @abc.abstractmethod
157
+ def get_run(self, run_id: int) -> Tuple[int, str, str]:
158
+ """Retrieve information about the run with the specified `run_id`.
159
+
160
+ Parameters
161
+ ----------
162
+ run_id : int
163
+ The identifier of the run.
164
+
165
+ Returns
166
+ -------
167
+ Tuple[int, str, str]
168
+ A tuple containing three elements:
169
+ - `run_id`: The identifier of the run, same as the specified `run_id`.
170
+ - `fab_id`: The identifier of the FAB used in the specified run.
171
+ - `fab_version`: The version of the FAB used in the specified run.
172
+ """
155
173
 
156
174
  @abc.abstractmethod
157
175
  def acknowledge_ping(self, node_id: int, ping_interval: float) -> bool: