tracdap-runtime 0.6.1.dev3__py3-none-any.whl → 0.6.3__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.
- tracdap/rt/_exec/actors.py +87 -10
- tracdap/rt/_exec/context.py +25 -1
- tracdap/rt/_exec/dev_mode.py +277 -221
- tracdap/rt/_exec/engine.py +79 -14
- tracdap/rt/_exec/functions.py +37 -8
- tracdap/rt/_exec/graph.py +2 -0
- tracdap/rt/_exec/graph_builder.py +118 -56
- tracdap/rt/_exec/runtime.py +108 -37
- tracdap/rt/_exec/server.py +345 -0
- tracdap/rt/_impl/config_parser.py +219 -49
- tracdap/rt/_impl/data.py +14 -0
- tracdap/rt/_impl/grpc/__init__.py +13 -0
- tracdap/rt/_impl/grpc/codec.py +99 -0
- tracdap/rt/_impl/grpc/tracdap/api/internal/runtime_pb2.py +51 -0
- tracdap/rt/_impl/grpc/tracdap/api/internal/runtime_pb2.pyi +61 -0
- tracdap/rt/_impl/grpc/tracdap/api/internal/runtime_pb2_grpc.py +183 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/common_pb2.py +33 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/common_pb2.pyi +34 -0
- tracdap/rt/{metadata → _impl/grpc/tracdap/metadata}/custom_pb2.py +5 -5
- tracdap/rt/_impl/grpc/tracdap/metadata/custom_pb2.pyi +15 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/data_pb2.py +51 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/data_pb2.pyi +115 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/file_pb2.py +28 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/file_pb2.pyi +22 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/flow_pb2.py +59 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/flow_pb2.pyi +109 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/job_pb2.py +76 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/job_pb2.pyi +177 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/model_pb2.py +63 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/model_pb2.pyi +119 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/object_id_pb2.py +32 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/object_id_pb2.pyi +68 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/object_pb2.py +40 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/object_pb2.pyi +46 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/search_pb2.py +39 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/search_pb2.pyi +83 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/stoarge_pb2.py +50 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/stoarge_pb2.pyi +89 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/tag_pb2.py +34 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/tag_pb2.pyi +26 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/tag_update_pb2.py +30 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/tag_update_pb2.pyi +34 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/type_pb2.py +47 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/type_pb2.pyi +101 -0
- tracdap/rt/_impl/guard_rails.py +26 -6
- tracdap/rt/_impl/models.py +25 -0
- tracdap/rt/_impl/static_api.py +27 -9
- tracdap/rt/_impl/type_system.py +17 -0
- tracdap/rt/_impl/validation.py +10 -0
- tracdap/rt/_plugins/config_local.py +49 -0
- tracdap/rt/_version.py +1 -1
- tracdap/rt/api/hook.py +10 -3
- tracdap/rt/api/model_api.py +22 -0
- tracdap/rt/api/static_api.py +79 -19
- tracdap/rt/config/__init__.py +3 -3
- tracdap/rt/config/common.py +10 -0
- tracdap/rt/config/platform.py +9 -19
- tracdap/rt/config/runtime.py +2 -0
- tracdap/rt/ext/config.py +34 -0
- tracdap/rt/ext/embed.py +1 -3
- tracdap/rt/ext/plugins.py +47 -6
- tracdap/rt/launch/cli.py +7 -5
- tracdap/rt/launch/launch.py +49 -12
- tracdap/rt/metadata/__init__.py +24 -24
- tracdap/rt/metadata/common.py +7 -7
- tracdap/rt/metadata/custom.py +2 -0
- tracdap/rt/metadata/data.py +28 -5
- tracdap/rt/metadata/file.py +2 -0
- tracdap/rt/metadata/flow.py +66 -4
- tracdap/rt/metadata/job.py +56 -16
- tracdap/rt/metadata/model.py +10 -0
- tracdap/rt/metadata/object.py +3 -0
- tracdap/rt/metadata/object_id.py +9 -9
- tracdap/rt/metadata/search.py +35 -13
- tracdap/rt/metadata/stoarge.py +64 -6
- tracdap/rt/metadata/tag_update.py +21 -7
- tracdap/rt/metadata/type.py +28 -13
- {tracdap_runtime-0.6.1.dev3.dist-info → tracdap_runtime-0.6.3.dist-info}/METADATA +22 -19
- tracdap_runtime-0.6.3.dist-info/RECORD +112 -0
- {tracdap_runtime-0.6.1.dev3.dist-info → tracdap_runtime-0.6.3.dist-info}/WHEEL +1 -1
- tracdap/rt/config/common_pb2.py +0 -55
- tracdap/rt/config/job_pb2.py +0 -42
- tracdap/rt/config/platform_pb2.py +0 -71
- tracdap/rt/config/result_pb2.py +0 -37
- tracdap/rt/config/runtime_pb2.py +0 -42
- tracdap/rt/ext/_guard.py +0 -37
- tracdap/rt/metadata/common_pb2.py +0 -33
- tracdap/rt/metadata/data_pb2.py +0 -51
- tracdap/rt/metadata/file_pb2.py +0 -28
- tracdap/rt/metadata/flow_pb2.py +0 -55
- tracdap/rt/metadata/job_pb2.py +0 -76
- tracdap/rt/metadata/model_pb2.py +0 -51
- tracdap/rt/metadata/object_id_pb2.py +0 -32
- tracdap/rt/metadata/object_pb2.py +0 -35
- tracdap/rt/metadata/search_pb2.py +0 -39
- tracdap/rt/metadata/stoarge_pb2.py +0 -50
- tracdap/rt/metadata/tag_pb2.py +0 -34
- tracdap/rt/metadata/tag_update_pb2.py +0 -30
- tracdap/rt/metadata/type_pb2.py +0 -48
- tracdap_runtime-0.6.1.dev3.dist-info/RECORD +0 -96
- {tracdap_runtime-0.6.1.dev3.dist-info → tracdap_runtime-0.6.3.dist-info}/LICENSE +0 -0
- {tracdap_runtime-0.6.1.dev3.dist-info → tracdap_runtime-0.6.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
from google.protobuf.internal import containers as _containers
|
2
|
+
from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
|
3
|
+
from google.protobuf import descriptor as _descriptor
|
4
|
+
from google.protobuf import message as _message
|
5
|
+
from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union
|
6
|
+
|
7
|
+
DESCRIPTOR: _descriptor.FileDescriptor
|
8
|
+
|
9
|
+
class BasicType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
|
10
|
+
__slots__ = ()
|
11
|
+
BASIC_TYPE_NOT_SET: _ClassVar[BasicType]
|
12
|
+
BOOLEAN: _ClassVar[BasicType]
|
13
|
+
INTEGER: _ClassVar[BasicType]
|
14
|
+
FLOAT: _ClassVar[BasicType]
|
15
|
+
STRING: _ClassVar[BasicType]
|
16
|
+
DECIMAL: _ClassVar[BasicType]
|
17
|
+
DATE: _ClassVar[BasicType]
|
18
|
+
DATETIME: _ClassVar[BasicType]
|
19
|
+
ARRAY: _ClassVar[BasicType]
|
20
|
+
MAP: _ClassVar[BasicType]
|
21
|
+
BASIC_TYPE_NOT_SET: BasicType
|
22
|
+
BOOLEAN: BasicType
|
23
|
+
INTEGER: BasicType
|
24
|
+
FLOAT: BasicType
|
25
|
+
STRING: BasicType
|
26
|
+
DECIMAL: BasicType
|
27
|
+
DATE: BasicType
|
28
|
+
DATETIME: BasicType
|
29
|
+
ARRAY: BasicType
|
30
|
+
MAP: BasicType
|
31
|
+
|
32
|
+
class TypeDescriptor(_message.Message):
|
33
|
+
__slots__ = ("basicType", "arrayType", "mapType")
|
34
|
+
BASICTYPE_FIELD_NUMBER: _ClassVar[int]
|
35
|
+
ARRAYTYPE_FIELD_NUMBER: _ClassVar[int]
|
36
|
+
MAPTYPE_FIELD_NUMBER: _ClassVar[int]
|
37
|
+
basicType: BasicType
|
38
|
+
arrayType: TypeDescriptor
|
39
|
+
mapType: TypeDescriptor
|
40
|
+
def __init__(self, basicType: _Optional[_Union[BasicType, str]] = ..., arrayType: _Optional[_Union[TypeDescriptor, _Mapping]] = ..., mapType: _Optional[_Union[TypeDescriptor, _Mapping]] = ...) -> None: ...
|
41
|
+
|
42
|
+
class DecimalValue(_message.Message):
|
43
|
+
__slots__ = ("decimal",)
|
44
|
+
DECIMAL_FIELD_NUMBER: _ClassVar[int]
|
45
|
+
decimal: str
|
46
|
+
def __init__(self, decimal: _Optional[str] = ...) -> None: ...
|
47
|
+
|
48
|
+
class DateValue(_message.Message):
|
49
|
+
__slots__ = ("isoDate",)
|
50
|
+
ISODATE_FIELD_NUMBER: _ClassVar[int]
|
51
|
+
isoDate: str
|
52
|
+
def __init__(self, isoDate: _Optional[str] = ...) -> None: ...
|
53
|
+
|
54
|
+
class DatetimeValue(_message.Message):
|
55
|
+
__slots__ = ("isoDatetime",)
|
56
|
+
ISODATETIME_FIELD_NUMBER: _ClassVar[int]
|
57
|
+
isoDatetime: str
|
58
|
+
def __init__(self, isoDatetime: _Optional[str] = ...) -> None: ...
|
59
|
+
|
60
|
+
class Value(_message.Message):
|
61
|
+
__slots__ = ("type", "booleanValue", "integerValue", "floatValue", "stringValue", "decimalValue", "dateValue", "datetimeValue", "arrayValue", "mapValue")
|
62
|
+
TYPE_FIELD_NUMBER: _ClassVar[int]
|
63
|
+
BOOLEANVALUE_FIELD_NUMBER: _ClassVar[int]
|
64
|
+
INTEGERVALUE_FIELD_NUMBER: _ClassVar[int]
|
65
|
+
FLOATVALUE_FIELD_NUMBER: _ClassVar[int]
|
66
|
+
STRINGVALUE_FIELD_NUMBER: _ClassVar[int]
|
67
|
+
DECIMALVALUE_FIELD_NUMBER: _ClassVar[int]
|
68
|
+
DATEVALUE_FIELD_NUMBER: _ClassVar[int]
|
69
|
+
DATETIMEVALUE_FIELD_NUMBER: _ClassVar[int]
|
70
|
+
ARRAYVALUE_FIELD_NUMBER: _ClassVar[int]
|
71
|
+
MAPVALUE_FIELD_NUMBER: _ClassVar[int]
|
72
|
+
type: TypeDescriptor
|
73
|
+
booleanValue: bool
|
74
|
+
integerValue: int
|
75
|
+
floatValue: float
|
76
|
+
stringValue: str
|
77
|
+
decimalValue: DecimalValue
|
78
|
+
dateValue: DateValue
|
79
|
+
datetimeValue: DatetimeValue
|
80
|
+
arrayValue: ArrayValue
|
81
|
+
mapValue: MapValue
|
82
|
+
def __init__(self, type: _Optional[_Union[TypeDescriptor, _Mapping]] = ..., booleanValue: bool = ..., integerValue: _Optional[int] = ..., floatValue: _Optional[float] = ..., stringValue: _Optional[str] = ..., decimalValue: _Optional[_Union[DecimalValue, _Mapping]] = ..., dateValue: _Optional[_Union[DateValue, _Mapping]] = ..., datetimeValue: _Optional[_Union[DatetimeValue, _Mapping]] = ..., arrayValue: _Optional[_Union[ArrayValue, _Mapping]] = ..., mapValue: _Optional[_Union[MapValue, _Mapping]] = ...) -> None: ...
|
83
|
+
|
84
|
+
class ArrayValue(_message.Message):
|
85
|
+
__slots__ = ("items",)
|
86
|
+
ITEMS_FIELD_NUMBER: _ClassVar[int]
|
87
|
+
items: _containers.RepeatedCompositeFieldContainer[Value]
|
88
|
+
def __init__(self, items: _Optional[_Iterable[_Union[Value, _Mapping]]] = ...) -> None: ...
|
89
|
+
|
90
|
+
class MapValue(_message.Message):
|
91
|
+
__slots__ = ("entries",)
|
92
|
+
class EntriesEntry(_message.Message):
|
93
|
+
__slots__ = ("key", "value")
|
94
|
+
KEY_FIELD_NUMBER: _ClassVar[int]
|
95
|
+
VALUE_FIELD_NUMBER: _ClassVar[int]
|
96
|
+
key: str
|
97
|
+
value: Value
|
98
|
+
def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[Value, _Mapping]] = ...) -> None: ...
|
99
|
+
ENTRIES_FIELD_NUMBER: _ClassVar[int]
|
100
|
+
entries: _containers.MessageMap[str, Value]
|
101
|
+
def __init__(self, entries: _Optional[_Mapping[str, Value]] = ...) -> None: ...
|
tracdap/rt/_impl/guard_rails.py
CHANGED
@@ -46,6 +46,27 @@ def _get_package_path(module_name):
|
|
46
46
|
return module_path.parents[depth]
|
47
47
|
|
48
48
|
|
49
|
+
def run_model_guard(operation: str = None):
|
50
|
+
|
51
|
+
# A simple guard method to block model code from accessing parts of the TRAC runtime framework
|
52
|
+
# To blocks calls to the Python stdlib or 3rd party libs, use PythonGuardRails instead
|
53
|
+
|
54
|
+
stack = inspect.stack()
|
55
|
+
frame = stack[-1]
|
56
|
+
|
57
|
+
if operation is None:
|
58
|
+
operation = f"Calling {frame.function}()"
|
59
|
+
|
60
|
+
for frame_index in range(len(stack) - 2, 0, -1):
|
61
|
+
|
62
|
+
parent_frame = frame
|
63
|
+
frame = stack[frame_index]
|
64
|
+
|
65
|
+
if frame.function == "run_model" and parent_frame.function == "_execute":
|
66
|
+
err = f"{operation} is not allowed inside run_model()"
|
67
|
+
raise ex.ERuntimeValidation(err)
|
68
|
+
|
69
|
+
|
49
70
|
class PythonGuardRails:
|
50
71
|
|
51
72
|
DANGEROUS_BUILTIN_FUNCTIONS = ["exec", "eval", "compile", "open", "input", "memoryview"]
|
@@ -258,14 +279,13 @@ class PythonGuardRails:
|
|
258
279
|
@classmethod
|
259
280
|
def is_debug(cls):
|
260
281
|
|
261
|
-
|
282
|
+
has_trace = hasattr(sys, 'gettrace') and sys.gettrace() is not None
|
283
|
+
has_breakpoint = sys.breakpointhook.__module__ != "sys"
|
262
284
|
|
263
|
-
if
|
264
|
-
return
|
285
|
+
if has_trace or has_breakpoint:
|
286
|
+
return True
|
265
287
|
|
266
|
-
|
267
|
-
trace = get_trace_func()
|
268
|
-
return trace is not None
|
288
|
+
return False
|
269
289
|
|
270
290
|
@classmethod
|
271
291
|
def is_import(cls):
|
tracdap/rt/_impl/models.py
CHANGED
@@ -215,12 +215,15 @@ class ModelLoader:
|
|
215
215
|
|
216
216
|
for name, param in model_def.parameters.items():
|
217
217
|
self.__log.info(f"Parameter [{name}] - {param.paramType.basicType.name}")
|
218
|
+
param.paramProps = self._encoded_props(param.paramProps, "parameter", name)
|
218
219
|
|
219
220
|
for name, schema in model_def.inputs.items():
|
220
221
|
self.__log.info(f"Input [{name}] - {schema.schema.schemaType.name}")
|
222
|
+
schema.inputProps = self._encoded_props(schema.inputProps, "input", name)
|
221
223
|
|
222
224
|
for name, schema in model_def.outputs.items():
|
223
225
|
self.__log.info(f"Output [{name}] - {schema.schema.schemaType.name}")
|
226
|
+
schema.outputProps = self._encoded_props(schema.outputProps, "input", name)
|
224
227
|
|
225
228
|
return model_def
|
226
229
|
|
@@ -231,3 +234,25 @@ class ModelLoader:
|
|
231
234
|
|
232
235
|
self.__log.error(msg, exc_info=True)
|
233
236
|
raise _ex.EModelValidation(msg) from e
|
237
|
+
|
238
|
+
@staticmethod
|
239
|
+
def _encoded_props(
|
240
|
+
raw_props: tp.Dict[str, tp.Any],
|
241
|
+
item_type: str, item_name: str) \
|
242
|
+
-> tp.Dict[str, _meta.Value]:
|
243
|
+
|
244
|
+
if raw_props is None:
|
245
|
+
return dict()
|
246
|
+
|
247
|
+
encoded_props = dict()
|
248
|
+
|
249
|
+
for key, raw_value in raw_props.items():
|
250
|
+
|
251
|
+
if raw_value is None:
|
252
|
+
raise _ex.EModelValidation(f"Invalid null property [{key}] for {item_type} [{item_name}]")
|
253
|
+
elif isinstance(raw_value, _meta.Value):
|
254
|
+
encoded_props[key] = raw_value
|
255
|
+
else:
|
256
|
+
encoded_props[key] = _types.MetadataCodec.encode_value(raw_value)
|
257
|
+
|
258
|
+
return encoded_props
|
tracdap/rt/_impl/static_api.py
CHANGED
@@ -71,10 +71,14 @@ class StaticApiImpl(_StaticApiHook):
|
|
71
71
|
|
72
72
|
def define_parameter(
|
73
73
|
self, param_name: str, param_type: _tp.Union[_meta.TypeDescriptor, _meta.BasicType],
|
74
|
-
label: str, default_value: _tp.Optional[_tp.Any] = None
|
74
|
+
label: str, default_value: _tp.Optional[_tp.Any] = None,
|
75
|
+
*, param_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) \
|
75
76
|
-> _Named[_meta.ModelParameter]:
|
76
77
|
|
77
|
-
_val.validate_signature(
|
78
|
+
_val.validate_signature(
|
79
|
+
self.define_parameter,
|
80
|
+
param_name, param_type, label, default_value,
|
81
|
+
param_props=param_props)
|
78
82
|
|
79
83
|
if isinstance(param_type, _meta.TypeDescriptor):
|
80
84
|
param_type_descriptor = param_type
|
@@ -88,7 +92,9 @@ class StaticApiImpl(_StaticApiHook):
|
|
88
92
|
msg = f"Default value for parameter [{param_name}] does not match the declared type"
|
89
93
|
raise _ex.EModelValidation(msg) from e
|
90
94
|
|
91
|
-
return _Named(param_name, _meta.ModelParameter(
|
95
|
+
return _Named(param_name, _meta.ModelParameter(
|
96
|
+
param_type_descriptor, label, default_value,
|
97
|
+
paramProps=param_props))
|
92
98
|
|
93
99
|
def define_parameters(
|
94
100
|
self, *params: _tp.Union[_Named[_meta.ModelParameter], _tp.List[_Named[_meta.ModelParameter]]]) \
|
@@ -147,22 +153,34 @@ class StaticApiImpl(_StaticApiHook):
|
|
147
153
|
return _schemas.SchemaLoader.load_schema(package, schema_file)
|
148
154
|
|
149
155
|
def define_input_table(
|
150
|
-
self, *fields: _tp.Union[_meta.FieldSchema, _tp.List[_meta.FieldSchema]],
|
156
|
+
self, *fields: _tp.Union[_meta.FieldSchema, _tp.List[_meta.FieldSchema]],
|
157
|
+
label: _tp.Optional[str] = None,
|
158
|
+
optional: bool = False,
|
159
|
+
input_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) \
|
151
160
|
-> _meta.ModelInputSchema:
|
152
161
|
|
153
|
-
_val.validate_signature(
|
162
|
+
_val.validate_signature(
|
163
|
+
self.define_input_table, *fields,
|
164
|
+
label=label, optional=optional,
|
165
|
+
input_props=input_props)
|
154
166
|
|
155
167
|
schema_def = self.define_schema(*fields, schema_type=_meta.SchemaType.TABLE)
|
156
|
-
return _meta.ModelInputSchema(schema=schema_def, label=label)
|
168
|
+
return _meta.ModelInputSchema(schema=schema_def, label=label, optional=optional, inputProps=input_props)
|
157
169
|
|
158
170
|
def define_output_table(
|
159
|
-
self, *fields: _tp.Union[_meta.FieldSchema, _tp.List[_meta.FieldSchema]],
|
171
|
+
self, *fields: _tp.Union[_meta.FieldSchema, _tp.List[_meta.FieldSchema]],
|
172
|
+
label: _tp.Optional[str] = None,
|
173
|
+
optional: bool = False,
|
174
|
+
output_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) \
|
160
175
|
-> _meta.ModelOutputSchema:
|
161
176
|
|
162
|
-
_val.validate_signature(
|
177
|
+
_val.validate_signature(
|
178
|
+
self.define_output_table, *fields,
|
179
|
+
label=label, optional=optional,
|
180
|
+
output_props=output_props)
|
163
181
|
|
164
182
|
schema_def = self.define_schema(*fields, schema_type=_meta.SchemaType.TABLE)
|
165
|
-
return _meta.ModelOutputSchema(schema=schema_def, label=label)
|
183
|
+
return _meta.ModelOutputSchema(schema=schema_def, label=label, optional=optional, outputProps=output_props)
|
166
184
|
|
167
185
|
@staticmethod
|
168
186
|
def _build_named_dict(
|
tracdap/rt/_impl/type_system.py
CHANGED
@@ -171,6 +171,23 @@ class MetadataCodec:
|
|
171
171
|
type_desc = _meta.TypeDescriptor(_meta.BasicType.DATE)
|
172
172
|
return _meta.Value(type_desc, dateValue=_meta.DateValue(value.isoformat()))
|
173
173
|
|
174
|
+
if isinstance(value, list):
|
175
|
+
|
176
|
+
if len(value) == 0:
|
177
|
+
raise _ex.ETracInternal("Cannot encode an empty list")
|
178
|
+
|
179
|
+
array_raw_type = type(value[0])
|
180
|
+
array_trac_type = TypeMapping.python_to_trac(array_raw_type)
|
181
|
+
|
182
|
+
if any(map(lambda x: type(x) != array_raw_type, value)):
|
183
|
+
raise _ex.ETracInternal("Cannot encode a list with values of different types")
|
184
|
+
|
185
|
+
encoded_items = list(map(lambda x: cls.convert_value(x, array_trac_type), value))
|
186
|
+
|
187
|
+
return _meta.Value(
|
188
|
+
_meta.TypeDescriptor(_meta.BasicType.ARRAY, arrayType=array_trac_type),
|
189
|
+
arrayValue=_meta.ArrayValue(encoded_items))
|
190
|
+
|
174
191
|
raise _ex.ETracInternal(f"Value type [{type(value)}] is not supported yet")
|
175
192
|
|
176
193
|
@classmethod
|
tracdap/rt/_impl/validation.py
CHANGED
@@ -320,6 +320,9 @@ class _StaticValidator:
|
|
320
320
|
else:
|
321
321
|
cls._check_label(param.label, param_name)
|
322
322
|
|
323
|
+
if param.paramProps is not None:
|
324
|
+
cls._valid_identifiers(param.paramProps.keys(), "entry in param props")
|
325
|
+
|
323
326
|
@classmethod
|
324
327
|
def _check_inputs_or_outputs(cls, inputs_or_outputs):
|
325
328
|
|
@@ -340,6 +343,13 @@ class _StaticValidator:
|
|
340
343
|
label = input_schema.label
|
341
344
|
cls._check_label(label, input_name)
|
342
345
|
|
346
|
+
if isinstance(input_schema, meta.ModelInputSchema):
|
347
|
+
if input_schema.inputProps is not None:
|
348
|
+
cls._valid_identifiers(input_schema.inputProps.keys(), "entry in input props")
|
349
|
+
else:
|
350
|
+
if input_schema.outputProps is not None:
|
351
|
+
cls._valid_identifiers(input_schema.outputProps.keys(), "entry in output props")
|
352
|
+
|
343
353
|
@classmethod
|
344
354
|
def _check_single_field(cls, field: meta.FieldSchema, property_type):
|
345
355
|
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Copyright 2024 Accenture Global Solutions Limited
|
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
|
+
import pathlib as pathlib
|
16
|
+
import typing as tp
|
17
|
+
|
18
|
+
import tracdap.rt.ext.plugins as plugins
|
19
|
+
import tracdap.rt.exceptions as ex
|
20
|
+
|
21
|
+
from tracdap.rt.ext.config import *
|
22
|
+
|
23
|
+
|
24
|
+
class LocalConfigLoader(IConfigLoader):
|
25
|
+
|
26
|
+
# Properties dict will be empty for config plugins
|
27
|
+
def __init__(self, properties: tp.Dict[str, str]): # noqa
|
28
|
+
pass
|
29
|
+
|
30
|
+
def has_config_file(self, config_url: str) -> bool:
|
31
|
+
if config_url.startswith("file:"):
|
32
|
+
config_url = config_url[5:]
|
33
|
+
config_path = pathlib.Path(config_url).resolve()
|
34
|
+
return config_path.exists() and config_path.is_file()
|
35
|
+
|
36
|
+
def load_config_file(self, config_url: str) -> bytes:
|
37
|
+
if config_url.startswith("file:"):
|
38
|
+
config_url = config_url[5:]
|
39
|
+
config_path = pathlib.Path(config_url).resolve()
|
40
|
+
return config_path.read_bytes()
|
41
|
+
|
42
|
+
def has_config_dict(self, config_url: str) -> bool:
|
43
|
+
return False
|
44
|
+
|
45
|
+
def load_config_dict(self, config_url: str) -> dict:
|
46
|
+
raise ex.ETracInternal("Local config loader does not support loading objects")
|
47
|
+
|
48
|
+
|
49
|
+
plugins.PluginManager.register_plugin(IConfigLoader, LocalConfigLoader, ["LOCAL", "file"])
|
tracdap/rt/_version.py
CHANGED
tracdap/rt/api/hook.py
CHANGED
@@ -80,7 +80,8 @@ class _StaticApiHook:
|
|
80
80
|
@_abc.abstractmethod
|
81
81
|
def define_parameter(
|
82
82
|
self, param_name: str, param_type: _tp.Union[_meta.TypeDescriptor, _meta.BasicType],
|
83
|
-
label: str, default_value: _tp.Optional[_tp.Any] = None
|
83
|
+
label: str, default_value: _tp.Optional[_tp.Any] = None,
|
84
|
+
*, param_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) \
|
84
85
|
-> _Named[_meta.ModelParameter]:
|
85
86
|
|
86
87
|
pass
|
@@ -119,14 +120,20 @@ class _StaticApiHook:
|
|
119
120
|
|
120
121
|
@_abc.abstractmethod
|
121
122
|
def define_input_table(
|
122
|
-
self, *fields: _tp.Union[_meta.FieldSchema, _tp.List[_meta.FieldSchema]],
|
123
|
+
self, *fields: _tp.Union[_meta.FieldSchema, _tp.List[_meta.FieldSchema]],
|
124
|
+
label: _tp.Optional[str] = None,
|
125
|
+
optional: bool = False,
|
126
|
+
input_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) \
|
123
127
|
-> _meta.ModelInputSchema:
|
124
128
|
|
125
129
|
pass
|
126
130
|
|
127
131
|
@_abc.abstractmethod
|
128
132
|
def define_output_table(
|
129
|
-
self, *fields: _tp.Union[_meta.FieldSchema, _tp.List[_meta.FieldSchema]],
|
133
|
+
self, *fields: _tp.Union[_meta.FieldSchema, _tp.List[_meta.FieldSchema]],
|
134
|
+
label: _tp.Optional[str] = None,
|
135
|
+
optional: bool = False,
|
136
|
+
output_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) \
|
130
137
|
-> _meta.ModelOutputSchema:
|
131
138
|
|
132
139
|
pass
|
tracdap/rt/api/model_api.py
CHANGED
@@ -72,6 +72,28 @@ class TracContext:
|
|
72
72
|
|
73
73
|
pass
|
74
74
|
|
75
|
+
@_abc.abstractmethod
|
76
|
+
def has_dataset(self, dataset_name: str) -> bool:
|
77
|
+
|
78
|
+
"""
|
79
|
+
Check whether a dataset is available in the current context
|
80
|
+
|
81
|
+
This method can be used to check whether optional model inputs have been supplied or not.
|
82
|
+
Models should use this method before calling get methods on optional inputs.
|
83
|
+
For inputs not marked as optional, this method will always return true. For outputs,
|
84
|
+
this method will return true after the model calls a put method for the dataset.
|
85
|
+
|
86
|
+
A runtime validation error will be raised if the dataset name is not defined
|
87
|
+
as a model input or output.
|
88
|
+
|
89
|
+
:param dataset_name: The name of the dataset to check
|
90
|
+
:return: True if the dataset exists in the current context, False otherwise
|
91
|
+
:rtype: bool
|
92
|
+
:raises: :py:class:`ERuntimeValidation <tracdap.rt.exceptions.ERuntimeValidation>`
|
93
|
+
"""
|
94
|
+
|
95
|
+
pass
|
96
|
+
|
75
97
|
@_abc.abstractmethod
|
76
98
|
def get_schema(self, dataset_name: str) -> SchemaDefinition:
|
77
99
|
|