flwr 1.14.0__tar.gz → 1.15.1__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 (339) hide show
  1. {flwr-1.14.0 → flwr-1.15.1}/PKG-INFO +8 -8
  2. {flwr-1.14.0 → flwr-1.15.1}/README.md +2 -2
  3. {flwr-1.14.0 → flwr-1.15.1}/pyproject.toml +18 -16
  4. flwr-1.15.1/src/py/flwr/cli/auth_plugin/__init__.py +31 -0
  5. flwr-1.15.1/src/py/flwr/cli/auth_plugin/oidc_cli_plugin.py +150 -0
  6. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/cli_user_auth_interceptor.py +6 -2
  7. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/config_utils.py +24 -147
  8. flwr-1.15.1/src/py/flwr/cli/constant.py +27 -0
  9. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/install.py +1 -1
  10. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/log.py +18 -3
  11. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/login/login.py +43 -8
  12. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/ls.py +14 -5
  13. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/README.md.tpl +3 -2
  14. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +4 -4
  15. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +2 -2
  16. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +4 -4
  17. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/pyproject.jax.toml.tpl +2 -2
  18. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +2 -2
  19. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +2 -2
  20. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +4 -4
  21. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +3 -3
  22. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +2 -2
  23. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/run/run.py +21 -11
  24. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/stop.py +13 -4
  25. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/utils.py +54 -40
  26. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/app.py +36 -48
  27. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/clientapp/app.py +19 -25
  28. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/clientapp/utils.py +1 -1
  29. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/grpc_client/connection.py +1 -12
  30. flwr-1.15.1/src/py/flwr/client/grpc_rere_client/client_interceptor.py +70 -0
  31. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/grpc_rere_client/connection.py +46 -36
  32. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/grpc_rere_client/grpc_adapter.py +12 -12
  33. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/message_handler/task_handler.py +0 -17
  34. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/rest_client/connection.py +34 -26
  35. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/supernode/app.py +18 -72
  36. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/args.py +25 -47
  37. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/auth_plugin/auth_plugin.py +34 -23
  38. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/config.py +166 -16
  39. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/constant.py +24 -9
  40. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/differential_privacy.py +2 -1
  41. flwr-1.15.1/src/py/flwr/common/exit/__init__.py +24 -0
  42. flwr-1.15.1/src/py/flwr/common/exit/exit.py +99 -0
  43. flwr-1.15.1/src/py/flwr/common/exit/exit_code.py +93 -0
  44. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/exit_handlers.py +32 -30
  45. flwr-1.14.0/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py → flwr-1.15.1/src/py/flwr/common/grpc.py +62 -120
  46. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/logger.py +26 -7
  47. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/object_ref.py +0 -14
  48. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/record/recordset.py +1 -1
  49. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py +45 -0
  50. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/serde.py +6 -4
  51. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/typing.py +20 -0
  52. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/clientappio_pb2.py +1 -1
  53. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/error_pb2.py +1 -1
  54. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/exec_pb2.py +13 -25
  55. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/exec_pb2.pyi +27 -54
  56. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/fab_pb2.py +1 -1
  57. flwr-1.15.1/src/py/flwr/proto/fleet_pb2.py +56 -0
  58. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/fleet_pb2.pyi +23 -23
  59. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/fleet_pb2_grpc.py +30 -30
  60. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/fleet_pb2_grpc.pyi +20 -20
  61. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/grpcadapter_pb2.py +1 -1
  62. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/log_pb2.py +1 -1
  63. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/message_pb2.py +1 -1
  64. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/node_pb2.py +3 -3
  65. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/node_pb2.pyi +1 -4
  66. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/recordset_pb2.py +1 -1
  67. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/run_pb2.py +1 -1
  68. flwr-1.15.1/src/py/flwr/proto/serverappio_pb2.py +51 -0
  69. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/serverappio_pb2.pyi +26 -32
  70. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/serverappio_pb2_grpc.py +28 -28
  71. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/serverappio_pb2_grpc.pyi +16 -16
  72. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/simulationio_pb2.py +1 -1
  73. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/task_pb2.py +1 -1
  74. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/transport_pb2.py +1 -1
  75. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/app.py +116 -128
  76. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/compat/app_utils.py +0 -1
  77. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/compat/driver_client_proxy.py +1 -2
  78. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/driver/grpc_driver.py +32 -27
  79. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/driver/inmemory_driver.py +2 -1
  80. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/serverapp/app.py +12 -10
  81. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/driver/serverappio_grpc.py +1 -1
  82. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/driver/serverappio_servicer.py +74 -48
  83. flwr-1.15.1/src/py/flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +94 -0
  84. flwr-1.15.1/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +126 -0
  85. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +25 -24
  86. flwr-1.15.1/src/py/flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +169 -0
  87. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py +37 -24
  88. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py +16 -18
  89. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/vce/vce_api.py +2 -2
  90. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/linkstate/in_memory_linkstate.py +45 -75
  91. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/linkstate/linkstate.py +17 -38
  92. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/linkstate/sqlite_linkstate.py +81 -145
  93. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/linkstate/utils.py +18 -8
  94. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/simulation/simulationio_grpc.py +1 -1
  95. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/utils/validator.py +9 -34
  96. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/simulation/app.py +4 -6
  97. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/simulation/legacy_app.py +4 -2
  98. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/simulation/run_simulation.py +1 -1
  99. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/simulation/simulationio_connection.py +2 -1
  100. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/superexec/exec_grpc.py +1 -1
  101. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/superexec/exec_servicer.py +23 -2
  102. flwr-1.14.0/src/py/flwr/client/grpc_rere_client/client_interceptor.py +0 -170
  103. flwr-1.14.0/src/py/flwr/common/grpc.py +0 -68
  104. flwr-1.14.0/src/py/flwr/proto/fleet_pb2.py +0 -56
  105. flwr-1.14.0/src/py/flwr/proto/serverappio_pb2.py +0 -52
  106. flwr-1.14.0/src/py/flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +0 -162
  107. flwr-1.14.0/src/py/flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +0 -227
  108. {flwr-1.14.0 → flwr-1.15.1}/LICENSE +0 -0
  109. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/__init__.py +0 -0
  110. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/__init__.py +0 -0
  111. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/app.py +0 -0
  112. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/build.py +0 -0
  113. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/example.py +0 -0
  114. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/login/__init__.py +0 -0
  115. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/__init__.py +0 -0
  116. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/new.py +0 -0
  117. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/__init__.py +0 -0
  118. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/.gitignore.tpl +0 -0
  119. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/LICENSE.tpl +0 -0
  120. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/README.baseline.md.tpl +0 -0
  121. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/README.flowertune.md.tpl +0 -0
  122. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/__init__.py +0 -0
  123. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/__init__.baseline.py.tpl +0 -0
  124. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/__init__.py +0 -0
  125. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/__init__.py.tpl +0 -0
  126. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/client.baseline.py.tpl +0 -0
  127. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/client.huggingface.py.tpl +0 -0
  128. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/client.jax.py.tpl +0 -0
  129. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/client.mlx.py.tpl +0 -0
  130. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -0
  131. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -0
  132. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/client.sklearn.py.tpl +0 -0
  133. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -0
  134. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/dataset.baseline.py.tpl +0 -0
  135. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/flwr_tune/__init__.py +0 -0
  136. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +0 -0
  137. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +0 -0
  138. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +0 -0
  139. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +0 -0
  140. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +0 -0
  141. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/model.baseline.py.tpl +0 -0
  142. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/server.baseline.py.tpl +0 -0
  143. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/server.huggingface.py.tpl +0 -0
  144. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/server.jax.py.tpl +0 -0
  145. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/server.mlx.py.tpl +0 -0
  146. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -0
  147. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -0
  148. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/server.sklearn.py.tpl +0 -0
  149. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -0
  150. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/strategy.baseline.py.tpl +0 -0
  151. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/task.huggingface.py.tpl +0 -0
  152. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/task.jax.py.tpl +0 -0
  153. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/task.mlx.py.tpl +0 -0
  154. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/task.numpy.py.tpl +0 -0
  155. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -0
  156. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/task.sklearn.py.tpl +0 -0
  157. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +0 -0
  158. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/new/templates/app/code/utils.baseline.py.tpl +0 -0
  159. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/cli/run/__init__.py +0 -0
  160. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/__init__.py +0 -0
  161. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/client.py +0 -0
  162. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/client_app.py +0 -0
  163. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/clientapp/__init__.py +0 -0
  164. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/clientapp/clientappio_servicer.py +0 -0
  165. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/dpfedavg_numpy_client.py +0 -0
  166. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/grpc_adapter_client/__init__.py +0 -0
  167. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/grpc_adapter_client/connection.py +0 -0
  168. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/grpc_client/__init__.py +0 -0
  169. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/grpc_rere_client/__init__.py +0 -0
  170. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/heartbeat.py +0 -0
  171. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/message_handler/__init__.py +0 -0
  172. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/message_handler/message_handler.py +0 -0
  173. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/mod/__init__.py +0 -0
  174. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/mod/centraldp_mods.py +0 -0
  175. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/mod/comms_mods.py +0 -0
  176. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/mod/localdp_mod.py +0 -0
  177. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/mod/secure_aggregation/__init__.py +0 -0
  178. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/mod/secure_aggregation/secagg_mod.py +0 -0
  179. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +0 -0
  180. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/mod/utils.py +0 -0
  181. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/nodestate/__init__.py +0 -0
  182. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/nodestate/in_memory_nodestate.py +0 -0
  183. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/nodestate/nodestate.py +0 -0
  184. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/nodestate/nodestate_factory.py +0 -0
  185. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/numpy_client.py +0 -0
  186. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/rest_client/__init__.py +0 -0
  187. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/run_info_store.py +0 -0
  188. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/supernode/__init__.py +0 -0
  189. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/client/typing.py +0 -0
  190. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/__init__.py +0 -0
  191. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/address.py +0 -0
  192. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/auth_plugin/__init__.py +0 -0
  193. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/context.py +0 -0
  194. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/date.py +0 -0
  195. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/differential_privacy_constants.py +0 -0
  196. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/dp.py +0 -0
  197. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/message.py +0 -0
  198. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/parameter.py +0 -0
  199. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/pyproject.py +0 -0
  200. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/record/__init__.py +0 -0
  201. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/record/configsrecord.py +0 -0
  202. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/record/conversion_utils.py +0 -0
  203. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/record/metricsrecord.py +0 -0
  204. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/record/parametersrecord.py +0 -0
  205. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/record/typeddict.py +0 -0
  206. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/recordset_compat.py +0 -0
  207. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/retry_invoker.py +0 -0
  208. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/secure_aggregation/__init__.py +0 -0
  209. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/secure_aggregation/crypto/__init__.py +0 -0
  210. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/secure_aggregation/crypto/shamir.py +0 -0
  211. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py +0 -0
  212. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/secure_aggregation/quantization.py +0 -0
  213. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/secure_aggregation/secaggplus_constants.py +0 -0
  214. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/secure_aggregation/secaggplus_utils.py +0 -0
  215. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/telemetry.py +0 -0
  216. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/common/version.py +0 -0
  217. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/__init__.py +0 -0
  218. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/clientappio_pb2.pyi +0 -0
  219. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/clientappio_pb2_grpc.py +0 -0
  220. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/clientappio_pb2_grpc.pyi +0 -0
  221. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/error_pb2.pyi +0 -0
  222. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/error_pb2_grpc.py +0 -0
  223. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/error_pb2_grpc.pyi +0 -0
  224. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/exec_pb2_grpc.py +0 -0
  225. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/exec_pb2_grpc.pyi +0 -0
  226. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/fab_pb2.pyi +0 -0
  227. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/fab_pb2_grpc.py +0 -0
  228. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/fab_pb2_grpc.pyi +0 -0
  229. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/grpcadapter_pb2.pyi +0 -0
  230. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/grpcadapter_pb2_grpc.py +0 -0
  231. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/grpcadapter_pb2_grpc.pyi +0 -0
  232. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/log_pb2.pyi +0 -0
  233. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/log_pb2_grpc.py +0 -0
  234. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/log_pb2_grpc.pyi +0 -0
  235. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/message_pb2.pyi +0 -0
  236. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/message_pb2_grpc.py +0 -0
  237. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/message_pb2_grpc.pyi +0 -0
  238. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/node_pb2_grpc.py +0 -0
  239. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/node_pb2_grpc.pyi +0 -0
  240. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/recordset_pb2.pyi +0 -0
  241. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/recordset_pb2_grpc.py +0 -0
  242. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/recordset_pb2_grpc.pyi +0 -0
  243. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/run_pb2.pyi +0 -0
  244. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/run_pb2_grpc.py +0 -0
  245. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/run_pb2_grpc.pyi +0 -0
  246. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/simulationio_pb2.pyi +0 -0
  247. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/simulationio_pb2_grpc.py +0 -0
  248. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/simulationio_pb2_grpc.pyi +0 -0
  249. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/task_pb2.pyi +0 -0
  250. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/task_pb2_grpc.py +0 -0
  251. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/task_pb2_grpc.pyi +0 -0
  252. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/transport_pb2.pyi +0 -0
  253. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/transport_pb2_grpc.py +0 -0
  254. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/proto/transport_pb2_grpc.pyi +0 -0
  255. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/py.typed +0 -0
  256. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/__init__.py +0 -0
  257. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/client_manager.py +0 -0
  258. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/client_proxy.py +0 -0
  259. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/compat/__init__.py +0 -0
  260. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/compat/app.py +0 -0
  261. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/compat/legacy_context.py +0 -0
  262. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/criterion.py +0 -0
  263. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/driver/__init__.py +0 -0
  264. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/driver/driver.py +0 -0
  265. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/history.py +0 -0
  266. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/run_serverapp.py +0 -0
  267. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/server.py +0 -0
  268. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/server_app.py +0 -0
  269. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/server_config.py +0 -0
  270. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/serverapp/__init__.py +0 -0
  271. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/serverapp_components.py +0 -0
  272. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/__init__.py +0 -0
  273. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/aggregate.py +0 -0
  274. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/bulyan.py +0 -0
  275. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/dp_adaptive_clipping.py +0 -0
  276. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/dp_fixed_clipping.py +0 -0
  277. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/dpfedavg_adaptive.py +0 -0
  278. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/dpfedavg_fixed.py +0 -0
  279. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/fault_tolerant_fedavg.py +0 -0
  280. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/fedadagrad.py +0 -0
  281. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/fedadam.py +0 -0
  282. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/fedavg.py +0 -0
  283. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/fedavg_android.py +0 -0
  284. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/fedavgm.py +0 -0
  285. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/fedmedian.py +0 -0
  286. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/fedopt.py +0 -0
  287. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/fedprox.py +0 -0
  288. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/fedtrimmedavg.py +0 -0
  289. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/fedxgb_bagging.py +0 -0
  290. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/fedxgb_cyclic.py +0 -0
  291. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/fedxgb_nn_avg.py +0 -0
  292. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/fedyogi.py +0 -0
  293. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/krum.py +0 -0
  294. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/qfedavg.py +0 -0
  295. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/strategy/strategy.py +0 -0
  296. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/__init__.py +0 -0
  297. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/driver/__init__.py +0 -0
  298. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/ffs/__init__.py +0 -0
  299. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/ffs/disk_ffs.py +0 -0
  300. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/ffs/ffs.py +0 -0
  301. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/ffs/ffs_factory.py +0 -0
  302. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/__init__.py +0 -0
  303. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/grpc_adapter/__init__.py +0 -0
  304. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py +0 -0
  305. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +0 -0
  306. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +0 -0
  307. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +0 -0
  308. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/grpc_rere/__init__.py +0 -0
  309. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/message_handler/__init__.py +0 -0
  310. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/rest_rere/__init__.py +0 -0
  311. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/vce/__init__.py +0 -0
  312. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/vce/backend/__init__.py +0 -0
  313. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/vce/backend/backend.py +0 -0
  314. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/fleet/vce/backend/raybackend.py +0 -0
  315. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/linkstate/__init__.py +0 -0
  316. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/linkstate/linkstate_factory.py +0 -0
  317. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/simulation/__init__.py +0 -0
  318. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/simulation/simulationio_servicer.py +0 -0
  319. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/superlink/utils.py +0 -0
  320. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/typing.py +0 -0
  321. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/utils/__init__.py +0 -0
  322. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/utils/tensorboard.py +0 -0
  323. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/workflow/__init__.py +0 -0
  324. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/workflow/constant.py +0 -0
  325. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/workflow/default_workflows.py +0 -0
  326. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/workflow/secure_aggregation/__init__.py +0 -0
  327. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/workflow/secure_aggregation/secagg_workflow.py +0 -0
  328. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +0 -0
  329. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/simulation/__init__.py +0 -0
  330. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/simulation/ray_transport/__init__.py +0 -0
  331. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/simulation/ray_transport/ray_actor.py +0 -0
  332. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/simulation/ray_transport/ray_client_proxy.py +0 -0
  333. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/simulation/ray_transport/utils.py +0 -0
  334. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/superexec/__init__.py +0 -0
  335. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/superexec/app.py +0 -0
  336. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/superexec/deployment.py +0 -0
  337. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/superexec/exec_user_auth_interceptor.py +0 -0
  338. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/superexec/executor.py +0 -0
  339. {flwr-1.14.0 → flwr-1.15.1}/src/py/flwr/superexec/simulation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flwr
3
- Version: 1.14.0
3
+ Version: 1.15.1
4
4
  Summary: Flower: A Friendly Federated AI Framework
5
5
  Home-page: https://flower.ai
6
6
  License: Apache-2.0
@@ -32,22 +32,22 @@ 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 (>=42.0.4,<43.0.0)
36
- Requires-Dist: grpcio (>=1.60.0,<2.0.0,!=1.64.2,<=1.64.3)
35
+ Requires-Dist: cryptography (>=43.0.1,<44.0.0)
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)
39
39
  Requires-Dist: pathspec (>=0.12.1,<0.13.0)
40
- Requires-Dist: protobuf (>=4.25.2,<5.0.0)
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
43
  Requires-Dist: ray (==2.10.0) ; (python_version >= "3.9" and python_version < "3.12") 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
- Requires-Dist: starlette (>=0.31.0,<0.32.0) ; extra == "rest"
46
+ Requires-Dist: starlette (>=0.45.2,<0.46.0) ; extra == "rest"
47
47
  Requires-Dist: tomli (>=2.0.1,<3.0.0)
48
48
  Requires-Dist: tomli-w (>=1.0.0,<2.0.0)
49
49
  Requires-Dist: typer (>=0.12.5,<0.13.0)
50
- Requires-Dist: uvicorn[standard] (>=0.23.0,<0.24.0) ; extra == "rest"
50
+ Requires-Dist: uvicorn[standard] (>=0.34.0,<0.35.0) ; extra == "rest"
51
51
  Project-URL: Documentation, https://flower.ai
52
52
  Project-URL: Repository, https://github.com/adap/flower
53
53
  Description-Content-Type: text/markdown
@@ -88,7 +88,7 @@ design of Flower is based on a few guiding principles:
88
88
 
89
89
  - **Framework-agnostic**: Different machine learning frameworks have different
90
90
  strengths. Flower can be used with any machine learning framework, for
91
- example, [PyTorch](https://pytorch.org), [TensorFlow](https://tensorflow.org), [Hugging Face Transformers](https://huggingface.co/), [PyTorch Lightning](https://pytorchlightning.ai/), [scikit-learn](https://scikit-learn.org/), [JAX](https://jax.readthedocs.io/), [TFLite](https://tensorflow.org/lite/), [MONAI](https://docs.monai.io/en/latest/index.html), [fastai](https://www.fast.ai/), [MLX](https://ml-explore.github.io/mlx/build/html/index.html), [XGBoost](https://xgboost.readthedocs.io/en/stable/), [Pandas](https://pandas.pydata.org/) for federated analytics, or even raw [NumPy](https://numpy.org/)
91
+ example, [PyTorch](https://pytorch.org), [TensorFlow](https://tensorflow.org), [Hugging Face Transformers](https://huggingface.co/), [PyTorch Lightning](https://pytorchlightning.ai/), [scikit-learn](https://scikit-learn.org/), [JAX](https://jax.readthedocs.io/), [TFLite](https://tensorflow.org/lite/), [MONAI](https://docs.monai.io/en/latest/index.html), [fastai](https://www.fast.ai/), [MLX](https://ml-explore.github.io/mlx/build/html/index.html), [XGBoost](https://xgboost.readthedocs.io/en/stable/), [LeRobot](https://github.com/huggingface/lerobot) for federated robots, [Pandas](https://pandas.pydata.org/) for federated analytics, or even raw [NumPy](https://numpy.org/)
92
92
  for users who enjoy computing gradients by hand.
93
93
 
94
94
  - **Understandable**: Flower is written with maintainability in mind. The
@@ -118,7 +118,7 @@ Flower's goal is to make federated learning accessible to everyone. This series
118
118
 
119
119
  4. **Custom Clients for Federated Learning**
120
120
 
121
- [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/adap/flower/blob/main/doc/source/tutorial-series-customize-the-client-pytorch.ipynb) (or open the [Jupyter Notebook](https://github.com/adap/flower/blob/main/framework/docs/source/tutorial-series-customize-the-client-pytorch.ipynb))
121
+ [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/adap/flower/blob/main/framework/docs/source/tutorial-series-customize-the-client-pytorch.ipynb) (or open the [Jupyter Notebook](https://github.com/adap/flower/blob/main/framework/docs/source/tutorial-series-customize-the-client-pytorch.ipynb))
122
122
 
123
123
  Stay tuned, more tutorials are coming soon. Topics include **Privacy and Security in Federated Learning**, and **Scaling Federated Learning**.
124
124
 
@@ -34,7 +34,7 @@ design of Flower is based on a few guiding principles:
34
34
 
35
35
  - **Framework-agnostic**: Different machine learning frameworks have different
36
36
  strengths. Flower can be used with any machine learning framework, for
37
- example, [PyTorch](https://pytorch.org), [TensorFlow](https://tensorflow.org), [Hugging Face Transformers](https://huggingface.co/), [PyTorch Lightning](https://pytorchlightning.ai/), [scikit-learn](https://scikit-learn.org/), [JAX](https://jax.readthedocs.io/), [TFLite](https://tensorflow.org/lite/), [MONAI](https://docs.monai.io/en/latest/index.html), [fastai](https://www.fast.ai/), [MLX](https://ml-explore.github.io/mlx/build/html/index.html), [XGBoost](https://xgboost.readthedocs.io/en/stable/), [Pandas](https://pandas.pydata.org/) for federated analytics, or even raw [NumPy](https://numpy.org/)
37
+ example, [PyTorch](https://pytorch.org), [TensorFlow](https://tensorflow.org), [Hugging Face Transformers](https://huggingface.co/), [PyTorch Lightning](https://pytorchlightning.ai/), [scikit-learn](https://scikit-learn.org/), [JAX](https://jax.readthedocs.io/), [TFLite](https://tensorflow.org/lite/), [MONAI](https://docs.monai.io/en/latest/index.html), [fastai](https://www.fast.ai/), [MLX](https://ml-explore.github.io/mlx/build/html/index.html), [XGBoost](https://xgboost.readthedocs.io/en/stable/), [LeRobot](https://github.com/huggingface/lerobot) for federated robots, [Pandas](https://pandas.pydata.org/) for federated analytics, or even raw [NumPy](https://numpy.org/)
38
38
  for users who enjoy computing gradients by hand.
39
39
 
40
40
  - **Understandable**: Flower is written with maintainability in mind. The
@@ -64,7 +64,7 @@ Flower's goal is to make federated learning accessible to everyone. This series
64
64
 
65
65
  4. **Custom Clients for Federated Learning**
66
66
 
67
- [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/adap/flower/blob/main/doc/source/tutorial-series-customize-the-client-pytorch.ipynb) (or open the [Jupyter Notebook](https://github.com/adap/flower/blob/main/framework/docs/source/tutorial-series-customize-the-client-pytorch.ipynb))
67
+ [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/adap/flower/blob/main/framework/docs/source/tutorial-series-customize-the-client-pytorch.ipynb) (or open the [Jupyter Notebook](https://github.com/adap/flower/blob/main/framework/docs/source/tutorial-series-customize-the-client-pytorch.ipynb))
68
68
 
69
69
  Stay tuned, more tutorials are coming soon. Topics include **Privacy and Security in Federated Learning**, and **Scaling Federated Learning**.
70
70
 
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "flwr"
7
- version = "1.14.0"
7
+ version = "1.15.1"
8
8
  description = "Flower: A Friendly Federated AI Framework"
9
9
  license = "Apache-2.0"
10
10
  authors = ["The Flower Authors <hello@flower.ai>"]
@@ -68,9 +68,9 @@ flower-client-app = "flwr.client.supernode:run_client_app" # Deprecated
68
68
  python = "^3.9"
69
69
  # Mandatory dependencies
70
70
  numpy = ">=1.26.0,<3.0.0"
71
- grpcio = "^1.60.0,!=1.64.2,<=1.64.3"
72
- protobuf = "^4.25.2"
73
- cryptography = "^42.0.4"
71
+ grpcio = "^1.62.3,!=1.65.0"
72
+ protobuf = "^4.21.6"
73
+ cryptography = "^43.0.1"
74
74
  pycryptodome = "^3.18.0"
75
75
  iterators = "^0.0.2"
76
76
  typer = "^0.12.5"
@@ -83,8 +83,8 @@ requests = "^2.31.0"
83
83
  # Optional dependencies (Simulation Engine)
84
84
  ray = { version = "==2.10.0", optional = true, python = ">=3.9,<3.12" }
85
85
  # Optional dependencies (REST transport layer)
86
- starlette = { version = "^0.31.0", optional = true }
87
- uvicorn = { version = "^0.23.0", extras = ["standard"], optional = true }
86
+ starlette = { version = "^0.45.2", optional = true }
87
+ uvicorn = { version = "^0.34.0", extras = ["standard"], optional = true }
88
88
 
89
89
  [tool.poetry.extras]
90
90
  simulation = ["ray"]
@@ -92,7 +92,7 @@ rest = ["starlette", "uvicorn"]
92
92
 
93
93
  [tool.poetry.group.dev.dependencies]
94
94
  types-dataclasses = "==0.6.6"
95
- types-protobuf = "==3.19.18"
95
+ types-protobuf = "==4.21.0.7"
96
96
  types-requests = "==2.31.0.20240125"
97
97
  types-setuptools = "==69.0.0.20240125"
98
98
  clang-format = "==17.0.6"
@@ -106,11 +106,11 @@ flake8 = "==5.0.4"
106
106
  parameterized = "==0.9.0"
107
107
  pytest = "==7.4.4"
108
108
  pytest-cov = "==4.1.0"
109
- pytest-watcher = "==0.4.1"
110
- grpcio-tools = "==1.60.0"
109
+ pytest-watcher = "==0.4.3"
110
+ grpcio-tools = "==1.62.3"
111
111
  mypy-protobuf = "==3.2.0"
112
112
  jupyterlab = "==4.0.12"
113
- rope = "==1.11.0"
113
+ rope = "==1.13.0"
114
114
  semver = "==3.0.2"
115
115
  sphinx = "==7.4.7"
116
116
  sphinx-intl = "==2.2.0"
@@ -124,7 +124,7 @@ furo = "==2024.8.6"
124
124
  sphinx-reredirects = "==0.1.5"
125
125
  nbsphinx = "==0.9.5"
126
126
  nbstripout = "==0.6.1"
127
- ruff = "==0.1.9"
127
+ ruff = "==0.4.5"
128
128
  sphinx-argparse = "==0.4.0"
129
129
  pipreqs = "==0.4.13"
130
130
  mdformat = "==0.7.18"
@@ -201,9 +201,6 @@ wrap-descriptions = 88
201
201
  [tool.ruff]
202
202
  target-version = "py39"
203
203
  line-length = 88
204
- select = ["D", "E", "F", "W", "B", "ISC", "C4", "UP"]
205
- fixable = ["D", "E", "F", "W", "B", "ISC", "C4", "UP"]
206
- ignore = ["B024", "B027", "D205", "D209"]
207
204
  exclude = [
208
205
  ".bzr",
209
206
  ".direnv",
@@ -228,10 +225,15 @@ exclude = [
228
225
  "proto",
229
226
  ]
230
227
 
231
- [tool.ruff.pydocstyle]
228
+ [tool.ruff.lint]
229
+ select = ["D", "E", "F", "W", "B", "ISC", "C4", "UP"]
230
+ fixable = ["D", "E", "F", "W", "B", "ISC", "C4", "UP"]
231
+ ignore = ["B024", "B027", "D205", "D209"]
232
+
233
+ [tool.ruff.lint.pydocstyle]
232
234
  convention = "numpy"
233
235
 
234
- [tool.ruff.per-file-ignores]
236
+ [tool.ruff.lint.per-file-ignores]
235
237
  "src/py/flwr/server/strategy/*.py" = ["E501"]
236
238
 
237
239
  [tool.docsig]
@@ -0,0 +1,31 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Flower user auth plugins."""
16
+
17
+
18
+ from flwr.common.auth_plugin import CliAuthPlugin
19
+ from flwr.common.constant import AuthType
20
+
21
+ from .oidc_cli_plugin import OidcCliPlugin
22
+
23
+
24
+ def get_cli_auth_plugins() -> dict[str, type[CliAuthPlugin]]:
25
+ """Return all CLI authentication plugins."""
26
+ return {AuthType.OIDC: OidcCliPlugin}
27
+
28
+
29
+ __all__ = [
30
+ "get_cli_auth_plugins",
31
+ ]
@@ -0,0 +1,150 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Flower CLI user auth plugin for OIDC."""
16
+
17
+
18
+ import json
19
+ import time
20
+ from collections.abc import Sequence
21
+ from pathlib import Path
22
+ from typing import Any, Optional, Union
23
+
24
+ import typer
25
+
26
+ from flwr.common.auth_plugin import CliAuthPlugin
27
+ from flwr.common.constant import (
28
+ ACCESS_TOKEN_KEY,
29
+ AUTH_TYPE_JSON_KEY,
30
+ REFRESH_TOKEN_KEY,
31
+ AuthType,
32
+ )
33
+ from flwr.common.typing import UserAuthCredentials, UserAuthLoginDetails
34
+ from flwr.proto.exec_pb2 import ( # pylint: disable=E0611
35
+ GetAuthTokensRequest,
36
+ GetAuthTokensResponse,
37
+ )
38
+ from flwr.proto.exec_pb2_grpc import ExecStub
39
+
40
+
41
+ class OidcCliPlugin(CliAuthPlugin):
42
+ """Flower OIDC auth plugin for CLI."""
43
+
44
+ def __init__(self, credentials_path: Path):
45
+ self.access_token: Optional[str] = None
46
+ self.refresh_token: Optional[str] = None
47
+ self.credentials_path = credentials_path
48
+
49
+ @staticmethod
50
+ def login(
51
+ login_details: UserAuthLoginDetails,
52
+ exec_stub: ExecStub,
53
+ ) -> UserAuthCredentials:
54
+ """Authenticate the user and retrieve authentication credentials."""
55
+ typer.secho(
56
+ "Please login with your user credentials here: "
57
+ f"{login_details.verification_uri_complete}",
58
+ fg=typer.colors.BLUE,
59
+ )
60
+ start_time = time.time()
61
+ time.sleep(login_details.interval)
62
+
63
+ while (time.time() - start_time) < login_details.expires_in:
64
+ res: GetAuthTokensResponse = exec_stub.GetAuthTokens(
65
+ GetAuthTokensRequest(device_code=login_details.device_code)
66
+ )
67
+
68
+ access_token = res.access_token
69
+ refresh_token = res.refresh_token
70
+
71
+ if access_token and refresh_token:
72
+ typer.secho(
73
+ "✅ Login successful.",
74
+ fg=typer.colors.GREEN,
75
+ bold=False,
76
+ )
77
+ return UserAuthCredentials(
78
+ access_token=access_token,
79
+ refresh_token=refresh_token,
80
+ )
81
+
82
+ time.sleep(login_details.interval)
83
+
84
+ typer.secho(
85
+ "❌ Timeout, failed to sign in.",
86
+ fg=typer.colors.RED,
87
+ bold=True,
88
+ )
89
+ raise typer.Exit(code=1)
90
+
91
+ def store_tokens(self, credentials: UserAuthCredentials) -> None:
92
+ """Store authentication tokens to the `credentials_path`.
93
+
94
+ The credentials, including tokens, will be saved as a JSON file
95
+ at `credentials_path`.
96
+ """
97
+ self.access_token = credentials.access_token
98
+ self.refresh_token = credentials.refresh_token
99
+ json_dict = {
100
+ AUTH_TYPE_JSON_KEY: AuthType.OIDC,
101
+ ACCESS_TOKEN_KEY: credentials.access_token,
102
+ REFRESH_TOKEN_KEY: credentials.refresh_token,
103
+ }
104
+
105
+ with open(self.credentials_path, "w", encoding="utf-8") as file:
106
+ json.dump(json_dict, file, indent=4)
107
+
108
+ def load_tokens(self) -> None:
109
+ """Load authentication tokens from the `credentials_path`."""
110
+ with open(self.credentials_path, encoding="utf-8") as file:
111
+ json_dict: dict[str, Any] = json.load(file)
112
+ access_token = json_dict.get(ACCESS_TOKEN_KEY)
113
+ refresh_token = json_dict.get(REFRESH_TOKEN_KEY)
114
+
115
+ if isinstance(access_token, str) and isinstance(refresh_token, str):
116
+ self.access_token = access_token
117
+ self.refresh_token = refresh_token
118
+
119
+ def write_tokens_to_metadata(
120
+ self, metadata: Sequence[tuple[str, Union[str, bytes]]]
121
+ ) -> Sequence[tuple[str, Union[str, bytes]]]:
122
+ """Write authentication tokens to the provided metadata."""
123
+ if self.access_token is None or self.refresh_token is None:
124
+ typer.secho(
125
+ "❌ Missing authentication tokens. Please login first.",
126
+ fg=typer.colors.RED,
127
+ bold=True,
128
+ )
129
+ raise typer.Exit(code=1)
130
+
131
+ return list(metadata) + [
132
+ (ACCESS_TOKEN_KEY, self.access_token),
133
+ (REFRESH_TOKEN_KEY, self.refresh_token),
134
+ ]
135
+
136
+ def read_tokens_from_metadata(
137
+ self, metadata: Sequence[tuple[str, Union[str, bytes]]]
138
+ ) -> Optional[UserAuthCredentials]:
139
+ """Read authentication tokens from the provided metadata."""
140
+ metadata_dict = dict(metadata)
141
+ access_token = metadata_dict.get(ACCESS_TOKEN_KEY)
142
+ refresh_token = metadata_dict.get(REFRESH_TOKEN_KEY)
143
+
144
+ if isinstance(access_token, str) and isinstance(refresh_token, str):
145
+ return UserAuthCredentials(
146
+ access_token=access_token,
147
+ refresh_token=refresh_token,
148
+ )
149
+
150
+ return None
@@ -54,8 +54,12 @@ class CliUserAuthInterceptor(
54
54
 
55
55
  response = continuation(details, request)
56
56
  if response.initial_metadata():
57
- retrieved_metadata = dict(response.initial_metadata())
58
- self.auth_plugin.store_tokens(retrieved_metadata)
57
+ credentials = self.auth_plugin.read_tokens_from_metadata(
58
+ response.initial_metadata()
59
+ )
60
+ # The metadata contains tokens only if they have been refreshed
61
+ if credentials is not None:
62
+ self.auth_plugin.store_tokens(credentials)
59
63
 
60
64
  return response
61
65
 
@@ -15,53 +15,19 @@
15
15
  """Utility to validate the `pyproject.toml` file."""
16
16
 
17
17
 
18
- import zipfile
19
- from io import BytesIO
20
18
  from pathlib import Path
21
- from typing import IO, Any, Optional, Union, get_args
19
+ from typing import Any, Optional, Union
22
20
 
23
21
  import tomli
24
22
  import typer
25
23
 
26
- from flwr.common import object_ref
27
- from flwr.common.typing import UserConfigValue
28
-
29
-
30
- def get_fab_config(fab_file: Union[Path, bytes]) -> dict[str, Any]:
31
- """Extract the config from a FAB file or path.
32
-
33
- Parameters
34
- ----------
35
- fab_file : Union[Path, bytes]
36
- The Flower App Bundle file to validate and extract the metadata from.
37
- It can either be a path to the file or the file itself as bytes.
38
-
39
- Returns
40
- -------
41
- Dict[str, Any]
42
- The `config` of the given Flower App Bundle.
43
- """
44
- fab_file_archive: Union[Path, IO[bytes]]
45
- if isinstance(fab_file, bytes):
46
- fab_file_archive = BytesIO(fab_file)
47
- elif isinstance(fab_file, Path):
48
- fab_file_archive = fab_file
49
- else:
50
- raise ValueError("fab_file must be either a Path or bytes")
51
-
52
- with zipfile.ZipFile(fab_file_archive, "r") as zipf:
53
- with zipf.open("pyproject.toml") as file:
54
- toml_content = file.read().decode("utf-8")
55
-
56
- conf = load_from_string(toml_content)
57
- if conf is None:
58
- raise ValueError("Invalid TOML content in pyproject.toml")
59
-
60
- is_valid, errors, _ = validate(conf, check_module=False)
61
- if not is_valid:
62
- raise ValueError(errors)
63
-
64
- return conf
24
+ from flwr.common.config import (
25
+ fuse_dicts,
26
+ get_fab_config,
27
+ get_metadata_from_config,
28
+ parse_config_args,
29
+ validate_config,
30
+ )
65
31
 
66
32
 
67
33
  def get_fab_metadata(fab_file: Union[Path, bytes]) -> tuple[str, str]:
@@ -78,12 +44,7 @@ def get_fab_metadata(fab_file: Union[Path, bytes]) -> tuple[str, str]:
78
44
  Tuple[str, str]
79
45
  The `fab_id` and `fab_version` of the given Flower App Bundle.
80
46
  """
81
- conf = get_fab_config(fab_file)
82
-
83
- return (
84
- f"{conf['tool']['flwr']['app']['publisher']}/{conf['project']['name']}",
85
- conf["project"]["version"],
86
- )
47
+ return get_metadata_from_config(get_fab_config(fab_file))
87
48
 
88
49
 
89
50
  def load_and_validate(
@@ -120,7 +81,7 @@ def load_and_validate(
120
81
  ]
121
82
  return (None, errors, [])
122
83
 
123
- is_valid, errors, warnings = validate(config, check_module, path.parent)
84
+ is_valid, errors, warnings = validate_config(config, check_module, path.parent)
124
85
 
125
86
  if not is_valid:
126
87
  return (None, errors, warnings)
@@ -133,102 +94,11 @@ def load(toml_path: Path) -> Optional[dict[str, Any]]:
133
94
  if not toml_path.is_file():
134
95
  return None
135
96
 
136
- with toml_path.open(encoding="utf-8") as toml_file:
137
- return load_from_string(toml_file.read())
138
-
139
-
140
- def _validate_run_config(config_dict: dict[str, Any], errors: list[str]) -> None:
141
- for key, value in config_dict.items():
142
- if isinstance(value, dict):
143
- _validate_run_config(config_dict[key], errors)
144
- elif not isinstance(value, get_args(UserConfigValue)):
145
- raise ValueError(
146
- f"The value for key {key} needs to be of type `int`, `float`, "
147
- "`bool, `str`, or a `dict` of those.",
148
- )
149
-
150
-
151
- # pylint: disable=too-many-branches
152
- def validate_fields(config: dict[str, Any]) -> tuple[bool, list[str], list[str]]:
153
- """Validate pyproject.toml fields."""
154
- errors = []
155
- warnings = []
156
-
157
- if "project" not in config:
158
- errors.append("Missing [project] section")
159
- else:
160
- if "name" not in config["project"]:
161
- errors.append('Property "name" missing in [project]')
162
- if "version" not in config["project"]:
163
- errors.append('Property "version" missing in [project]')
164
- if "description" not in config["project"]:
165
- warnings.append('Recommended property "description" missing in [project]')
166
- if "license" not in config["project"]:
167
- warnings.append('Recommended property "license" missing in [project]')
168
- if "authors" not in config["project"]:
169
- warnings.append('Recommended property "authors" missing in [project]')
170
-
171
- if (
172
- "tool" not in config
173
- or "flwr" not in config["tool"]
174
- or "app" not in config["tool"]["flwr"]
175
- ):
176
- errors.append("Missing [tool.flwr.app] section")
177
- else:
178
- if "publisher" not in config["tool"]["flwr"]["app"]:
179
- errors.append('Property "publisher" missing in [tool.flwr.app]')
180
- if "config" in config["tool"]["flwr"]["app"]:
181
- _validate_run_config(config["tool"]["flwr"]["app"]["config"], errors)
182
- if "components" not in config["tool"]["flwr"]["app"]:
183
- errors.append("Missing [tool.flwr.app.components] section")
184
- else:
185
- if "serverapp" not in config["tool"]["flwr"]["app"]["components"]:
186
- errors.append(
187
- 'Property "serverapp" missing in [tool.flwr.app.components]'
188
- )
189
- if "clientapp" not in config["tool"]["flwr"]["app"]["components"]:
190
- errors.append(
191
- 'Property "clientapp" missing in [tool.flwr.app.components]'
192
- )
193
-
194
- return len(errors) == 0, errors, warnings
195
-
196
-
197
- def validate(
198
- config: dict[str, Any],
199
- check_module: bool = True,
200
- project_dir: Optional[Union[str, Path]] = None,
201
- ) -> tuple[bool, list[str], list[str]]:
202
- """Validate pyproject.toml."""
203
- is_valid, errors, warnings = validate_fields(config)
204
-
205
- if not is_valid:
206
- return False, errors, warnings
207
-
208
- # Validate serverapp
209
- serverapp_ref = config["tool"]["flwr"]["app"]["components"]["serverapp"]
210
- is_valid, reason = object_ref.validate(serverapp_ref, check_module, project_dir)
211
-
212
- if not is_valid and isinstance(reason, str):
213
- return False, [reason], []
214
-
215
- # Validate clientapp
216
- clientapp_ref = config["tool"]["flwr"]["app"]["components"]["clientapp"]
217
- is_valid, reason = object_ref.validate(clientapp_ref, check_module, project_dir)
218
-
219
- if not is_valid and isinstance(reason, str):
220
- return False, [reason], []
221
-
222
- return True, [], []
223
-
224
-
225
- def load_from_string(toml_content: str) -> Optional[dict[str, Any]]:
226
- """Load TOML content from a string and return as dict."""
227
- try:
228
- data = tomli.loads(toml_content)
229
- return data
230
- except tomli.TOMLDecodeError:
231
- return None
97
+ with toml_path.open("rb") as toml_file:
98
+ try:
99
+ return tomli.load(toml_file)
100
+ except tomli.TOMLDecodeError:
101
+ return None
232
102
 
233
103
 
234
104
  def process_loaded_project_config(
@@ -263,7 +133,9 @@ def process_loaded_project_config(
263
133
 
264
134
 
265
135
  def validate_federation_in_project_config(
266
- federation: Optional[str], config: dict[str, Any]
136
+ federation: Optional[str],
137
+ config: dict[str, Any],
138
+ overrides: Optional[list[str]] = None,
267
139
  ) -> tuple[str, dict[str, Any]]:
268
140
  """Validate the federation name in the Flower project configuration."""
269
141
  federation = federation or config["tool"]["flwr"]["federations"].get("default")
@@ -293,6 +165,11 @@ def validate_federation_in_project_config(
293
165
  )
294
166
  raise typer.Exit(code=1)
295
167
 
168
+ # Override the federation configuration if provided
169
+ if overrides:
170
+ overrides_dict = parse_config_args(overrides, flatten=False)
171
+ federation_config = fuse_dicts(federation_config, overrides_dict)
172
+
296
173
  return federation, federation_config
297
174
 
298
175
 
@@ -305,7 +182,7 @@ def validate_certificate_in_federation_config(
305
182
  root_certificates_bytes = (app / root_certificates).read_bytes()
306
183
  if insecure := bool(insecure_str):
307
184
  typer.secho(
308
- "❌ `root_certificates` were provided but the `insecure` parameter "
185
+ "❌ `root-certificates` were provided but the `insecure` parameter "
309
186
  "is set to `True`.",
310
187
  fg=typer.colors.RED,
311
188
  bold=True,
@@ -0,0 +1,27 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Constants for CLI commands."""
16
+
17
+
18
+ # The help message for `--federation-config` option
19
+ FEDERATION_CONFIG_HELP_MESSAGE = (
20
+ "Override federation configuration values in the format:\n\n"
21
+ "`--federation-config 'key1=value1 key2=value2' --federation-config "
22
+ "'key3=value3'`\n\nValues can be of any type supported in TOML, such as "
23
+ "bool, int, float, or string. Ensure that the keys (`key1`, `key2`, `key3` "
24
+ "in this example) exist in the federation configuration under the "
25
+ "`[tool.flwr.federations.<YOUR_FEDERATION>]` table of the `pyproject.toml` "
26
+ "for proper overriding."
27
+ )
@@ -154,7 +154,7 @@ def validate_and_install(
154
154
  )
155
155
  raise typer.Exit(code=1)
156
156
 
157
- version, fab_id = get_metadata_from_config(config)
157
+ fab_id, version = get_metadata_from_config(config)
158
158
  publisher, project_name = fab_id.split("/")
159
159
  config_metadata = (publisher, project_name, version, fab_hash)
160
160