flwr 1.17.0__tar.gz → 1.19.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 (378) hide show
  1. {flwr-1.17.0 → flwr-1.19.0}/PKG-INFO +6 -5
  2. {flwr-1.17.0 → flwr-1.19.0}/README.md +1 -1
  3. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/__init__.py +1 -1
  4. flwr-1.19.0/py/flwr/app/__init__.py +15 -0
  5. flwr-1.19.0/py/flwr/app/error.py +68 -0
  6. flwr-1.19.0/py/flwr/app/metadata.py +223 -0
  7. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/__init__.py +1 -1
  8. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/app.py +21 -2
  9. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/build.py +83 -58
  10. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/cli_user_auth_interceptor.py +1 -1
  11. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/config_utils.py +53 -17
  12. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/example.py +1 -1
  13. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/install.py +1 -1
  14. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/log.py +4 -4
  15. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/login/__init__.py +1 -1
  16. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/login/login.py +15 -8
  17. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/ls.py +16 -37
  18. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/__init__.py +1 -1
  19. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/new.py +4 -4
  20. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/__init__.py +1 -1
  21. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/__init__.py +1 -1
  22. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/__init__.py +1 -1
  23. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/flwr_tune/__init__.py +1 -1
  24. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +4 -4
  25. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/model.baseline.py.tpl +1 -1
  26. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/server.baseline.py.tpl +2 -3
  27. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/task.sklearn.py.tpl +1 -1
  28. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +14 -17
  29. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +4 -4
  30. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +1 -1
  31. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/pyproject.jax.toml.tpl +1 -1
  32. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +1 -1
  33. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +1 -1
  34. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +1 -1
  35. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +1 -1
  36. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +1 -1
  37. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/run/__init__.py +1 -1
  38. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/run/run.py +11 -19
  39. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/stop.py +3 -3
  40. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/utils.py +42 -17
  41. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/__init__.py +3 -3
  42. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/client.py +1 -1
  43. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/client_app.py +140 -138
  44. flwr-1.19.0/py/flwr/client/clientapp/__init__.py +15 -0
  45. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/clientapp/utils.py +1 -1
  46. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/dpfedavg_numpy_client.py +1 -1
  47. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/grpc_adapter_client/__init__.py +1 -1
  48. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/grpc_adapter_client/connection.py +5 -5
  49. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/grpc_rere_client/__init__.py +1 -1
  50. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/grpc_rere_client/client_interceptor.py +1 -1
  51. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/grpc_rere_client/connection.py +131 -61
  52. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/grpc_rere_client/grpc_adapter.py +35 -7
  53. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/message_handler/__init__.py +1 -1
  54. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/message_handler/message_handler.py +2 -2
  55. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/mod/__init__.py +1 -1
  56. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/mod/centraldp_mods.py +1 -1
  57. flwr-1.19.0/py/flwr/client/mod/comms_mods.py +93 -0
  58. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/mod/localdp_mod.py +6 -6
  59. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/mod/secure_aggregation/__init__.py +1 -1
  60. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/mod/secure_aggregation/secagg_mod.py +1 -1
  61. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +1 -1
  62. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/mod/utils.py +1 -1
  63. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/numpy_client.py +1 -1
  64. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/rest_client/__init__.py +1 -1
  65. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/rest_client/connection.py +174 -68
  66. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/run_info_store.py +1 -1
  67. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/client/typing.py +1 -1
  68. flwr-1.19.0/py/flwr/clientapp/__init__.py +15 -0
  69. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/__init__.py +3 -3
  70. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/address.py +1 -1
  71. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/args.py +1 -1
  72. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/auth_plugin/__init__.py +3 -1
  73. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/auth_plugin/auth_plugin.py +30 -4
  74. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/config.py +1 -1
  75. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/constant.py +37 -8
  76. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/context.py +1 -1
  77. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/date.py +1 -1
  78. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/differential_privacy.py +1 -1
  79. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/differential_privacy_constants.py +1 -1
  80. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/dp.py +1 -1
  81. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/event_log_plugin/event_log_plugin.py +3 -3
  82. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/exit/exit.py +6 -6
  83. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/exit_handlers.py +31 -1
  84. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/grpc.py +1 -1
  85. flwr-1.19.0/py/flwr/common/heartbeat.py +165 -0
  86. flwr-1.19.0/py/flwr/common/inflatable.py +290 -0
  87. flwr-1.19.0/py/flwr/common/inflatable_grpc_utils.py +99 -0
  88. flwr-1.19.0/py/flwr/common/inflatable_rest_utils.py +99 -0
  89. flwr-1.19.0/py/flwr/common/inflatable_utils.py +341 -0
  90. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/logger.py +1 -1
  91. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/message.py +137 -252
  92. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/object_ref.py +1 -1
  93. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/parameter.py +1 -1
  94. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/pyproject.py +1 -1
  95. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/record/__init__.py +3 -2
  96. flwr-1.19.0/py/flwr/common/record/array.py +323 -0
  97. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/record/arrayrecord.py +121 -243
  98. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/record/configrecord.py +71 -16
  99. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/record/conversion_utils.py +2 -2
  100. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/record/metricrecord.py +71 -20
  101. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/record/recorddict.py +207 -90
  102. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/record/typeddict.py +1 -1
  103. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/recorddict_compat.py +2 -2
  104. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/retry_invoker.py +15 -11
  105. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/secure_aggregation/__init__.py +1 -1
  106. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/secure_aggregation/crypto/__init__.py +1 -1
  107. flwr-1.19.0/py/flwr/common/secure_aggregation/crypto/shamir.py +97 -0
  108. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py +1 -1
  109. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py +1 -1
  110. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/secure_aggregation/quantization.py +1 -1
  111. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/secure_aggregation/secaggplus_constants.py +1 -1
  112. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/secure_aggregation/secaggplus_utils.py +1 -1
  113. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/serde.py +60 -184
  114. flwr-1.19.0/py/flwr/common/serde_utils.py +175 -0
  115. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/telemetry.py +2 -2
  116. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/typing.py +6 -4
  117. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/version.py +1 -1
  118. flwr-1.19.0/py/flwr/compat/__init__.py +15 -0
  119. flwr-1.19.0/py/flwr/compat/client/__init__.py +15 -0
  120. {flwr-1.17.0/src/py/flwr → flwr-1.19.0/py/flwr/compat}/client/app.py +71 -211
  121. {flwr-1.17.0/src/py/flwr → flwr-1.19.0/py/flwr/compat}/client/grpc_client/__init__.py +1 -1
  122. {flwr-1.17.0/src/py/flwr → flwr-1.19.0/py/flwr/compat}/client/grpc_client/connection.py +13 -13
  123. flwr-1.19.0/py/flwr/compat/common/__init__.py +15 -0
  124. flwr-1.19.0/py/flwr/compat/server/__init__.py +15 -0
  125. flwr-1.19.0/py/flwr/compat/server/app.py +174 -0
  126. flwr-1.19.0/py/flwr/compat/simulation/__init__.py +15 -0
  127. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/__init__.py +1 -1
  128. flwr-1.19.0/py/flwr/proto/fleet_pb2.py +61 -0
  129. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/fleet_pb2.pyi +49 -35
  130. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/fleet_pb2_grpc.py +117 -13
  131. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/fleet_pb2_grpc.pyi +47 -6
  132. flwr-1.19.0/py/flwr/proto/heartbeat_pb2.py +33 -0
  133. flwr-1.19.0/py/flwr/proto/heartbeat_pb2.pyi +66 -0
  134. flwr-1.19.0/py/flwr/proto/message_pb2.py +58 -0
  135. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/message_pb2.pyi +125 -0
  136. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/recorddict_pb2.py +16 -28
  137. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/recorddict_pb2.pyi +46 -64
  138. flwr-1.19.0/py/flwr/proto/run_pb2.py +56 -0
  139. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/run_pb2.pyi +4 -52
  140. flwr-1.19.0/py/flwr/proto/run_pb2_grpc.py +4 -0
  141. flwr-1.19.0/py/flwr/proto/run_pb2_grpc.pyi +4 -0
  142. flwr-1.19.0/py/flwr/proto/serverappio_pb2.py +60 -0
  143. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/serverappio_pb2.pyi +45 -3
  144. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/serverappio_pb2_grpc.py +138 -34
  145. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/serverappio_pb2_grpc.pyi +54 -13
  146. flwr-1.19.0/py/flwr/proto/simulationio_pb2.py +39 -0
  147. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/simulationio_pb2_grpc.py +35 -0
  148. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/simulationio_pb2_grpc.pyi +14 -0
  149. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/__init__.py +2 -2
  150. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/app.py +69 -187
  151. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/client_manager.py +1 -1
  152. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/client_proxy.py +1 -1
  153. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/compat/__init__.py +1 -1
  154. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/compat/app.py +1 -1
  155. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/compat/app_utils.py +51 -29
  156. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/compat/legacy_context.py +1 -1
  157. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/criterion.py +1 -1
  158. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/fleet_event_log_interceptor.py +2 -2
  159. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/grid/grid.py +3 -3
  160. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/grid/grpc_grid.py +104 -34
  161. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/grid/inmemory_grid.py +5 -4
  162. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/history.py +1 -1
  163. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/run_serverapp.py +1 -1
  164. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/server.py +1 -1
  165. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/server_app.py +65 -58
  166. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/server_config.py +1 -1
  167. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/serverapp/__init__.py +1 -1
  168. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/serverapp/app.py +19 -1
  169. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/serverapp_components.py +1 -1
  170. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/__init__.py +1 -1
  171. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/aggregate.py +1 -1
  172. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/bulyan.py +2 -2
  173. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/dp_adaptive_clipping.py +17 -17
  174. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/dp_fixed_clipping.py +17 -17
  175. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/dpfedavg_adaptive.py +1 -1
  176. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/dpfedavg_fixed.py +1 -1
  177. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/fault_tolerant_fedavg.py +1 -1
  178. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/fedadagrad.py +1 -1
  179. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/fedadam.py +1 -1
  180. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/fedavg.py +1 -1
  181. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/fedavg_android.py +1 -1
  182. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/fedavgm.py +1 -1
  183. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/fedmedian.py +1 -1
  184. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/fedopt.py +1 -1
  185. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/fedprox.py +1 -1
  186. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/fedtrimmedavg.py +1 -1
  187. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/fedxgb_bagging.py +1 -1
  188. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/fedxgb_cyclic.py +1 -1
  189. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/fedxgb_nn_avg.py +3 -2
  190. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/fedyogi.py +1 -1
  191. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/krum.py +1 -1
  192. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/qfedavg.py +1 -1
  193. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/strategy/strategy.py +1 -1
  194. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/__init__.py +1 -1
  195. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/ffs/__init__.py +3 -1
  196. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/ffs/disk_ffs.py +1 -1
  197. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/ffs/ffs.py +1 -1
  198. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/ffs/ffs_factory.py +1 -1
  199. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/__init__.py +1 -1
  200. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/grpc_adapter/__init__.py +1 -1
  201. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +14 -4
  202. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py +1 -1
  203. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +1 -1
  204. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +1 -1
  205. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +1 -1
  206. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +13 -13
  207. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/grpc_rere/__init__.py +1 -1
  208. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +102 -8
  209. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +1 -1
  210. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/message_handler/__init__.py +1 -1
  211. flwr-1.19.0/py/flwr/server/superlink/fleet/message_handler/message_handler.py +292 -0
  212. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/rest_rere/__init__.py +1 -1
  213. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/rest_rere/rest_api.py +73 -12
  214. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/vce/__init__.py +1 -1
  215. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/vce/backend/__init__.py +1 -1
  216. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/vce/backend/backend.py +1 -1
  217. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/vce/backend/raybackend.py +1 -1
  218. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/fleet/vce/vce_api.py +7 -4
  219. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/linkstate/__init__.py +1 -1
  220. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/linkstate/in_memory_linkstate.py +139 -44
  221. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/linkstate/linkstate.py +54 -21
  222. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/linkstate/linkstate_factory.py +1 -1
  223. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/linkstate/sqlite_linkstate.py +150 -56
  224. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/linkstate/utils.py +34 -30
  225. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/serverappio/serverappio_grpc.py +3 -0
  226. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/serverappio/serverappio_servicer.py +211 -57
  227. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/simulation/__init__.py +1 -1
  228. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/simulation/simulationio_grpc.py +1 -1
  229. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/simulation/simulationio_servicer.py +26 -2
  230. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/utils.py +45 -3
  231. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/typing.py +1 -1
  232. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/utils/__init__.py +1 -1
  233. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/utils/tensorboard.py +1 -1
  234. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/utils/validator.py +3 -3
  235. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/workflow/__init__.py +1 -1
  236. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/workflow/constant.py +1 -1
  237. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/workflow/default_workflows.py +1 -1
  238. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/workflow/secure_aggregation/__init__.py +1 -1
  239. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/workflow/secure_aggregation/secagg_workflow.py +1 -1
  240. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +1 -1
  241. flwr-1.19.0/py/flwr/serverapp/__init__.py +15 -0
  242. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/simulation/__init__.py +1 -1
  243. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/simulation/app.py +18 -1
  244. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/simulation/legacy_app.py +1 -1
  245. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/simulation/ray_transport/__init__.py +1 -1
  246. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/simulation/ray_transport/ray_actor.py +1 -1
  247. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/simulation/ray_transport/ray_client_proxy.py +1 -1
  248. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/simulation/ray_transport/utils.py +1 -1
  249. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/simulation/run_simulation.py +2 -2
  250. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/simulation/simulationio_connection.py +1 -1
  251. flwr-1.19.0/py/flwr/supercore/__init__.py +15 -0
  252. flwr-1.19.0/py/flwr/supercore/object_store/__init__.py +24 -0
  253. flwr-1.19.0/py/flwr/supercore/object_store/in_memory_object_store.py +229 -0
  254. flwr-1.19.0/py/flwr/supercore/object_store/object_store.py +192 -0
  255. flwr-1.19.0/py/flwr/supercore/object_store/object_store_factory.py +44 -0
  256. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/superexec/__init__.py +1 -1
  257. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/superexec/app.py +1 -1
  258. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/superexec/deployment.py +7 -3
  259. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/superexec/exec_event_log_interceptor.py +4 -4
  260. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/superexec/exec_grpc.py +8 -4
  261. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/superexec/exec_servicer.py +126 -24
  262. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/superexec/exec_user_auth_interceptor.py +38 -9
  263. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/superexec/executor.py +5 -1
  264. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/superexec/simulation.py +8 -2
  265. flwr-1.19.0/py/flwr/superlink/__init__.py +15 -0
  266. flwr-1.19.0/py/flwr/supernode/__init__.py +15 -0
  267. flwr-1.19.0/py/flwr/supernode/cli/__init__.py +24 -0
  268. flwr-1.17.0/src/py/flwr/client/supernode/app.py → flwr-1.19.0/py/flwr/supernode/cli/flower_supernode.py +4 -13
  269. flwr-1.19.0/py/flwr/supernode/cli/flwr_clientapp.py +81 -0
  270. {flwr-1.17.0/src/py/flwr/client → flwr-1.19.0/py/flwr/supernode}/nodestate/__init__.py +1 -1
  271. flwr-1.19.0/py/flwr/supernode/nodestate/in_memory_nodestate.py +190 -0
  272. flwr-1.19.0/py/flwr/supernode/nodestate/nodestate.py +212 -0
  273. {flwr-1.17.0/src/py/flwr/client → flwr-1.19.0/py/flwr/supernode}/nodestate/nodestate_factory.py +1 -1
  274. flwr-1.19.0/py/flwr/supernode/runtime/__init__.py +15 -0
  275. flwr-1.17.0/src/py/flwr/client/clientapp/app.py → flwr-1.19.0/py/flwr/supernode/runtime/run_clientapp.py +26 -57
  276. flwr-1.19.0/py/flwr/supernode/servicer/__init__.py +15 -0
  277. flwr-1.19.0/py/flwr/supernode/servicer/clientappio/__init__.py +24 -0
  278. {flwr-1.17.0/src/py/flwr/client/clientapp → flwr-1.19.0/py/flwr/supernode/servicer/clientappio}/clientappio_servicer.py +1 -1
  279. flwr-1.19.0/py/flwr/supernode/start_client_internal.py +491 -0
  280. {flwr-1.17.0 → flwr-1.19.0}/pyproject.toml +15 -18
  281. flwr-1.17.0/LICENSE +0 -202
  282. flwr-1.17.0/src/py/flwr/client/clientapp/__init__.py +0 -22
  283. flwr-1.17.0/src/py/flwr/client/heartbeat.py +0 -74
  284. flwr-1.17.0/src/py/flwr/client/mod/comms_mods.py +0 -74
  285. flwr-1.17.0/src/py/flwr/client/nodestate/in_memory_nodestate.py +0 -38
  286. flwr-1.17.0/src/py/flwr/client/nodestate/nodestate.py +0 -31
  287. flwr-1.17.0/src/py/flwr/client/supernode/__init__.py +0 -22
  288. flwr-1.17.0/src/py/flwr/common/secure_aggregation/crypto/shamir.py +0 -75
  289. flwr-1.17.0/src/py/flwr/proto/fleet_pb2.py +0 -56
  290. flwr-1.17.0/src/py/flwr/proto/message_pb2.py +0 -41
  291. flwr-1.17.0/src/py/flwr/proto/run_pb2.py +0 -64
  292. flwr-1.17.0/src/py/flwr/proto/serverappio_pb2.py +0 -51
  293. flwr-1.17.0/src/py/flwr/proto/simulationio_pb2.py +0 -38
  294. flwr-1.17.0/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py +0 -175
  295. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/auth_plugin/__init__.py +0 -0
  296. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/auth_plugin/oidc_cli_plugin.py +0 -0
  297. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/constant.py +0 -0
  298. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/.gitignore.tpl +0 -0
  299. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/LICENSE.tpl +0 -0
  300. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/README.baseline.md.tpl +0 -0
  301. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/README.flowertune.md.tpl +0 -0
  302. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/README.md.tpl +0 -0
  303. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/__init__.baseline.py.tpl +0 -0
  304. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/__init__.py.tpl +0 -0
  305. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/client.baseline.py.tpl +1 -1
  306. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/client.huggingface.py.tpl +0 -0
  307. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/client.jax.py.tpl +0 -0
  308. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/client.mlx.py.tpl +0 -0
  309. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -0
  310. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -0
  311. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/client.sklearn.py.tpl +0 -0
  312. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -0
  313. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/dataset.baseline.py.tpl +0 -0
  314. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +0 -0
  315. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +0 -0
  316. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +0 -0
  317. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +0 -0
  318. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/server.huggingface.py.tpl +0 -0
  319. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/server.jax.py.tpl +0 -0
  320. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/server.mlx.py.tpl +0 -0
  321. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -0
  322. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -0
  323. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/server.sklearn.py.tpl +0 -0
  324. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -0
  325. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/strategy.baseline.py.tpl +0 -0
  326. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/task.huggingface.py.tpl +0 -0
  327. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/task.jax.py.tpl +0 -0
  328. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/task.mlx.py.tpl +0 -0
  329. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/task.numpy.py.tpl +0 -0
  330. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -0
  331. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +0 -0
  332. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/cli/new/templates/app/code/utils.baseline.py.tpl +0 -0
  333. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/event_log_plugin/__init__.py +0 -0
  334. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/exit/__init__.py +0 -0
  335. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/common/exit/exit_code.py +0 -0
  336. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/clientappio_pb2.py +0 -0
  337. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/clientappio_pb2.pyi +0 -0
  338. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/clientappio_pb2_grpc.py +0 -0
  339. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/clientappio_pb2_grpc.pyi +0 -0
  340. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/error_pb2.py +0 -0
  341. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/error_pb2.pyi +0 -0
  342. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/error_pb2_grpc.py +0 -0
  343. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/error_pb2_grpc.pyi +0 -0
  344. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/exec_pb2.py +0 -0
  345. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/exec_pb2.pyi +0 -0
  346. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/exec_pb2_grpc.py +0 -0
  347. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/exec_pb2_grpc.pyi +0 -0
  348. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/fab_pb2.py +0 -0
  349. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/fab_pb2.pyi +0 -0
  350. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/fab_pb2_grpc.py +0 -0
  351. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/fab_pb2_grpc.pyi +0 -0
  352. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/grpcadapter_pb2.py +0 -0
  353. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/grpcadapter_pb2.pyi +0 -0
  354. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/grpcadapter_pb2_grpc.py +0 -0
  355. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/grpcadapter_pb2_grpc.pyi +0 -0
  356. /flwr-1.17.0/src/py/flwr/proto/log_pb2_grpc.py → /flwr-1.19.0/py/flwr/proto/heartbeat_pb2_grpc.py +0 -0
  357. /flwr-1.17.0/src/py/flwr/proto/log_pb2_grpc.pyi → /flwr-1.19.0/py/flwr/proto/heartbeat_pb2_grpc.pyi +0 -0
  358. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/log_pb2.py +0 -0
  359. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/log_pb2.pyi +0 -0
  360. /flwr-1.17.0/src/py/flwr/proto/message_pb2_grpc.py → /flwr-1.19.0/py/flwr/proto/log_pb2_grpc.py +0 -0
  361. /flwr-1.17.0/src/py/flwr/proto/message_pb2_grpc.pyi → /flwr-1.19.0/py/flwr/proto/log_pb2_grpc.pyi +0 -0
  362. /flwr-1.17.0/src/py/flwr/proto/node_pb2_grpc.py → /flwr-1.19.0/py/flwr/proto/message_pb2_grpc.py +0 -0
  363. /flwr-1.17.0/src/py/flwr/proto/node_pb2_grpc.pyi → /flwr-1.19.0/py/flwr/proto/message_pb2_grpc.pyi +0 -0
  364. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/node_pb2.py +0 -0
  365. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/node_pb2.pyi +0 -0
  366. /flwr-1.17.0/src/py/flwr/proto/recorddict_pb2_grpc.py → /flwr-1.19.0/py/flwr/proto/node_pb2_grpc.py +0 -0
  367. /flwr-1.17.0/src/py/flwr/proto/recorddict_pb2_grpc.pyi → /flwr-1.19.0/py/flwr/proto/node_pb2_grpc.pyi +0 -0
  368. /flwr-1.17.0/src/py/flwr/proto/run_pb2_grpc.py → /flwr-1.19.0/py/flwr/proto/recorddict_pb2_grpc.py +0 -0
  369. /flwr-1.17.0/src/py/flwr/proto/run_pb2_grpc.pyi → /flwr-1.19.0/py/flwr/proto/recorddict_pb2_grpc.pyi +0 -0
  370. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/simulationio_pb2.pyi +0 -0
  371. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/transport_pb2.py +0 -0
  372. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/transport_pb2.pyi +0 -0
  373. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/transport_pb2_grpc.py +0 -0
  374. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/proto/transport_pb2_grpc.pyi +0 -0
  375. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/py.typed +0 -0
  376. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/compat/grid_client_proxy.py +0 -0
  377. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/grid/__init__.py +0 -0
  378. {flwr-1.17.0/src → flwr-1.19.0}/py/flwr/server/superlink/serverappio/__init__.py +0 -0
@@ -1,8 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: flwr
3
- Version: 1.17.0
3
+ Version: 1.19.0
4
4
  Summary: Flower: A Friendly Federated AI Framework
5
- Home-page: https://flower.ai
6
5
  License: Apache-2.0
7
6
  Keywords: Artificial Intelligence,Federated AI,Federated Analytics,Federated Evaluation,Federated Learning,Flower,Machine Learning
8
7
  Author: The Flower Authors
@@ -19,8 +18,8 @@ Classifier: Programming Language :: Python :: 3
19
18
  Classifier: Programming Language :: Python :: 3.10
20
19
  Classifier: Programming Language :: Python :: 3.11
21
20
  Classifier: Programming Language :: Python :: 3.12
22
- Classifier: Programming Language :: Python :: 3 :: Only
23
21
  Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3 :: Only
24
23
  Classifier: Programming Language :: Python :: 3.9
25
24
  Classifier: Programming Language :: Python :: Implementation :: CPython
26
25
  Classifier: Topic :: Scientific/Engineering
@@ -32,6 +31,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
32
31
  Classifier: Typing :: Typed
33
32
  Provides-Extra: rest
34
33
  Provides-Extra: simulation
34
+ Requires-Dist: click (<8.2.0)
35
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)
@@ -49,6 +49,7 @@ Requires-Dist: tomli-w (>=1.0.0,<2.0.0)
49
49
  Requires-Dist: typer (>=0.12.5,<0.13.0)
50
50
  Requires-Dist: uvicorn[standard] (>=0.34.0,<0.35.0) ; extra == "rest"
51
51
  Project-URL: Documentation, https://flower.ai
52
+ Project-URL: Homepage, https://flower.ai
52
53
  Project-URL: Repository, https://github.com/adap/flower
53
54
  Description-Content-Type: text/markdown
54
55
 
@@ -56,7 +57,7 @@ Description-Content-Type: text/markdown
56
57
 
57
58
  <p align="center">
58
59
  <a href="https://flower.ai/">
59
- <img src="https://flower.ai/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fflower_white_border.c2012e70.png&w=640&q=75" width="140px" alt="Flower Website" />
60
+ <img src="https://flower.ai/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fflwr-head.4d68867a.png&w=384&q=75" width="140px" alt="Flower Website" />
60
61
  </a>
61
62
  </p>
62
63
  <p align="center">
@@ -2,7 +2,7 @@
2
2
 
3
3
  <p align="center">
4
4
  <a href="https://flower.ai/">
5
- <img src="https://flower.ai/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fflower_white_border.c2012e70.png&w=640&q=75" width="140px" alt="Flower Website" />
5
+ <img src="https://flower.ai/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fflwr-head.4d68867a.png&w=384&q=75" width="140px" alt="Flower Website" />
6
6
  </a>
7
7
  </p>
8
8
  <p align="center">
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -0,0 +1,15 @@
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
+ """Public Flower App APIs."""
@@ -0,0 +1,68 @@
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
+ """Error."""
16
+
17
+
18
+ from __future__ import annotations
19
+
20
+ from typing import Optional, cast
21
+
22
+ DEFAULT_TTL = 43200 # This is 12 hours
23
+ MESSAGE_INIT_ERROR_MESSAGE = (
24
+ "Invalid arguments for Message. Expected one of the documented "
25
+ "signatures: Message(content: RecordDict, dst_node_id: int, message_type: str,"
26
+ " *, [ttl: float, group_id: str]) or Message(content: RecordDict | error: Error,"
27
+ " *, reply_to: Message, [ttl: float])."
28
+ )
29
+
30
+
31
+ class Error:
32
+ """The class storing information about an error that occurred.
33
+
34
+ Parameters
35
+ ----------
36
+ code : int
37
+ An identifier for the error.
38
+ reason : Optional[str]
39
+ A reason for why the error arose (e.g. an exception stack-trace)
40
+ """
41
+
42
+ def __init__(self, code: int, reason: str | None = None) -> None:
43
+ var_dict = {
44
+ "_code": code,
45
+ "_reason": reason,
46
+ }
47
+ self.__dict__.update(var_dict)
48
+
49
+ @property
50
+ def code(self) -> int:
51
+ """Error code."""
52
+ return cast(int, self.__dict__["_code"])
53
+
54
+ @property
55
+ def reason(self) -> str | None:
56
+ """Reason reported about the error."""
57
+ return cast(Optional[str], self.__dict__["_reason"])
58
+
59
+ def __repr__(self) -> str:
60
+ """Return a string representation of this instance."""
61
+ view = ", ".join([f"{k.lstrip('_')}={v!r}" for k, v in self.__dict__.items()])
62
+ return f"{self.__class__.__qualname__}({view})"
63
+
64
+ def __eq__(self, other: object) -> bool:
65
+ """Compare two instances of the class."""
66
+ if not isinstance(other, self.__class__):
67
+ raise NotImplementedError
68
+ return self.__dict__ == other.__dict__
@@ -0,0 +1,223 @@
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
+ """Metadata."""
16
+
17
+
18
+ from __future__ import annotations
19
+
20
+ from typing import cast
21
+
22
+ from ..common.constant import MessageType, MessageTypeLegacy
23
+
24
+
25
+ class Metadata: # pylint: disable=too-many-instance-attributes
26
+ """The class representing metadata associated with the current message.
27
+
28
+ Parameters
29
+ ----------
30
+ run_id : int
31
+ An identifier for the current run.
32
+ message_id : str
33
+ An identifier for the current message.
34
+ src_node_id : int
35
+ An identifier for the node sending this message.
36
+ dst_node_id : int
37
+ An identifier for the node receiving this message.
38
+ reply_to_message_id : str
39
+ An identifier for the message to which this message is a reply.
40
+ group_id : str
41
+ An identifier for grouping messages. In some settings,
42
+ this is used as the FL round.
43
+ created_at : float
44
+ Unix timestamp when the message was created.
45
+ ttl : float
46
+ Time-to-live for this message in seconds.
47
+ message_type : str
48
+ A string that encodes the action to be executed on
49
+ the receiving end.
50
+ """
51
+
52
+ def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments
53
+ self,
54
+ run_id: int,
55
+ message_id: str,
56
+ src_node_id: int,
57
+ dst_node_id: int,
58
+ reply_to_message_id: str,
59
+ group_id: str,
60
+ created_at: float,
61
+ ttl: float,
62
+ message_type: str,
63
+ ) -> None:
64
+ var_dict = {
65
+ "_run_id": run_id,
66
+ "_message_id": message_id,
67
+ "_src_node_id": src_node_id,
68
+ "_dst_node_id": dst_node_id,
69
+ "_reply_to_message_id": reply_to_message_id,
70
+ "_group_id": group_id,
71
+ "_created_at": created_at,
72
+ "_ttl": ttl,
73
+ "_message_type": message_type,
74
+ }
75
+ self.__dict__.update(var_dict)
76
+ self.message_type = message_type # Trigger validation
77
+
78
+ @property
79
+ def run_id(self) -> int:
80
+ """An identifier for the current run."""
81
+ return cast(int, self.__dict__["_run_id"])
82
+
83
+ @property
84
+ def message_id(self) -> str:
85
+ """An identifier for the current message."""
86
+ return cast(str, self.__dict__["_message_id"])
87
+
88
+ @property
89
+ def src_node_id(self) -> int:
90
+ """An identifier for the node sending this message."""
91
+ return cast(int, self.__dict__["_src_node_id"])
92
+
93
+ @property
94
+ def reply_to_message_id(self) -> str:
95
+ """An identifier for the message to which this message is a reply."""
96
+ return cast(str, self.__dict__["_reply_to_message_id"])
97
+
98
+ @property
99
+ def dst_node_id(self) -> int:
100
+ """An identifier for the node receiving this message."""
101
+ return cast(int, self.__dict__["_dst_node_id"])
102
+
103
+ @dst_node_id.setter
104
+ def dst_node_id(self, value: int) -> None:
105
+ """Set dst_node_id."""
106
+ self.__dict__["_dst_node_id"] = value
107
+
108
+ @property
109
+ def group_id(self) -> str:
110
+ """An identifier for grouping messages."""
111
+ return cast(str, self.__dict__["_group_id"])
112
+
113
+ @group_id.setter
114
+ def group_id(self, value: str) -> None:
115
+ """Set group_id."""
116
+ self.__dict__["_group_id"] = value
117
+
118
+ @property
119
+ def created_at(self) -> float:
120
+ """Unix timestamp when the message was created."""
121
+ return cast(float, self.__dict__["_created_at"])
122
+
123
+ @created_at.setter
124
+ def created_at(self, value: float) -> None:
125
+ """Set creation timestamp of this message."""
126
+ self.__dict__["_created_at"] = value
127
+
128
+ @property
129
+ def delivered_at(self) -> str:
130
+ """Unix timestamp when the message was delivered."""
131
+ return cast(str, self.__dict__["_delivered_at"])
132
+
133
+ @delivered_at.setter
134
+ def delivered_at(self, value: str) -> None:
135
+ """Set delivery timestamp of this message."""
136
+ self.__dict__["_delivered_at"] = value
137
+
138
+ @property
139
+ def ttl(self) -> float:
140
+ """Time-to-live for this message."""
141
+ return cast(float, self.__dict__["_ttl"])
142
+
143
+ @ttl.setter
144
+ def ttl(self, value: float) -> None:
145
+ """Set ttl."""
146
+ self.__dict__["_ttl"] = value
147
+
148
+ @property
149
+ def message_type(self) -> str:
150
+ """A string that encodes the action to be executed on the receiving end."""
151
+ return cast(str, self.__dict__["_message_type"])
152
+
153
+ @message_type.setter
154
+ def message_type(self, value: str) -> None:
155
+ """Set message_type."""
156
+ # Validate message type
157
+ if validate_legacy_message_type(value):
158
+ pass # Backward compatibility for legacy message types
159
+ elif not validate_message_type(value):
160
+ raise ValueError(
161
+ f"Invalid message type: '{value}'. "
162
+ "Expected format: '<category>' or '<category>.<action>', "
163
+ "where <category> must be 'train', 'evaluate', or 'query', "
164
+ "and <action> must be a valid Python identifier."
165
+ )
166
+
167
+ self.__dict__["_message_type"] = value
168
+
169
+ def __repr__(self) -> str:
170
+ """Return a string representation of this instance."""
171
+ view = ", ".join([f"{k.lstrip('_')}={v!r}" for k, v in self.__dict__.items()])
172
+ return f"{self.__class__.__qualname__}({view})"
173
+
174
+ def __eq__(self, other: object) -> bool:
175
+ """Compare two instances of the class."""
176
+ if not isinstance(other, self.__class__):
177
+ raise NotImplementedError
178
+ return self.__dict__ == other.__dict__
179
+
180
+
181
+ def validate_message_type(message_type: str) -> bool:
182
+ """Validate if the message type is valid.
183
+
184
+ A valid message type format must be one of the following:
185
+
186
+ - "<category>"
187
+ - "<category>.<action>"
188
+
189
+ where `category` must be one of "train", "evaluate", or "query",
190
+ and `action` must be a valid Python identifier.
191
+ """
192
+ # Check if conforming to the format "<category>"
193
+ valid_types = {
194
+ MessageType.TRAIN,
195
+ MessageType.EVALUATE,
196
+ MessageType.QUERY,
197
+ MessageType.SYSTEM,
198
+ }
199
+ if message_type in valid_types:
200
+ return True
201
+
202
+ # Check if conforming to the format "<category>.<action>"
203
+ if message_type.count(".") != 1:
204
+ return False
205
+
206
+ category, action = message_type.split(".")
207
+ if category in valid_types and action.isidentifier():
208
+ return True
209
+
210
+ return False
211
+
212
+
213
+ def validate_legacy_message_type(message_type: str) -> bool:
214
+ """Validate if the legacy message type is valid."""
215
+ # Backward compatibility for legacy message types
216
+ if message_type in (
217
+ MessageTypeLegacy.GET_PARAMETERS,
218
+ MessageTypeLegacy.GET_PROPERTIES,
219
+ "reconnect",
220
+ ):
221
+ return True
222
+
223
+ return False
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -14,10 +14,11 @@
14
14
  # ==============================================================================
15
15
  """Flower command line interface."""
16
16
 
17
-
18
17
  import typer
19
18
  from typer.main import get_command
20
19
 
20
+ from flwr.common.version import package_version
21
+
21
22
  from .build import build
22
23
  from .install import install
23
24
  from .log import log
@@ -34,6 +35,7 @@ app = typer.Typer(
34
35
  bold=True,
35
36
  ),
36
37
  no_args_is_help=True,
38
+ context_settings={"help_option_names": ["-h", "--help"]},
37
39
  )
38
40
 
39
41
  app.command()(new)
@@ -47,5 +49,22 @@ app.command()(login)
47
49
 
48
50
  typer_click_object = get_command(app)
49
51
 
52
+
53
+ @app.callback(invoke_without_command=True)
54
+ def version_callback(
55
+ ver: bool = typer.Option(
56
+ None,
57
+ "-V",
58
+ "--version",
59
+ is_eager=True,
60
+ help="Show the version and exit.",
61
+ ),
62
+ ) -> None:
63
+ """Print version."""
64
+ if ver:
65
+ typer.secho(f"Flower version: {package_version}", fg="blue")
66
+ raise typer.Exit()
67
+
68
+
50
69
  if __name__ == "__main__":
51
70
  app()
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -16,10 +16,8 @@
16
16
 
17
17
 
18
18
  import hashlib
19
- import os
20
- import shutil
21
- import tempfile
22
19
  import zipfile
20
+ from io import BytesIO
23
21
  from pathlib import Path
24
22
  from typing import Annotated, Any, Optional, Union
25
23
 
@@ -29,6 +27,7 @@ import typer
29
27
 
30
28
  from flwr.common.constant import FAB_ALLOWED_EXTENSIONS, FAB_DATE, FAB_HASH_TRUNCATION
31
29
 
30
+ from .config_utils import load as load_toml
32
31
  from .config_utils import load_and_validate
33
32
  from .utils import is_valid_project_name
34
33
 
@@ -43,11 +42,11 @@ def write_to_zip(
43
42
  return zipfile_obj
44
43
 
45
44
 
46
- def get_fab_filename(conf: dict[str, Any], fab_hash: str) -> str:
45
+ def get_fab_filename(config: dict[str, Any], fab_hash: str) -> str:
47
46
  """Get the FAB filename based on the given config and FAB hash."""
48
- publisher = conf["tool"]["flwr"]["app"]["publisher"]
49
- name = conf["project"]["name"]
50
- version = conf["project"]["version"].replace(".", "-")
47
+ publisher = config["tool"]["flwr"]["app"]["publisher"]
48
+ name = config["project"]["name"]
49
+ version = config["project"]["version"].replace(".", "-")
51
50
  fab_hash_truncated = fab_hash[:FAB_HASH_TRUNCATION]
52
51
  return f"{publisher}.{name}.{version}.{fab_hash_truncated}.fab"
53
52
 
@@ -89,8 +88,8 @@ def build(
89
88
  )
90
89
  raise typer.Exit(code=1)
91
90
 
92
- conf, errors, warnings = load_and_validate(app / "pyproject.toml")
93
- if conf is None:
91
+ config, errors, warnings = load_and_validate(app / "pyproject.toml")
92
+ if config is None:
94
93
  typer.secho(
95
94
  "Project configuration could not be loaded.\npyproject.toml is invalid:\n"
96
95
  + "\n".join([f"- {line}" for line in errors]),
@@ -107,70 +106,96 @@ def build(
107
106
  bold=True,
108
107
  )
109
108
 
110
- # Load .gitignore rules if present
111
- ignore_spec = _load_gitignore(app)
109
+ # Build FAB
110
+ fab_bytes, fab_hash, _ = build_fab(app)
112
111
 
113
- list_file_content = ""
112
+ # Get the name of the zip file
113
+ fab_filename = get_fab_filename(config, fab_hash)
114
+
115
+ # Write the FAB
116
+ Path(fab_filename).write_bytes(fab_bytes)
117
+
118
+ typer.secho(
119
+ f"🎊 Successfully built {fab_filename}", fg=typer.colors.GREEN, bold=True
120
+ )
121
+
122
+ return fab_filename, fab_hash
114
123
 
115
- # Remove the 'federations' field from 'tool.flwr' if it exists
116
- if (
117
- "tool" in conf
118
- and "flwr" in conf["tool"]
119
- and "federations" in conf["tool"]["flwr"]
120
- ):
121
- del conf["tool"]["flwr"]["federations"]
122
124
 
123
- toml_contents = tomli_w.dumps(conf)
125
+ def build_fab(app: Path) -> tuple[bytes, str, dict[str, Any]]:
126
+ """Build a FAB in memory and return the bytes, hash, and config.
124
127
 
125
- with tempfile.NamedTemporaryFile(suffix=".zip", delete=False) as temp_file:
126
- temp_filename = temp_file.name
128
+ This function assumes that the provided path points to a valid Flower app and
129
+ bundles it into a FAB without performing additional validation.
127
130
 
128
- with zipfile.ZipFile(temp_filename, "w", zipfile.ZIP_DEFLATED) as fab_file:
129
- write_to_zip(fab_file, "pyproject.toml", toml_contents)
131
+ Parameters
132
+ ----------
133
+ app : Path
134
+ Path to the Flower app to bundle into a FAB.
130
135
 
131
- # Continue with adding other files
132
- all_files = [
133
- f
134
- for f in app.rglob("*")
135
- if not ignore_spec.match_file(f)
136
- and f.name != temp_filename
137
- and f.suffix in FAB_ALLOWED_EXTENSIONS
138
- and f.name != "pyproject.toml" # Exclude the original pyproject.toml
139
- ]
136
+ Returns
137
+ -------
138
+ tuple[bytes, str, dict[str, Any]]
139
+ A tuple containing:
140
+ - the FAB as bytes
141
+ - the SHA256 hash of the FAB
142
+ - the project configuration (with the 'federations' field removed)
143
+ """
144
+ app = app.resolve()
145
+
146
+ # Load the pyproject.toml file
147
+ config = load_toml(app / "pyproject.toml")
148
+ if config is None:
149
+ raise ValueError("Project configuration could not be loaded.")
140
150
 
141
- all_files.sort()
151
+ # Remove the 'federations' field if it exists
152
+ if (
153
+ "tool" in config
154
+ and "flwr" in config["tool"]
155
+ and "federations" in config["tool"]["flwr"]
156
+ ):
157
+ del config["tool"]["flwr"]["federations"]
142
158
 
143
- for file_path in all_files:
144
- # Read the file content manually
145
- with open(file_path, "rb") as f:
146
- file_contents = f.read()
159
+ # Load .gitignore rules if present
160
+ ignore_spec = _load_gitignore(app)
147
161
 
148
- archive_path = file_path.relative_to(app)
149
- write_to_zip(fab_file, str(archive_path), file_contents)
162
+ # Search for all files in the app directory
163
+ all_files = [
164
+ f
165
+ for f in app.rglob("*")
166
+ if not ignore_spec.match_file(f)
167
+ and f.suffix in FAB_ALLOWED_EXTENSIONS
168
+ and f.name != "pyproject.toml" # Exclude the original pyproject.toml
169
+ ]
170
+ all_files.sort()
171
+
172
+ # Create a zip file in memory
173
+ list_file_content = ""
150
174
 
151
- # Calculate file info
152
- sha256_hash = hashlib.sha256(file_contents).hexdigest()
153
- file_size_bits = os.path.getsize(file_path) * 8 # size in bits
154
- list_file_content += f"{archive_path},{sha256_hash},{file_size_bits}\n"
175
+ fab_buffer = BytesIO()
176
+ with zipfile.ZipFile(fab_buffer, "w", zipfile.ZIP_DEFLATED) as fab_file:
177
+ # Add pyproject.toml
178
+ write_to_zip(fab_file, "pyproject.toml", tomli_w.dumps(config))
155
179
 
156
- # Add CONTENT and CONTENT.jwt to the zip file
157
- write_to_zip(fab_file, ".info/CONTENT", list_file_content)
180
+ for file_path in all_files:
181
+ # Read the file content manually
182
+ file_contents = file_path.read_bytes()
158
183
 
159
- # Get hash of FAB file
160
- content = Path(temp_filename).read_bytes()
161
- fab_hash = hashlib.sha256(content).hexdigest()
184
+ archive_path = str(file_path.relative_to(app))
185
+ write_to_zip(fab_file, archive_path, file_contents)
162
186
 
163
- # Set the name of the zip file
164
- fab_filename = get_fab_filename(conf, fab_hash)
187
+ # Calculate file info
188
+ sha256_hash = hashlib.sha256(file_contents).hexdigest()
189
+ file_size_bits = len(file_contents) * 8 # size in bits
190
+ list_file_content += f"{archive_path},{sha256_hash},{file_size_bits}\n"
165
191
 
166
- # Once the temporary zip file is created, rename it to the final filename
167
- shutil.move(temp_filename, fab_filename)
192
+ # Add CONTENT and CONTENT.jwt to the zip file
193
+ write_to_zip(fab_file, ".info/CONTENT", list_file_content)
168
194
 
169
- typer.secho(
170
- f"🎊 Successfully built {fab_filename}", fg=typer.colors.GREEN, bold=True
171
- )
195
+ fab_bytes = fab_buffer.getvalue()
196
+ fab_hash = hashlib.sha256(fab_bytes).hexdigest()
172
197
 
173
- return fab_filename, fab_hash
198
+ return fab_bytes, fab_hash, config
174
199
 
175
200
 
176
201
  def _load_gitignore(app: Path) -> pathspec.PathSpec:
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.