flwr-nightly 1.19.0.dev20250511__tar.gz → 1.19.0.dev20250513__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 (338) hide show
  1. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/PKG-INFO +1 -1
  2. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/constant.py +1 -0
  3. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/heartbeat.py +5 -0
  4. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/inflatable.py +14 -1
  5. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/record/array.py +10 -1
  6. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/record/arrayrecord.py +65 -1
  7. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/record/configrecord.py +10 -1
  8. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/record/metricrecord.py +10 -1
  9. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/record/recorddict.py +69 -1
  10. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/linkstate/in_memory_linkstate.py +84 -4
  11. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/linkstate/linkstate.py +23 -0
  12. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/linkstate/sqlite_linkstate.py +98 -8
  13. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/pyproject.toml +1 -1
  14. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/README.md +0 -0
  15. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/__init__.py +0 -0
  16. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/__init__.py +0 -0
  17. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/app.py +0 -0
  18. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/auth_plugin/__init__.py +0 -0
  19. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/auth_plugin/oidc_cli_plugin.py +0 -0
  20. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/build.py +0 -0
  21. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/cli_user_auth_interceptor.py +0 -0
  22. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/config_utils.py +0 -0
  23. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/constant.py +0 -0
  24. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/example.py +0 -0
  25. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/install.py +0 -0
  26. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/log.py +0 -0
  27. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/login/__init__.py +0 -0
  28. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/login/login.py +0 -0
  29. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/ls.py +0 -0
  30. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/__init__.py +0 -0
  31. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/new.py +0 -0
  32. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/__init__.py +0 -0
  33. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/.gitignore.tpl +0 -0
  34. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/LICENSE.tpl +0 -0
  35. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/README.baseline.md.tpl +0 -0
  36. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/README.flowertune.md.tpl +0 -0
  37. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/README.md.tpl +0 -0
  38. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/__init__.py +0 -0
  39. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/__init__.baseline.py.tpl +0 -0
  40. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/__init__.py +0 -0
  41. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/__init__.py.tpl +0 -0
  42. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/client.baseline.py.tpl +0 -0
  43. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/client.huggingface.py.tpl +0 -0
  44. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/client.jax.py.tpl +0 -0
  45. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/client.mlx.py.tpl +0 -0
  46. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -0
  47. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -0
  48. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/client.sklearn.py.tpl +0 -0
  49. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -0
  50. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/dataset.baseline.py.tpl +0 -0
  51. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/flwr_tune/__init__.py +0 -0
  52. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +0 -0
  53. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +0 -0
  54. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +0 -0
  55. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +0 -0
  56. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +0 -0
  57. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/model.baseline.py.tpl +0 -0
  58. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/server.baseline.py.tpl +0 -0
  59. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/server.huggingface.py.tpl +0 -0
  60. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/server.jax.py.tpl +0 -0
  61. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/server.mlx.py.tpl +0 -0
  62. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -0
  63. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -0
  64. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/server.sklearn.py.tpl +0 -0
  65. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -0
  66. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/strategy.baseline.py.tpl +0 -0
  67. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/task.huggingface.py.tpl +0 -0
  68. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/task.jax.py.tpl +0 -0
  69. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/task.mlx.py.tpl +0 -0
  70. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/task.numpy.py.tpl +0 -0
  71. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -0
  72. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/task.sklearn.py.tpl +0 -0
  73. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +0 -0
  74. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/code/utils.baseline.py.tpl +0 -0
  75. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +0 -0
  76. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +0 -0
  77. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +0 -0
  78. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/pyproject.jax.toml.tpl +0 -0
  79. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +0 -0
  80. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +0 -0
  81. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +0 -0
  82. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +0 -0
  83. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +0 -0
  84. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/run/__init__.py +0 -0
  85. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/run/run.py +0 -0
  86. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/stop.py +0 -0
  87. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/cli/utils.py +0 -0
  88. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/__init__.py +0 -0
  89. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/app.py +0 -0
  90. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/client.py +0 -0
  91. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/client_app.py +0 -0
  92. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/clientapp/__init__.py +0 -0
  93. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/clientapp/app.py +0 -0
  94. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/clientapp/clientappio_servicer.py +0 -0
  95. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/clientapp/utils.py +0 -0
  96. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/dpfedavg_numpy_client.py +0 -0
  97. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/grpc_adapter_client/__init__.py +0 -0
  98. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/grpc_adapter_client/connection.py +0 -0
  99. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/grpc_client/__init__.py +0 -0
  100. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/grpc_client/connection.py +0 -0
  101. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/grpc_rere_client/__init__.py +0 -0
  102. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/grpc_rere_client/client_interceptor.py +0 -0
  103. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/grpc_rere_client/connection.py +0 -0
  104. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/grpc_rere_client/grpc_adapter.py +0 -0
  105. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/message_handler/__init__.py +0 -0
  106. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/message_handler/message_handler.py +0 -0
  107. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/mod/__init__.py +0 -0
  108. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/mod/centraldp_mods.py +0 -0
  109. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/mod/comms_mods.py +0 -0
  110. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/mod/localdp_mod.py +0 -0
  111. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/mod/secure_aggregation/__init__.py +0 -0
  112. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/mod/secure_aggregation/secagg_mod.py +0 -0
  113. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +0 -0
  114. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/mod/utils.py +0 -0
  115. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/nodestate/__init__.py +0 -0
  116. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/nodestate/in_memory_nodestate.py +0 -0
  117. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/nodestate/nodestate.py +0 -0
  118. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/nodestate/nodestate_factory.py +0 -0
  119. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/numpy_client.py +0 -0
  120. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/rest_client/__init__.py +0 -0
  121. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/rest_client/connection.py +0 -0
  122. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/run_info_store.py +0 -0
  123. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/supernode/__init__.py +0 -0
  124. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/supernode/app.py +0 -0
  125. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/client/typing.py +0 -0
  126. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/__init__.py +0 -0
  127. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/address.py +0 -0
  128. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/args.py +0 -0
  129. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/auth_plugin/__init__.py +0 -0
  130. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/auth_plugin/auth_plugin.py +0 -0
  131. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/config.py +0 -0
  132. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/context.py +0 -0
  133. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/date.py +0 -0
  134. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/differential_privacy.py +0 -0
  135. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/differential_privacy_constants.py +0 -0
  136. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/dp.py +0 -0
  137. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/event_log_plugin/__init__.py +0 -0
  138. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/event_log_plugin/event_log_plugin.py +0 -0
  139. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/exit/__init__.py +0 -0
  140. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/exit/exit.py +0 -0
  141. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/exit/exit_code.py +0 -0
  142. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/exit_handlers.py +0 -0
  143. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/grpc.py +0 -0
  144. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/logger.py +0 -0
  145. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/message.py +0 -0
  146. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/object_ref.py +0 -0
  147. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/parameter.py +0 -0
  148. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/pyproject.py +0 -0
  149. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/record/__init__.py +0 -0
  150. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/record/conversion_utils.py +0 -0
  151. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/record/typeddict.py +0 -0
  152. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/recorddict_compat.py +0 -0
  153. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/retry_invoker.py +0 -0
  154. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/secure_aggregation/__init__.py +0 -0
  155. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/secure_aggregation/crypto/__init__.py +0 -0
  156. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/secure_aggregation/crypto/shamir.py +0 -0
  157. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py +0 -0
  158. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py +0 -0
  159. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/secure_aggregation/quantization.py +0 -0
  160. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/secure_aggregation/secaggplus_constants.py +0 -0
  161. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/secure_aggregation/secaggplus_utils.py +0 -0
  162. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/serde.py +0 -0
  163. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/serde_utils.py +0 -0
  164. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/telemetry.py +0 -0
  165. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/typing.py +0 -0
  166. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/common/version.py +0 -0
  167. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/__init__.py +0 -0
  168. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/clientappio_pb2.py +0 -0
  169. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/clientappio_pb2.pyi +0 -0
  170. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/clientappio_pb2_grpc.py +0 -0
  171. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/clientappio_pb2_grpc.pyi +0 -0
  172. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/error_pb2.py +0 -0
  173. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/error_pb2.pyi +0 -0
  174. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/error_pb2_grpc.py +0 -0
  175. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/error_pb2_grpc.pyi +0 -0
  176. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/exec_pb2.py +0 -0
  177. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/exec_pb2.pyi +0 -0
  178. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/exec_pb2_grpc.py +0 -0
  179. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/exec_pb2_grpc.pyi +0 -0
  180. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/fab_pb2.py +0 -0
  181. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/fab_pb2.pyi +0 -0
  182. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/fab_pb2_grpc.py +0 -0
  183. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/fab_pb2_grpc.pyi +0 -0
  184. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/fleet_pb2.py +0 -0
  185. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/fleet_pb2.pyi +0 -0
  186. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/fleet_pb2_grpc.py +0 -0
  187. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/fleet_pb2_grpc.pyi +0 -0
  188. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/grpcadapter_pb2.py +0 -0
  189. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/grpcadapter_pb2.pyi +0 -0
  190. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/grpcadapter_pb2_grpc.py +0 -0
  191. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/grpcadapter_pb2_grpc.pyi +0 -0
  192. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/heartbeat_pb2.py +0 -0
  193. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/heartbeat_pb2.pyi +0 -0
  194. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/heartbeat_pb2_grpc.py +0 -0
  195. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/heartbeat_pb2_grpc.pyi +0 -0
  196. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/log_pb2.py +0 -0
  197. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/log_pb2.pyi +0 -0
  198. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/log_pb2_grpc.py +0 -0
  199. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/log_pb2_grpc.pyi +0 -0
  200. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/message_pb2.py +0 -0
  201. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/message_pb2.pyi +0 -0
  202. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/message_pb2_grpc.py +0 -0
  203. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/message_pb2_grpc.pyi +0 -0
  204. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/node_pb2.py +0 -0
  205. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/node_pb2.pyi +0 -0
  206. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/node_pb2_grpc.py +0 -0
  207. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/node_pb2_grpc.pyi +0 -0
  208. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/recorddict_pb2.py +0 -0
  209. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/recorddict_pb2.pyi +0 -0
  210. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/recorddict_pb2_grpc.py +0 -0
  211. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/recorddict_pb2_grpc.pyi +0 -0
  212. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/run_pb2.py +0 -0
  213. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/run_pb2.pyi +0 -0
  214. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/run_pb2_grpc.py +0 -0
  215. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/run_pb2_grpc.pyi +0 -0
  216. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/serverappio_pb2.py +0 -0
  217. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/serverappio_pb2.pyi +0 -0
  218. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/serverappio_pb2_grpc.py +0 -0
  219. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/serverappio_pb2_grpc.pyi +0 -0
  220. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/simulationio_pb2.py +0 -0
  221. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/simulationio_pb2.pyi +0 -0
  222. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/simulationio_pb2_grpc.py +0 -0
  223. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/simulationio_pb2_grpc.pyi +0 -0
  224. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/transport_pb2.py +0 -0
  225. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/transport_pb2.pyi +0 -0
  226. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/transport_pb2_grpc.py +0 -0
  227. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/proto/transport_pb2_grpc.pyi +0 -0
  228. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/py.typed +0 -0
  229. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/__init__.py +0 -0
  230. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/app.py +0 -0
  231. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/client_manager.py +0 -0
  232. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/client_proxy.py +0 -0
  233. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/compat/__init__.py +0 -0
  234. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/compat/app.py +0 -0
  235. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/compat/app_utils.py +0 -0
  236. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/compat/grid_client_proxy.py +0 -0
  237. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/compat/legacy_context.py +0 -0
  238. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/criterion.py +0 -0
  239. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/fleet_event_log_interceptor.py +0 -0
  240. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/grid/__init__.py +0 -0
  241. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/grid/grid.py +0 -0
  242. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/grid/grpc_grid.py +0 -0
  243. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/grid/inmemory_grid.py +0 -0
  244. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/history.py +0 -0
  245. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/run_serverapp.py +0 -0
  246. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/server.py +0 -0
  247. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/server_app.py +0 -0
  248. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/server_config.py +0 -0
  249. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/serverapp/__init__.py +0 -0
  250. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/serverapp/app.py +0 -0
  251. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/serverapp_components.py +0 -0
  252. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/__init__.py +0 -0
  253. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/aggregate.py +0 -0
  254. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/bulyan.py +0 -0
  255. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/dp_adaptive_clipping.py +0 -0
  256. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/dp_fixed_clipping.py +0 -0
  257. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/dpfedavg_adaptive.py +0 -0
  258. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/dpfedavg_fixed.py +0 -0
  259. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/fault_tolerant_fedavg.py +0 -0
  260. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/fedadagrad.py +0 -0
  261. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/fedadam.py +0 -0
  262. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/fedavg.py +0 -0
  263. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/fedavg_android.py +0 -0
  264. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/fedavgm.py +0 -0
  265. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/fedmedian.py +0 -0
  266. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/fedopt.py +0 -0
  267. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/fedprox.py +0 -0
  268. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/fedtrimmedavg.py +0 -0
  269. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/fedxgb_bagging.py +0 -0
  270. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/fedxgb_cyclic.py +0 -0
  271. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/fedxgb_nn_avg.py +0 -0
  272. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/fedyogi.py +0 -0
  273. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/krum.py +0 -0
  274. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/qfedavg.py +0 -0
  275. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/strategy/strategy.py +0 -0
  276. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/__init__.py +0 -0
  277. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/ffs/__init__.py +0 -0
  278. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/ffs/disk_ffs.py +0 -0
  279. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/ffs/ffs.py +0 -0
  280. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/ffs/ffs_factory.py +0 -0
  281. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/__init__.py +0 -0
  282. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/grpc_adapter/__init__.py +0 -0
  283. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +0 -0
  284. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py +0 -0
  285. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +0 -0
  286. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +0 -0
  287. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +0 -0
  288. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +0 -0
  289. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/grpc_rere/__init__.py +0 -0
  290. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +0 -0
  291. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +0 -0
  292. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/message_handler/__init__.py +0 -0
  293. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/message_handler/message_handler.py +0 -0
  294. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/rest_rere/__init__.py +0 -0
  295. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/rest_rere/rest_api.py +0 -0
  296. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/vce/__init__.py +0 -0
  297. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/vce/backend/__init__.py +0 -0
  298. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/vce/backend/backend.py +0 -0
  299. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/vce/backend/raybackend.py +0 -0
  300. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/fleet/vce/vce_api.py +0 -0
  301. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/linkstate/__init__.py +0 -0
  302. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/linkstate/linkstate_factory.py +0 -0
  303. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/linkstate/utils.py +0 -0
  304. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/serverappio/__init__.py +0 -0
  305. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/serverappio/serverappio_grpc.py +0 -0
  306. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/serverappio/serverappio_servicer.py +0 -0
  307. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/simulation/__init__.py +0 -0
  308. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/simulation/simulationio_grpc.py +0 -0
  309. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/simulation/simulationio_servicer.py +0 -0
  310. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/superlink/utils.py +0 -0
  311. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/typing.py +0 -0
  312. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/utils/__init__.py +0 -0
  313. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/utils/tensorboard.py +0 -0
  314. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/utils/validator.py +0 -0
  315. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/workflow/__init__.py +0 -0
  316. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/workflow/constant.py +0 -0
  317. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/workflow/default_workflows.py +0 -0
  318. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/workflow/secure_aggregation/__init__.py +0 -0
  319. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/workflow/secure_aggregation/secagg_workflow.py +0 -0
  320. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +0 -0
  321. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/simulation/__init__.py +0 -0
  322. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/simulation/app.py +0 -0
  323. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/simulation/legacy_app.py +0 -0
  324. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/simulation/ray_transport/__init__.py +0 -0
  325. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/simulation/ray_transport/ray_actor.py +0 -0
  326. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/simulation/ray_transport/ray_client_proxy.py +0 -0
  327. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/simulation/ray_transport/utils.py +0 -0
  328. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/simulation/run_simulation.py +0 -0
  329. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/simulation/simulationio_connection.py +0 -0
  330. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/superexec/__init__.py +0 -0
  331. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/superexec/app.py +0 -0
  332. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/superexec/deployment.py +0 -0
  333. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/superexec/exec_event_log_interceptor.py +0 -0
  334. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/superexec/exec_grpc.py +0 -0
  335. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/superexec/exec_servicer.py +0 -0
  336. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/superexec/exec_user_auth_interceptor.py +0 -0
  337. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/superexec/executor.py +0 -0
  338. {flwr_nightly-1.19.0.dev20250511 → flwr_nightly-1.19.0.dev20250513}/py/flwr/superexec/simulation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: flwr-nightly
3
- Version: 1.19.0.dev20250511
3
+ Version: 1.19.0.dev20250513
4
4
  Summary: Flower: A Friendly Federated AI Framework
5
5
  License: Apache-2.0
6
6
  Keywords: Artificial Intelligence,Federated AI,Federated Analytics,Federated Evaluation,Federated Learning,Flower,Machine Learning
@@ -62,6 +62,7 @@ HEARTBEAT_BASE_MULTIPLIER = 0.8
62
62
  HEARTBEAT_RANDOM_RANGE = (-0.1, 0.1)
63
63
  HEARTBEAT_MAX_INTERVAL = 1e300
64
64
  HEARTBEAT_PATIENCE = 2
65
+ RUN_FAILURE_DETAILS_NO_HEARTBEAT = "No heartbeat received from the run."
65
66
 
66
67
  # IDs
67
68
  RUN_ID_NUM_BYTES = 8
@@ -77,6 +77,11 @@ class HeartbeatSender:
77
77
  self._stop_event.set()
78
78
  self._thread.join()
79
79
 
80
+ @property
81
+ def is_running(self) -> bool:
82
+ """Return True if the heartbeat sender is running, False otherwise."""
83
+ return self._thread.is_alive() and not self._stop_event.is_set()
84
+
80
85
  def _run(self) -> None:
81
86
  """Periodically send heartbeats until stopped."""
82
87
  while not self._stop_event.is_set():
@@ -15,6 +15,8 @@
15
15
  """InflatableObject base class."""
16
16
 
17
17
 
18
+ from __future__ import annotations
19
+
18
20
  import hashlib
19
21
  from typing import TypeVar
20
22
 
@@ -31,7 +33,9 @@ class InflatableObject:
31
33
  raise NotImplementedError()
32
34
 
33
35
  @classmethod
34
- def inflate(cls, object_content: bytes) -> "InflatableObject":
36
+ def inflate(
37
+ cls, object_content: bytes, children: dict[str, InflatableObject] | None = None
38
+ ) -> InflatableObject:
35
39
  """Inflate the object from bytes.
36
40
 
37
41
  Parameters
@@ -39,6 +43,10 @@ class InflatableObject:
39
43
  object_content : bytes
40
44
  The deflated object content.
41
45
 
46
+ children : Optional[dict[str, InflatableObject]] (default: None)
47
+ Dictionary of children InflatableObjects mapped to their object IDs. These
48
+ childrens enable the full inflation of the parent InflatableObject.
49
+
42
50
  Returns
43
51
  -------
44
52
  InflatableObject
@@ -51,6 +59,11 @@ class InflatableObject:
51
59
  """Get object_id."""
52
60
  return get_object_id(self.deflate())
53
61
 
62
+ @property
63
+ def children(self) -> dict[str, InflatableObject] | None:
64
+ """Get all child objects as a dictionary or None if there are no children."""
65
+ return None
66
+
54
67
 
55
68
  def get_object_id(object_content: bytes) -> str:
56
69
  """Return a SHA-256 hash of the (deflated) object content."""
@@ -265,7 +265,9 @@ class Array(InflatableObject):
265
265
  return add_header_to_object_body(object_body=obj_body, cls=self)
266
266
 
267
267
  @classmethod
268
- def inflate(cls, object_content: bytes) -> Array:
268
+ def inflate(
269
+ cls, object_content: bytes, children: dict[str, InflatableObject] | None = None
270
+ ) -> Array:
269
271
  """Inflate an Array from bytes.
270
272
 
271
273
  Parameters
@@ -273,11 +275,18 @@ class Array(InflatableObject):
273
275
  object_content : bytes
274
276
  The deflated object content of the Array.
275
277
 
278
+ children : Optional[dict[str, InflatableObject]] (default: None)
279
+ Must be ``None``. ``Array`` does not support child objects.
280
+ Providing any children will raise a ``ValueError``.
281
+
276
282
  Returns
277
283
  -------
278
284
  Array
279
285
  The inflated Array.
280
286
  """
287
+ if children is not None:
288
+ raise ValueError("`Array` objects do not have children.")
289
+
281
290
  obj_body = get_object_body(object_content, cls)
282
291
  proto_array = ArrayProto.FromString(obj_body)
283
292
  return cls(
@@ -18,6 +18,7 @@
18
18
  from __future__ import annotations
19
19
 
20
20
  import gc
21
+ import json
21
22
  import sys
22
23
  from collections import OrderedDict
23
24
  from logging import WARN
@@ -26,6 +27,7 @@ from typing import TYPE_CHECKING, Any, cast, overload
26
27
  import numpy as np
27
28
 
28
29
  from ..constant import GC_THRESHOLD
30
+ from ..inflatable import InflatableObject, add_header_to_object_body, get_object_body
29
31
  from ..logger import log
30
32
  from ..typing import NDArray
31
33
  from .array import Array
@@ -56,7 +58,7 @@ def _check_value(value: Array) -> None:
56
58
  )
57
59
 
58
60
 
59
- class ArrayRecord(TypedDict[str, Array]):
61
+ class ArrayRecord(TypedDict[str, Array], InflatableObject):
60
62
  """Array record.
61
63
 
62
64
  A typed dictionary (``str`` to :class:`Array`) that can store named arrays,
@@ -365,6 +367,68 @@ class ArrayRecord(TypedDict[str, Array]):
365
367
 
366
368
  return num_bytes
367
369
 
370
+ @property
371
+ def children(self) -> dict[str, InflatableObject]:
372
+ """Return a dictionary of Arrays with their Object IDs as keys."""
373
+ return {arr.object_id: arr for arr in self.values()}
374
+
375
+ def deflate(self) -> bytes:
376
+ """Deflate the ArrayRecord."""
377
+ # array_name: array_object_id mapping
378
+ array_refs: dict[str, str] = {}
379
+
380
+ for array_name, array in self.items():
381
+ array_refs[array_name] = array.object_id
382
+
383
+ # Serialize references dict
384
+ object_body = json.dumps(array_refs).encode("utf-8")
385
+ return add_header_to_object_body(object_body=object_body, cls=self)
386
+
387
+ @classmethod
388
+ def inflate(
389
+ cls, object_content: bytes, children: dict[str, InflatableObject] | None = None
390
+ ) -> ArrayRecord:
391
+ """Inflate an ArrayRecord from bytes.
392
+
393
+ Parameters
394
+ ----------
395
+ object_content : bytes
396
+ The deflated object content of the ArrayRecord.
397
+ children : Optional[dict[str, InflatableObject]] (default: None)
398
+ Dictionary of children InflatableObjects mapped to their Object IDs.
399
+ These children enable the full inflation of the ArrayRecord.
400
+
401
+ Returns
402
+ -------
403
+ ArrayRecord
404
+ The inflated ArrayRecord.
405
+ """
406
+ if children is None:
407
+ children = {}
408
+
409
+ # Inflate mapping of array_names (keys in the ArrayRecord) to Arrays' object IDs
410
+ obj_body = get_object_body(object_content, cls)
411
+ array_refs: dict[str, str] = json.loads(obj_body.decode(encoding="utf-8"))
412
+
413
+ unique_arrays = set(array_refs.values())
414
+ children_obj_ids = set(children.keys())
415
+ if unique_arrays != children_obj_ids:
416
+ raise ValueError(
417
+ "Unexpected set of `children`. "
418
+ f"Expected {unique_arrays} but got {children_obj_ids}."
419
+ )
420
+
421
+ # Ensure children are of type Array
422
+ if not all(isinstance(arr, Array) for arr in children.values()):
423
+ raise ValueError("`Children` are expected to be of type `Array`.")
424
+
425
+ # Instantiate new ArrayRecord
426
+ return ArrayRecord(
427
+ OrderedDict(
428
+ {name: children[object_id] for name, object_id in array_refs.items()}
429
+ )
430
+ )
431
+
368
432
 
369
433
  class ParametersRecord(ArrayRecord):
370
434
  """Deprecated class ``ParametersRecord``, use ``ArrayRecord`` instead.
@@ -185,7 +185,9 @@ class ConfigRecord(TypedDict[str, ConfigRecordValues], InflatableObject):
185
185
  return add_header_to_object_body(object_body=obj_body, cls=self)
186
186
 
187
187
  @classmethod
188
- def inflate(cls, object_content: bytes) -> ConfigRecord:
188
+ def inflate(
189
+ cls, object_content: bytes, children: dict[str, InflatableObject] | None = None
190
+ ) -> ConfigRecord:
189
191
  """Inflate a ConfigRecord from bytes.
190
192
 
191
193
  Parameters
@@ -193,11 +195,18 @@ class ConfigRecord(TypedDict[str, ConfigRecordValues], InflatableObject):
193
195
  object_content : bytes
194
196
  The deflated object content of the ConfigRecord.
195
197
 
198
+ children : Optional[dict[str, InflatableObject]] (default: None)
199
+ Must be ``None``. ``ConfigRecord`` does not support child objects.
200
+ Providing any children will raise a ``ValueError``.
201
+
196
202
  Returns
197
203
  -------
198
204
  ConfigRecord
199
205
  The inflated ConfigRecord.
200
206
  """
207
+ if children is not None:
208
+ raise ValueError("`ConfigRecord` objects do not have children.")
209
+
201
210
  obj_body = get_object_body(object_content, cls)
202
211
  config_record_proto = ProtoConfigRecord.FromString(obj_body)
203
212
 
@@ -160,7 +160,9 @@ class MetricRecord(TypedDict[str, MetricRecordValues], InflatableObject):
160
160
  return add_header_to_object_body(object_body=obj_body, cls=self)
161
161
 
162
162
  @classmethod
163
- def inflate(cls, object_content: bytes) -> MetricRecord:
163
+ def inflate(
164
+ cls, object_content: bytes, children: dict[str, InflatableObject] | None = None
165
+ ) -> MetricRecord:
164
166
  """Inflate a MetricRecord from bytes.
165
167
 
166
168
  Parameters
@@ -168,11 +170,18 @@ class MetricRecord(TypedDict[str, MetricRecordValues], InflatableObject):
168
170
  object_content : bytes
169
171
  The deflated object content of the MetricRecord.
170
172
 
173
+ children : Optional[dict[str, InflatableObject]] (default: None)
174
+ Must be ``None``. ``MetricRecord`` does not support child objects.
175
+ Providing any children will raise a ``ValueError``.
176
+
171
177
  Returns
172
178
  -------
173
179
  MetricRecord
174
180
  The inflated MetricRecord.
175
181
  """
182
+ if children is not None:
183
+ raise ValueError("`MetricRecord` objects do not have children.")
184
+
176
185
  obj_body = get_object_body(object_content, cls)
177
186
  metric_record_proto = ProtoMetricRecord.FromString(obj_body)
178
187
 
@@ -17,10 +17,12 @@
17
17
 
18
18
  from __future__ import annotations
19
19
 
20
+ import json
20
21
  from logging import WARN
21
22
  from textwrap import indent
22
23
  from typing import TypeVar, Union, cast
23
24
 
25
+ from ..inflatable import InflatableObject, add_header_to_object_body, get_object_body
24
26
  from ..logger import log
25
27
  from .arrayrecord import ArrayRecord
26
28
  from .configrecord import ConfigRecord
@@ -97,7 +99,7 @@ class _SyncedDict(TypedDict[str, T]):
97
99
  )
98
100
 
99
101
 
100
- class RecordDict(TypedDict[str, RecordType]):
102
+ class RecordDict(TypedDict[str, RecordType], InflatableObject):
101
103
  """RecordDict stores groups of arrays, metrics and configs.
102
104
 
103
105
  A :class:`RecordDict` is the unified mechanism by which arrays,
@@ -286,6 +288,72 @@ class RecordDict(TypedDict[str, RecordType]):
286
288
  )
287
289
  return self.config_records
288
290
 
291
+ @property
292
+ def children(self) -> dict[str, InflatableObject]:
293
+ """Return a dictionary of records with their Object IDs as keys."""
294
+ return {record.object_id: record for record in self.values()}
295
+
296
+ def deflate(self) -> bytes:
297
+ """Deflate the RecordDict."""
298
+ # record_name: record_object_id mapping
299
+ record_refs: dict[str, str] = {}
300
+
301
+ for record_name, record in self.items():
302
+ record_refs[record_name] = record.object_id
303
+
304
+ # Serialize references dict
305
+ object_body = json.dumps(record_refs).encode("utf-8")
306
+ return add_header_to_object_body(object_body=object_body, cls=self)
307
+
308
+ @classmethod
309
+ def inflate(
310
+ cls, object_content: bytes, children: dict[str, InflatableObject] | None = None
311
+ ) -> RecordDict:
312
+ """Inflate an RecordDict from bytes.
313
+
314
+ Parameters
315
+ ----------
316
+ object_content : bytes
317
+ The deflated object content of the RecordDict.
318
+ children : Optional[dict[str, InflatableObject]] (default: None)
319
+ Dictionary of children InflatableObjects mapped to their Object IDs.
320
+ These children enable the full inflation of the RecordDict. Default is None.
321
+
322
+ Returns
323
+ -------
324
+ RecordDict
325
+ The inflated RecordDict.
326
+ """
327
+ if children is None:
328
+ children = {}
329
+
330
+ # Inflate mapping of record_names (keys in the RecordDict) to Record' object IDs
331
+ obj_body = get_object_body(object_content, cls)
332
+ record_refs: dict[str, str] = json.loads(obj_body.decode(encoding="utf-8"))
333
+
334
+ unique_records = set(record_refs.values())
335
+ children_obj_ids = set(children.keys())
336
+ if unique_records != children_obj_ids:
337
+ raise ValueError(
338
+ "Unexpected set of `children`. "
339
+ f"Expected {unique_records} but got {children_obj_ids}."
340
+ )
341
+
342
+ # Ensure children are one of the *Record objects exepecte in a RecordDict
343
+ if not all(
344
+ isinstance(ch, (ArrayRecord, ConfigRecord, MetricRecord))
345
+ for ch in children.values()
346
+ ):
347
+ raise ValueError(
348
+ "`Children` are expected to be of type `ArrayRecord`, "
349
+ "`ConfigRecord` or `MetricRecord`."
350
+ )
351
+
352
+ # Instantiate new RecordDict
353
+ return RecordDict(
354
+ {name: children[object_id] for name, object_id in record_refs.items()} # type: ignore
355
+ )
356
+
289
357
 
290
358
  class RecordSet(RecordDict):
291
359
  """Deprecated class ``RecordSet``, use ``RecordDict`` instead.
@@ -25,12 +25,15 @@ from uuid import UUID, uuid4
25
25
 
26
26
  from flwr.common import Context, Message, log, now
27
27
  from flwr.common.constant import (
28
+ HEARTBEAT_MAX_INTERVAL,
28
29
  HEARTBEAT_PATIENCE,
29
30
  MESSAGE_TTL_TOLERANCE,
30
31
  NODE_ID_NUM_BYTES,
32
+ RUN_FAILURE_DETAILS_NO_HEARTBEAT,
31
33
  RUN_ID_NUM_BYTES,
32
34
  SUPERLINK_NODE_ID,
33
35
  Status,
36
+ SubStatus,
34
37
  )
35
38
  from flwr.common.record import ConfigRecord
36
39
  from flwr.common.typing import Run, RunStatus, UserConfig
@@ -52,8 +55,11 @@ class RunRecord: # pylint: disable=R0902
52
55
  """The record of a specific run, including its status and timestamps."""
53
56
 
54
57
  run: Run
58
+ active_until: float = 0.0
59
+ heartbeat_interval: float = 0.0
55
60
  logs: list[tuple[float, str]] = field(default_factory=list)
56
61
  log_lock: threading.Lock = field(default_factory=threading.Lock)
62
+ lock: threading.RLock = field(default_factory=threading.RLock)
57
63
 
58
64
 
59
65
  class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
@@ -461,8 +467,29 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
461
467
  with self.lock:
462
468
  return set(self.run_ids.keys())
463
469
 
470
+ def _check_and_tag_inactive_run(self, run_ids: set[int]) -> None:
471
+ """Check if any runs are no longer active.
472
+
473
+ Marks runs with status 'starting' or 'running' as failed
474
+ if they have not sent a heartbeat before `active_until`.
475
+ """
476
+ current = now()
477
+ for record in [self.run_ids[run_id] for run_id in run_ids]:
478
+ with record.lock:
479
+ if record.run.status.status in (Status.STARTING, Status.RUNNING):
480
+ if record.active_until < current.timestamp():
481
+ record.run.status = RunStatus(
482
+ status=Status.FINISHED,
483
+ sub_status=SubStatus.FAILED,
484
+ details=RUN_FAILURE_DETAILS_NO_HEARTBEAT,
485
+ )
486
+ record.run.finished_at = now().isoformat()
487
+
464
488
  def get_run(self, run_id: int) -> Optional[Run]:
465
489
  """Retrieve information about the run with the specified `run_id`."""
490
+ # Check if runs are still active
491
+ self._check_and_tag_inactive_run(run_ids={run_id})
492
+
466
493
  with self.lock:
467
494
  if run_id not in self.run_ids:
468
495
  log(ERROR, "`run_id` is invalid")
@@ -471,6 +498,9 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
471
498
 
472
499
  def get_run_status(self, run_ids: set[int]) -> dict[int, RunStatus]:
473
500
  """Retrieve the statuses for the specified runs."""
501
+ # Check if runs are still active
502
+ self._check_and_tag_inactive_run(run_ids=run_ids)
503
+
474
504
  with self.lock:
475
505
  return {
476
506
  run_id: self.run_ids[run_id].run.status
@@ -480,12 +510,16 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
480
510
 
481
511
  def update_run_status(self, run_id: int, new_status: RunStatus) -> bool:
482
512
  """Update the status of the run with the specified `run_id`."""
513
+ # Check if runs are still active
514
+ self._check_and_tag_inactive_run(run_ids={run_id})
515
+
483
516
  with self.lock:
484
517
  # Check if the run_id exists
485
518
  if run_id not in self.run_ids:
486
519
  log(ERROR, "`run_id` is invalid")
487
520
  return False
488
521
 
522
+ with self.run_ids[run_id].lock:
489
523
  # Check if the status transition is valid
490
524
  current_status = self.run_ids[run_id].run.status
491
525
  if not is_valid_transition(current_status, new_status):
@@ -507,14 +541,23 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
507
541
  )
508
542
  return False
509
543
 
510
- # Update the status
544
+ # Initialize heartbeat_interval and active_until
545
+ # when switching to starting or running
546
+ current = now()
511
547
  run_record = self.run_ids[run_id]
548
+ if new_status.status in (Status.STARTING, Status.RUNNING):
549
+ run_record.heartbeat_interval = HEARTBEAT_MAX_INTERVAL
550
+ run_record.active_until = (
551
+ current.timestamp() + run_record.heartbeat_interval
552
+ )
553
+
554
+ # Update the run status
512
555
  if new_status.status == Status.STARTING:
513
- run_record.run.starting_at = now().isoformat()
556
+ run_record.run.starting_at = current.isoformat()
514
557
  elif new_status.status == Status.RUNNING:
515
- run_record.run.running_at = now().isoformat()
558
+ run_record.run.running_at = current.isoformat()
516
559
  elif new_status.status == Status.FINISHED:
517
- run_record.run.finished_at = now().isoformat()
560
+ run_record.run.finished_at = current.isoformat()
518
561
  run_record.run.status = new_status
519
562
  return True
520
563
 
@@ -558,6 +601,43 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
558
601
  return True
559
602
  return False
560
603
 
604
+ def acknowledge_app_heartbeat(self, run_id: int, heartbeat_interval: float) -> bool:
605
+ """Acknowledge a heartbeat received from a ServerApp for a given run.
606
+
607
+ A run with status `"running"` is considered alive as long as it sends heartbeats
608
+ within the tolerated interval: HEARTBEAT_PATIENCE × heartbeat_interval.
609
+ HEARTBEAT_PATIENCE = N allows for N-1 missed heartbeat before the run is
610
+ marked as `"completed:failed"`.
611
+ """
612
+ with self.lock:
613
+ # Search for the run
614
+ record = self.run_ids.get(run_id)
615
+
616
+ # Check if the run_id exists
617
+ if record is None:
618
+ log(ERROR, "`run_id` is invalid")
619
+ return False
620
+
621
+ with record.lock:
622
+ # Check if runs are still active
623
+ self._check_and_tag_inactive_run(run_ids={run_id})
624
+
625
+ # Check if the run is of status "running"/"starting"
626
+ current_status = record.run.status
627
+ if current_status.status not in (Status.RUNNING, Status.STARTING):
628
+ log(
629
+ ERROR,
630
+ 'Cannot acknowledge heartbeat for run with status "%s"',
631
+ current_status.status,
632
+ )
633
+ return False
634
+
635
+ # Update the `active_until` and `heartbeat_interval` for the given run
636
+ current = now().timestamp()
637
+ record.active_until = current + HEARTBEAT_PATIENCE * heartbeat_interval
638
+ record.heartbeat_interval = heartbeat_interval
639
+ return True
640
+
561
641
  def get_serverapp_context(self, run_id: int) -> Optional[Context]:
562
642
  """Get the context for the specified `run_id`."""
563
643
  return self.contexts.get(run_id)
@@ -292,6 +292,29 @@ class LinkState(abc.ABC): # pylint: disable=R0904
292
292
  True if the heartbeat is successfully acknowledged; otherwise, False.
293
293
  """
294
294
 
295
+ @abc.abstractmethod
296
+ def acknowledge_app_heartbeat(self, run_id: int, heartbeat_interval: float) -> bool:
297
+ """Acknowledge a heartbeat received from a ServerApp for a given run.
298
+
299
+ A run with status `"running"` is considered alive as long as it sends heartbeats
300
+ within the tolerated interval: HEARTBEAT_PATIENCE × heartbeat_interval.
301
+ HEARTBEAT_PATIENCE = N allows for N-1 missed heartbeat before the run is
302
+ marked as `"completed:failed"`.
303
+
304
+ Parameters
305
+ ----------
306
+ run_id : int
307
+ The `run_id` from which the heartbeat was received.
308
+ heartbeat_interval : float
309
+ The interval (in seconds) from the current timestamp within which the next
310
+ heartbeat from the ServerApp for this run must be received.
311
+
312
+ Returns
313
+ -------
314
+ is_acknowledged : bool
315
+ True if the heartbeat is successfully acknowledged; otherwise, False.
316
+ """
317
+
295
318
  @abc.abstractmethod
296
319
  def get_serverapp_context(self, run_id: int) -> Optional[Context]:
297
320
  """Get the context for the specified `run_id`.