flwr 1.15.1__tar.gz → 1.16.0__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 (337) hide show
  1. {flwr-1.15.1 → flwr-1.16.0}/PKG-INFO +5 -5
  2. {flwr-1.15.1 → flwr-1.16.0}/pyproject.toml +4 -8
  3. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/build.py +2 -0
  4. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/log.py +20 -21
  5. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/new.py +1 -1
  6. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/README.baseline.md.tpl +4 -4
  7. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/README.md.tpl +1 -1
  8. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +1 -1
  9. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +1 -1
  10. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +1 -1
  11. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/pyproject.jax.toml.tpl +1 -1
  12. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +1 -1
  13. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +1 -1
  14. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +1 -1
  15. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +1 -1
  16. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +1 -1
  17. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/client_app.py +147 -36
  18. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/clientapp/app.py +4 -0
  19. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/message_handler/message_handler.py +1 -1
  20. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/rest_client/connection.py +4 -6
  21. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/supernode/__init__.py +0 -2
  22. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/supernode/app.py +1 -11
  23. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/address.py +35 -0
  24. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/args.py +8 -2
  25. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/auth_plugin/auth_plugin.py +2 -1
  26. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/constant.py +16 -0
  27. flwr-1.16.0/src/py/flwr/common/event_log_plugin/__init__.py +22 -0
  28. flwr-1.16.0/src/py/flwr/common/event_log_plugin/event_log_plugin.py +60 -0
  29. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/grpc.py +1 -1
  30. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/message.py +18 -7
  31. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/object_ref.py +0 -10
  32. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/record/conversion_utils.py +8 -17
  33. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/record/parametersrecord.py +151 -16
  34. flwr-1.16.0/src/py/flwr/common/record/recordset.py +209 -0
  35. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/secure_aggregation/quantization.py +5 -1
  36. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/serde.py +8 -126
  37. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/telemetry.py +0 -10
  38. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/typing.py +36 -0
  39. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/app.py +18 -2
  40. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/compat/app.py +4 -1
  41. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/compat/app_utils.py +10 -2
  42. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/compat/driver_client_proxy.py +2 -2
  43. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/driver/driver.py +1 -1
  44. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/driver/grpc_driver.py +10 -1
  45. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/driver/inmemory_driver.py +17 -21
  46. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/run_serverapp.py +2 -13
  47. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/server_app.py +93 -20
  48. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/driver/serverappio_servicer.py +27 -33
  49. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +2 -2
  50. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py +8 -16
  51. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/vce/backend/backend.py +1 -1
  52. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/vce/vce_api.py +32 -36
  53. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/linkstate/in_memory_linkstate.py +140 -126
  54. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/linkstate/linkstate.py +47 -60
  55. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/linkstate/sqlite_linkstate.py +210 -282
  56. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/linkstate/utils.py +91 -119
  57. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/utils/__init__.py +2 -2
  58. flwr-1.16.0/src/py/flwr/server/utils/validator.py +93 -0
  59. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/workflow/default_workflows.py +4 -1
  60. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +3 -3
  61. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/superexec/app.py +0 -14
  62. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/superexec/exec_servicer.py +4 -4
  63. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/superexec/exec_user_auth_interceptor.py +5 -3
  64. flwr-1.15.1/src/py/flwr/client/message_handler/task_handler.py +0 -37
  65. flwr-1.15.1/src/py/flwr/common/record/recordset.py +0 -202
  66. flwr-1.15.1/src/py/flwr/proto/task_pb2.py +0 -33
  67. flwr-1.15.1/src/py/flwr/proto/task_pb2.pyi +0 -103
  68. flwr-1.15.1/src/py/flwr/proto/task_pb2_grpc.py +0 -4
  69. flwr-1.15.1/src/py/flwr/proto/task_pb2_grpc.pyi +0 -4
  70. flwr-1.15.1/src/py/flwr/server/utils/validator.py +0 -111
  71. {flwr-1.15.1 → flwr-1.16.0}/LICENSE +0 -0
  72. {flwr-1.15.1 → flwr-1.16.0}/README.md +0 -0
  73. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/__init__.py +0 -0
  74. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/__init__.py +0 -0
  75. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/app.py +0 -0
  76. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/auth_plugin/__init__.py +0 -0
  77. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/auth_plugin/oidc_cli_plugin.py +0 -0
  78. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/cli_user_auth_interceptor.py +0 -0
  79. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/config_utils.py +0 -0
  80. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/constant.py +0 -0
  81. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/example.py +0 -0
  82. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/install.py +0 -0
  83. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/login/__init__.py +0 -0
  84. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/login/login.py +0 -0
  85. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/ls.py +0 -0
  86. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/__init__.py +0 -0
  87. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/__init__.py +0 -0
  88. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/.gitignore.tpl +0 -0
  89. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/LICENSE.tpl +0 -0
  90. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/README.flowertune.md.tpl +0 -0
  91. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/__init__.py +0 -0
  92. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/__init__.baseline.py.tpl +0 -0
  93. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/__init__.py +0 -0
  94. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/__init__.py.tpl +0 -0
  95. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/client.baseline.py.tpl +0 -0
  96. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/client.huggingface.py.tpl +0 -0
  97. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/client.jax.py.tpl +0 -0
  98. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/client.mlx.py.tpl +0 -0
  99. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -0
  100. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -0
  101. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/client.sklearn.py.tpl +0 -0
  102. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -0
  103. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/dataset.baseline.py.tpl +0 -0
  104. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/flwr_tune/__init__.py +0 -0
  105. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +0 -0
  106. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +0 -0
  107. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +0 -0
  108. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +0 -0
  109. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +0 -0
  110. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/model.baseline.py.tpl +0 -0
  111. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/server.baseline.py.tpl +0 -0
  112. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/server.huggingface.py.tpl +0 -0
  113. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/server.jax.py.tpl +0 -0
  114. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/server.mlx.py.tpl +0 -0
  115. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -0
  116. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -0
  117. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/server.sklearn.py.tpl +0 -0
  118. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -0
  119. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/strategy.baseline.py.tpl +0 -0
  120. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/task.huggingface.py.tpl +0 -0
  121. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/task.jax.py.tpl +0 -0
  122. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/task.mlx.py.tpl +0 -0
  123. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/task.numpy.py.tpl +0 -0
  124. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -0
  125. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/task.sklearn.py.tpl +0 -0
  126. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +0 -0
  127. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/new/templates/app/code/utils.baseline.py.tpl +0 -0
  128. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/run/__init__.py +0 -0
  129. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/run/run.py +0 -0
  130. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/stop.py +0 -0
  131. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/cli/utils.py +0 -0
  132. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/__init__.py +0 -0
  133. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/app.py +0 -0
  134. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/client.py +0 -0
  135. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/clientapp/__init__.py +0 -0
  136. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/clientapp/clientappio_servicer.py +0 -0
  137. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/clientapp/utils.py +0 -0
  138. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/dpfedavg_numpy_client.py +0 -0
  139. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/grpc_adapter_client/__init__.py +0 -0
  140. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/grpc_adapter_client/connection.py +0 -0
  141. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/grpc_client/__init__.py +0 -0
  142. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/grpc_client/connection.py +0 -0
  143. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/grpc_rere_client/__init__.py +0 -0
  144. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/grpc_rere_client/client_interceptor.py +0 -0
  145. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/grpc_rere_client/connection.py +0 -0
  146. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/grpc_rere_client/grpc_adapter.py +0 -0
  147. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/heartbeat.py +0 -0
  148. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/message_handler/__init__.py +0 -0
  149. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/mod/__init__.py +0 -0
  150. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/mod/centraldp_mods.py +0 -0
  151. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/mod/comms_mods.py +0 -0
  152. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/mod/localdp_mod.py +0 -0
  153. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/mod/secure_aggregation/__init__.py +0 -0
  154. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/mod/secure_aggregation/secagg_mod.py +0 -0
  155. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +0 -0
  156. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/mod/utils.py +0 -0
  157. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/nodestate/__init__.py +0 -0
  158. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/nodestate/in_memory_nodestate.py +0 -0
  159. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/nodestate/nodestate.py +0 -0
  160. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/nodestate/nodestate_factory.py +0 -0
  161. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/numpy_client.py +0 -0
  162. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/rest_client/__init__.py +0 -0
  163. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/run_info_store.py +0 -0
  164. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/client/typing.py +0 -0
  165. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/__init__.py +0 -0
  166. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/auth_plugin/__init__.py +0 -0
  167. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/config.py +0 -0
  168. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/context.py +0 -0
  169. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/date.py +0 -0
  170. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/differential_privacy.py +0 -0
  171. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/differential_privacy_constants.py +0 -0
  172. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/dp.py +0 -0
  173. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/exit/__init__.py +0 -0
  174. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/exit/exit.py +0 -0
  175. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/exit/exit_code.py +0 -0
  176. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/exit_handlers.py +0 -0
  177. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/logger.py +0 -0
  178. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/parameter.py +0 -0
  179. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/pyproject.py +0 -0
  180. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/record/__init__.py +0 -0
  181. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/record/configsrecord.py +0 -0
  182. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/record/metricsrecord.py +0 -0
  183. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/record/typeddict.py +0 -0
  184. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/recordset_compat.py +0 -0
  185. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/retry_invoker.py +0 -0
  186. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/secure_aggregation/__init__.py +0 -0
  187. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/secure_aggregation/crypto/__init__.py +0 -0
  188. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/secure_aggregation/crypto/shamir.py +0 -0
  189. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py +0 -0
  190. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py +0 -0
  191. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/secure_aggregation/secaggplus_constants.py +0 -0
  192. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/secure_aggregation/secaggplus_utils.py +0 -0
  193. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/common/version.py +0 -0
  194. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/__init__.py +0 -0
  195. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/clientappio_pb2.py +0 -0
  196. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/clientappio_pb2.pyi +0 -0
  197. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/clientappio_pb2_grpc.py +0 -0
  198. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/clientappio_pb2_grpc.pyi +0 -0
  199. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/error_pb2.py +0 -0
  200. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/error_pb2.pyi +0 -0
  201. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/error_pb2_grpc.py +0 -0
  202. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/error_pb2_grpc.pyi +0 -0
  203. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/exec_pb2.py +0 -0
  204. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/exec_pb2.pyi +0 -0
  205. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/exec_pb2_grpc.py +0 -0
  206. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/exec_pb2_grpc.pyi +0 -0
  207. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/fab_pb2.py +0 -0
  208. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/fab_pb2.pyi +0 -0
  209. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/fab_pb2_grpc.py +0 -0
  210. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/fab_pb2_grpc.pyi +0 -0
  211. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/fleet_pb2.py +0 -0
  212. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/fleet_pb2.pyi +0 -0
  213. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/fleet_pb2_grpc.py +0 -0
  214. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/fleet_pb2_grpc.pyi +0 -0
  215. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/grpcadapter_pb2.py +0 -0
  216. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/grpcadapter_pb2.pyi +0 -0
  217. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/grpcadapter_pb2_grpc.py +0 -0
  218. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/grpcadapter_pb2_grpc.pyi +0 -0
  219. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/log_pb2.py +0 -0
  220. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/log_pb2.pyi +0 -0
  221. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/log_pb2_grpc.py +0 -0
  222. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/log_pb2_grpc.pyi +0 -0
  223. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/message_pb2.py +0 -0
  224. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/message_pb2.pyi +0 -0
  225. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/message_pb2_grpc.py +0 -0
  226. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/message_pb2_grpc.pyi +0 -0
  227. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/node_pb2.py +0 -0
  228. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/node_pb2.pyi +0 -0
  229. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/node_pb2_grpc.py +0 -0
  230. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/node_pb2_grpc.pyi +0 -0
  231. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/recordset_pb2.py +0 -0
  232. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/recordset_pb2.pyi +0 -0
  233. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/recordset_pb2_grpc.py +0 -0
  234. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/recordset_pb2_grpc.pyi +0 -0
  235. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/run_pb2.py +0 -0
  236. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/run_pb2.pyi +0 -0
  237. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/run_pb2_grpc.py +0 -0
  238. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/run_pb2_grpc.pyi +0 -0
  239. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/serverappio_pb2.py +0 -0
  240. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/serverappio_pb2.pyi +0 -0
  241. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/serverappio_pb2_grpc.py +0 -0
  242. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/serverappio_pb2_grpc.pyi +0 -0
  243. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/simulationio_pb2.py +0 -0
  244. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/simulationio_pb2.pyi +0 -0
  245. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/simulationio_pb2_grpc.py +0 -0
  246. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/simulationio_pb2_grpc.pyi +0 -0
  247. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/transport_pb2.py +0 -0
  248. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/transport_pb2.pyi +0 -0
  249. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/transport_pb2_grpc.py +0 -0
  250. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/proto/transport_pb2_grpc.pyi +0 -0
  251. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/py.typed +0 -0
  252. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/__init__.py +0 -0
  253. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/client_manager.py +0 -0
  254. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/client_proxy.py +0 -0
  255. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/compat/__init__.py +0 -0
  256. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/compat/legacy_context.py +0 -0
  257. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/criterion.py +0 -0
  258. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/driver/__init__.py +0 -0
  259. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/history.py +0 -0
  260. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/server.py +0 -0
  261. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/server_config.py +0 -0
  262. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/serverapp/__init__.py +0 -0
  263. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/serverapp/app.py +0 -0
  264. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/serverapp_components.py +0 -0
  265. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/__init__.py +0 -0
  266. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/aggregate.py +0 -0
  267. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/bulyan.py +0 -0
  268. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/dp_adaptive_clipping.py +0 -0
  269. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/dp_fixed_clipping.py +0 -0
  270. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/dpfedavg_adaptive.py +0 -0
  271. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/dpfedavg_fixed.py +0 -0
  272. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/fault_tolerant_fedavg.py +0 -0
  273. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/fedadagrad.py +0 -0
  274. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/fedadam.py +0 -0
  275. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/fedavg.py +0 -0
  276. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/fedavg_android.py +0 -0
  277. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/fedavgm.py +0 -0
  278. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/fedmedian.py +0 -0
  279. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/fedopt.py +0 -0
  280. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/fedprox.py +0 -0
  281. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/fedtrimmedavg.py +0 -0
  282. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/fedxgb_bagging.py +0 -0
  283. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/fedxgb_cyclic.py +0 -0
  284. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/fedxgb_nn_avg.py +0 -0
  285. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/fedyogi.py +0 -0
  286. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/krum.py +0 -0
  287. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/qfedavg.py +0 -0
  288. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/strategy/strategy.py +0 -0
  289. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/__init__.py +0 -0
  290. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/driver/__init__.py +0 -0
  291. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/driver/serverappio_grpc.py +0 -0
  292. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/ffs/__init__.py +0 -0
  293. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/ffs/disk_ffs.py +0 -0
  294. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/ffs/ffs.py +0 -0
  295. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/ffs/ffs_factory.py +0 -0
  296. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/__init__.py +0 -0
  297. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/grpc_adapter/__init__.py +0 -0
  298. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +0 -0
  299. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py +0 -0
  300. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +0 -0
  301. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +0 -0
  302. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +0 -0
  303. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +0 -0
  304. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/grpc_rere/__init__.py +0 -0
  305. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +0 -0
  306. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/message_handler/__init__.py +0 -0
  307. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/rest_rere/__init__.py +0 -0
  308. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py +0 -0
  309. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/vce/__init__.py +0 -0
  310. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/vce/backend/__init__.py +0 -0
  311. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/fleet/vce/backend/raybackend.py +0 -0
  312. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/linkstate/__init__.py +0 -0
  313. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/linkstate/linkstate_factory.py +0 -0
  314. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/simulation/__init__.py +0 -0
  315. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/simulation/simulationio_grpc.py +0 -0
  316. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/simulation/simulationio_servicer.py +0 -0
  317. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/superlink/utils.py +0 -0
  318. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/typing.py +0 -0
  319. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/utils/tensorboard.py +0 -0
  320. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/workflow/__init__.py +0 -0
  321. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/workflow/constant.py +0 -0
  322. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/workflow/secure_aggregation/__init__.py +0 -0
  323. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/server/workflow/secure_aggregation/secagg_workflow.py +0 -0
  324. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/simulation/__init__.py +0 -0
  325. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/simulation/app.py +0 -0
  326. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/simulation/legacy_app.py +0 -0
  327. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/simulation/ray_transport/__init__.py +0 -0
  328. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/simulation/ray_transport/ray_actor.py +0 -0
  329. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/simulation/ray_transport/ray_client_proxy.py +0 -0
  330. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/simulation/ray_transport/utils.py +0 -0
  331. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/simulation/run_simulation.py +0 -0
  332. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/simulation/simulationio_connection.py +0 -0
  333. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/superexec/__init__.py +0 -0
  334. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/superexec/deployment.py +0 -0
  335. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/superexec/exec_grpc.py +0 -0
  336. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/superexec/executor.py +0 -0
  337. {flwr-1.15.1 → flwr-1.16.0}/src/py/flwr/superexec/simulation.py +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flwr
3
- Version: 1.15.1
3
+ Version: 1.16.0
4
4
  Summary: Flower: A Friendly Federated AI Framework
5
5
  Home-page: https://flower.ai
6
6
  License: Apache-2.0
7
7
  Keywords: Artificial Intelligence,Federated AI,Federated Analytics,Federated Evaluation,Federated Learning,Flower,Machine Learning
8
8
  Author: The Flower Authors
9
9
  Author-email: hello@flower.ai
10
- Requires-Python: >=3.9,<4.0
10
+ Requires-Python: >=3.9.2,<4.0.0
11
11
  Classifier: Development Status :: 5 - Production/Stable
12
12
  Classifier: Intended Audience :: Developers
13
13
  Classifier: Intended Audience :: Science/Research
@@ -16,12 +16,12 @@ Classifier: Operating System :: MacOS :: MacOS X
16
16
  Classifier: Operating System :: POSIX :: Linux
17
17
  Classifier: Programming Language :: Python
18
18
  Classifier: Programming Language :: Python :: 3
19
- Classifier: Programming Language :: Python :: 3.9
20
19
  Classifier: Programming Language :: Python :: 3.10
21
20
  Classifier: Programming Language :: Python :: 3.11
22
21
  Classifier: Programming Language :: Python :: 3.12
23
22
  Classifier: Programming Language :: Python :: 3 :: Only
24
23
  Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Programming Language :: Python :: 3.9
25
25
  Classifier: Programming Language :: Python :: Implementation :: CPython
26
26
  Classifier: Topic :: Scientific/Engineering
27
27
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
@@ -32,7 +32,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
32
32
  Classifier: Typing :: Typed
33
33
  Provides-Extra: rest
34
34
  Provides-Extra: simulation
35
- Requires-Dist: cryptography (>=43.0.1,<44.0.0)
35
+ Requires-Dist: cryptography (>=44.0.1,<45.0.0)
36
36
  Requires-Dist: grpcio (>=1.62.3,<2.0.0,!=1.65.0)
37
37
  Requires-Dist: iterators (>=0.0.2,<0.0.3)
38
38
  Requires-Dist: numpy (>=1.26.0,<3.0.0)
@@ -40,7 +40,7 @@ Requires-Dist: pathspec (>=0.12.1,<0.13.0)
40
40
  Requires-Dist: protobuf (>=4.21.6,<5.0.0)
41
41
  Requires-Dist: pycryptodome (>=3.18.0,<4.0.0)
42
42
  Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
43
- Requires-Dist: ray (==2.10.0) ; (python_version >= "3.9" and python_version < "3.12") and (extra == "simulation")
43
+ Requires-Dist: ray (==2.31.0) ; (python_version >= "3.9" and python_version < "3.13") and (extra == "simulation")
44
44
  Requires-Dist: requests (>=2.31.0,<3.0.0)
45
45
  Requires-Dist: rich (>=13.5.0,<14.0.0)
46
46
  Requires-Dist: starlette (>=0.45.2,<0.46.0) ; extra == "rest"
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "flwr"
7
- version = "1.15.1"
7
+ version = "1.16.0"
8
8
  description = "Flower: A Friendly Federated AI Framework"
9
9
  license = "Apache-2.0"
10
10
  authors = ["The Flower Authors <hello@flower.ai>"]
@@ -51,8 +51,6 @@ exclude = ["src/py/**/*_test.py"]
51
51
  [tool.poetry.scripts]
52
52
  # `flwr` CLI
53
53
  flwr = "flwr.cli.app:app"
54
- # SuperExec (can run with either Deployment Engine or Simulation Engine)
55
- flower-superexec = "flwr.superexec.app:run_superexec" # Deprecated
56
54
  # Simulation Engine
57
55
  flwr-simulation = "flwr.simulation.app:flwr_simulation"
58
56
  flower-simulation = "flwr.simulation.run_simulation:run_simulation_from_cli"
@@ -60,17 +58,15 @@ flower-simulation = "flwr.simulation.run_simulation:run_simulation_from_cli"
60
58
  flower-superlink = "flwr.server.app:run_superlink"
61
59
  flower-supernode = "flwr.client.supernode.app:run_supernode"
62
60
  flwr-serverapp = "flwr.server.serverapp:flwr_serverapp"
63
- flower-server-app = "flwr.server.run_serverapp:run_server_app" # Deprecated
64
61
  flwr-clientapp = "flwr.client.clientapp:flwr_clientapp"
65
- flower-client-app = "flwr.client.supernode:run_client_app" # Deprecated
66
62
 
67
63
  [tool.poetry.dependencies]
68
- python = "^3.9"
64
+ python = "^3.9.2"
69
65
  # Mandatory dependencies
70
66
  numpy = ">=1.26.0,<3.0.0"
71
67
  grpcio = "^1.62.3,!=1.65.0"
72
68
  protobuf = "^4.21.6"
73
- cryptography = "^43.0.1"
69
+ cryptography = "^44.0.1"
74
70
  pycryptodome = "^3.18.0"
75
71
  iterators = "^0.0.2"
76
72
  typer = "^0.12.5"
@@ -81,7 +77,7 @@ rich = "^13.5.0"
81
77
  pyyaml = "^6.0.2"
82
78
  requests = "^2.31.0"
83
79
  # Optional dependencies (Simulation Engine)
84
- ray = { version = "==2.10.0", optional = true, python = ">=3.9,<3.12" }
80
+ ray = { version = "==2.31.0", optional = true, python = ">=3.9,<3.13" }
85
81
  # Optional dependencies (REST transport layer)
86
82
  starlette = { version = "^0.45.2", optional = true }
87
83
  uvicorn = { version = "^0.34.0", extras = ["standard"], optional = true }
@@ -138,6 +138,8 @@ def build(
138
138
  and f.name != "pyproject.toml" # Exclude the original pyproject.toml
139
139
  ]
140
140
 
141
+ all_files.sort()
142
+
141
143
  for file_path in all_files:
142
144
  # Read the file content manually
143
145
  with open(file_path, "rb") as f:
@@ -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")
@@ -213,7 +213,7 @@ def new(
213
213
  else:
214
214
  challenge_name = "Code"
215
215
  num_clients = "10"
216
- dataset_name = "lucasmccabe-lmi/CodeAlpaca-20k"
216
+ dataset_name = "flwrlabs/code-alpaca-20k"
217
217
 
218
218
  context["llm_challenge_str"] = llm_challenge_str
219
219
  context["fraction_fit"] = fraction_fit
@@ -13,7 +13,7 @@ dataset: [dataset1, dataset2] # TODO: list of datasets you include in your basel
13
13
 
14
14
  > [!IMPORTANT]
15
15
  > To help having all baselines similarly formatted and structured, we have included two scripts in `baselines/dev` that when run will format your code and run some tests checking if it's formatted.
16
- > These checks use standard packages such as `isort`, `black`, `pylint` and others. You as a baseline creator will need to install additional pacakges. These are already specified in the `pyproject.toml` of
16
+ > These checks use standard packages such as `isort`, `black`, `pylint` and others. You as a baseline creator will need to install additional packages. These are already specified in the `pyproject.toml` of
17
17
  > your baseline. Follow these steps:
18
18
 
19
19
  ```bash
@@ -66,9 +66,9 @@ cd .. # so you are in the `flower/baselines` directory
66
66
 
67
67
  ## About this baseline
68
68
 
69
- **What’s implemented:** :warning: *_Concisely describe what experiment(s) (e.g. Figure 1, Table 2, etc) in the publication can be replicated by running the code. Please only use a few sentences. ”_*
69
+ **What’s implemented:** :warning: *_Concisely describe what experiment(s) (e.g. Figure 1, Table 2, etc.) in the publication can be replicated by running the code. Please only use a few sentences. ”_*
70
70
 
71
- **Datasets:** :warning: *_List the datasets you used (if you used a medium to large dataset, >10GB please also include the sizes of the dataset). We highly recommend using [FlowerDatasets](https://flower.ai/docs/datasets/index.html) to download and partition your dataset. If you have other ways to download the data, you can also use `FlowerDatasets` to partiion it._*
71
+ **Datasets:** :warning: *_List the datasets you used (if you used a medium to large dataset, >10GB please also include the sizes of the dataset). We highly recommend using [FlowerDatasets](https://flower.ai/docs/datasets/index.html) to download and partition your dataset. If you have other ways to download the data, you can also use `FlowerDatasets` to partition it._*
72
72
 
73
73
  **Hardware Setup:** :warning: *_Give some details about the hardware (e.g. a server with 8x V100 32GB and 256GB of RAM) you used to run the experiments for this baseline. Indicate how long it took to run the experiments. Someone out there might not have access to the same resources you have so, could you list the absolute minimum hardware needed to run the experiment in a reasonable amount of time ? (e.g. minimum is 1x 16GB GPU otherwise a client model can’t be trained with a sufficiently large batch size). Could you test this works too?_*
74
74
 
@@ -122,6 +122,6 @@ flwr run . --run-config learning-rate=0.1,coefficient=0.123
122
122
  flwr run . --run-config <my-big-experiment-config>.toml
123
123
  ```
124
124
 
125
- :warning: _It is preferable to show a single commmand (or multilple commands if they belong to the same experiment) and then a table/plot with the expected results, instead of showing all the commands first and then all the results/plots._
125
+ :warning: _It is preferable to show a single command (or multiple commands if they belong to the same experiment) and then a table/plot with the expected results, instead of showing all the commands first and then all the results/plots._
126
126
  :warning: _If you present plots or other figures, please include either a Jupyter notebook showing how to create them or include a utility function that can be called after the experiments finish running._
127
127
  :warning: If you include plots or figures, save them in `.png` format and place them in a new directory named `_static` at the same level as your `README.md`.
@@ -18,7 +18,7 @@ Refer to the [How to Run Simulations](https://flower.ai/docs/framework/how-to-ru
18
18
 
19
19
  ## Run with the Deployment Engine
20
20
 
21
- Follow this [how-to guide](https://flower.ai/docs/framework/how-to-run-flower-with-deployment-engine.html) to run the same app in this example but with Flower's Deployment Engine. After that, you might be intersted in setting up [secure TLS-enabled communications](https://flower.ai/docs/framework/how-to-enable-tls-connections.html) and [SuperNode authentication](https://flower.ai/docs/framework/how-to-authenticate-supernodes.html) in your federation.
21
+ Follow this [how-to guide](https://flower.ai/docs/framework/how-to-run-flower-with-deployment-engine.html) to run the same app in this example but with Flower's Deployment Engine. After that, you might be interested in setting up [secure TLS-enabled communications](https://flower.ai/docs/framework/how-to-enable-tls-connections.html) and [SuperNode authentication](https://flower.ai/docs/framework/how-to-authenticate-supernodes.html) in your federation.
22
22
 
23
23
  You can run Flower on Docker too! Check out the [Flower with Docker](https://flower.ai/docs/framework/docker/index.html) documentation.
24
24
 
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.1",
11
+ "flwr[simulation]>=1.16.0",
12
12
  "flwr-datasets[vision]>=0.5.0",
13
13
  "torch==2.5.1",
14
14
  "torchvision==0.20.1",
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.1",
11
+ "flwr[simulation]>=1.16.0",
12
12
  "flwr-datasets>=0.5.0",
13
13
  "torch==2.3.1",
14
14
  "trl==0.8.1",
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.1",
11
+ "flwr[simulation]>=1.16.0",
12
12
  "flwr-datasets>=0.5.0",
13
13
  "torch==2.5.1",
14
14
  "transformers>=4.30.0,<5.0",
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.1",
11
+ "flwr[simulation]>=1.16.0",
12
12
  "jax==0.4.30",
13
13
  "jaxlib==0.4.30",
14
14
  "scikit-learn==1.6.1",
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.1",
11
+ "flwr[simulation]>=1.16.0",
12
12
  "flwr-datasets[vision]>=0.5.0",
13
13
  "mlx==0.21.1",
14
14
  ]
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.1",
11
+ "flwr[simulation]>=1.16.0",
12
12
  "numpy>=2.0.2",
13
13
  ]
14
14
 
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.1",
11
+ "flwr[simulation]>=1.16.0",
12
12
  "flwr-datasets[vision]>=0.5.0",
13
13
  "torch==2.5.1",
14
14
  "torchvision==0.20.1",
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.1",
11
+ "flwr[simulation]>=1.16.0",
12
12
  "flwr-datasets[vision]>=0.5.0",
13
13
  "scikit-learn>=1.6.1",
14
14
  ]
@@ -8,7 +8,7 @@ version = "1.0.0"
8
8
  description = ""
9
9
  license = "Apache-2.0"
10
10
  dependencies = [
11
- "flwr[simulation]>=1.15.1",
11
+ "flwr[simulation]>=1.16.0",
12
12
  "flwr-datasets[vision]>=0.5.0",
13
13
  "tensorflow>=2.11.1,<2.18.0",
14
14
  ]
@@ -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_lifespan(_: 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
 
@@ -95,15 +102,6 @@ class ClientApp:
95
102
  >>> return FlowerClient().to_client()
96
103
  >>>
97
104
  >>> app = ClientApp(client_fn)
98
-
99
- If the above code is in a Python module called `client`, it can be started as
100
- follows:
101
-
102
- >>> flower-client-app client:app --insecure
103
-
104
- In this `client:app` example, `client` refers to the Python module `client.py` in
105
- which the previous code lives in and `app` refers to the global attribute `app` that
106
- points to an object of type `ClientApp`.
107
105
  """
108
106
 
109
107
  def __init__(
@@ -135,35 +133,41 @@ class ClientApp:
135
133
  self._train: Optional[ClientAppCallable] = None
136
134
  self._evaluate: Optional[ClientAppCallable] = None
137
135
  self._query: Optional[ClientAppCallable] = None
136
+ self._lifespan = _empty_lifespan
138
137
 
139
138
  def __call__(self, message: Message, context: Context) -> Message:
140
139
  """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}")
161
-
162
- def train(self) -> Callable[[ClientAppCallable], ClientAppCallable]:
140
+ with self._lifespan(context):
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}")
161
+
162
+ def train(
163
+ self, mods: Optional[list[Mod]] = None
164
+ ) -> Callable[[ClientAppCallable], ClientAppCallable]:
163
165
  """Return a decorator that registers the train fn with the client app.
164
166
 
165
167
  Examples
166
168
  --------
169
+ Registering a train function:
170
+
167
171
  >>> app = ClientApp()
168
172
  >>>
169
173
  >>> @app.train()
@@ -171,6 +175,17 @@ class ClientApp:
171
175
  >>> print("ClientApp training running")
172
176
  >>> # Create and return an echo reply message
173
177
  >>> return message.create_reply(content=message.content())
178
+
179
+ Registering a train function with a function-specific modifier:
180
+
181
+ >>> from flwr.client.mod import message_size_mod
182
+ >>>
183
+ >>> app = ClientApp()
184
+ >>>
185
+ >>> @app.train(mods=[message_size_mod])
186
+ >>> def train(message: Message, context: Context) -> Message:
187
+ >>> print("ClientApp training running with message size mod")
188
+ >>> return message.create_reply(content=message.content())
174
189
  """
175
190
 
176
191
  def train_decorator(train_fn: ClientAppCallable) -> ClientAppCallable:
@@ -182,18 +197,22 @@ class ClientApp:
182
197
 
183
198
  # Register provided function with the ClientApp object
184
199
  # Wrap mods around the wrapped step function
185
- self._train = make_ffn(train_fn, self._mods)
200
+ self._train = make_ffn(train_fn, self._mods + (mods or []))
186
201
 
187
202
  # Return provided function unmodified
188
203
  return train_fn
189
204
 
190
205
  return train_decorator
191
206
 
192
- def evaluate(self) -> Callable[[ClientAppCallable], ClientAppCallable]:
207
+ def evaluate(
208
+ self, mods: Optional[list[Mod]] = None
209
+ ) -> Callable[[ClientAppCallable], ClientAppCallable]:
193
210
  """Return a decorator that registers the evaluate fn with the client app.
194
211
 
195
212
  Examples
196
213
  --------
214
+ Registering an evaluate function:
215
+
197
216
  >>> app = ClientApp()
198
217
  >>>
199
218
  >>> @app.evaluate()
@@ -201,6 +220,18 @@ class ClientApp:
201
220
  >>> print("ClientApp evaluation running")
202
221
  >>> # Create and return an echo reply message
203
222
  >>> return message.create_reply(content=message.content())
223
+
224
+ Registering an evaluate function with a function-specific modifier:
225
+
226
+ >>> from flwr.client.mod import message_size_mod
227
+ >>>
228
+ >>> app = ClientApp()
229
+ >>>
230
+ >>> @app.evaluate(mods=[message_size_mod])
231
+ >>> def evaluate(message: Message, context: Context) -> Message:
232
+ >>> print("ClientApp evaluation running with message size mod")
233
+ >>> # Create and return an echo reply message
234
+ >>> return message.create_reply(content=message.content())
204
235
  """
205
236
 
206
237
  def evaluate_decorator(evaluate_fn: ClientAppCallable) -> ClientAppCallable:
@@ -212,18 +243,22 @@ class ClientApp:
212
243
 
213
244
  # Register provided function with the ClientApp object
214
245
  # Wrap mods around the wrapped step function
215
- self._evaluate = make_ffn(evaluate_fn, self._mods)
246
+ self._evaluate = make_ffn(evaluate_fn, self._mods + (mods or []))
216
247
 
217
248
  # Return provided function unmodified
218
249
  return evaluate_fn
219
250
 
220
251
  return evaluate_decorator
221
252
 
222
- def query(self) -> Callable[[ClientAppCallable], ClientAppCallable]:
253
+ def query(
254
+ self, mods: Optional[list[Mod]] = None
255
+ ) -> Callable[[ClientAppCallable], ClientAppCallable]:
223
256
  """Return a decorator that registers the query fn with the client app.
224
257
 
225
258
  Examples
226
259
  --------
260
+ Registering a query function:
261
+
227
262
  >>> app = ClientApp()
228
263
  >>>
229
264
  >>> @app.query()
@@ -231,6 +266,18 @@ class ClientApp:
231
266
  >>> print("ClientApp query running")
232
267
  >>> # Create and return an echo reply message
233
268
  >>> return message.create_reply(content=message.content())
269
+
270
+ Registering a query function with a function-specific modifier:
271
+
272
+ >>> from flwr.client.mod import message_size_mod
273
+ >>>
274
+ >>> app = ClientApp()
275
+ >>>
276
+ >>> @app.query(mods=[message_size_mod])
277
+ >>> def query(message: Message, context: Context) -> Message:
278
+ >>> print("ClientApp query running with message size mod")
279
+ >>> # Create and return an echo reply message
280
+ >>> return message.create_reply(content=message.content())
234
281
  """
235
282
 
236
283
  def query_decorator(query_fn: ClientAppCallable) -> ClientAppCallable:
@@ -242,13 +289,77 @@ class ClientApp:
242
289
 
243
290
  # Register provided function with the ClientApp object
244
291
  # Wrap mods around the wrapped step function
245
- self._query = make_ffn(query_fn, self._mods)
292
+ self._query = make_ffn(query_fn, self._mods + (mods or []))
246
293
 
247
294
  # Return provided function unmodified
248
295
  return query_fn
249
296
 
250
297
  return query_decorator
251
298
 
299
+ def lifespan(
300
+ self,
301
+ ) -> Callable[
302
+ [Callable[[Context], Iterator[None]]], Callable[[Context], Iterator[None]]
303
+ ]:
304
+ """Return a decorator that registers the lifespan fn with the client app.
305
+
306
+ The decorated function should accept a `Context` object and use `yield`
307
+ to define enter and exit behavior.
308
+
309
+ Examples
310
+ --------
311
+ >>> app = ClientApp()
312
+ >>>
313
+ >>> @app.lifespan()
314
+ >>> def lifespan(context: Context) -> None:
315
+ >>> # Perform initialization tasks before the app starts
316
+ >>> print("Initializing ClientApp")
317
+ >>>
318
+ >>> yield # ClientApp is running
319
+ >>>
320
+ >>> # Perform cleanup tasks after the app stops
321
+ >>> print("Cleaning up ClientApp")
322
+ """
323
+
324
+ def lifespan_decorator(
325
+ lifespan_fn: Callable[[Context], Iterator[None]]
326
+ ) -> Callable[[Context], Iterator[None]]:
327
+ """Register the lifespan fn with the ServerApp object."""
328
+ warn_preview_feature("ClientApp-register-lifespan-function")
329
+
330
+ @contextmanager
331
+ def decorated_lifespan(context: Context) -> Iterator[None]:
332
+ # Execute the code before `yield` in lifespan_fn
333
+ try:
334
+ if not isinstance(it := lifespan_fn(context), Iterator):
335
+ raise StopIteration
336
+ next(it)
337
+ except StopIteration:
338
+ raise RuntimeError(
339
+ "lifespan function should yield at least once."
340
+ ) from None
341
+
342
+ try:
343
+ # Enter the context
344
+ yield
345
+ finally:
346
+ try:
347
+ # Execute the code after `yield` in lifespan_fn
348
+ next(it)
349
+ except StopIteration:
350
+ pass
351
+ else:
352
+ raise RuntimeError("lifespan function should only yield once.")
353
+
354
+ # Register provided function with the ClientApp object
355
+ # Ignore mypy error because of different argument names (`_` vs `context`)
356
+ self._lifespan = decorated_lifespan # type: ignore
357
+
358
+ # Return provided function unmodified
359
+ return lifespan_fn
360
+
361
+ return lifespan_decorator
362
+
252
363
 
253
364
  class LoadClientAppError(Exception):
254
365
  """Error when trying to load `ClientApp`."""
@@ -16,6 +16,7 @@
16
16
 
17
17
 
18
18
  import argparse
19
+ import gc
19
20
  import time
20
21
  from logging import DEBUG, ERROR, INFO
21
22
  from typing import Optional
@@ -160,6 +161,9 @@ def run_clientapp( # pylint: disable=R0914
160
161
  stub=stub, token=token, message=reply_message, context=context
161
162
  )
162
163
 
164
+ del client_app, message, context, run, fab, reply_message
165
+ gc.collect()
166
+
163
167
  # Reset token to `None` to prevent flwr-clientapp from trying to pull the
164
168
  # same inputs again
165
169
  token = None
@@ -82,7 +82,7 @@ def handle_control_message(message: Message) -> tuple[Optional[Message], int]:
82
82
  recordset = RecordSet()
83
83
  recordset.configs_records["config"] = ConfigsRecord({"reason": reason})
84
84
  out_message = message.create_reply(recordset)
85
- # Return TaskRes and sleep duration
85
+ # Return Message and sleep duration
86
86
  return out_message, sleep_duration
87
87
 
88
88
  # Any other message