flwr-nightly 1.8.0.dev20240315__py3-none-any.whl → 1.15.0.dev20250115__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (312) hide show
  1. flwr/cli/app.py +16 -2
  2. flwr/cli/build.py +181 -0
  3. flwr/cli/cli_user_auth_interceptor.py +90 -0
  4. flwr/cli/config_utils.py +343 -0
  5. flwr/cli/example.py +4 -1
  6. flwr/cli/install.py +253 -0
  7. flwr/cli/log.py +182 -0
  8. flwr/{server/superlink/state → cli/login}/__init__.py +4 -10
  9. flwr/cli/login/login.py +88 -0
  10. flwr/cli/ls.py +327 -0
  11. flwr/cli/new/__init__.py +1 -0
  12. flwr/cli/new/new.py +210 -66
  13. flwr/cli/new/templates/app/.gitignore.tpl +163 -0
  14. flwr/cli/new/templates/app/LICENSE.tpl +202 -0
  15. flwr/cli/new/templates/app/README.baseline.md.tpl +127 -0
  16. flwr/cli/new/templates/app/README.flowertune.md.tpl +66 -0
  17. flwr/cli/new/templates/app/README.md.tpl +16 -32
  18. flwr/cli/new/templates/app/code/__init__.baseline.py.tpl +1 -0
  19. flwr/cli/new/templates/app/code/__init__.py.tpl +1 -1
  20. flwr/cli/new/templates/app/code/client.baseline.py.tpl +58 -0
  21. flwr/cli/new/templates/app/code/client.huggingface.py.tpl +55 -0
  22. flwr/cli/new/templates/app/code/client.jax.py.tpl +50 -0
  23. flwr/cli/new/templates/app/code/client.mlx.py.tpl +73 -0
  24. flwr/cli/new/templates/app/code/client.numpy.py.tpl +7 -7
  25. flwr/cli/new/templates/app/code/client.pytorch.py.tpl +30 -21
  26. flwr/cli/new/templates/app/code/client.sklearn.py.tpl +63 -0
  27. flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +57 -1
  28. flwr/cli/new/templates/app/code/dataset.baseline.py.tpl +36 -0
  29. flwr/cli/new/templates/app/code/flwr_tune/__init__.py +15 -0
  30. flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +126 -0
  31. flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +87 -0
  32. flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +78 -0
  33. flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +94 -0
  34. flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +83 -0
  35. flwr/cli/new/templates/app/code/model.baseline.py.tpl +80 -0
  36. flwr/cli/new/templates/app/code/server.baseline.py.tpl +46 -0
  37. flwr/cli/new/templates/app/code/server.huggingface.py.tpl +38 -0
  38. flwr/cli/new/templates/app/code/server.jax.py.tpl +26 -0
  39. flwr/cli/new/templates/app/code/server.mlx.py.tpl +31 -0
  40. flwr/cli/new/templates/app/code/server.numpy.py.tpl +22 -9
  41. flwr/cli/new/templates/app/code/server.pytorch.py.tpl +21 -18
  42. flwr/cli/new/templates/app/code/server.sklearn.py.tpl +36 -0
  43. flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +29 -1
  44. flwr/cli/new/templates/app/code/strategy.baseline.py.tpl +1 -0
  45. flwr/cli/new/templates/app/code/task.huggingface.py.tpl +102 -0
  46. flwr/cli/new/templates/app/code/task.jax.py.tpl +57 -0
  47. flwr/cli/new/templates/app/code/task.mlx.py.tpl +102 -0
  48. flwr/cli/new/templates/app/code/task.numpy.py.tpl +7 -0
  49. flwr/cli/new/templates/app/code/task.pytorch.py.tpl +29 -24
  50. flwr/cli/new/templates/app/code/task.sklearn.py.tpl +67 -0
  51. flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +53 -0
  52. flwr/cli/new/templates/app/code/utils.baseline.py.tpl +1 -0
  53. flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +138 -0
  54. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +68 -0
  55. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +46 -0
  56. flwr/cli/new/templates/app/pyproject.jax.toml.tpl +35 -0
  57. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +39 -0
  58. flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +25 -12
  59. flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +29 -14
  60. flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +35 -0
  61. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +29 -14
  62. flwr/cli/run/__init__.py +1 -0
  63. flwr/cli/run/run.py +212 -34
  64. flwr/cli/stop.py +130 -0
  65. flwr/cli/utils.py +240 -5
  66. flwr/client/__init__.py +3 -2
  67. flwr/client/app.py +432 -255
  68. flwr/client/client.py +1 -11
  69. flwr/client/client_app.py +74 -13
  70. flwr/client/clientapp/__init__.py +22 -0
  71. flwr/client/clientapp/app.py +259 -0
  72. flwr/client/clientapp/clientappio_servicer.py +244 -0
  73. flwr/client/clientapp/utils.py +115 -0
  74. flwr/client/dpfedavg_numpy_client.py +7 -8
  75. flwr/client/grpc_adapter_client/__init__.py +15 -0
  76. flwr/client/grpc_adapter_client/connection.py +98 -0
  77. flwr/client/grpc_client/connection.py +21 -7
  78. flwr/client/grpc_rere_client/__init__.py +1 -1
  79. flwr/client/grpc_rere_client/client_interceptor.py +176 -0
  80. flwr/client/grpc_rere_client/connection.py +163 -56
  81. flwr/client/grpc_rere_client/grpc_adapter.py +167 -0
  82. flwr/client/heartbeat.py +74 -0
  83. flwr/client/message_handler/__init__.py +1 -1
  84. flwr/client/message_handler/message_handler.py +10 -11
  85. flwr/client/mod/__init__.py +5 -5
  86. flwr/client/mod/centraldp_mods.py +4 -2
  87. flwr/client/mod/comms_mods.py +5 -4
  88. flwr/client/mod/localdp_mod.py +10 -5
  89. flwr/client/mod/secure_aggregation/__init__.py +1 -1
  90. flwr/client/mod/secure_aggregation/secaggplus_mod.py +26 -26
  91. flwr/client/mod/utils.py +2 -4
  92. flwr/client/nodestate/__init__.py +26 -0
  93. flwr/client/nodestate/in_memory_nodestate.py +38 -0
  94. flwr/client/nodestate/nodestate.py +31 -0
  95. flwr/client/nodestate/nodestate_factory.py +38 -0
  96. flwr/client/numpy_client.py +8 -31
  97. flwr/client/rest_client/__init__.py +1 -1
  98. flwr/client/rest_client/connection.py +199 -176
  99. flwr/client/run_info_store.py +112 -0
  100. flwr/client/supernode/__init__.py +24 -0
  101. flwr/client/supernode/app.py +321 -0
  102. flwr/client/typing.py +1 -0
  103. flwr/common/__init__.py +17 -11
  104. flwr/common/address.py +47 -3
  105. flwr/common/args.py +153 -0
  106. flwr/common/auth_plugin/__init__.py +24 -0
  107. flwr/common/auth_plugin/auth_plugin.py +121 -0
  108. flwr/common/config.py +243 -0
  109. flwr/common/constant.py +135 -1
  110. flwr/common/context.py +32 -2
  111. flwr/common/date.py +22 -4
  112. flwr/common/differential_privacy.py +2 -2
  113. flwr/common/dp.py +2 -4
  114. flwr/common/exit_handlers.py +3 -3
  115. flwr/common/grpc.py +164 -5
  116. flwr/common/logger.py +230 -12
  117. flwr/common/message.py +191 -106
  118. flwr/common/object_ref.py +179 -44
  119. flwr/common/pyproject.py +1 -0
  120. flwr/common/record/__init__.py +2 -1
  121. flwr/common/record/configsrecord.py +58 -18
  122. flwr/common/record/metricsrecord.py +57 -17
  123. flwr/common/record/parametersrecord.py +88 -20
  124. flwr/common/record/recordset.py +153 -30
  125. flwr/common/record/typeddict.py +30 -55
  126. flwr/common/recordset_compat.py +31 -12
  127. flwr/common/retry_invoker.py +123 -30
  128. flwr/common/secure_aggregation/__init__.py +1 -1
  129. flwr/common/secure_aggregation/crypto/__init__.py +1 -1
  130. flwr/common/secure_aggregation/crypto/shamir.py +11 -11
  131. flwr/common/secure_aggregation/crypto/symmetric_encryption.py +68 -4
  132. flwr/common/secure_aggregation/ndarrays_arithmetic.py +17 -17
  133. flwr/common/secure_aggregation/quantization.py +8 -8
  134. flwr/common/secure_aggregation/secaggplus_constants.py +1 -1
  135. flwr/common/secure_aggregation/secaggplus_utils.py +10 -12
  136. flwr/common/serde.py +304 -23
  137. flwr/common/telemetry.py +65 -29
  138. flwr/common/typing.py +120 -19
  139. flwr/common/version.py +17 -3
  140. flwr/proto/clientappio_pb2.py +45 -0
  141. flwr/proto/clientappio_pb2.pyi +132 -0
  142. flwr/proto/clientappio_pb2_grpc.py +135 -0
  143. flwr/proto/clientappio_pb2_grpc.pyi +53 -0
  144. flwr/proto/exec_pb2.py +62 -0
  145. flwr/proto/exec_pb2.pyi +212 -0
  146. flwr/proto/exec_pb2_grpc.py +237 -0
  147. flwr/proto/exec_pb2_grpc.pyi +93 -0
  148. flwr/proto/fab_pb2.py +31 -0
  149. flwr/proto/fab_pb2.pyi +65 -0
  150. flwr/proto/fab_pb2_grpc.py +4 -0
  151. flwr/proto/fab_pb2_grpc.pyi +4 -0
  152. flwr/proto/fleet_pb2.py +42 -23
  153. flwr/proto/fleet_pb2.pyi +123 -1
  154. flwr/proto/fleet_pb2_grpc.py +170 -0
  155. flwr/proto/fleet_pb2_grpc.pyi +61 -0
  156. flwr/proto/grpcadapter_pb2.py +32 -0
  157. flwr/proto/grpcadapter_pb2.pyi +43 -0
  158. flwr/proto/grpcadapter_pb2_grpc.py +66 -0
  159. flwr/proto/grpcadapter_pb2_grpc.pyi +24 -0
  160. flwr/proto/log_pb2.py +29 -0
  161. flwr/proto/log_pb2.pyi +39 -0
  162. flwr/proto/log_pb2_grpc.py +4 -0
  163. flwr/proto/log_pb2_grpc.pyi +4 -0
  164. flwr/proto/message_pb2.py +41 -0
  165. flwr/proto/message_pb2.pyi +128 -0
  166. flwr/proto/message_pb2_grpc.py +4 -0
  167. flwr/proto/message_pb2_grpc.pyi +4 -0
  168. flwr/proto/node_pb2.py +2 -2
  169. flwr/proto/node_pb2.pyi +1 -4
  170. flwr/proto/recordset_pb2.py +35 -33
  171. flwr/proto/recordset_pb2.pyi +40 -14
  172. flwr/proto/run_pb2.py +64 -0
  173. flwr/proto/run_pb2.pyi +268 -0
  174. flwr/proto/run_pb2_grpc.py +4 -0
  175. flwr/proto/run_pb2_grpc.pyi +4 -0
  176. flwr/proto/serverappio_pb2.py +52 -0
  177. flwr/proto/{driver_pb2.pyi → serverappio_pb2.pyi} +62 -20
  178. flwr/proto/serverappio_pb2_grpc.py +410 -0
  179. flwr/proto/serverappio_pb2_grpc.pyi +160 -0
  180. flwr/proto/simulationio_pb2.py +38 -0
  181. flwr/proto/simulationio_pb2.pyi +65 -0
  182. flwr/proto/simulationio_pb2_grpc.py +239 -0
  183. flwr/proto/simulationio_pb2_grpc.pyi +94 -0
  184. flwr/proto/task_pb2.py +7 -8
  185. flwr/proto/task_pb2.pyi +8 -5
  186. flwr/proto/transport_pb2.py +8 -8
  187. flwr/proto/transport_pb2.pyi +9 -6
  188. flwr/server/__init__.py +2 -10
  189. flwr/server/app.py +579 -402
  190. flwr/server/client_manager.py +8 -6
  191. flwr/server/compat/app.py +6 -62
  192. flwr/server/compat/app_utils.py +14 -9
  193. flwr/server/compat/driver_client_proxy.py +25 -59
  194. flwr/server/compat/legacy_context.py +5 -4
  195. flwr/server/driver/__init__.py +2 -0
  196. flwr/server/driver/driver.py +36 -131
  197. flwr/server/driver/grpc_driver.py +220 -81
  198. flwr/server/driver/inmemory_driver.py +183 -0
  199. flwr/server/history.py +28 -29
  200. flwr/server/run_serverapp.py +15 -126
  201. flwr/server/server.py +50 -44
  202. flwr/server/server_app.py +59 -10
  203. flwr/server/serverapp/__init__.py +22 -0
  204. flwr/server/serverapp/app.py +256 -0
  205. flwr/server/serverapp_components.py +52 -0
  206. flwr/server/strategy/__init__.py +2 -2
  207. flwr/server/strategy/aggregate.py +37 -23
  208. flwr/server/strategy/bulyan.py +9 -9
  209. flwr/server/strategy/dp_adaptive_clipping.py +25 -25
  210. flwr/server/strategy/dp_fixed_clipping.py +23 -22
  211. flwr/server/strategy/dpfedavg_adaptive.py +8 -8
  212. flwr/server/strategy/dpfedavg_fixed.py +13 -12
  213. flwr/server/strategy/fault_tolerant_fedavg.py +11 -11
  214. flwr/server/strategy/fedadagrad.py +9 -9
  215. flwr/server/strategy/fedadam.py +20 -10
  216. flwr/server/strategy/fedavg.py +16 -16
  217. flwr/server/strategy/fedavg_android.py +17 -17
  218. flwr/server/strategy/fedavgm.py +9 -9
  219. flwr/server/strategy/fedmedian.py +5 -5
  220. flwr/server/strategy/fedopt.py +6 -6
  221. flwr/server/strategy/fedprox.py +7 -7
  222. flwr/server/strategy/fedtrimmedavg.py +8 -8
  223. flwr/server/strategy/fedxgb_bagging.py +12 -12
  224. flwr/server/strategy/fedxgb_cyclic.py +10 -10
  225. flwr/server/strategy/fedxgb_nn_avg.py +6 -6
  226. flwr/server/strategy/fedyogi.py +9 -9
  227. flwr/server/strategy/krum.py +9 -9
  228. flwr/server/strategy/qfedavg.py +16 -16
  229. flwr/server/strategy/strategy.py +10 -10
  230. flwr/server/superlink/driver/__init__.py +2 -2
  231. flwr/server/superlink/driver/serverappio_grpc.py +61 -0
  232. flwr/server/superlink/driver/serverappio_servicer.py +361 -0
  233. flwr/server/superlink/ffs/__init__.py +24 -0
  234. flwr/server/superlink/ffs/disk_ffs.py +108 -0
  235. flwr/server/superlink/ffs/ffs.py +79 -0
  236. flwr/server/superlink/ffs/ffs_factory.py +47 -0
  237. flwr/server/superlink/fleet/__init__.py +1 -1
  238. flwr/server/superlink/fleet/grpc_adapter/__init__.py +15 -0
  239. flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +162 -0
  240. flwr/server/superlink/fleet/grpc_bidi/__init__.py +1 -1
  241. flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +4 -2
  242. flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +3 -2
  243. flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +1 -1
  244. flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +5 -154
  245. flwr/server/superlink/fleet/grpc_rere/__init__.py +1 -1
  246. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +120 -13
  247. flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +228 -0
  248. flwr/server/superlink/fleet/message_handler/__init__.py +1 -1
  249. flwr/server/superlink/fleet/message_handler/message_handler.py +156 -13
  250. flwr/server/superlink/fleet/rest_rere/__init__.py +1 -1
  251. flwr/server/superlink/fleet/rest_rere/rest_api.py +119 -81
  252. flwr/server/superlink/fleet/vce/__init__.py +1 -0
  253. flwr/server/superlink/fleet/vce/backend/__init__.py +4 -4
  254. flwr/server/superlink/fleet/vce/backend/backend.py +8 -9
  255. flwr/server/superlink/fleet/vce/backend/raybackend.py +87 -68
  256. flwr/server/superlink/fleet/vce/vce_api.py +208 -146
  257. flwr/server/superlink/linkstate/__init__.py +28 -0
  258. flwr/server/superlink/linkstate/in_memory_linkstate.py +569 -0
  259. flwr/server/superlink/linkstate/linkstate.py +376 -0
  260. flwr/server/superlink/{state/state_factory.py → linkstate/linkstate_factory.py} +19 -10
  261. flwr/server/superlink/linkstate/sqlite_linkstate.py +1196 -0
  262. flwr/server/superlink/linkstate/utils.py +399 -0
  263. flwr/server/superlink/simulation/__init__.py +15 -0
  264. flwr/server/superlink/simulation/simulationio_grpc.py +65 -0
  265. flwr/server/superlink/simulation/simulationio_servicer.py +186 -0
  266. flwr/server/superlink/utils.py +65 -0
  267. flwr/server/typing.py +2 -0
  268. flwr/server/utils/__init__.py +1 -1
  269. flwr/server/utils/tensorboard.py +5 -5
  270. flwr/server/utils/validator.py +40 -45
  271. flwr/server/workflow/default_workflows.py +70 -26
  272. flwr/server/workflow/secure_aggregation/secagg_workflow.py +1 -0
  273. flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +40 -27
  274. flwr/simulation/__init__.py +12 -5
  275. flwr/simulation/app.py +247 -315
  276. flwr/simulation/legacy_app.py +404 -0
  277. flwr/simulation/ray_transport/__init__.py +1 -1
  278. flwr/simulation/ray_transport/ray_actor.py +42 -67
  279. flwr/simulation/ray_transport/ray_client_proxy.py +37 -17
  280. flwr/simulation/ray_transport/utils.py +1 -0
  281. flwr/simulation/run_simulation.py +306 -163
  282. flwr/simulation/simulationio_connection.py +89 -0
  283. flwr/superexec/__init__.py +15 -0
  284. flwr/superexec/app.py +59 -0
  285. flwr/superexec/deployment.py +188 -0
  286. flwr/superexec/exec_grpc.py +80 -0
  287. flwr/superexec/exec_servicer.py +231 -0
  288. flwr/superexec/exec_user_auth_interceptor.py +101 -0
  289. flwr/superexec/executor.py +96 -0
  290. flwr/superexec/simulation.py +124 -0
  291. {flwr_nightly-1.8.0.dev20240315.dist-info → flwr_nightly-1.15.0.dev20250115.dist-info}/METADATA +33 -26
  292. flwr_nightly-1.15.0.dev20250115.dist-info/RECORD +328 -0
  293. flwr_nightly-1.15.0.dev20250115.dist-info/entry_points.txt +12 -0
  294. flwr/cli/flower_toml.py +0 -140
  295. flwr/cli/new/templates/app/flower.toml.tpl +0 -13
  296. flwr/cli/new/templates/app/requirements.numpy.txt.tpl +0 -2
  297. flwr/cli/new/templates/app/requirements.pytorch.txt.tpl +0 -4
  298. flwr/cli/new/templates/app/requirements.tensorflow.txt.tpl +0 -4
  299. flwr/client/node_state.py +0 -48
  300. flwr/client/node_state_tests.py +0 -65
  301. flwr/proto/driver_pb2.py +0 -44
  302. flwr/proto/driver_pb2_grpc.py +0 -169
  303. flwr/proto/driver_pb2_grpc.pyi +0 -66
  304. flwr/server/superlink/driver/driver_grpc.py +0 -54
  305. flwr/server/superlink/driver/driver_servicer.py +0 -129
  306. flwr/server/superlink/state/in_memory_state.py +0 -230
  307. flwr/server/superlink/state/sqlite_state.py +0 -630
  308. flwr/server/superlink/state/state.py +0 -154
  309. flwr_nightly-1.8.0.dev20240315.dist-info/RECORD +0 -211
  310. flwr_nightly-1.8.0.dev20240315.dist-info/entry_points.txt +0 -9
  311. {flwr_nightly-1.8.0.dev20240315.dist-info → flwr_nightly-1.15.0.dev20250115.dist-info}/LICENSE +0 -0
  312. {flwr_nightly-1.8.0.dev20240315.dist-info → flwr_nightly-1.15.0.dev20250115.dist-info}/WHEEL +0 -0
@@ -0,0 +1,108 @@
1
+ # Copyright 2024 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
+ """Disk based Flower File Storage."""
16
+
17
+
18
+ import hashlib
19
+ import json
20
+ from pathlib import Path
21
+ from typing import Optional
22
+
23
+ from flwr.server.superlink.ffs.ffs import Ffs
24
+
25
+
26
+ class DiskFfs(Ffs): # pylint: disable=R0904
27
+ """Disk-based Flower File Storage interface for large objects."""
28
+
29
+ def __init__(self, base_dir: str) -> None:
30
+ """Create a new DiskFfs instance.
31
+
32
+ Parameters
33
+ ----------
34
+ base_dir : str
35
+ The base directory to store the objects.
36
+ """
37
+ self.base_dir = Path(base_dir)
38
+
39
+ def put(self, content: bytes, meta: dict[str, str]) -> str:
40
+ """Store bytes and metadata and return key (hash of content).
41
+
42
+ Parameters
43
+ ----------
44
+ content : bytes
45
+ The content to be stored.
46
+ meta : Dict[str, str]
47
+ The metadata to be stored.
48
+
49
+ Returns
50
+ -------
51
+ key : str
52
+ The key (sha256hex hash) of the content.
53
+ """
54
+ content_hash = hashlib.sha256(content).hexdigest()
55
+
56
+ self.base_dir.mkdir(exist_ok=True, parents=True)
57
+ (self.base_dir / content_hash).write_bytes(content)
58
+ (self.base_dir / f"{content_hash}.META").write_text(json.dumps(meta))
59
+
60
+ return content_hash
61
+
62
+ def get(self, key: str) -> Optional[tuple[bytes, dict[str, str]]]:
63
+ """Return tuple containing the object content and metadata.
64
+
65
+ Parameters
66
+ ----------
67
+ key : str
68
+ The sha256hex hash of the object to be retrieved.
69
+
70
+ Returns
71
+ -------
72
+ Optional[Tuple[bytes, Dict[str, str]]]
73
+ A tuple containing the object content and metadata.
74
+ """
75
+ if not (self.base_dir / key).exists():
76
+ return None
77
+
78
+ content = (self.base_dir / key).read_bytes()
79
+ meta = json.loads((self.base_dir / f"{key}.META").read_text())
80
+
81
+ return content, meta
82
+
83
+ def delete(self, key: str) -> None:
84
+ """Delete object with hash.
85
+
86
+ Parameters
87
+ ----------
88
+ key : str
89
+ The sha256hex hash of the object to be deleted.
90
+ """
91
+ (self.base_dir / key).unlink()
92
+ (self.base_dir / f"{key}.META").unlink()
93
+
94
+ def list(self) -> list[str]:
95
+ """List all keys.
96
+
97
+ Return all available keys in this `Ffs` instance.
98
+ This can be combined with, for example,
99
+ the `delete` method to delete objects.
100
+
101
+ Returns
102
+ -------
103
+ List[str]
104
+ A list of all available keys.
105
+ """
106
+ return [
107
+ item.name for item in self.base_dir.iterdir() if not item.suffix == ".META"
108
+ ]
@@ -0,0 +1,79 @@
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Abstract base class for Flower File Storage interface."""
16
+
17
+
18
+ import abc
19
+ from typing import Optional
20
+
21
+
22
+ class Ffs(abc.ABC): # pylint: disable=R0904
23
+ """Abstract Flower File Storage interface for large objects."""
24
+
25
+ @abc.abstractmethod
26
+ def put(self, content: bytes, meta: dict[str, str]) -> str:
27
+ """Store bytes and metadata and return sha256hex hash of data as str.
28
+
29
+ Parameters
30
+ ----------
31
+ content : bytes
32
+ The content to be stored.
33
+ meta : Dict[str, str]
34
+ The metadata to be stored.
35
+
36
+ Returns
37
+ -------
38
+ key : str
39
+ The key (sha256hex hash) of the content.
40
+ """
41
+
42
+ @abc.abstractmethod
43
+ def get(self, key: str) -> Optional[tuple[bytes, dict[str, str]]]:
44
+ """Return tuple containing the object content and metadata.
45
+
46
+ Parameters
47
+ ----------
48
+ key : str
49
+ The key (sha256hex hash) of the object to be retrieved.
50
+
51
+ Returns
52
+ -------
53
+ Optional[Tuple[bytes, Dict[str, str]]]
54
+ A tuple containing the object content and metadata.
55
+ """
56
+
57
+ @abc.abstractmethod
58
+ def delete(self, key: str) -> None:
59
+ """Delete object with hash.
60
+
61
+ Parameters
62
+ ----------
63
+ key : str
64
+ The key (sha256hex hash) of the object to be deleted.
65
+ """
66
+
67
+ @abc.abstractmethod
68
+ def list(self) -> list[str]:
69
+ """List keys of all stored objects.
70
+
71
+ Return all available keys in this `Ffs` instance.
72
+ This can be combined with, for example,
73
+ the `delete` method to delete objects.
74
+
75
+ Returns
76
+ -------
77
+ List[str]
78
+ A list of all available keys.
79
+ """
@@ -0,0 +1,47 @@
1
+ # Copyright 2024 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
+ """Factory class that creates Ffs instances."""
16
+
17
+
18
+ from logging import DEBUG
19
+ from typing import Optional
20
+
21
+ from flwr.common.logger import log
22
+
23
+ from .disk_ffs import DiskFfs
24
+ from .ffs import Ffs
25
+
26
+
27
+ class FfsFactory:
28
+ """Factory class that creates Ffs instances.
29
+
30
+ Parameters
31
+ ----------
32
+ base_dir : str
33
+ The base directory used by DiskFfs to store objects.
34
+ """
35
+
36
+ def __init__(self, base_dir: str) -> None:
37
+ self.base_dir = base_dir
38
+ self.ffs_instance: Optional[Ffs] = None
39
+
40
+ def ffs(self) -> Ffs:
41
+ """Return a Ffs instance and create it, if necessary."""
42
+ if not self.ffs_instance:
43
+ log(DEBUG, "Initializing DiskFfs")
44
+ self.ffs_instance = DiskFfs(self.base_dir)
45
+
46
+ log(DEBUG, "Using DiskFfs")
47
+ return self.ffs_instance
@@ -1,4 +1,4 @@
1
- # Copyright 2022 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 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 2024 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
+ """Server-side part of the GrpcAdapter transport layer."""
@@ -0,0 +1,162 @@
1
+ # Copyright 2024 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
+ """Fleet API gRPC adapter servicer."""
16
+
17
+
18
+ from logging import DEBUG, INFO
19
+ from typing import Callable, TypeVar
20
+
21
+ import grpc
22
+ from google.protobuf.message import Message as GrpcMessage
23
+
24
+ from flwr.common.constant import (
25
+ GRPC_ADAPTER_METADATA_FLOWER_PACKAGE_NAME_KEY,
26
+ GRPC_ADAPTER_METADATA_FLOWER_PACKAGE_VERSION_KEY,
27
+ GRPC_ADAPTER_METADATA_FLOWER_VERSION_KEY,
28
+ GRPC_ADAPTER_METADATA_MESSAGE_MODULE_KEY,
29
+ GRPC_ADAPTER_METADATA_MESSAGE_QUALNAME_KEY,
30
+ )
31
+ from flwr.common.logger import log
32
+ from flwr.common.version import package_name, package_version
33
+ from flwr.proto import grpcadapter_pb2_grpc # pylint: disable=E0611
34
+ from flwr.proto.fab_pb2 import GetFabRequest, GetFabResponse # pylint: disable=E0611
35
+ from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
36
+ CreateNodeRequest,
37
+ CreateNodeResponse,
38
+ DeleteNodeRequest,
39
+ DeleteNodeResponse,
40
+ PingRequest,
41
+ PingResponse,
42
+ PullTaskInsRequest,
43
+ PullTaskInsResponse,
44
+ PushTaskResRequest,
45
+ PushTaskResResponse,
46
+ )
47
+ from flwr.proto.grpcadapter_pb2 import MessageContainer # pylint: disable=E0611
48
+ from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611
49
+ from flwr.server.superlink.ffs.ffs_factory import FfsFactory
50
+ from flwr.server.superlink.fleet.message_handler import message_handler
51
+ from flwr.server.superlink.linkstate import LinkStateFactory
52
+
53
+ T = TypeVar("T", bound=GrpcMessage)
54
+
55
+
56
+ def _handle(
57
+ msg_container: MessageContainer,
58
+ request_type: type[T],
59
+ handler: Callable[[T], GrpcMessage],
60
+ ) -> MessageContainer:
61
+ req = request_type.FromString(msg_container.grpc_message_content)
62
+ res = handler(req)
63
+ res_cls = res.__class__
64
+ return MessageContainer(
65
+ metadata={
66
+ GRPC_ADAPTER_METADATA_FLOWER_PACKAGE_NAME_KEY: package_name,
67
+ GRPC_ADAPTER_METADATA_FLOWER_PACKAGE_VERSION_KEY: package_version,
68
+ GRPC_ADAPTER_METADATA_FLOWER_VERSION_KEY: package_version,
69
+ GRPC_ADAPTER_METADATA_MESSAGE_MODULE_KEY: res_cls.__module__,
70
+ GRPC_ADAPTER_METADATA_MESSAGE_QUALNAME_KEY: res_cls.__qualname__,
71
+ },
72
+ grpc_message_name=res_cls.__qualname__,
73
+ grpc_message_content=res.SerializeToString(),
74
+ )
75
+
76
+
77
+ class GrpcAdapterServicer(grpcadapter_pb2_grpc.GrpcAdapterServicer):
78
+ """Fleet API via GrpcAdapter servicer."""
79
+
80
+ def __init__(
81
+ self, state_factory: LinkStateFactory, ffs_factory: FfsFactory
82
+ ) -> None:
83
+ self.state_factory = state_factory
84
+ self.ffs_factory = ffs_factory
85
+
86
+ def SendReceive( # pylint: disable=too-many-return-statements
87
+ self, request: MessageContainer, context: grpc.ServicerContext
88
+ ) -> MessageContainer:
89
+ """."""
90
+ log(DEBUG, "GrpcAdapterServicer.SendReceive")
91
+ if request.grpc_message_name == CreateNodeRequest.__qualname__:
92
+ return _handle(request, CreateNodeRequest, self._create_node)
93
+ if request.grpc_message_name == DeleteNodeRequest.__qualname__:
94
+ return _handle(request, DeleteNodeRequest, self._delete_node)
95
+ if request.grpc_message_name == PingRequest.__qualname__:
96
+ return _handle(request, PingRequest, self._ping)
97
+ if request.grpc_message_name == PullTaskInsRequest.__qualname__:
98
+ return _handle(request, PullTaskInsRequest, self._pull_task_ins)
99
+ if request.grpc_message_name == PushTaskResRequest.__qualname__:
100
+ return _handle(request, PushTaskResRequest, self._push_task_res)
101
+ if request.grpc_message_name == GetRunRequest.__qualname__:
102
+ return _handle(request, GetRunRequest, self._get_run)
103
+ if request.grpc_message_name == GetFabRequest.__qualname__:
104
+ return _handle(request, GetFabRequest, self._get_fab)
105
+ raise ValueError(f"Invalid grpc_message_name: {request.grpc_message_name}")
106
+
107
+ def _create_node(self, request: CreateNodeRequest) -> CreateNodeResponse:
108
+ """."""
109
+ log(INFO, "GrpcAdapter.CreateNode")
110
+ return message_handler.create_node(
111
+ request=request,
112
+ state=self.state_factory.state(),
113
+ )
114
+
115
+ def _delete_node(self, request: DeleteNodeRequest) -> DeleteNodeResponse:
116
+ """."""
117
+ log(INFO, "GrpcAdapter.DeleteNode")
118
+ return message_handler.delete_node(
119
+ request=request,
120
+ state=self.state_factory.state(),
121
+ )
122
+
123
+ def _ping(self, request: PingRequest) -> PingResponse:
124
+ """."""
125
+ log(DEBUG, "GrpcAdapter.Ping")
126
+ return message_handler.ping(
127
+ request=request,
128
+ state=self.state_factory.state(),
129
+ )
130
+
131
+ def _pull_task_ins(self, request: PullTaskInsRequest) -> PullTaskInsResponse:
132
+ """Pull TaskIns."""
133
+ log(INFO, "GrpcAdapter.PullTaskIns")
134
+ return message_handler.pull_task_ins(
135
+ request=request,
136
+ state=self.state_factory.state(),
137
+ )
138
+
139
+ def _push_task_res(self, request: PushTaskResRequest) -> PushTaskResResponse:
140
+ """Push TaskRes."""
141
+ log(INFO, "GrpcAdapter.PushTaskRes")
142
+ return message_handler.push_task_res(
143
+ request=request,
144
+ state=self.state_factory.state(),
145
+ )
146
+
147
+ def _get_run(self, request: GetRunRequest) -> GetRunResponse:
148
+ """Get run information."""
149
+ log(INFO, "GrpcAdapter.GetRun")
150
+ return message_handler.get_run(
151
+ request=request,
152
+ state=self.state_factory.state(),
153
+ )
154
+
155
+ def _get_fab(self, request: GetFabRequest) -> GetFabResponse:
156
+ """Get FAB."""
157
+ log(INFO, "GrpcAdapter.GetFab")
158
+ return message_handler.get_fab(
159
+ request=request,
160
+ ffs=self.ffs_factory.ffs(),
161
+ state=self.state_factory.state(),
162
+ )
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 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 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 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.
@@ -18,8 +18,10 @@ Relevant knowledge for reading this modules code:
18
18
  - https://github.com/grpc/grpc/blob/master/doc/statuscodes.md
19
19
  """
20
20
 
21
+
21
22
  import uuid
22
- from typing import Callable, Iterator
23
+ from collections.abc import Iterator
24
+ from typing import Callable
23
25
 
24
26
  import grpc
25
27
  from iterators import TimeoutIterator
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 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.
@@ -15,10 +15,11 @@
15
15
  """Provides class GrpcBridge."""
16
16
 
17
17
 
18
+ from collections.abc import Iterator
18
19
  from dataclasses import dataclass
19
20
  from enum import Enum
20
21
  from threading import Condition
21
- from typing import Iterator, Optional
22
+ from typing import Optional
22
23
 
23
24
  from flwr.proto.transport_pb2 import ( # pylint: disable=E0611
24
25
  ClientMessage,
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 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 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 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.
@@ -15,53 +15,28 @@
15
15
  """Implements utility function to create a gRPC server."""
16
16
 
17
17
 
18
- import concurrent.futures
19
- import sys
20
- from logging import ERROR
21
- from typing import Any, Callable, Optional, Tuple, Union
18
+ from typing import Optional
22
19
 
23
20
  import grpc
24
21
 
25
22
  from flwr.common import GRPC_MAX_MESSAGE_LENGTH
26
- from flwr.common.logger import log
23
+ from flwr.common.grpc import generic_create_grpc_server
27
24
  from flwr.proto.transport_pb2_grpc import ( # pylint: disable=E0611
28
25
  add_FlowerServiceServicer_to_server,
29
26
  )
30
27
  from flwr.server.client_manager import ClientManager
31
- from flwr.server.superlink.driver.driver_servicer import DriverServicer
32
28
  from flwr.server.superlink.fleet.grpc_bidi.flower_service_servicer import (
33
29
  FlowerServiceServicer,
34
30
  )
35
- from flwr.server.superlink.fleet.grpc_rere.fleet_servicer import FleetServicer
36
31
 
37
- INVALID_CERTIFICATES_ERR_MSG = """
38
- When setting any of root_certificate, certificate, or private_key,
39
- all of them need to be set.
40
- """
41
32
 
42
- AddServicerToServerFn = Callable[..., Any]
43
-
44
-
45
- def valid_certificates(certificates: Tuple[bytes, bytes, bytes]) -> bool:
46
- """Validate certificates tuple."""
47
- is_valid = (
48
- all(isinstance(certificate, bytes) for certificate in certificates)
49
- and len(certificates) == 3
50
- )
51
-
52
- if not is_valid:
53
- log(ERROR, INVALID_CERTIFICATES_ERR_MSG)
54
-
55
- return is_valid
56
-
57
-
58
- def start_grpc_server( # pylint: disable=too-many-arguments
33
+ def start_grpc_server( # pylint: disable=too-many-arguments,R0917
59
34
  client_manager: ClientManager,
60
35
  server_address: str,
61
36
  max_concurrent_workers: int = 1000,
62
37
  max_message_length: int = GRPC_MAX_MESSAGE_LENGTH,
63
38
  keepalive_time_ms: int = 210000,
64
- certificates: Optional[Tuple[bytes, bytes, bytes]] = None,
39
+ certificates: Optional[tuple[bytes, bytes, bytes]] = None,
65
40
  ) -> grpc.Server:
66
41
  """Create and start a gRPC server running FlowerServiceServicer.
67
42
 
@@ -149,127 +124,3 @@ def start_grpc_server( # pylint: disable=too-many-arguments
149
124
  server.start()
150
125
 
151
126
  return server
152
-
153
-
154
- def generic_create_grpc_server( # pylint: disable=too-many-arguments
155
- servicer_and_add_fn: Union[
156
- Tuple[FleetServicer, AddServicerToServerFn],
157
- Tuple[FlowerServiceServicer, AddServicerToServerFn],
158
- Tuple[DriverServicer, AddServicerToServerFn],
159
- ],
160
- server_address: str,
161
- max_concurrent_workers: int = 1000,
162
- max_message_length: int = GRPC_MAX_MESSAGE_LENGTH,
163
- keepalive_time_ms: int = 210000,
164
- certificates: Optional[Tuple[bytes, bytes, bytes]] = None,
165
- ) -> grpc.Server:
166
- """Create a gRPC server with a single servicer.
167
-
168
- Parameters
169
- ----------
170
- servicer_and_add_fn : Tuple
171
- A tuple holding a servicer implementation and a matching
172
- add_Servicer_to_server function.
173
- server_address : str
174
- Server address in the form of HOST:PORT e.g. "[::]:8080"
175
- max_concurrent_workers : int
176
- Maximum number of clients the server can process before returning
177
- RESOURCE_EXHAUSTED status (default: 1000)
178
- max_message_length : int
179
- Maximum message length that the server can send or receive.
180
- Int valued in bytes. -1 means unlimited. (default: GRPC_MAX_MESSAGE_LENGTH)
181
- keepalive_time_ms : int
182
- Flower uses a default gRPC keepalive time of 210000ms (3 minutes 30 seconds)
183
- because some cloud providers (for example, Azure) agressively clean up idle
184
- TCP connections by terminating them after some time (4 minutes in the case
185
- of Azure). Flower does not use application-level keepalive signals and relies
186
- on the assumption that the transport layer will fail in cases where the
187
- connection is no longer active. `keepalive_time_ms` can be used to customize
188
- the keepalive interval for specific environments. The default Flower gRPC
189
- keepalive of 210000 ms (3 minutes 30 seconds) ensures that Flower can keep
190
- the long running streaming connection alive in most environments. The actual
191
- gRPC default of this setting is 7200000 (2 hours), which results in dropped
192
- connections in some cloud environments.
193
-
194
- These settings are related to the issue described here:
195
- - https://github.com/grpc/proposal/blob/master/A8-client-side-keepalive.md
196
- - https://github.com/grpc/grpc/blob/master/doc/keepalive.md
197
- - https://grpc.io/docs/guides/performance/
198
-
199
- Mobile Flower clients may choose to increase this value if their server
200
- environment allows long-running idle TCP connections.
201
- (default: 210000)
202
- certificates : Tuple[bytes, bytes, bytes] (default: None)
203
- Tuple containing root certificate, server certificate, and private key to
204
- start a secure SSL-enabled server. The tuple is expected to have three bytes
205
- elements in the following order:
206
-
207
- * CA certificate.
208
- * server certificate.
209
- * server private key.
210
-
211
- Returns
212
- -------
213
- server : grpc.Server
214
- A non-running instance of a gRPC server.
215
- """
216
- # Deconstruct tuple into servicer and function
217
- servicer, add_servicer_to_server_fn = servicer_and_add_fn
218
-
219
- # Possible options:
220
- # https://github.com/grpc/grpc/blob/v1.43.x/include/grpc/impl/codegen/grpc_types.h
221
- options = [
222
- # Maximum number of concurrent incoming streams to allow on a http2
223
- # connection. Int valued.
224
- ("grpc.max_concurrent_streams", max(100, max_concurrent_workers)),
225
- # Maximum message length that the channel can send.
226
- # Int valued, bytes. -1 means unlimited.
227
- ("grpc.max_send_message_length", max_message_length),
228
- # Maximum message length that the channel can receive.
229
- # Int valued, bytes. -1 means unlimited.
230
- ("grpc.max_receive_message_length", max_message_length),
231
- # The gRPC default for this setting is 7200000 (2 hours). Flower uses a
232
- # customized default of 210000 (3 minutes and 30 seconds) to improve
233
- # compatibility with popular cloud providers. Mobile Flower clients may
234
- # choose to increase this value if their server environment allows
235
- # long-running idle TCP connections.
236
- ("grpc.keepalive_time_ms", keepalive_time_ms),
237
- # Setting this to zero will allow sending unlimited keepalive pings in between
238
- # sending actual data frames.
239
- ("grpc.http2.max_pings_without_data", 0),
240
- # Is it permissible to send keepalive pings from the client without
241
- # any outstanding streams. More explanation here:
242
- # https://github.com/adap/flower/pull/2197
243
- ("grpc.keepalive_permit_without_calls", 0),
244
- ]
245
-
246
- server = grpc.server(
247
- concurrent.futures.ThreadPoolExecutor(max_workers=max_concurrent_workers),
248
- # Set the maximum number of concurrent RPCs this server will service before
249
- # returning RESOURCE_EXHAUSTED status, or None to indicate no limit.
250
- maximum_concurrent_rpcs=max_concurrent_workers,
251
- options=options,
252
- )
253
- add_servicer_to_server_fn(servicer, server)
254
-
255
- if certificates is not None:
256
- if not valid_certificates(certificates):
257
- sys.exit(1)
258
-
259
- root_certificate_b, certificate_b, private_key_b = certificates
260
-
261
- server_credentials = grpc.ssl_server_credentials(
262
- ((private_key_b, certificate_b),),
263
- root_certificates=root_certificate_b,
264
- # A boolean indicating whether or not to require clients to be
265
- # authenticated. May only be True if root_certificates is not None.
266
- # We are explicitly setting the current gRPC default to document
267
- # the option. For further reference see:
268
- # https://grpc.github.io/grpc/python/grpc.html#create-server-credentials
269
- require_client_auth=False,
270
- )
271
- server.add_secure_port(server_address, server_credentials)
272
- else:
273
- server.add_insecure_port(server_address)
274
-
275
- return server
@@ -1,4 +1,4 @@
1
- # Copyright 2020 Flower Labs GmbH. All Rights Reserved.
1
+ # Copyright 2024 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.