flwr-nightly 1.16.0.dev20250226__tar.gz → 1.16.0.dev20250228__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.
Files changed (335) hide show
  1. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/PKG-INFO +1 -1
  2. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/pyproject.toml +1 -1
  3. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/log.py +20 -21
  4. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/client_app.py +89 -20
  5. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/auth_plugin/auth_plugin.py +2 -1
  6. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/constant.py +16 -0
  7. flwr_nightly-1.16.0.dev20250228/src/py/flwr/common/event_log_plugin/__init__.py +26 -0
  8. flwr_nightly-1.16.0.dev20250228/src/py/flwr/common/event_log_plugin/event_log_plugin.py +87 -0
  9. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/object_ref.py +0 -10
  10. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/record/recordset.py +97 -82
  11. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/secure_aggregation/quantization.py +5 -1
  12. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/typing.py +36 -0
  13. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/app.py +16 -1
  14. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/server_app.py +89 -20
  15. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/superexec/exec_servicer.py +1 -1
  16. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/superexec/exec_user_auth_interceptor.py +5 -3
  17. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/LICENSE +0 -0
  18. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/README.md +0 -0
  19. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/__init__.py +0 -0
  20. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/__init__.py +0 -0
  21. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/app.py +0 -0
  22. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/auth_plugin/__init__.py +0 -0
  23. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/auth_plugin/oidc_cli_plugin.py +0 -0
  24. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/build.py +0 -0
  25. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/cli_user_auth_interceptor.py +0 -0
  26. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/config_utils.py +0 -0
  27. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/constant.py +0 -0
  28. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/example.py +0 -0
  29. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/install.py +0 -0
  30. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/login/__init__.py +0 -0
  31. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/login/login.py +0 -0
  32. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/ls.py +0 -0
  33. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/__init__.py +0 -0
  34. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/new.py +0 -0
  35. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/__init__.py +0 -0
  36. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/.gitignore.tpl +0 -0
  37. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/LICENSE.tpl +0 -0
  38. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/README.baseline.md.tpl +0 -0
  39. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/README.flowertune.md.tpl +0 -0
  40. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/README.md.tpl +0 -0
  41. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/__init__.py +0 -0
  42. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/__init__.baseline.py.tpl +0 -0
  43. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/__init__.py +0 -0
  44. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/__init__.py.tpl +0 -0
  45. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/client.baseline.py.tpl +0 -0
  46. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/client.huggingface.py.tpl +0 -0
  47. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/client.jax.py.tpl +0 -0
  48. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/client.mlx.py.tpl +0 -0
  49. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -0
  50. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -0
  51. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/client.sklearn.py.tpl +0 -0
  52. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -0
  53. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/dataset.baseline.py.tpl +0 -0
  54. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/flwr_tune/__init__.py +0 -0
  55. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +0 -0
  56. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +0 -0
  57. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +0 -0
  58. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +0 -0
  59. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +0 -0
  60. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/model.baseline.py.tpl +0 -0
  61. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/server.baseline.py.tpl +0 -0
  62. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/server.huggingface.py.tpl +0 -0
  63. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/server.jax.py.tpl +0 -0
  64. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/server.mlx.py.tpl +0 -0
  65. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -0
  66. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -0
  67. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/server.sklearn.py.tpl +0 -0
  68. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -0
  69. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/strategy.baseline.py.tpl +0 -0
  70. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/task.huggingface.py.tpl +0 -0
  71. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/task.jax.py.tpl +0 -0
  72. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/task.mlx.py.tpl +0 -0
  73. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/task.numpy.py.tpl +0 -0
  74. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -0
  75. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/task.sklearn.py.tpl +0 -0
  76. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +0 -0
  77. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/code/utils.baseline.py.tpl +0 -0
  78. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +0 -0
  79. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +0 -0
  80. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +0 -0
  81. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/pyproject.jax.toml.tpl +0 -0
  82. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +0 -0
  83. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +0 -0
  84. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +0 -0
  85. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +0 -0
  86. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +0 -0
  87. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/run/__init__.py +0 -0
  88. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/run/run.py +0 -0
  89. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/stop.py +0 -0
  90. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/cli/utils.py +0 -0
  91. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/__init__.py +0 -0
  92. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/app.py +0 -0
  93. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/client.py +0 -0
  94. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/clientapp/__init__.py +0 -0
  95. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/clientapp/app.py +0 -0
  96. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/clientapp/clientappio_servicer.py +0 -0
  97. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/clientapp/utils.py +0 -0
  98. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/dpfedavg_numpy_client.py +0 -0
  99. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/grpc_adapter_client/__init__.py +0 -0
  100. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/grpc_adapter_client/connection.py +0 -0
  101. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/grpc_client/__init__.py +0 -0
  102. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/grpc_client/connection.py +0 -0
  103. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/grpc_rere_client/__init__.py +0 -0
  104. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/grpc_rere_client/client_interceptor.py +0 -0
  105. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/grpc_rere_client/connection.py +0 -0
  106. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/grpc_rere_client/grpc_adapter.py +0 -0
  107. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/heartbeat.py +0 -0
  108. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/message_handler/__init__.py +0 -0
  109. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/message_handler/message_handler.py +0 -0
  110. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/message_handler/task_handler.py +0 -0
  111. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/mod/__init__.py +0 -0
  112. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/mod/centraldp_mods.py +0 -0
  113. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/mod/comms_mods.py +0 -0
  114. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/mod/localdp_mod.py +0 -0
  115. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/mod/secure_aggregation/__init__.py +0 -0
  116. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/mod/secure_aggregation/secagg_mod.py +0 -0
  117. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +0 -0
  118. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/mod/utils.py +0 -0
  119. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/nodestate/__init__.py +0 -0
  120. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/nodestate/in_memory_nodestate.py +0 -0
  121. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/nodestate/nodestate.py +0 -0
  122. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/nodestate/nodestate_factory.py +0 -0
  123. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/numpy_client.py +0 -0
  124. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/rest_client/__init__.py +0 -0
  125. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/rest_client/connection.py +0 -0
  126. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/run_info_store.py +0 -0
  127. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/supernode/__init__.py +0 -0
  128. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/supernode/app.py +0 -0
  129. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/client/typing.py +0 -0
  130. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/__init__.py +0 -0
  131. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/address.py +0 -0
  132. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/args.py +0 -0
  133. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/auth_plugin/__init__.py +0 -0
  134. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/config.py +0 -0
  135. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/context.py +0 -0
  136. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/date.py +0 -0
  137. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/differential_privacy.py +0 -0
  138. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/differential_privacy_constants.py +0 -0
  139. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/dp.py +0 -0
  140. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/exit/__init__.py +0 -0
  141. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/exit/exit.py +0 -0
  142. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/exit/exit_code.py +0 -0
  143. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/exit_handlers.py +0 -0
  144. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/grpc.py +0 -0
  145. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/logger.py +0 -0
  146. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/message.py +0 -0
  147. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/parameter.py +0 -0
  148. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/pyproject.py +0 -0
  149. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/record/__init__.py +0 -0
  150. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/record/configsrecord.py +0 -0
  151. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/record/conversion_utils.py +0 -0
  152. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/record/metricsrecord.py +0 -0
  153. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/record/parametersrecord.py +0 -0
  154. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/record/typeddict.py +0 -0
  155. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/recordset_compat.py +0 -0
  156. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/retry_invoker.py +0 -0
  157. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/secure_aggregation/__init__.py +0 -0
  158. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/secure_aggregation/crypto/__init__.py +0 -0
  159. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/secure_aggregation/crypto/shamir.py +0 -0
  160. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py +0 -0
  161. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py +0 -0
  162. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/secure_aggregation/secaggplus_constants.py +0 -0
  163. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/secure_aggregation/secaggplus_utils.py +0 -0
  164. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/serde.py +0 -0
  165. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/telemetry.py +0 -0
  166. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/common/version.py +0 -0
  167. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/__init__.py +0 -0
  168. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/clientappio_pb2.py +0 -0
  169. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/clientappio_pb2.pyi +0 -0
  170. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/clientappio_pb2_grpc.py +0 -0
  171. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/clientappio_pb2_grpc.pyi +0 -0
  172. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/error_pb2.py +0 -0
  173. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/error_pb2.pyi +0 -0
  174. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/error_pb2_grpc.py +0 -0
  175. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/error_pb2_grpc.pyi +0 -0
  176. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/exec_pb2.py +0 -0
  177. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/exec_pb2.pyi +0 -0
  178. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/exec_pb2_grpc.py +0 -0
  179. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/exec_pb2_grpc.pyi +0 -0
  180. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/fab_pb2.py +0 -0
  181. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/fab_pb2.pyi +0 -0
  182. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/fab_pb2_grpc.py +0 -0
  183. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/fab_pb2_grpc.pyi +0 -0
  184. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/fleet_pb2.py +0 -0
  185. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/fleet_pb2.pyi +0 -0
  186. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/fleet_pb2_grpc.py +0 -0
  187. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/fleet_pb2_grpc.pyi +0 -0
  188. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/grpcadapter_pb2.py +0 -0
  189. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/grpcadapter_pb2.pyi +0 -0
  190. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/grpcadapter_pb2_grpc.py +0 -0
  191. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/grpcadapter_pb2_grpc.pyi +0 -0
  192. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/log_pb2.py +0 -0
  193. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/log_pb2.pyi +0 -0
  194. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/log_pb2_grpc.py +0 -0
  195. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/log_pb2_grpc.pyi +0 -0
  196. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/message_pb2.py +0 -0
  197. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/message_pb2.pyi +0 -0
  198. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/message_pb2_grpc.py +0 -0
  199. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/message_pb2_grpc.pyi +0 -0
  200. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/node_pb2.py +0 -0
  201. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/node_pb2.pyi +0 -0
  202. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/node_pb2_grpc.py +0 -0
  203. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/node_pb2_grpc.pyi +0 -0
  204. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/recordset_pb2.py +0 -0
  205. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/recordset_pb2.pyi +0 -0
  206. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/recordset_pb2_grpc.py +0 -0
  207. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/recordset_pb2_grpc.pyi +0 -0
  208. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/run_pb2.py +0 -0
  209. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/run_pb2.pyi +0 -0
  210. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/run_pb2_grpc.py +0 -0
  211. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/run_pb2_grpc.pyi +0 -0
  212. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/serverappio_pb2.py +0 -0
  213. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/serverappio_pb2.pyi +0 -0
  214. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/serverappio_pb2_grpc.py +0 -0
  215. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/serverappio_pb2_grpc.pyi +0 -0
  216. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/simulationio_pb2.py +0 -0
  217. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/simulationio_pb2.pyi +0 -0
  218. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/simulationio_pb2_grpc.py +0 -0
  219. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/simulationio_pb2_grpc.pyi +0 -0
  220. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/task_pb2.py +0 -0
  221. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/task_pb2.pyi +0 -0
  222. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/task_pb2_grpc.py +0 -0
  223. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/task_pb2_grpc.pyi +0 -0
  224. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/transport_pb2.py +0 -0
  225. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/transport_pb2.pyi +0 -0
  226. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/transport_pb2_grpc.py +0 -0
  227. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/proto/transport_pb2_grpc.pyi +0 -0
  228. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/py.typed +0 -0
  229. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/__init__.py +0 -0
  230. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/client_manager.py +0 -0
  231. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/client_proxy.py +0 -0
  232. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/compat/__init__.py +0 -0
  233. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/compat/app.py +0 -0
  234. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/compat/app_utils.py +0 -0
  235. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/compat/driver_client_proxy.py +0 -0
  236. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/compat/legacy_context.py +0 -0
  237. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/criterion.py +0 -0
  238. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/driver/__init__.py +0 -0
  239. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/driver/driver.py +0 -0
  240. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/driver/grpc_driver.py +0 -0
  241. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/driver/inmemory_driver.py +0 -0
  242. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/history.py +0 -0
  243. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/run_serverapp.py +0 -0
  244. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/server.py +0 -0
  245. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/server_config.py +0 -0
  246. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/serverapp/__init__.py +0 -0
  247. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/serverapp/app.py +0 -0
  248. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/serverapp_components.py +0 -0
  249. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/__init__.py +0 -0
  250. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/aggregate.py +0 -0
  251. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/bulyan.py +0 -0
  252. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/dp_adaptive_clipping.py +0 -0
  253. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/dp_fixed_clipping.py +0 -0
  254. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/dpfedavg_adaptive.py +0 -0
  255. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/dpfedavg_fixed.py +0 -0
  256. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/fault_tolerant_fedavg.py +0 -0
  257. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/fedadagrad.py +0 -0
  258. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/fedadam.py +0 -0
  259. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/fedavg.py +0 -0
  260. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/fedavg_android.py +0 -0
  261. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/fedavgm.py +0 -0
  262. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/fedmedian.py +0 -0
  263. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/fedopt.py +0 -0
  264. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/fedprox.py +0 -0
  265. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/fedtrimmedavg.py +0 -0
  266. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/fedxgb_bagging.py +0 -0
  267. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/fedxgb_cyclic.py +0 -0
  268. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/fedxgb_nn_avg.py +0 -0
  269. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/fedyogi.py +0 -0
  270. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/krum.py +0 -0
  271. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/qfedavg.py +0 -0
  272. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/strategy/strategy.py +0 -0
  273. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/__init__.py +0 -0
  274. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/driver/__init__.py +0 -0
  275. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/driver/serverappio_grpc.py +0 -0
  276. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/driver/serverappio_servicer.py +0 -0
  277. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/ffs/__init__.py +0 -0
  278. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/ffs/disk_ffs.py +0 -0
  279. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/ffs/ffs.py +0 -0
  280. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/ffs/ffs_factory.py +0 -0
  281. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/__init__.py +0 -0
  282. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/grpc_adapter/__init__.py +0 -0
  283. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +0 -0
  284. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py +0 -0
  285. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +0 -0
  286. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +0 -0
  287. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +0 -0
  288. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +0 -0
  289. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/grpc_rere/__init__.py +0 -0
  290. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +0 -0
  291. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +0 -0
  292. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/message_handler/__init__.py +0 -0
  293. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py +0 -0
  294. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/rest_rere/__init__.py +0 -0
  295. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py +0 -0
  296. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/vce/__init__.py +0 -0
  297. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/vce/backend/__init__.py +0 -0
  298. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/vce/backend/backend.py +0 -0
  299. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/vce/backend/raybackend.py +0 -0
  300. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/fleet/vce/vce_api.py +0 -0
  301. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/linkstate/__init__.py +0 -0
  302. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/linkstate/in_memory_linkstate.py +0 -0
  303. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/linkstate/linkstate.py +0 -0
  304. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/linkstate/linkstate_factory.py +0 -0
  305. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/linkstate/sqlite_linkstate.py +0 -0
  306. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/linkstate/utils.py +0 -0
  307. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/simulation/__init__.py +0 -0
  308. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/simulation/simulationio_grpc.py +0 -0
  309. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/simulation/simulationio_servicer.py +0 -0
  310. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/superlink/utils.py +0 -0
  311. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/typing.py +0 -0
  312. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/utils/__init__.py +0 -0
  313. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/utils/tensorboard.py +0 -0
  314. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/utils/validator.py +0 -0
  315. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/workflow/__init__.py +0 -0
  316. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/workflow/constant.py +0 -0
  317. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/workflow/default_workflows.py +0 -0
  318. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/workflow/secure_aggregation/__init__.py +0 -0
  319. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/workflow/secure_aggregation/secagg_workflow.py +0 -0
  320. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +0 -0
  321. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/simulation/__init__.py +0 -0
  322. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/simulation/app.py +0 -0
  323. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/simulation/legacy_app.py +0 -0
  324. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/simulation/ray_transport/__init__.py +0 -0
  325. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/simulation/ray_transport/ray_actor.py +0 -0
  326. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/simulation/ray_transport/ray_client_proxy.py +0 -0
  327. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/simulation/ray_transport/utils.py +0 -0
  328. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/simulation/run_simulation.py +0 -0
  329. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/simulation/simulationio_connection.py +0 -0
  330. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/superexec/__init__.py +0 -0
  331. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/superexec/app.py +0 -0
  332. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/superexec/deployment.py +0 -0
  333. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/superexec/exec_grpc.py +0 -0
  334. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/superexec/executor.py +0 -0
  335. {flwr_nightly-1.16.0.dev20250226 → flwr_nightly-1.16.0.dev20250228}/src/py/flwr/superexec/simulation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flwr-nightly
3
- Version: 1.16.0.dev20250226
3
+ Version: 1.16.0.dev20250228
4
4
  Summary: Flower: A Friendly Federated AI 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.16.0.dev20250226"
7
+ version = "1.16.0.dev20250228"
8
8
  description = "Flower: A Friendly Federated AI Framework"
9
9
  license = "Apache-2.0"
10
10
  authors = ["The Flower Authors <hello@flower.ai>"]
@@ -38,6 +38,10 @@ from flwr.proto.exec_pb2_grpc import ExecStub
38
38
  from .utils import init_channel, try_obtain_cli_auth_plugin, unauthenticated_exc_handler
39
39
 
40
40
 
41
+ class AllLogsRetrieved(BaseException):
42
+ """Raised when all logs are retrieved."""
43
+
44
+
41
45
  def start_stream(
42
46
  run_id: int, channel: grpc.Channel, refresh_period: int = CONN_REFRESH_PERIOD
43
47
  ) -> None:
@@ -56,10 +60,10 @@ def start_stream(
56
60
  # pylint: disable=E1101
57
61
  if e.code() == grpc.StatusCode.NOT_FOUND:
58
62
  logger(ERROR, "Invalid run_id `%s`, exiting", run_id)
59
- if e.code() == grpc.StatusCode.CANCELLED:
60
- pass
61
63
  else:
62
64
  raise e
65
+ except AllLogsRetrieved:
66
+ pass
63
67
  finally:
64
68
  channel.close()
65
69
 
@@ -94,6 +98,7 @@ def stream_logs(
94
98
  with unauthenticated_exc_handler():
95
99
  for res in stub.StreamLogs(req, timeout=duration):
96
100
  print(res.log_output, end="")
101
+ raise AllLogsRetrieved()
97
102
  except grpc.RpcError as e:
98
103
  # pylint: disable=E1101
99
104
  if e.code() != grpc.StatusCode.DEADLINE_EXCEEDED:
@@ -108,27 +113,21 @@ def stream_logs(
108
113
  def print_logs(run_id: int, channel: grpc.Channel, timeout: int) -> None:
109
114
  """Print logs from the beginning of a run."""
110
115
  stub = ExecStub(channel)
111
- req = StreamLogsRequest(run_id=run_id)
116
+ req = StreamLogsRequest(run_id=run_id, after_timestamp=0.0)
112
117
 
113
118
  try:
114
- while True:
115
- try:
116
- with unauthenticated_exc_handler():
117
- # Enforce timeout for graceful exit
118
- for res in stub.StreamLogs(req, timeout=timeout):
119
- print(res.log_output)
120
- except grpc.RpcError as e:
121
- # pylint: disable=E1101
122
- if e.code() == grpc.StatusCode.DEADLINE_EXCEEDED:
123
- break
124
- if e.code() == grpc.StatusCode.NOT_FOUND:
125
- logger(ERROR, "Invalid run_id `%s`, exiting", run_id)
126
- break
127
- if e.code() == grpc.StatusCode.CANCELLED:
128
- break
129
- raise e
130
- except KeyboardInterrupt:
131
- logger(DEBUG, "Stream interrupted by user")
119
+ with unauthenticated_exc_handler():
120
+ # Enforce timeout for graceful exit
121
+ for res in stub.StreamLogs(req, timeout=timeout):
122
+ print(res.log_output)
123
+ break
124
+ except grpc.RpcError as e:
125
+ if e.code() == grpc.StatusCode.NOT_FOUND: # pylint: disable=E1101
126
+ logger(ERROR, "Invalid run_id `%s`, exiting", run_id)
127
+ elif e.code() == grpc.StatusCode.DEADLINE_EXCEEDED: # pylint: disable=E1101
128
+ pass
129
+ else:
130
+ raise e
132
131
  finally:
133
132
  channel.close()
134
133
  logger(DEBUG, "Channel closed")
@@ -16,6 +16,8 @@
16
16
 
17
17
 
18
18
  import inspect
19
+ from collections.abc import Iterator
20
+ from contextlib import contextmanager
19
21
  from typing import Callable, Optional
20
22
 
21
23
  from flwr.client.client import Client
@@ -71,6 +73,11 @@ def _inspect_maybe_adapt_client_fn_signature(client_fn: ClientFnExt) -> ClientFn
71
73
  return client_fn
72
74
 
73
75
 
76
+ @contextmanager
77
+ def _empty_lifecycle(_: Context) -> Iterator[None]:
78
+ yield
79
+
80
+
74
81
  class ClientAppException(Exception):
75
82
  """Exception raised when an exception is raised while executing a ClientApp."""
76
83
 
@@ -135,29 +142,31 @@ class ClientApp:
135
142
  self._train: Optional[ClientAppCallable] = None
136
143
  self._evaluate: Optional[ClientAppCallable] = None
137
144
  self._query: Optional[ClientAppCallable] = None
145
+ self._lifecycle = _empty_lifecycle
138
146
 
139
147
  def __call__(self, message: Message, context: Context) -> Message:
140
148
  """Execute `ClientApp`."""
141
- # Execute message using `client_fn`
142
- if self._call:
143
- return self._call(message, context)
144
-
145
- # Execute message using a new
146
- if message.metadata.message_type == MessageType.TRAIN:
147
- if self._train:
148
- return self._train(message, context)
149
- raise ValueError("No `train` function registered")
150
- if message.metadata.message_type == MessageType.EVALUATE:
151
- if self._evaluate:
152
- return self._evaluate(message, context)
153
- raise ValueError("No `evaluate` function registered")
154
- if message.metadata.message_type == MessageType.QUERY:
155
- if self._query:
156
- return self._query(message, context)
157
- raise ValueError("No `query` function registered")
158
-
159
- # Message type did not match one of the known message types abvoe
160
- raise ValueError(f"Unknown message_type: {message.metadata.message_type}")
149
+ with self._lifecycle(context):
150
+ # Execute message using `client_fn`
151
+ if self._call:
152
+ return self._call(message, context)
153
+
154
+ # Execute message using a new
155
+ if message.metadata.message_type == MessageType.TRAIN:
156
+ if self._train:
157
+ return self._train(message, context)
158
+ raise ValueError("No `train` function registered")
159
+ if message.metadata.message_type == MessageType.EVALUATE:
160
+ if self._evaluate:
161
+ return self._evaluate(message, context)
162
+ raise ValueError("No `evaluate` function registered")
163
+ if message.metadata.message_type == MessageType.QUERY:
164
+ if self._query:
165
+ return self._query(message, context)
166
+ raise ValueError("No `query` function registered")
167
+
168
+ # Message type did not match one of the known message types abvoe
169
+ raise ValueError(f"Unknown message_type: {message.metadata.message_type}")
161
170
 
162
171
  def train(
163
172
  self, mods: Optional[list[Mod]] = None
@@ -296,6 +305,66 @@ class ClientApp:
296
305
 
297
306
  return query_decorator
298
307
 
308
+ def lifecycle(
309
+ self,
310
+ ) -> Callable[
311
+ [Callable[[Context], Iterator[None]]], Callable[[Context], Iterator[None]]
312
+ ]:
313
+ """Return a decorator that registers the lifecycle fn with the client app.
314
+
315
+ The decorated function should accept a `Context` object and use `yield`
316
+ to define enter and exit behavior.
317
+
318
+ Examples
319
+ --------
320
+ >>> app = ClientApp()
321
+ >>>
322
+ >>> @app.lifecycle()
323
+ >>> def lifecycle(context: Context) -> None:
324
+ >>> print("Initializing ClientApp")
325
+ >>> yield
326
+ >>> print("Cleaning up ClientApp")
327
+ """
328
+
329
+ def lifecycle_decorator(
330
+ lifecycle_fn: Callable[[Context], Iterator[None]]
331
+ ) -> Callable[[Context], Iterator[None]]:
332
+ """Register the lifecycle fn with the ServerApp object."""
333
+ warn_preview_feature("ClientApp-register-lifecycle-function")
334
+
335
+ @contextmanager
336
+ def decorated_lifecycle(context: Context) -> Iterator[None]:
337
+ # Execute the code before `yield` in lifecycle_fn
338
+ try:
339
+ if not isinstance(it := lifecycle_fn(context), Iterator):
340
+ raise StopIteration
341
+ next(it)
342
+ except StopIteration:
343
+ raise RuntimeError(
344
+ "Lifecycle function should yield at least once."
345
+ ) from None
346
+
347
+ try:
348
+ # Enter the context
349
+ yield
350
+ finally:
351
+ try:
352
+ # Execute the code after `yield` in lifecycle_fn
353
+ next(it)
354
+ except StopIteration:
355
+ pass
356
+ else:
357
+ raise RuntimeError("Lifecycle function should only yield once.")
358
+
359
+ # Register provided function with the ClientApp object
360
+ # Ignore mypy error because of different argument names (`_` vs `context`)
361
+ self._lifecycle = decorated_lifecycle # type: ignore
362
+
363
+ # Return provided function unmodified
364
+ return lifecycle_fn
365
+
366
+ return lifecycle_decorator
367
+
299
368
 
300
369
  class LoadClientAppError(Exception):
301
370
  """Error when trying to load `ClientApp`."""
@@ -20,6 +20,7 @@ from collections.abc import Sequence
20
20
  from pathlib import Path
21
21
  from typing import Optional, Union
22
22
 
23
+ from flwr.common.typing import UserInfo
23
24
  from flwr.proto.exec_pb2_grpc import ExecStub
24
25
 
25
26
  from ..typing import UserAuthCredentials, UserAuthLoginDetails
@@ -49,7 +50,7 @@ class ExecAuthPlugin(ABC):
49
50
  @abstractmethod
50
51
  def validate_tokens_in_metadata(
51
52
  self, metadata: Sequence[tuple[str, Union[str, bytes]]]
52
- ) -> bool:
53
+ ) -> tuple[bool, Optional[UserInfo]]:
53
54
  """Validate authentication tokens in the provided metadata."""
54
55
 
55
56
  @abstractmethod
@@ -212,3 +212,19 @@ class AuthType:
212
212
  def __new__(cls) -> AuthType:
213
213
  """Prevent instantiation."""
214
214
  raise TypeError(f"{cls.__name__} cannot be instantiated.")
215
+
216
+
217
+ class EventLogWriterType:
218
+ """Event log writer types."""
219
+
220
+ FALSE = "false"
221
+ STDOUT = "stdout"
222
+
223
+ def __new__(cls) -> EventLogWriterType:
224
+ """Prevent instantiation."""
225
+ raise TypeError(f"{cls.__name__} cannot be instantiated.")
226
+
227
+ @classmethod
228
+ def choices(cls) -> list[str]:
229
+ """Return a list of available log writer choices."""
230
+ return [cls.FALSE, cls.STDOUT]
@@ -0,0 +1,26 @@
1
+ # Copyright 2025 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
+ """Event log plugin components."""
16
+
17
+
18
+ from .event_log_plugin import EventLogRequest as EventLogRequest
19
+ from .event_log_plugin import EventLogResponse as EventLogResponse
20
+ from .event_log_plugin import EventLogWriterPlugin as EventLogWriterPlugin
21
+
22
+ __all__ = [
23
+ "EventLogRequest",
24
+ "EventLogResponse",
25
+ "EventLogWriterPlugin",
26
+ ]
@@ -0,0 +1,87 @@
1
+ # Copyright 2025 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
+ """Abstract class for Flower Event Log Writer Plugin."""
16
+
17
+
18
+ from abc import ABC, abstractmethod
19
+ from typing import Union
20
+
21
+ import grpc
22
+
23
+ from flwr.common.typing import LogEntry, UserInfo
24
+ from flwr.proto.exec_pb2 import ( # pylint: disable=E0611
25
+ GetLoginDetailsRequest,
26
+ GetLoginDetailsResponse,
27
+ ListRunsRequest,
28
+ ListRunsResponse,
29
+ StartRunRequest,
30
+ StartRunResponse,
31
+ StopRunRequest,
32
+ StopRunResponse,
33
+ StreamLogsRequest,
34
+ StreamLogsResponse,
35
+ )
36
+
37
+ # Type variables for request and response messages
38
+ EventLogRequest = Union[
39
+ StartRunRequest,
40
+ ListRunsRequest,
41
+ StreamLogsRequest,
42
+ StopRunRequest,
43
+ GetLoginDetailsRequest,
44
+ ]
45
+ EventLogResponse = Union[
46
+ StartRunResponse,
47
+ ListRunsResponse,
48
+ StreamLogsResponse,
49
+ StopRunResponse,
50
+ GetLoginDetailsResponse,
51
+ ]
52
+
53
+
54
+ class EventLogWriterPlugin(ABC):
55
+ """Abstract Flower Event Log Writer Plugin class for ExecServicer."""
56
+
57
+ @abstractmethod
58
+ def __init__(self) -> None:
59
+ """Abstract constructor."""
60
+
61
+ @abstractmethod
62
+ def compose_log_before_event( # pylint: disable=too-many-arguments
63
+ self,
64
+ request: EventLogRequest,
65
+ context: grpc.ServicerContext,
66
+ user_info: UserInfo,
67
+ method_name: str,
68
+ ) -> LogEntry:
69
+ """Compose pre-event log entry from the provided request and context."""
70
+
71
+ @abstractmethod
72
+ def compose_log_after_event( # pylint: disable=too-many-arguments,R0917
73
+ self,
74
+ request: EventLogRequest,
75
+ context: grpc.ServicerContext,
76
+ user_info: UserInfo,
77
+ method_name: str,
78
+ response: EventLogResponse,
79
+ ) -> LogEntry:
80
+ """Compose post-event log entry from the provided response and context."""
81
+
82
+ @abstractmethod
83
+ def write_log(
84
+ self,
85
+ log_entry: LogEntry,
86
+ ) -> None:
87
+ """Write the event log to the specified data sink."""
@@ -170,7 +170,6 @@ def load_app( # pylint: disable= too-many-branches
170
170
  module = importlib.import_module(module_str)
171
171
  else:
172
172
  module = sys.modules[module_str]
173
- _reload_modules(project_dir)
174
173
 
175
174
  except ModuleNotFoundError as err:
176
175
  raise error_type(
@@ -200,15 +199,6 @@ def _unload_modules(project_dir: Path) -> None:
200
199
  del sys.modules[name]
201
200
 
202
201
 
203
- def _reload_modules(project_dir: Path) -> None:
204
- """Reload modules from the project directory."""
205
- dir_str = str(project_dir.absolute())
206
- for m in list(sys.modules.values()):
207
- path: Optional[str] = getattr(m, "__file__", None)
208
- if path is not None and path.startswith(dir_str):
209
- importlib.reload(m)
210
-
211
-
212
202
  def _set_sys_path(directory: Optional[Union[str, Path]]) -> None:
213
203
  """Set the system path."""
214
204
  if directory is None:
@@ -17,82 +17,79 @@
17
17
 
18
18
  from __future__ import annotations
19
19
 
20
- from dataclasses import dataclass
21
- from typing import cast
20
+ from logging import WARN
21
+ from textwrap import indent
22
+ from typing import TypeVar, Union, cast
22
23
 
24
+ from ..logger import log
23
25
  from .configsrecord import ConfigsRecord
24
26
  from .metricsrecord import MetricsRecord
25
27
  from .parametersrecord import ParametersRecord
26
28
  from .typeddict import TypedDict
27
29
 
30
+ RecordType = Union[ParametersRecord, MetricsRecord, ConfigsRecord]
28
31
 
29
- @dataclass
30
- class RecordSetData:
31
- """Inner data container for the RecordSet class."""
32
+ T = TypeVar("T")
32
33
 
33
- parameters_records: TypedDict[str, ParametersRecord]
34
- metrics_records: TypedDict[str, MetricsRecord]
35
- configs_records: TypedDict[str, ConfigsRecord]
36
34
 
37
- def __init__(
38
- self,
39
- parameters_records: dict[str, ParametersRecord] | None = None,
40
- metrics_records: dict[str, MetricsRecord] | None = None,
41
- configs_records: dict[str, ConfigsRecord] | None = None,
42
- ) -> None:
43
- self.parameters_records = TypedDict[str, ParametersRecord](
44
- self._check_fn_str, self._check_fn_params
45
- )
46
- self.metrics_records = TypedDict[str, MetricsRecord](
47
- self._check_fn_str, self._check_fn_metrics
35
+ def _check_key(key: str) -> None:
36
+ if not isinstance(key, str):
37
+ raise TypeError(
38
+ f"Expected `{str.__name__}`, but "
39
+ f"received `{type(key).__name__}` for the key."
48
40
  )
49
- self.configs_records = TypedDict[str, ConfigsRecord](
50
- self._check_fn_str, self._check_fn_configs
41
+
42
+
43
+ def _check_value(value: RecordType) -> None:
44
+ if not isinstance(value, (ParametersRecord, MetricsRecord, ConfigsRecord)):
45
+ raise TypeError(
46
+ f"Expected `{ParametersRecord.__name__}`, `{MetricsRecord.__name__}`, "
47
+ f"or `{ConfigsRecord.__name__}` but received "
48
+ f"`{type(value).__name__}` for the value."
51
49
  )
52
- if parameters_records is not None:
53
- self.parameters_records.update(parameters_records)
54
- if metrics_records is not None:
55
- self.metrics_records.update(metrics_records)
56
- if configs_records is not None:
57
- self.configs_records.update(configs_records)
58
-
59
- def _check_fn_str(self, key: str) -> None:
60
- if not isinstance(key, str):
61
- raise TypeError(
62
- f"Expected `{str.__name__}`, but "
63
- f"received `{type(key).__name__}` for the key."
64
- )
65
50
 
66
- def _check_fn_params(self, record: ParametersRecord) -> None:
67
- if not isinstance(record, ParametersRecord):
68
- raise TypeError(
69
- f"Expected `{ParametersRecord.__name__}`, but "
70
- f"received `{type(record).__name__}` for the value."
71
- )
72
51
 
73
- def _check_fn_metrics(self, record: MetricsRecord) -> None:
74
- if not isinstance(record, MetricsRecord):
75
- raise TypeError(
76
- f"Expected `{MetricsRecord.__name__}`, but "
77
- f"received `{type(record).__name__}` for the value."
78
- )
52
+ class _SyncedDict(TypedDict[str, T]):
53
+ """A synchronized dictionary that mirrors changes to an underlying RecordSet.
79
54
 
80
- def _check_fn_configs(self, record: ConfigsRecord) -> None:
81
- if not isinstance(record, ConfigsRecord):
55
+ This dictionary ensures that any modifications (set or delete operations)
56
+ are automatically reflected in the associated `RecordSet`. Only values of
57
+ the specified `allowed_type` are permitted.
58
+ """
59
+
60
+ def __init__(self, ref_recordset: RecordSet, allowed_type: type[T]) -> None:
61
+ if not issubclass(
62
+ allowed_type, (ParametersRecord, MetricsRecord, ConfigsRecord)
63
+ ):
64
+ raise TypeError(f"{allowed_type} is not a valid type.")
65
+ super().__init__(_check_key, self.check_value)
66
+ self.recordset = ref_recordset
67
+ self.allowed_type = allowed_type
68
+
69
+ def __setitem__(self, key: str, value: T) -> None:
70
+ super().__setitem__(key, value)
71
+ self.recordset[key] = cast(RecordType, value)
72
+
73
+ def __delitem__(self, key: str) -> None:
74
+ super().__delitem__(key)
75
+ del self.recordset[key]
76
+
77
+ def check_value(self, value: T) -> None:
78
+ """Check if value is of expected type."""
79
+ if not isinstance(value, self.allowed_type):
82
80
  raise TypeError(
83
- f"Expected `{ConfigsRecord.__name__}`, but "
84
- f"received `{type(record).__name__}` for the value."
81
+ f"Expected `{self.allowed_type.__name__}`, but "
82
+ f"received `{type(value).__name__}` for the value."
85
83
  )
86
84
 
87
85
 
88
- class RecordSet:
86
+ class RecordSet(TypedDict[str, RecordType]):
89
87
  """RecordSet stores groups of parameters, metrics and configs.
90
88
 
91
- A :code:`RecordSet` is the unified mechanism by which parameters,
92
- metrics and configs can be either stored as part of a
93
- `flwr.common.Context <flwr.common.Context.html>`_ in your apps
94
- or communicated as part of a
95
- `flwr.common.Message <flwr.common.Message.html>`_ between your apps.
89
+ A :class:`RecordSet` is the unified mechanism by which parameters,
90
+ metrics and configs can be either stored as part of a :class:`Context`
91
+ in your apps or communicated as part of a :class:`Message` between
92
+ your apps.
96
93
 
97
94
  Parameters
98
95
  ----------
@@ -127,12 +124,12 @@ class RecordSet:
127
124
  >>> # We can create a ConfigsRecord
128
125
  >>> c_record = ConfigsRecord({"lr": 0.1, "batch-size": 128})
129
126
  >>> # Adding it to the record_set would look like this
130
- >>> my_recordset.configs_records["my_config"] = c_record
127
+ >>> my_recordset["my_config"] = c_record
131
128
  >>>
132
129
  >>> # We can create a MetricsRecord following a similar process
133
130
  >>> m_record = MetricsRecord({"accuracy": 0.93, "losses": [0.23, 0.1]})
134
131
  >>> # Adding it to the record_set would look like this
135
- >>> my_recordset.metrics_records["my_metrics"] = m_record
132
+ >>> my_recordset["my_metrics"] = m_record
136
133
 
137
134
  Adding a :code:`ParametersRecord` follows the same steps as above but first,
138
135
  the array needs to be serialized and represented as a :code:`flwr.common.Array`.
@@ -151,7 +148,7 @@ class RecordSet:
151
148
  >>> p_record = ParametersRecord({"my_array": arr})
152
149
  >>>
153
150
  >>> # Adding it to the record_set would look like this
154
- >>> my_recordset.parameters_records["my_parameters"] = p_record
151
+ >>> my_recordset["my_parameters"] = p_record
155
152
 
156
153
  For additional examples on how to construct each of the records types shown
157
154
  above, please refer to the documentation for :code:`ConfigsRecord`,
@@ -164,39 +161,57 @@ class RecordSet:
164
161
  metrics_records: dict[str, MetricsRecord] | None = None,
165
162
  configs_records: dict[str, ConfigsRecord] | None = None,
166
163
  ) -> None:
167
- data = RecordSetData(
168
- parameters_records=parameters_records,
169
- metrics_records=metrics_records,
170
- configs_records=configs_records,
171
- )
172
- self.__dict__["_data"] = data
164
+ super().__init__(_check_key, _check_value)
165
+ for key, p_record in (parameters_records or {}).items():
166
+ self[key] = p_record
167
+ for key, m_record in (metrics_records or {}).items():
168
+ self[key] = m_record
169
+ for key, c_record in (configs_records or {}).items():
170
+ self[key] = c_record
173
171
 
174
172
  @property
175
173
  def parameters_records(self) -> TypedDict[str, ParametersRecord]:
176
- """Dictionary holding ParametersRecord instances."""
177
- data = cast(RecordSetData, self.__dict__["_data"])
178
- return data.parameters_records
174
+ """Dictionary holding only ParametersRecord instances."""
175
+ synced_dict = _SyncedDict[ParametersRecord](self, ParametersRecord)
176
+ for key, record in self.items():
177
+ if isinstance(record, ParametersRecord):
178
+ synced_dict[key] = record
179
+ return synced_dict
179
180
 
180
181
  @property
181
182
  def metrics_records(self) -> TypedDict[str, MetricsRecord]:
182
- """Dictionary holding MetricsRecord instances."""
183
- data = cast(RecordSetData, self.__dict__["_data"])
184
- return data.metrics_records
183
+ """Dictionary holding only MetricsRecord instances."""
184
+ synced_dict = _SyncedDict[MetricsRecord](self, MetricsRecord)
185
+ for key, record in self.items():
186
+ if isinstance(record, MetricsRecord):
187
+ synced_dict[key] = record
188
+ return synced_dict
185
189
 
186
190
  @property
187
191
  def configs_records(self) -> TypedDict[str, ConfigsRecord]:
188
- """Dictionary holding ConfigsRecord instances."""
189
- data = cast(RecordSetData, self.__dict__["_data"])
190
- return data.configs_records
192
+ """Dictionary holding only ConfigsRecord instances."""
193
+ synced_dict = _SyncedDict[ConfigsRecord](self, ConfigsRecord)
194
+ for key, record in self.items():
195
+ if isinstance(record, ConfigsRecord):
196
+ synced_dict[key] = record
197
+ return synced_dict
191
198
 
192
199
  def __repr__(self) -> str:
193
200
  """Return a string representation of this instance."""
194
201
  flds = ("parameters_records", "metrics_records", "configs_records")
195
- view = ", ".join([f"{fld}={getattr(self, fld)!r}" for fld in flds])
196
- return f"{self.__class__.__qualname__}({view})"
197
-
198
- def __eq__(self, other: object) -> bool:
199
- """Compare two instances of the class."""
200
- if not isinstance(other, self.__class__):
201
- raise NotImplementedError
202
- return self.__dict__ == other.__dict__
202
+ fld_views = [f"{fld}={dict(getattr(self, fld))!r}" for fld in flds]
203
+ view = indent(",\n".join(fld_views), " ")
204
+ return f"{self.__class__.__qualname__}(\n{view}\n)"
205
+
206
+ def __setitem__(self, key: str, value: RecordType) -> None:
207
+ """Set the given key to the given value after type checking."""
208
+ original_value = self.get(key, None)
209
+ super().__setitem__(key, value)
210
+ if original_value is not None and not isinstance(value, type(original_value)):
211
+ log(
212
+ WARN,
213
+ "Key '%s' was overwritten: record of type `%s` replaced with type `%s`",
214
+ key,
215
+ type(original_value).__name__,
216
+ type(value).__name__,
217
+ )
@@ -25,7 +25,11 @@ from flwr.common.typing import NDArrayFloat, NDArrayInt
25
25
  def _stochastic_round(arr: NDArrayFloat) -> NDArrayInt:
26
26
  ret: NDArrayInt = np.ceil(arr).astype(np.int32)
27
27
  rand_arr = np.random.rand(*ret.shape)
28
- ret[rand_arr < ret - arr] -= 1
28
+ if len(ret.shape) == 0:
29
+ if rand_arr < ret - arr:
30
+ ret -= 1
31
+ else:
32
+ ret[rand_arr < ret - arr] -= 1
29
33
  return ret
30
34
 
31
35