flwr 1.19.0__py3-none-any.whl → 1.21.0__py3-none-any.whl

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 (167) hide show
  1. flwr/__init__.py +4 -1
  2. flwr/app/__init__.py +28 -0
  3. flwr/app/exception.py +31 -0
  4. flwr/cli/auth_plugin/oidc_cli_plugin.py +4 -4
  5. flwr/cli/build.py +15 -5
  6. flwr/cli/cli_user_auth_interceptor.py +1 -1
  7. flwr/cli/config_utils.py +3 -3
  8. flwr/cli/constant.py +25 -8
  9. flwr/cli/log.py +9 -9
  10. flwr/cli/login/login.py +3 -3
  11. flwr/cli/ls.py +5 -5
  12. flwr/cli/new/new.py +23 -4
  13. flwr/cli/new/templates/app/README.flowertune.md.tpl +2 -0
  14. flwr/cli/new/templates/app/README.md.tpl +5 -0
  15. flwr/cli/new/templates/app/code/__init__.pytorch_msg_api.py.tpl +1 -0
  16. flwr/cli/new/templates/app/code/client.pytorch_msg_api.py.tpl +80 -0
  17. flwr/cli/new/templates/app/code/server.pytorch_msg_api.py.tpl +41 -0
  18. flwr/cli/new/templates/app/code/task.pytorch_msg_api.py.tpl +98 -0
  19. flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +14 -3
  20. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +13 -1
  21. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +21 -2
  22. flwr/cli/new/templates/app/pyproject.jax.toml.tpl +18 -1
  23. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +19 -2
  24. flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +18 -1
  25. flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +20 -3
  26. flwr/cli/new/templates/app/pyproject.pytorch_msg_api.toml.tpl +53 -0
  27. flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +18 -1
  28. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +18 -1
  29. flwr/cli/run/run.py +53 -50
  30. flwr/cli/stop.py +7 -4
  31. flwr/cli/utils.py +29 -11
  32. flwr/client/grpc_adapter_client/connection.py +11 -4
  33. flwr/client/grpc_rere_client/connection.py +93 -129
  34. flwr/client/rest_client/connection.py +134 -164
  35. flwr/clientapp/__init__.py +10 -0
  36. flwr/clientapp/mod/__init__.py +26 -0
  37. flwr/clientapp/mod/centraldp_mods.py +132 -0
  38. flwr/common/args.py +20 -6
  39. flwr/common/auth_plugin/__init__.py +4 -4
  40. flwr/common/auth_plugin/auth_plugin.py +7 -7
  41. flwr/common/constant.py +26 -5
  42. flwr/common/event_log_plugin/event_log_plugin.py +1 -1
  43. flwr/common/exit/__init__.py +4 -0
  44. flwr/common/exit/exit.py +8 -1
  45. flwr/common/exit/exit_code.py +42 -8
  46. flwr/common/exit/exit_handler.py +62 -0
  47. flwr/common/{exit_handlers.py → exit/signal_handler.py} +20 -37
  48. flwr/common/grpc.py +1 -1
  49. flwr/common/{inflatable_grpc_utils.py → inflatable_protobuf_utils.py} +52 -10
  50. flwr/common/inflatable_utils.py +191 -24
  51. flwr/common/logger.py +1 -1
  52. flwr/common/record/array.py +101 -22
  53. flwr/common/record/arraychunk.py +59 -0
  54. flwr/common/retry_invoker.py +30 -11
  55. flwr/common/serde.py +0 -28
  56. flwr/common/telemetry.py +4 -0
  57. flwr/compat/client/app.py +14 -31
  58. flwr/compat/server/app.py +2 -2
  59. flwr/proto/appio_pb2.py +51 -0
  60. flwr/proto/appio_pb2.pyi +195 -0
  61. flwr/proto/appio_pb2_grpc.py +4 -0
  62. flwr/proto/appio_pb2_grpc.pyi +4 -0
  63. flwr/proto/clientappio_pb2.py +4 -19
  64. flwr/proto/clientappio_pb2.pyi +0 -125
  65. flwr/proto/clientappio_pb2_grpc.py +269 -29
  66. flwr/proto/clientappio_pb2_grpc.pyi +114 -21
  67. flwr/proto/control_pb2.py +62 -0
  68. flwr/proto/{exec_pb2_grpc.py → control_pb2_grpc.py} +54 -54
  69. flwr/proto/{exec_pb2_grpc.pyi → control_pb2_grpc.pyi} +28 -28
  70. flwr/proto/fleet_pb2.py +12 -20
  71. flwr/proto/fleet_pb2.pyi +6 -36
  72. flwr/proto/serverappio_pb2.py +8 -31
  73. flwr/proto/serverappio_pb2.pyi +0 -152
  74. flwr/proto/serverappio_pb2_grpc.py +107 -38
  75. flwr/proto/serverappio_pb2_grpc.pyi +47 -20
  76. flwr/proto/simulationio_pb2.py +4 -11
  77. flwr/proto/simulationio_pb2.pyi +0 -58
  78. flwr/proto/simulationio_pb2_grpc.py +129 -27
  79. flwr/proto/simulationio_pb2_grpc.pyi +52 -13
  80. flwr/server/app.py +130 -153
  81. flwr/server/fleet_event_log_interceptor.py +4 -0
  82. flwr/server/grid/grpc_grid.py +94 -54
  83. flwr/server/grid/inmemory_grid.py +1 -0
  84. flwr/server/serverapp/app.py +165 -144
  85. flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +8 -0
  86. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +1 -1
  87. flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +2 -5
  88. flwr/server/superlink/fleet/message_handler/message_handler.py +10 -16
  89. flwr/server/superlink/fleet/rest_rere/rest_api.py +1 -2
  90. flwr/server/superlink/fleet/vce/backend/raybackend.py +3 -1
  91. flwr/server/superlink/fleet/vce/vce_api.py +6 -6
  92. flwr/server/superlink/linkstate/in_memory_linkstate.py +34 -0
  93. flwr/server/superlink/linkstate/linkstate.py +2 -1
  94. flwr/server/superlink/linkstate/sqlite_linkstate.py +45 -0
  95. flwr/server/superlink/serverappio/serverappio_grpc.py +2 -2
  96. flwr/server/superlink/serverappio/serverappio_servicer.py +95 -48
  97. flwr/server/superlink/simulation/simulationio_grpc.py +1 -1
  98. flwr/server/superlink/simulation/simulationio_servicer.py +98 -22
  99. flwr/server/superlink/utils.py +0 -35
  100. flwr/serverapp/__init__.py +12 -0
  101. flwr/serverapp/dp_fixed_clipping.py +352 -0
  102. flwr/serverapp/exception.py +38 -0
  103. flwr/serverapp/strategy/__init__.py +38 -0
  104. flwr/serverapp/strategy/dp_fixed_clipping.py +352 -0
  105. flwr/serverapp/strategy/fedadagrad.py +162 -0
  106. flwr/serverapp/strategy/fedadam.py +181 -0
  107. flwr/serverapp/strategy/fedavg.py +295 -0
  108. flwr/serverapp/strategy/fedopt.py +218 -0
  109. flwr/serverapp/strategy/fedyogi.py +173 -0
  110. flwr/serverapp/strategy/result.py +105 -0
  111. flwr/serverapp/strategy/strategy.py +285 -0
  112. flwr/serverapp/strategy/strategy_utils.py +251 -0
  113. flwr/serverapp/strategy/strategy_utils_tests.py +304 -0
  114. flwr/simulation/app.py +159 -154
  115. flwr/simulation/run_simulation.py +17 -0
  116. flwr/supercore/app_utils.py +58 -0
  117. flwr/supercore/cli/__init__.py +22 -0
  118. flwr/supercore/cli/flower_superexec.py +141 -0
  119. flwr/supercore/corestate/__init__.py +22 -0
  120. flwr/supercore/corestate/corestate.py +81 -0
  121. flwr/{server/superlink → supercore}/ffs/disk_ffs.py +1 -1
  122. flwr/supercore/grpc_health/__init__.py +25 -0
  123. flwr/supercore/grpc_health/health_server.py +53 -0
  124. flwr/supercore/grpc_health/simple_health_servicer.py +38 -0
  125. flwr/supercore/license_plugin/__init__.py +22 -0
  126. flwr/supercore/license_plugin/license_plugin.py +26 -0
  127. flwr/supercore/object_store/in_memory_object_store.py +31 -31
  128. flwr/supercore/object_store/object_store.py +20 -42
  129. flwr/supercore/object_store/utils.py +43 -0
  130. flwr/{superexec → supercore/superexec}/__init__.py +1 -1
  131. flwr/supercore/superexec/plugin/__init__.py +28 -0
  132. flwr/supercore/superexec/plugin/base_exec_plugin.py +53 -0
  133. flwr/supercore/superexec/plugin/clientapp_exec_plugin.py +28 -0
  134. flwr/supercore/superexec/plugin/exec_plugin.py +71 -0
  135. flwr/supercore/superexec/plugin/serverapp_exec_plugin.py +28 -0
  136. flwr/supercore/superexec/plugin/simulation_exec_plugin.py +28 -0
  137. flwr/supercore/superexec/run_superexec.py +185 -0
  138. flwr/supercore/utils.py +32 -0
  139. flwr/superlink/servicer/__init__.py +15 -0
  140. flwr/superlink/servicer/control/__init__.py +22 -0
  141. flwr/{superexec/exec_event_log_interceptor.py → superlink/servicer/control/control_event_log_interceptor.py} +9 -5
  142. flwr/{superexec/exec_grpc.py → superlink/servicer/control/control_grpc.py} +39 -28
  143. flwr/superlink/servicer/control/control_license_interceptor.py +82 -0
  144. flwr/{superexec/exec_servicer.py → superlink/servicer/control/control_servicer.py} +79 -31
  145. flwr/{superexec/exec_user_auth_interceptor.py → superlink/servicer/control/control_user_auth_interceptor.py} +18 -10
  146. flwr/supernode/cli/flower_supernode.py +3 -7
  147. flwr/supernode/cli/flwr_clientapp.py +20 -16
  148. flwr/supernode/nodestate/in_memory_nodestate.py +13 -4
  149. flwr/supernode/nodestate/nodestate.py +3 -44
  150. flwr/supernode/runtime/run_clientapp.py +129 -115
  151. flwr/supernode/servicer/clientappio/__init__.py +1 -3
  152. flwr/supernode/servicer/clientappio/clientappio_servicer.py +217 -165
  153. flwr/supernode/start_client_internal.py +205 -148
  154. {flwr-1.19.0.dist-info → flwr-1.21.0.dist-info}/METADATA +5 -3
  155. {flwr-1.19.0.dist-info → flwr-1.21.0.dist-info}/RECORD +161 -117
  156. {flwr-1.19.0.dist-info → flwr-1.21.0.dist-info}/entry_points.txt +1 -0
  157. flwr/common/inflatable_rest_utils.py +0 -99
  158. flwr/proto/exec_pb2.py +0 -62
  159. flwr/superexec/app.py +0 -45
  160. flwr/superexec/deployment.py +0 -192
  161. flwr/superexec/executor.py +0 -100
  162. flwr/superexec/simulation.py +0 -130
  163. /flwr/proto/{exec_pb2.pyi → control_pb2.pyi} +0 -0
  164. /flwr/{server/superlink → supercore}/ffs/__init__.py +0 -0
  165. /flwr/{server/superlink → supercore}/ffs/ffs.py +0 -0
  166. /flwr/{server/superlink → supercore}/ffs/ffs_factory.py +0 -0
  167. {flwr-1.19.0.dist-info → flwr-1.21.0.dist-info}/WHEEL +0 -0
@@ -16,9 +16,6 @@
16
16
 
17
17
 
18
18
  import gc
19
- import os
20
- import threading
21
- import time
22
19
  from logging import DEBUG, ERROR, INFO
23
20
  from typing import Optional
24
21
 
@@ -32,34 +29,46 @@ from flwr.common import Context, Message
32
29
  from flwr.common.config import get_flwr_dir
33
30
  from flwr.common.constant import ErrorCode
34
31
  from flwr.common.grpc import create_channel, on_channel_state_change
32
+ from flwr.common.inflatable import (
33
+ get_all_nested_objects,
34
+ get_object_tree,
35
+ no_object_id_recompute,
36
+ )
37
+ from flwr.common.inflatable_protobuf_utils import (
38
+ make_confirm_message_received_fn_protobuf,
39
+ make_pull_object_fn_protobuf,
40
+ make_push_object_fn_protobuf,
41
+ )
42
+ from flwr.common.inflatable_utils import pull_and_inflate_object_from_tree, push_objects
35
43
  from flwr.common.logger import log
44
+ from flwr.common.message import remove_content_from_message
36
45
  from flwr.common.retry_invoker import _make_simple_grpc_retry_invoker, _wrap_stub
37
46
  from flwr.common.serde import (
38
47
  context_from_proto,
39
48
  context_to_proto,
40
49
  fab_from_proto,
41
- message_from_proto,
42
50
  message_to_proto,
43
51
  run_from_proto,
44
52
  )
45
53
  from flwr.common.typing import Fab, Run
46
-
47
- # pylint: disable=E0611
48
- from flwr.proto.clientappio_pb2 import (
49
- GetTokenRequest,
50
- GetTokenResponse,
51
- PullClientAppInputsRequest,
52
- PullClientAppInputsResponse,
53
- PushClientAppOutputsRequest,
54
- PushClientAppOutputsResponse,
54
+ from flwr.proto.appio_pb2 import ( # pylint: disable=E0611
55
+ PullAppInputsRequest,
56
+ PullAppInputsResponse,
57
+ PullAppMessagesRequest,
58
+ PullAppMessagesResponse,
59
+ PushAppMessagesRequest,
60
+ PushAppOutputsRequest,
61
+ PushAppOutputsResponse,
55
62
  )
56
63
  from flwr.proto.clientappio_pb2_grpc import ClientAppIoStub
64
+ from flwr.proto.node_pb2 import Node # pylint: disable=E0611
65
+ from flwr.supercore.app_utils import start_parent_process_monitor
66
+ from flwr.supercore.utils import mask_string
57
67
 
58
68
 
59
69
  def run_clientapp( # pylint: disable=R0913, R0914, R0917
60
70
  clientappio_api_address: str,
61
- run_once: bool,
62
- token: Optional[int] = None,
71
+ token: str,
63
72
  flwr_dir: Optional[str] = None,
64
73
  certificates: Optional[bytes] = None,
65
74
  parent_pid: Optional[int] = None,
@@ -82,124 +91,95 @@ def run_clientapp( # pylint: disable=R0913, R0914, R0917
82
91
  stub = ClientAppIoStub(channel)
83
92
  _wrap_stub(stub, _make_simple_grpc_retry_invoker())
84
93
 
85
- while True:
86
- # If token is not set, loop until token is received from SuperNode
87
- while token is None:
88
- token = get_token(stub)
89
- time.sleep(1)
90
-
91
- # Pull Message, Context, Run and (optional) FAB from SuperNode
92
- message, context, run, fab = pull_clientappinputs(stub=stub, token=token)
93
-
94
- # Install FAB, if provided
95
- if fab:
96
- log(DEBUG, "[flwr-clientapp] Start FAB installation.")
97
- install_from_fab(fab.content, flwr_dir=flwr_dir_, skip_prompt=True)
98
-
99
- load_client_app_fn = get_load_client_app_fn(
100
- default_app_ref="",
101
- app_path=None,
102
- multi_app=True,
103
- flwr_dir=str(flwr_dir_),
104
- )
94
+ # Pull Message, Context, Run and (optional) FAB from SuperNode
95
+ message, context, run, fab = pull_clientappinputs(stub=stub, token=token)
105
96
 
106
- try:
107
- # Load ClientApp
108
- log(DEBUG, "[flwr-clientapp] Start `ClientApp` Loading.")
109
- client_app: ClientApp = load_client_app_fn(
110
- run.fab_id, run.fab_version, fab.hash_str if fab else ""
111
- )
97
+ # Install FAB, if provided
98
+ if fab:
99
+ log(DEBUG, "[flwr-clientapp] Start FAB installation.")
100
+ install_from_fab(fab.content, flwr_dir=flwr_dir_, skip_prompt=True)
112
101
 
113
- # Execute ClientApp
114
- reply_message = client_app(message=message, context=context)
102
+ load_client_app_fn = get_load_client_app_fn(
103
+ default_app_ref="",
104
+ app_path=None,
105
+ multi_app=True,
106
+ flwr_dir=str(flwr_dir_),
107
+ )
115
108
 
116
- except Exception as ex: # pylint: disable=broad-exception-caught
117
- # Don't update/change NodeState
109
+ try:
110
+ # Load ClientApp
111
+ log(DEBUG, "[flwr-clientapp] Start `ClientApp` Loading.")
112
+ client_app: ClientApp = load_client_app_fn(
113
+ run.fab_id, run.fab_version, fab.hash_str if fab else ""
114
+ )
118
115
 
119
- e_code = ErrorCode.CLIENT_APP_RAISED_EXCEPTION
120
- # Ex fmt: "<class 'ZeroDivisionError'>:<'division by zero'>"
121
- reason = str(type(ex)) + ":<'" + str(ex) + "'>"
122
- exc_entity = "ClientApp"
123
- if isinstance(ex, LoadClientAppError):
124
- reason = (
125
- "An exception was raised when attempting to load `ClientApp`"
126
- )
127
- e_code = ErrorCode.LOAD_CLIENT_APP_EXCEPTION
116
+ # Execute ClientApp
117
+ reply_message = client_app(message=message, context=context)
128
118
 
129
- log(ERROR, "%s raised an exception", exc_entity, exc_info=ex)
119
+ except Exception as ex: # pylint: disable=broad-exception-caught
120
+ # Don't update/change NodeState
130
121
 
131
- # Create error message
132
- reply_message = Message(
133
- Error(code=e_code, reason=reason), reply_to=message
134
- )
122
+ e_code = ErrorCode.CLIENT_APP_RAISED_EXCEPTION
123
+ # Ex fmt: "<class 'ZeroDivisionError'>:<'division by zero'>"
124
+ reason = str(type(ex)) + ":<'" + str(ex) + "'>"
125
+ exc_entity = "ClientApp"
126
+ if isinstance(ex, LoadClientAppError):
127
+ reason = "An exception was raised when attempting to load `ClientApp`"
128
+ e_code = ErrorCode.LOAD_CLIENT_APP_EXCEPTION
135
129
 
136
- # Push Message and Context to SuperNode
137
- _ = push_clientappoutputs(
138
- stub=stub, token=token, message=reply_message, context=context
139
- )
130
+ log(ERROR, "%s raised an exception", exc_entity, exc_info=ex)
140
131
 
141
- del client_app, message, context, run, fab, reply_message
142
- gc.collect()
132
+ # Create error message
133
+ reply_message = Message(Error(code=e_code, reason=reason), reply_to=message)
143
134
 
144
- # Reset token to `None` to prevent flwr-clientapp from trying to pull the
145
- # same inputs again
146
- token = None
135
+ # Push Message and Context to SuperNode
136
+ _ = push_clientappoutputs(
137
+ stub=stub, token=token, message=reply_message, context=context
138
+ )
147
139
 
148
- # Stop the loop if `flwr-clientapp` is expected to process only a single
149
- # message
150
- if run_once:
151
- break
140
+ del client_app, message, context, run, fab, reply_message
141
+ gc.collect()
152
142
 
153
- except KeyboardInterrupt:
154
- log(INFO, "Closing connection")
155
143
  except grpc.RpcError as e:
156
144
  log(ERROR, "GRPC error occurred: %s", str(e))
157
145
  finally:
158
146
  channel.close()
159
147
 
160
148
 
161
- def start_parent_process_monitor(
162
- parent_pid: int,
163
- ) -> None:
164
- """Monitor the parent process and exit if it terminates."""
165
-
166
- def monitor() -> None:
167
- while True:
168
- time.sleep(0.2)
169
- if os.getppid() != parent_pid:
170
- os.kill(os.getpid(), 9)
171
-
172
- threading.Thread(target=monitor, daemon=True).start()
173
-
174
-
175
- def get_token(stub: grpc.Channel) -> Optional[int]:
176
- """Get a token from SuperNode."""
177
- log(DEBUG, "[flwr-clientapp] Request token")
178
- try:
179
- res: GetTokenResponse = stub.GetToken(GetTokenRequest())
180
- log(DEBUG, "[GetToken] Received token: %s", res.token)
181
- return res.token
182
- except grpc.RpcError as e:
183
- if e.code() == grpc.StatusCode.FAILED_PRECONDITION: # pylint: disable=no-member
184
- log(DEBUG, "[GetToken] No token available yet")
185
- else:
186
- log(ERROR, "[GetToken] gRPC error occurred: %s", str(e))
187
- return None
188
-
189
-
190
149
  def pull_clientappinputs(
191
- stub: grpc.Channel, token: int
150
+ stub: ClientAppIoStub, token: str
192
151
  ) -> tuple[Message, Context, Run, Optional[Fab]]:
193
152
  """Pull ClientAppInputs from SuperNode."""
194
- log(INFO, "[flwr-clientapp] Pull `ClientAppInputs` for token %s", token)
153
+ masked_token = mask_string(token)
154
+ log(INFO, "[flwr-clientapp] Pull `ClientAppInputs` for token %s", masked_token)
195
155
  try:
196
- res: PullClientAppInputsResponse = stub.PullClientAppInputs(
197
- PullClientAppInputsRequest(token=token)
156
+ # Pull Context, Run and (optional) FAB
157
+ res: PullAppInputsResponse = stub.PullClientAppInputs(
158
+ PullAppInputsRequest(token=token)
198
159
  )
199
- message = message_from_proto(res.message)
200
160
  context = context_from_proto(res.context)
201
161
  run = run_from_proto(res.run)
202
162
  fab = fab_from_proto(res.fab) if res.fab else None
163
+
164
+ # Pull and inflate the message
165
+ pull_msg_res: PullAppMessagesResponse = stub.PullMessage(
166
+ PullAppMessagesRequest(token=token)
167
+ )
168
+ run_id = context.run_id
169
+ node = Node(node_id=context.node_id)
170
+ object_tree = pull_msg_res.message_object_trees[0]
171
+ message = pull_and_inflate_object_from_tree(
172
+ object_tree,
173
+ make_pull_object_fn_protobuf(stub.PullObject, node, run_id),
174
+ make_confirm_message_received_fn_protobuf(
175
+ stub.ConfirmMessageReceived, node, run_id
176
+ ),
177
+ return_type=Message,
178
+ )
179
+
180
+ # Set the message ID
181
+ # The deflated message doesn't contain the message_id (its own object_id)
182
+ message.metadata.__dict__["_message_id"] = object_tree.object_id
203
183
  return message, context, run, fab
204
184
  except grpc.RpcError as e:
205
185
  log(ERROR, "[PullClientAppInputs] gRPC error occurred: %s", str(e))
@@ -207,18 +187,52 @@ def pull_clientappinputs(
207
187
 
208
188
 
209
189
  def push_clientappoutputs(
210
- stub: grpc.Channel, token: int, message: Message, context: Context
211
- ) -> PushClientAppOutputsResponse:
190
+ stub: ClientAppIoStub, token: str, message: Message, context: Context
191
+ ) -> PushAppOutputsResponse:
212
192
  """Push ClientAppOutputs to SuperNode."""
213
- log(INFO, "[flwr-clientapp] Push `ClientAppOutputs` for token %s", token)
214
- proto_message = message_to_proto(message)
193
+ masked_token = mask_string(token)
194
+ log(INFO, "[flwr-clientapp] Push `ClientAppOutputs` for token %s", masked_token)
195
+ # Set message ID
196
+ message.metadata.__dict__["_message_id"] = message.object_id
197
+ proto_message = message_to_proto(remove_content_from_message(message))
215
198
  proto_context = context_to_proto(context)
216
199
 
217
200
  try:
218
- res: PushClientAppOutputsResponse = stub.PushClientAppOutputs(
219
- PushClientAppOutputsRequest(
220
- token=token, message=proto_message, context=proto_context
201
+
202
+ with no_object_id_recompute():
203
+ # Get object tree and all objects to push
204
+ object_tree = get_object_tree(message)
205
+
206
+ # Push Message
207
+ # This is temporary. The message should not contain its content
208
+ push_msg_res = stub.PushMessage(
209
+ PushAppMessagesRequest(
210
+ token=token,
211
+ messages_list=[proto_message],
212
+ message_object_trees=[object_tree],
213
+ )
214
+ )
215
+ del proto_message
216
+
217
+ # Retrieve the object IDs to push
218
+ object_ids_to_push = set(push_msg_res.objects_to_push)
219
+
220
+ # Push all objects
221
+ all_objects = get_all_nested_objects(message)
222
+ del message
223
+ push_objects(
224
+ all_objects,
225
+ make_push_object_fn_protobuf(
226
+ stub.PushObject,
227
+ Node(node_id=context.node_id),
228
+ run_id=context.run_id,
229
+ ),
230
+ object_ids_to_push=object_ids_to_push,
221
231
  )
232
+
233
+ # Push Context
234
+ res: PushAppOutputsResponse = stub.PushClientAppOutputs(
235
+ PushAppOutputsRequest(token=token, context=proto_context)
222
236
  )
223
237
  return res
224
238
  except grpc.RpcError as e:
@@ -15,10 +15,8 @@
15
15
  """ClientAppIo API Servicer."""
16
16
 
17
17
 
18
- from .clientappio_servicer import ClientAppInputs, ClientAppIoServicer, ClientAppOutputs
18
+ from .clientappio_servicer import ClientAppIoServicer
19
19
 
20
20
  __all__ = [
21
- "ClientAppInputs",
22
21
  "ClientAppIoServicer",
23
- "ClientAppOutputs",
24
22
  ]