oocana 0.16.9__py3-none-any.whl → 0.16.11__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.
oocana/context.py CHANGED
@@ -11,8 +11,33 @@ from .preview import PreviewPayload, TablePreviewData, DataFrame, ShapeDataFrame
11
11
  from .data import EXECUTOR_NAME
12
12
  import os.path
13
13
  import logging
14
+ import copy
14
15
 
15
- __all__ = ["Context"]
16
+ __all__ = ["Context", "HandleDefDict"]
17
+
18
+ class HandleDefDict(TypedDict):
19
+ """a dict that represents the handle definition, used in the block schema output and input defs.
20
+ """
21
+
22
+ handle: str
23
+ """the handle of the output, should be defined in the block schema output defs, the field name is handle
24
+ """
25
+
26
+ description: str | None
27
+ """the description of the output, should be defined in the block schema output defs, the field name is description
28
+ """
29
+
30
+ json_schema: Dict[str, Any] | None
31
+ """the schema of the output, should be defined in the block schema output defs, the field name is json_schema
32
+ """
33
+
34
+ kind: str | None
35
+ """the kind of the output, should be defined in the block schema output defs, the field name is kind
36
+ """
37
+
38
+ nullable: bool
39
+ """if the output can be None, should be defined in the block schema output defs, the field name is nullable
40
+ """
16
41
 
17
42
  class OnlyEqualSelf:
18
43
  def __eq__(self, value: object) -> bool:
@@ -35,8 +60,8 @@ class Context:
35
60
 
36
61
  __block_info: BlockInfo
37
62
  __outputs_def: Dict[str, HandleDef]
63
+ __inputs_def: Dict[str, Any]
38
64
  __store: Any
39
- __is_done: bool = False
40
65
  __keep_alive: OnlyEqualSelf = OnlyEqualSelf()
41
66
  __session_dir: str
42
67
  __tmp_dir: str
@@ -45,7 +70,7 @@ class Context:
45
70
  __pkg_dir: str
46
71
 
47
72
  def __init__(
48
- self, inputs: Dict[str, Any], blockInfo: BlockInfo, mainframe: Mainframe, store, outputs, session_dir: str, tmp_dir: str, package_name: str, pkg_dir: str
73
+ self, *, inputs: Dict[str, Any], blockInfo: BlockInfo, mainframe: Mainframe, store, inputs_def, outputs_def, session_dir: str, tmp_dir: str, package_name: str, pkg_dir: str
49
74
  ) -> None:
50
75
 
51
76
  self.__block_info = blockInfo
@@ -55,10 +80,11 @@ class Context:
55
80
  self.__inputs = inputs
56
81
 
57
82
  outputs_defs = {}
58
- if outputs is not None:
59
- for k, v in outputs.items():
83
+ if outputs_def is not None:
84
+ for k, v in outputs_def.items():
60
85
  outputs_defs[k] = HandleDef(**v)
61
86
  self.__outputs_def = outputs_defs
87
+ self.__inputs_def = inputs_def
62
88
  self.__session_dir = session_dir
63
89
  self.__tmp_dir = tmp_dir
64
90
  self.__package_name = package_name
@@ -105,6 +131,17 @@ class Context:
105
131
  @property
106
132
  def inputs(self):
107
133
  return self.__inputs
134
+
135
+ @property
136
+ def inputs_def(self) -> Dict[str, HandleDefDict]:
137
+ return copy.deepcopy(self.__inputs_def) if self.__inputs_def is not None else {}
138
+
139
+ @property
140
+ def outputs_def(self) -> Dict[str, HandleDefDict]:
141
+ outputs = {}
142
+ for k, v in self.__outputs_def.items():
143
+ outputs[k] = asdict(v)
144
+ return outputs
108
145
 
109
146
  @property
110
147
  def session_id(self):
@@ -156,10 +193,6 @@ class Context:
156
193
  """
157
194
  return os.getenv("OO_HOST_ENDPOINT", None)
158
195
 
159
- @property
160
- def is_done(self) -> bool:
161
- return self.__is_done
162
-
163
196
  def __store_ref(self, handle: str):
164
197
  return StoreKey(
165
198
  executor=EXECUTOR_NAME,
@@ -170,8 +203,67 @@ class Context:
170
203
 
171
204
  def __is_basic_type(self, value: Any) -> bool:
172
205
  return isinstance(value, (int, float, str, bool))
206
+
207
+ def __wrap_output_value(self, handle: str, value: Any):
208
+ """
209
+ wrap the output value:
210
+ if the value is a var handle, store it in the store and return the reference.
211
+ if the value is a bin handle, store it in the store and return the reference.
212
+ if the handle is not defined in the block outputs schema, raise an ValueError.
213
+ otherwise, return the value.
214
+ :param handle: the handle of the output
215
+ :param value: the value of the output
216
+ :return: the wrapped value
217
+ """
218
+ # __outputs_def should never be None
219
+ if self.__outputs_def is None:
220
+ return value
221
+
222
+ output_def = self.__outputs_def.get(handle)
223
+ if output_def is None:
224
+ raise ValueError(
225
+ f"Output handle key: [{handle}] is not defined in Block outputs schema."
226
+ )
227
+
228
+ if output_def.is_var_handle() and not self.__is_basic_type(value):
229
+ ref = self.__store_ref(handle)
230
+ self.__store[ref] = value
231
+ var: VarValueDict = {
232
+ "__OOMOL_TYPE__": "oomol/var",
233
+ "value": asdict(ref)
234
+ }
235
+ return var
236
+
237
+ if output_def.is_bin_handle():
238
+ if not isinstance(value, bytes):
239
+ self.send_warning(
240
+ f"Output handle key: [{handle}] is defined as binary, but the value is not bytes."
241
+ )
242
+ return value
243
+
244
+ bin_file = f"{self.session_dir}/binary/{self.session_id}/{self.job_id}/{handle}"
245
+ os.makedirs(os.path.dirname(bin_file), exist_ok=True)
246
+ try:
247
+ with open(bin_file, "wb") as f:
248
+ f.write(value)
249
+ except IOError as e:
250
+ raise IOError(
251
+ f"Output handle key: [{handle}] is defined as binary, but an error occurred while writing the file: {e}"
252
+ )
253
+
254
+ if os.path.exists(bin_file):
255
+ bin_value: BinValueDict = {
256
+ "__OOMOL_TYPE__": "oomol/bin",
257
+ "value": bin_file,
258
+ }
259
+ return bin_value
260
+ else:
261
+ raise IOError(
262
+ f"Output handle key: [{handle}] is defined as binary, but the file is not written."
263
+ )
264
+ return value
173
265
 
174
- def output(self, key: str, value: Any, done: bool = False):
266
+ def output(self, key: str, value: Any):
175
267
  """
176
268
  output the value to the next block
177
269
 
@@ -179,81 +271,85 @@ class Context:
179
271
  value: Any, the value of the output
180
272
  """
181
273
 
182
- v = value
183
-
184
- if self.__outputs_def is not None:
185
- output_def = self.__outputs_def.get(key)
186
- if (
187
- output_def is not None and output_def.is_var_handle() and not self.__is_basic_type(value) # 基础类型即使是变量也不放进 store,直接作为 json 内容传递
188
- ):
189
- ref = self.__store_ref(key)
190
- self.__store[ref] = value
191
- d: VarValueDict = {
192
- "__OOMOL_TYPE__": "oomol/var",
193
- "value": asdict(ref)
194
- }
195
- v = d
196
- elif output_def is not None and output_def.is_bin_handle():
197
- if not isinstance(value, bytes):
198
- self.send_warning(
199
- f"Output handle key: [{key}] is defined as binary, but the value is not bytes."
200
- )
201
- return
202
-
203
- bin_file = f"{self.session_dir}/binary/{self.session_id}/{self.job_id}/{key}"
204
- os.makedirs(os.path.dirname(bin_file), exist_ok=True)
205
- try:
206
- with open(bin_file, "wb") as f:
207
- f.write(value)
208
- except IOError as e:
209
- self.send_warning(
210
- f"Output handle key: [{key}] is defined as binary, but an error occurred while writing the file: {e}"
211
- )
212
- return
213
-
214
- if os.path.exists(bin_file):
215
- bin_value: BinValueDict = {
216
- "__OOMOL_TYPE__": "oomol/bin",
217
- "value": bin_file,
218
- }
219
- v = bin_value
220
- else:
221
- self.send_warning(
222
- f"Output handle key: [{key}] is defined as binary, but the file is not written."
223
- )
224
- return
225
-
226
- # 如果传入 key 在输出定义中不存在,直接忽略,不发送数据。但是 done 仍然生效。
227
- if self.__outputs_def is not None and self.__outputs_def.get(key) is None:
274
+ try:
275
+ wrap_value = self.__wrap_output_value(key, value)
276
+ except ValueError as e:
228
277
  self.send_warning(
229
- f"Output handle key: [{key}] is not defined in Block outputs schema."
278
+ f"{e}"
279
+ )
280
+ return
281
+ except IOError as e:
282
+ self.send_warning(
283
+ f"{e}"
230
284
  )
231
- if done:
232
- self.done()
233
285
  return
234
286
 
235
287
  node_result = {
236
288
  "type": "BlockOutput",
237
289
  "handle": key,
238
- "output": v,
239
- "done": done,
290
+ "output": wrap_value,
240
291
  }
241
292
  self.__mainframe.send(self.job_info, node_result)
293
+
294
+ def outputs(self, outputs: Dict[str, Any]):
295
+ """
296
+ output the value to the next block
242
297
 
243
- if done:
244
- self.done()
298
+ map: Dict[str, Any], the key of the output, should be defined in the block schema output defs, the field name is handle
299
+ """
245
300
 
246
- def done(self, error: str | None = None):
247
- if self.__is_done:
248
- self.send_warning("done has been called multiple times, will be ignored.")
249
- return
250
- self.__is_done = True
251
- if error is None:
252
- self.__mainframe.send(self.job_info, {"type": "BlockFinished"})
301
+ values = {}
302
+ for key, value in outputs.items():
303
+ try:
304
+ wrap_value = self.__wrap_output_value(key, value)
305
+ values[key] = wrap_value
306
+ except ValueError as e:
307
+ self.send_warning(
308
+ f"{e}"
309
+ )
310
+ except IOError as e:
311
+ self.send_warning(
312
+ f"{e}"
313
+ )
314
+ self.__mainframe.send(self.job_info, {
315
+ "type": "BlockOutputs",
316
+ "outputs": values,
317
+ })
318
+
319
+
320
+
321
+ def finish(self, *, result: Dict[str, Any] | None = None, error: str | None = None):
322
+ """
323
+ finish the block, and send the result to oocana.
324
+ if error is not None, the block will be finished with error.
325
+ then if result is not None, the block will be finished with result.
326
+ lastly, if both error and result are None, the block will be finished without any result.
327
+ """
328
+
329
+ if error is not None:
330
+ self.__mainframe.send(self.job_info, {"type": "BlockFinished", "error": error})
331
+ elif result is not None:
332
+ wrap_result = {}
333
+ if isinstance(result, dict):
334
+ for key, value in result.items():
335
+ try:
336
+ wrap_result[key] = self.__wrap_output_value(key, value)
337
+ except ValueError as e:
338
+ self.send_warning(
339
+ f"Output handle key: [{key}] is not defined in Block outputs schema. {e}"
340
+ )
341
+ except IOError as e:
342
+ self.send_warning(
343
+ f"Output handle key: [{key}] is not defined in Block outputs schema. {e}"
344
+ )
345
+
346
+ self.__mainframe.send(self.job_info, {"type": "BlockFinished", "result": wrap_result})
347
+ else:
348
+ raise ValueError(
349
+ f"result should be a dict, but got {type(result)}"
350
+ )
253
351
  else:
254
- self.__mainframe.send(
255
- self.job_info, {"type": "BlockFinished", "error": error}
256
- )
352
+ self.__mainframe.send(self.job_info, {"type": "BlockFinished"})
257
353
 
258
354
  def send_message(self, payload):
259
355
  self.__mainframe.report(
oocana/handle_data.py CHANGED
@@ -11,12 +11,18 @@ class HandleDef:
11
11
  handle: str
12
12
  """The name of the handle. it should be unique in handle list."""
13
13
 
14
+ """The description of the handle. It is used to display in the UI."""
15
+ description: Optional[str] = None
16
+
14
17
  json_schema: Optional[FieldSchema] = None
15
18
  """The schema of the handle. It is used to validate the handle's content."""
16
19
 
17
- name: Optional[str] = None
20
+ kind: Optional[str] = None
18
21
  """A alias of the handle's type name. It is used to display in the UI and connect to the other handle match"""
19
22
 
23
+ nullable: bool = False
24
+ """If the handle value can be None. If True, the handle can be None, otherwise it must have a value."""
25
+
20
26
  def __init__(self, **kwargs):
21
27
  for key, value in kwargs.items():
22
28
  object.__setattr__(self, key, value)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: oocana
3
- Version: 0.16.9
3
+ Version: 0.16.11
4
4
  Summary: python implement of oocana to give a context for oocana block
5
5
  License: MIT
6
6
  Requires-Python: >=3.9
@@ -1,14 +1,14 @@
1
- oocana-0.16.9.dist-info/METADATA,sha256=G_tNXd71n6dTXHfvfkCZkNE6OhGlTDKXNNcXvgzTTS4,221
2
- oocana-0.16.9.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
- oocana-0.16.9.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
1
+ oocana-0.16.11.dist-info/METADATA,sha256=tO5QL4es5cCZZQb6LzO85Abqw7n19YB7KKOqMD-Sv_Y,222
2
+ oocana-0.16.11.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
+ oocana-0.16.11.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
4
4
  oocana/__init__.py,sha256=kuZa-aY4bqStH_15K4KL9hjOeO9d-M9mJYKs4fm3n08,317
5
- oocana/context.py,sha256=5wWUZr4BjojizFH-9yeadWvIpiUt2v7wUN3b7y34CFc,14677
5
+ oocana/context.py,sha256=YmKjWB6KStzWUPL09zNTCXWitOn7Q_449VLKST2JoFc,18136
6
6
  oocana/data.py,sha256=0KpJyckz_X5JbrncBRFbOaU00CxcDx2UYHk6xuH1Poc,2890
7
7
  oocana/extra.py,sha256=1f7cu0QA3jnb6PJtEDXMsQOSGWtjUhsRz82DaPRyjKY,289
8
- oocana/handle_data.py,sha256=p0iEvdsVV3BqcelM8rvq0a_VPI52SeahaGCszfhZ0TI,1927
8
+ oocana/handle_data.py,sha256=Y9cPKJ5q7kIHutad_2sXLVJ0bHcWc0bPIXeh82sk48g,2176
9
9
  oocana/mainframe.py,sha256=Jixk9PjvJh7PnYwPGqOR5viwcOHWfaPhEiQFNHxHCxw,5219
10
10
  oocana/preview.py,sha256=qJEoBQWno0BkuU501vd16VwE0okTC3PydFc_jpkwc98,2096
11
11
  oocana/schema.py,sha256=8LwMaW4eXa3EmKxR4kzyTOpZiClMRMMsMA6f9CXodW4,4332
12
12
  oocana/service.py,sha256=dPCcScQfMBlEjIodFnKU17-HlbBzrQbQK6CNRw7SmOE,2442
13
13
  oocana/throtter.py,sha256=xTldm2OZ5uYPiyC6Aatug4FJAoMylPjtXftxHvSr_50,1104
14
- oocana-0.16.9.dist-info/RECORD,,
14
+ oocana-0.16.11.dist-info/RECORD,,