tracdap-runtime 0.6.3__py3-none-any.whl → 0.6.4__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/context.py +207 -100
- tracdap/rt/_exec/dev_mode.py +43 -3
- tracdap/rt/_exec/functions.py +14 -17
- tracdap/rt/_impl/data.py +70 -5
- tracdap/rt/_impl/grpc/tracdap/metadata/data_pb2.py +18 -18
- tracdap/rt/_impl/grpc/tracdap/metadata/model_pb2.py +18 -18
- tracdap/rt/_impl/grpc/tracdap/metadata/model_pb2.pyi +8 -4
- tracdap/rt/_impl/static_api.py +26 -10
- tracdap/rt/_impl/validation.py +37 -4
- tracdap/rt/_version.py +1 -1
- tracdap/rt/api/hook.py +2 -4
- tracdap/rt/api/model_api.py +50 -7
- tracdap/rt/api/static_api.py +14 -6
- tracdap/rt/config/common.py +17 -17
- tracdap/rt/config/job.py +2 -2
- tracdap/rt/config/platform.py +25 -25
- tracdap/rt/config/result.py +2 -2
- tracdap/rt/config/runtime.py +3 -3
- tracdap/rt/launch/cli.py +7 -4
- tracdap/rt/launch/launch.py +19 -3
- tracdap/rt/metadata/common.py +2 -2
- tracdap/rt/metadata/custom.py +3 -3
- tracdap/rt/metadata/data.py +12 -12
- tracdap/rt/metadata/file.py +6 -6
- tracdap/rt/metadata/flow.py +6 -6
- tracdap/rt/metadata/job.py +8 -8
- tracdap/rt/metadata/model.py +15 -11
- tracdap/rt/metadata/object_id.py +8 -8
- tracdap/rt/metadata/search.py +5 -5
- tracdap/rt/metadata/stoarge.py +6 -6
- tracdap/rt/metadata/tag.py +1 -1
- tracdap/rt/metadata/tag_update.py +1 -1
- tracdap/rt/metadata/type.py +4 -4
- {tracdap_runtime-0.6.3.dist-info → tracdap_runtime-0.6.4.dist-info}/METADATA +1 -1
- {tracdap_runtime-0.6.3.dist-info → tracdap_runtime-0.6.4.dist-info}/RECORD +38 -38
- {tracdap_runtime-0.6.3.dist-info → tracdap_runtime-0.6.4.dist-info}/LICENSE +0 -0
- {tracdap_runtime-0.6.3.dist-info → tracdap_runtime-0.6.4.dist-info}/WHEEL +0 -0
- {tracdap_runtime-0.6.3.dist-info → tracdap_runtime-0.6.4.dist-info}/top_level.txt +0 -0
tracdap/rt/_impl/data.py
CHANGED
@@ -74,17 +74,21 @@ class DataView:
|
|
74
74
|
|
75
75
|
parts: tp.Dict[DataPartKey, tp.List[DataItem]]
|
76
76
|
|
77
|
+
@staticmethod
|
78
|
+
def create_empty() -> DataView:
|
79
|
+
return DataView(_meta.SchemaDefinition(), pa.schema([]), dict())
|
80
|
+
|
77
81
|
@staticmethod
|
78
82
|
def for_trac_schema(trac_schema: _meta.SchemaDefinition):
|
79
83
|
arrow_schema = DataMapping.trac_to_arrow_schema(trac_schema)
|
80
84
|
return DataView(trac_schema, arrow_schema, dict())
|
81
85
|
|
82
|
-
def
|
83
|
-
|
86
|
+
def with_trac_schema(self, trac_schema: _meta.SchemaDefinition):
|
87
|
+
arrow_schema = DataMapping.trac_to_arrow_schema(trac_schema)
|
88
|
+
return DataView(trac_schema, arrow_schema, self.parts)
|
84
89
|
|
85
|
-
|
86
|
-
|
87
|
-
return DataView(_meta.SchemaDefinition(), pa.schema([]), dict())
|
90
|
+
def is_empty(self) -> bool:
|
91
|
+
return self.parts is None or not any(self.parts.values())
|
88
92
|
|
89
93
|
|
90
94
|
class _DataInternal:
|
@@ -170,9 +174,29 @@ class DataMapping:
|
|
170
174
|
pa.float16(): pd.Float32Dtype(),
|
171
175
|
pa.float32(): pd.Float32Dtype(),
|
172
176
|
pa.float64(): pd.Float64Dtype(),
|
177
|
+
pa.string(): pd.StringDtype(),
|
173
178
|
pa.utf8(): pd.StringDtype()
|
174
179
|
}
|
175
180
|
|
181
|
+
__ARROW_TO_TRAC_BASIC_TYPE_MAPPING = {
|
182
|
+
pa.bool_(): _meta.BasicType.BOOLEAN,
|
183
|
+
pa.int8(): _meta.BasicType.INTEGER,
|
184
|
+
pa.int16(): _meta.BasicType.INTEGER,
|
185
|
+
pa.int32(): _meta.BasicType.INTEGER,
|
186
|
+
pa.int64():_meta.BasicType.INTEGER,
|
187
|
+
pa.uint8(): _meta.BasicType.INTEGER,
|
188
|
+
pa.uint16(): _meta.BasicType.INTEGER,
|
189
|
+
pa.uint32(): _meta.BasicType.INTEGER,
|
190
|
+
pa.uint64(): _meta.BasicType.INTEGER,
|
191
|
+
pa.float16(): _meta.BasicType.FLOAT,
|
192
|
+
pa.float32(): _meta.BasicType.FLOAT,
|
193
|
+
pa.float64(): _meta.BasicType.FLOAT,
|
194
|
+
pa.string(): _meta.BasicType.STRING,
|
195
|
+
pa.utf8(): _meta.BasicType.STRING,
|
196
|
+
pa.date32(): _meta.BasicType.DATE,
|
197
|
+
pa.date64(): _meta.BasicType.DATE
|
198
|
+
}
|
199
|
+
|
176
200
|
@staticmethod
|
177
201
|
def arrow_to_python_type(arrow_type: pa.DataType) -> type:
|
178
202
|
|
@@ -265,6 +289,47 @@ class DataMapping:
|
|
265
289
|
cls.__TRAC_DECIMAL_PRECISION,
|
266
290
|
cls.__TRAC_DECIMAL_SCALE)
|
267
291
|
|
292
|
+
@classmethod
|
293
|
+
def arrow_to_trac_schema(cls, arrow_schema: pa.Schema) -> _meta.SchemaDefinition:
|
294
|
+
|
295
|
+
trac_fields = list(
|
296
|
+
cls.arrow_to_trac_field(i, arrow_schema.field(i))
|
297
|
+
for (i, f) in enumerate(arrow_schema.names))
|
298
|
+
|
299
|
+
return _meta.SchemaDefinition(
|
300
|
+
schemaType=_meta.SchemaType.TABLE,
|
301
|
+
partType=_meta.PartType.PART_ROOT,
|
302
|
+
table=_meta.TableSchema(trac_fields))
|
303
|
+
|
304
|
+
@classmethod
|
305
|
+
def arrow_to_trac_field(cls, field_index: int, field: pa.Field) -> _meta.FieldSchema:
|
306
|
+
|
307
|
+
field_type = cls.arrow_to_trac_type(field.type)
|
308
|
+
label = field.metadata["label"] if field.metadata and "label" in field.metadata else field.name
|
309
|
+
|
310
|
+
return _meta.FieldSchema(
|
311
|
+
field.name, field_index, field_type,
|
312
|
+
label=label,
|
313
|
+
businessKey=False,
|
314
|
+
notNull=not field.nullable,
|
315
|
+
categorical=False)
|
316
|
+
|
317
|
+
@classmethod
|
318
|
+
def arrow_to_trac_type(cls, arrow_type: pa.DataType) -> _meta.BasicType:
|
319
|
+
|
320
|
+
mapped_basic_type = cls.__ARROW_TO_TRAC_BASIC_TYPE_MAPPING.get(arrow_type) # noqa
|
321
|
+
|
322
|
+
if mapped_basic_type is not None:
|
323
|
+
return mapped_basic_type
|
324
|
+
|
325
|
+
if pa.types.is_decimal(arrow_type):
|
326
|
+
return _meta.BasicType.DECIMAL
|
327
|
+
|
328
|
+
if pa.types.is_timestamp(arrow_type):
|
329
|
+
return _meta.BasicType.DATETIME
|
330
|
+
|
331
|
+
raise _ex.ETracInternal(f"No data type mapping available for Arrow type [{arrow_type}]")
|
332
|
+
|
268
333
|
@classmethod
|
269
334
|
def pandas_date_type(cls):
|
270
335
|
return cls.__PANDAS_DATE_TYPE
|
@@ -16,7 +16,7 @@ from tracdap.rt._impl.grpc.tracdap.metadata import type_pb2 as tracdap_dot_rt_do
|
|
16
16
|
from tracdap.rt._impl.grpc.tracdap.metadata import object_id_pb2 as tracdap_dot_rt_dot___impl_dot_grpc_dot_tracdap_dot_metadata_dot_object__id__pb2
|
17
17
|
|
18
18
|
|
19
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n1tracdap/rt/_impl/grpc/tracdap/metadata/data.proto\x12\x10tracdap.metadata\x1a\x31tracdap/rt/_impl/grpc/tracdap/metadata/type.proto\x1a\x36tracdap/rt/_impl/grpc/tracdap/metadata/object_id.proto\"\xe7\x01\n\x0b\x46ieldSchema\x12\x11\n\tfieldName\x18\x01 \x01(\t\x12\x12\n\nfieldOrder\x18\x02 \x01(\x11\x12.\n\tfieldType\x18\x03 \x01(\x0e\x32\x1b.tracdap.metadata.BasicType\x12\r\n\x05label\x18\x04 \x01(\t\x12\x13\n\x0b\x62usinessKey\x18\x05 \x01(\x08\x12\x13\n\x0b\x63\x61tegorical\x18\x06 \x01(\x08\x12\x14\n\x07notNull\x18\x08 \x01(\x08H\x00\x88\x01\x01\x12\x17\n\nformatCode\x18\x07 \x01(\tH\x01\x88\x01\x01\x42\n\n\x08_notNullB\r\n\x0b_formatCode\"<\n\x0bTableSchema\x12-\n\x06\x66ields\x18\x01 \x03(\x0b\x32\x1d.tracdap.metadata.FieldSchema\"\
|
19
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n1tracdap/rt/_impl/grpc/tracdap/metadata/data.proto\x12\x10tracdap.metadata\x1a\x31tracdap/rt/_impl/grpc/tracdap/metadata/type.proto\x1a\x36tracdap/rt/_impl/grpc/tracdap/metadata/object_id.proto\"\xe7\x01\n\x0b\x46ieldSchema\x12\x11\n\tfieldName\x18\x01 \x01(\t\x12\x12\n\nfieldOrder\x18\x02 \x01(\x11\x12.\n\tfieldType\x18\x03 \x01(\x0e\x32\x1b.tracdap.metadata.BasicType\x12\r\n\x05label\x18\x04 \x01(\t\x12\x13\n\x0b\x62usinessKey\x18\x05 \x01(\x08\x12\x13\n\x0b\x63\x61tegorical\x18\x06 \x01(\x08\x12\x14\n\x07notNull\x18\x08 \x01(\x08H\x00\x88\x01\x01\x12\x17\n\nformatCode\x18\x07 \x01(\tH\x01\x88\x01\x01\x42\n\n\x08_notNullB\r\n\x0b_formatCode\"<\n\x0bTableSchema\x12-\n\x06\x66ields\x18\x01 \x03(\x0b\x32\x1d.tracdap.metadata.FieldSchema\"\xb3\x01\n\x10SchemaDefinition\x12\x30\n\nschemaType\x18\x01 \x01(\x0e\x32\x1c.tracdap.metadata.SchemaType\x12,\n\x08partType\x18\x02 \x01(\x0e\x32\x1a.tracdap.metadata.PartType\x12.\n\x05table\x18\x03 \x01(\x0b\x32\x1d.tracdap.metadata.TableSchemaH\x00\x42\x0f\n\rschemaDetails\"\x81\x02\n\x07PartKey\x12\x11\n\topaqueKey\x18\x01 \x01(\t\x12,\n\x08partType\x18\x02 \x01(\x0e\x32\x1a.tracdap.metadata.PartType\x12+\n\npartValues\x18\x03 \x03(\x0b\x32\x17.tracdap.metadata.Value\x12\x32\n\x0cpartRangeMin\x18\x04 \x01(\x0b\x32\x17.tracdap.metadata.ValueH\x00\x88\x01\x01\x12\x32\n\x0cpartRangeMax\x18\x05 \x01(\x0b\x32\x17.tracdap.metadata.ValueH\x01\x88\x01\x01\x42\x0f\n\r_partRangeMinB\x0f\n\r_partRangeMax\"\xba\x04\n\x0e\x44\x61taDefinition\x12\x31\n\x08schemaId\x18\x01 \x01(\x0b\x32\x1d.tracdap.metadata.TagSelectorH\x00\x12\x34\n\x06schema\x18\x02 \x01(\x0b\x32\".tracdap.metadata.SchemaDefinitionH\x00\x12:\n\x05parts\x18\x03 \x03(\x0b\x32+.tracdap.metadata.DataDefinition.PartsEntry\x12\x30\n\tstorageId\x18\x04 \x01(\x0b\x32\x1d.tracdap.metadata.TagSelector\x1a-\n\x05\x44\x65lta\x12\x12\n\ndeltaIndex\x18\x01 \x01(\r\x12\x10\n\x08\x64\x61taItem\x18\x02 \x01(\t\x1aQ\n\x04Snap\x12\x11\n\tsnapIndex\x18\x01 \x01(\r\x12\x36\n\x06\x64\x65ltas\x18\x02 \x03(\x0b\x32&.tracdap.metadata.DataDefinition.Delta\x1ag\n\x04Part\x12*\n\x07partKey\x18\x01 \x01(\x0b\x32\x19.tracdap.metadata.PartKey\x12\x33\n\x04snap\x18\x02 \x01(\x0b\x32%.tracdap.metadata.DataDefinition.Snap\x1aS\n\nPartsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x34\n\x05value\x18\x02 \x01(\x0b\x32%.tracdap.metadata.DataDefinition.Part:\x02\x38\x01\x42\x11\n\x0fschemaSpecifier*0\n\nSchemaType\x12\x17\n\x13SCHEMA_TYPE_NOT_SET\x10\x00\x12\t\n\x05TABLE\x10\x01*?\n\x08PartType\x12\r\n\tPART_ROOT\x10\x00\x12\x11\n\rPART_BY_RANGE\x10\x01\x12\x11\n\rPART_BY_VALUE\x10\x02\x42\x1e\n\x1aorg.finos.tracdap.metadataP\x01\x62\x06proto3')
|
20
20
|
|
21
21
|
_globals = globals()
|
22
22
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
@@ -26,26 +26,26 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|
26
26
|
_globals['DESCRIPTOR']._serialized_options = b'\n\032org.finos.tracdap.metadataP\001'
|
27
27
|
_globals['_DATADEFINITION_PARTSENTRY']._options = None
|
28
28
|
_globals['_DATADEFINITION_PARTSENTRY']._serialized_options = b'8\001'
|
29
|
-
_globals['_SCHEMATYPE']._serialized_start=
|
30
|
-
_globals['_SCHEMATYPE']._serialized_end=
|
31
|
-
_globals['_PARTTYPE']._serialized_start=
|
32
|
-
_globals['_PARTTYPE']._serialized_end=
|
29
|
+
_globals['_SCHEMATYPE']._serialized_start=1489
|
30
|
+
_globals['_SCHEMATYPE']._serialized_end=1537
|
31
|
+
_globals['_PARTTYPE']._serialized_start=1539
|
32
|
+
_globals['_PARTTYPE']._serialized_end=1602
|
33
33
|
_globals['_FIELDSCHEMA']._serialized_start=179
|
34
34
|
_globals['_FIELDSCHEMA']._serialized_end=410
|
35
35
|
_globals['_TABLESCHEMA']._serialized_start=412
|
36
36
|
_globals['_TABLESCHEMA']._serialized_end=472
|
37
37
|
_globals['_SCHEMADEFINITION']._serialized_start=475
|
38
|
-
_globals['_SCHEMADEFINITION']._serialized_end=
|
39
|
-
_globals['_PARTKEY']._serialized_start=
|
40
|
-
_globals['_PARTKEY']._serialized_end=
|
41
|
-
_globals['_DATADEFINITION']._serialized_start=
|
42
|
-
_globals['_DATADEFINITION']._serialized_end=
|
43
|
-
_globals['_DATADEFINITION_DELTA']._serialized_start=
|
44
|
-
_globals['_DATADEFINITION_DELTA']._serialized_end=
|
45
|
-
_globals['_DATADEFINITION_SNAP']._serialized_start=
|
46
|
-
_globals['_DATADEFINITION_SNAP']._serialized_end=
|
47
|
-
_globals['_DATADEFINITION_PART']._serialized_start=
|
48
|
-
_globals['_DATADEFINITION_PART']._serialized_end=
|
49
|
-
_globals['_DATADEFINITION_PARTSENTRY']._serialized_start=
|
50
|
-
_globals['_DATADEFINITION_PARTSENTRY']._serialized_end=
|
38
|
+
_globals['_SCHEMADEFINITION']._serialized_end=654
|
39
|
+
_globals['_PARTKEY']._serialized_start=657
|
40
|
+
_globals['_PARTKEY']._serialized_end=914
|
41
|
+
_globals['_DATADEFINITION']._serialized_start=917
|
42
|
+
_globals['_DATADEFINITION']._serialized_end=1487
|
43
|
+
_globals['_DATADEFINITION_DELTA']._serialized_start=1150
|
44
|
+
_globals['_DATADEFINITION_DELTA']._serialized_end=1195
|
45
|
+
_globals['_DATADEFINITION_SNAP']._serialized_start=1197
|
46
|
+
_globals['_DATADEFINITION_SNAP']._serialized_end=1278
|
47
|
+
_globals['_DATADEFINITION_PART']._serialized_start=1280
|
48
|
+
_globals['_DATADEFINITION_PART']._serialized_end=1383
|
49
|
+
_globals['_DATADEFINITION_PARTSENTRY']._serialized_start=1385
|
50
|
+
_globals['_DATADEFINITION_PARTSENTRY']._serialized_end=1468
|
51
51
|
# @@protoc_insertion_point(module_scope)
|
@@ -16,7 +16,7 @@ from tracdap.rt._impl.grpc.tracdap.metadata import type_pb2 as tracdap_dot_rt_do
|
|
16
16
|
from tracdap.rt._impl.grpc.tracdap.metadata import data_pb2 as tracdap_dot_rt_dot___impl_dot_grpc_dot_tracdap_dot_metadata_dot_data__pb2
|
17
17
|
|
18
18
|
|
19
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n2tracdap/rt/_impl/grpc/tracdap/metadata/model.proto\x12\x10tracdap.metadata\x1a\x31tracdap/rt/_impl/grpc/tracdap/metadata/type.proto\x1a\x31tracdap/rt/_impl/grpc/tracdap/metadata/data.proto\"\xab\x02\n\x0eModelParameter\x12\x33\n\tparamType\x18\x01 \x01(\x0b\x32 .tracdap.metadata.TypeDescriptor\x12\r\n\x05label\x18\x02 \x01(\t\x12\x32\n\x0c\x64\x65\x66\x61ultValue\x18\x03 \x01(\x0b\x32\x17.tracdap.metadata.ValueH\x00\x88\x01\x01\x12\x44\n\nparamProps\x18\x04 \x03(\x0b\x32\x30.tracdap.metadata.ModelParameter.ParamPropsEntry\x1aJ\n\x0fParamPropsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05value\x18\x02 \x01(\x0b\x32\x17.tracdap.metadata.Value:\x02\x38\x01\x42\x0f\n\r_defaultValue\"\
|
19
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n2tracdap/rt/_impl/grpc/tracdap/metadata/model.proto\x12\x10tracdap.metadata\x1a\x31tracdap/rt/_impl/grpc/tracdap/metadata/type.proto\x1a\x31tracdap/rt/_impl/grpc/tracdap/metadata/data.proto\"\xab\x02\n\x0eModelParameter\x12\x33\n\tparamType\x18\x01 \x01(\x0b\x32 .tracdap.metadata.TypeDescriptor\x12\r\n\x05label\x18\x02 \x01(\t\x12\x32\n\x0c\x64\x65\x66\x61ultValue\x18\x03 \x01(\x0b\x32\x17.tracdap.metadata.ValueH\x00\x88\x01\x01\x12\x44\n\nparamProps\x18\x04 \x03(\x0b\x32\x30.tracdap.metadata.ModelParameter.ParamPropsEntry\x1aJ\n\x0fParamPropsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05value\x18\x02 \x01(\x0b\x32\x17.tracdap.metadata.Value:\x02\x38\x01\x42\x0f\n\r_defaultValue\"\x9b\x02\n\x10ModelInputSchema\x12\x32\n\x06schema\x18\x01 \x01(\x0b\x32\".tracdap.metadata.SchemaDefinition\x12\x12\n\x05label\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x10\n\x08optional\x18\x03 \x01(\x08\x12\x0f\n\x07\x64ynamic\x18\x05 \x01(\x08\x12\x46\n\ninputProps\x18\x04 \x03(\x0b\x32\x32.tracdap.metadata.ModelInputSchema.InputPropsEntry\x1aJ\n\x0fInputPropsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05value\x18\x02 \x01(\x0b\x32\x17.tracdap.metadata.Value:\x02\x38\x01\x42\x08\n\x06_label\"\xa0\x02\n\x11ModelOutputSchema\x12\x32\n\x06schema\x18\x01 \x01(\x0b\x32\".tracdap.metadata.SchemaDefinition\x12\x12\n\x05label\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x10\n\x08optional\x18\x03 \x01(\x08\x12\x0f\n\x07\x64ynamic\x18\x05 \x01(\x08\x12I\n\x0boutputProps\x18\x04 \x03(\x0b\x32\x34.tracdap.metadata.ModelOutputSchema.OutputPropsEntry\x1aK\n\x10OutputPropsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05value\x18\x02 \x01(\x0b\x32\x17.tracdap.metadata.Value:\x02\x38\x01\x42\x08\n\x06_label\"\x9e\x06\n\x0fModelDefinition\x12\x10\n\x08language\x18\x01 \x01(\t\x12\x12\n\nrepository\x18\x02 \x01(\t\x12\x19\n\x0cpackageGroup\x18\n \x01(\tH\x00\x88\x01\x01\x12\x0f\n\x07package\x18\x0b \x01(\t\x12\x0f\n\x07version\x18\x06 \x01(\t\x12\x12\n\nentryPoint\x18\x05 \x01(\t\x12\x11\n\x04path\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x45\n\nparameters\x18\x07 \x03(\x0b\x32\x31.tracdap.metadata.ModelDefinition.ParametersEntry\x12=\n\x06inputs\x18\x08 \x03(\x0b\x32-.tracdap.metadata.ModelDefinition.InputsEntry\x12?\n\x07outputs\x18\t \x03(\x0b\x32..tracdap.metadata.ModelDefinition.OutputsEntry\x12Q\n\x10staticAttributes\x18\x0c \x03(\x0b\x32\x37.tracdap.metadata.ModelDefinition.StaticAttributesEntry\x1aS\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .tracdap.metadata.ModelParameter:\x02\x38\x01\x1aQ\n\x0bInputsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x31\n\x05value\x18\x02 \x01(\x0b\x32\".tracdap.metadata.ModelInputSchema:\x02\x38\x01\x1aS\n\x0cOutputsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x32\n\x05value\x18\x02 \x01(\x0b\x32#.tracdap.metadata.ModelOutputSchema:\x02\x38\x01\x1aP\n\x15StaticAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05value\x18\x02 \x01(\x0b\x32\x17.tracdap.metadata.Value:\x02\x38\x01\x42\x0f\n\r_packageGroupB\x07\n\x05_pathB\x1e\n\x1aorg.finos.tracdap.metadataP\x01\x62\x06proto3')
|
20
20
|
|
21
21
|
_globals = globals()
|
22
22
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
@@ -43,21 +43,21 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|
43
43
|
_globals['_MODELPARAMETER_PARAMPROPSENTRY']._serialized_start=383
|
44
44
|
_globals['_MODELPARAMETER_PARAMPROPSENTRY']._serialized_end=457
|
45
45
|
_globals['_MODELINPUTSCHEMA']._serialized_start=477
|
46
|
-
_globals['_MODELINPUTSCHEMA']._serialized_end=
|
47
|
-
_globals['_MODELINPUTSCHEMA_INPUTPROPSENTRY']._serialized_start=
|
48
|
-
_globals['_MODELINPUTSCHEMA_INPUTPROPSENTRY']._serialized_end=
|
49
|
-
_globals['_MODELOUTPUTSCHEMA']._serialized_start=
|
50
|
-
_globals['_MODELOUTPUTSCHEMA']._serialized_end=
|
51
|
-
_globals['_MODELOUTPUTSCHEMA_OUTPUTPROPSENTRY']._serialized_start=
|
52
|
-
_globals['_MODELOUTPUTSCHEMA_OUTPUTPROPSENTRY']._serialized_end=
|
53
|
-
_globals['_MODELDEFINITION']._serialized_start=
|
54
|
-
_globals['_MODELDEFINITION']._serialized_end=
|
55
|
-
_globals['_MODELDEFINITION_PARAMETERSENTRY']._serialized_start=
|
56
|
-
_globals['_MODELDEFINITION_PARAMETERSENTRY']._serialized_end=
|
57
|
-
_globals['_MODELDEFINITION_INPUTSENTRY']._serialized_start=
|
58
|
-
_globals['_MODELDEFINITION_INPUTSENTRY']._serialized_end=
|
59
|
-
_globals['_MODELDEFINITION_OUTPUTSENTRY']._serialized_start=
|
60
|
-
_globals['_MODELDEFINITION_OUTPUTSENTRY']._serialized_end=
|
61
|
-
_globals['_MODELDEFINITION_STATICATTRIBUTESENTRY']._serialized_start=
|
62
|
-
_globals['_MODELDEFINITION_STATICATTRIBUTESENTRY']._serialized_end=
|
46
|
+
_globals['_MODELINPUTSCHEMA']._serialized_end=760
|
47
|
+
_globals['_MODELINPUTSCHEMA_INPUTPROPSENTRY']._serialized_start=676
|
48
|
+
_globals['_MODELINPUTSCHEMA_INPUTPROPSENTRY']._serialized_end=750
|
49
|
+
_globals['_MODELOUTPUTSCHEMA']._serialized_start=763
|
50
|
+
_globals['_MODELOUTPUTSCHEMA']._serialized_end=1051
|
51
|
+
_globals['_MODELOUTPUTSCHEMA_OUTPUTPROPSENTRY']._serialized_start=966
|
52
|
+
_globals['_MODELOUTPUTSCHEMA_OUTPUTPROPSENTRY']._serialized_end=1041
|
53
|
+
_globals['_MODELDEFINITION']._serialized_start=1054
|
54
|
+
_globals['_MODELDEFINITION']._serialized_end=1852
|
55
|
+
_globals['_MODELDEFINITION_PARAMETERSENTRY']._serialized_start=1493
|
56
|
+
_globals['_MODELDEFINITION_PARAMETERSENTRY']._serialized_end=1576
|
57
|
+
_globals['_MODELDEFINITION_INPUTSENTRY']._serialized_start=1578
|
58
|
+
_globals['_MODELDEFINITION_INPUTSENTRY']._serialized_end=1659
|
59
|
+
_globals['_MODELDEFINITION_OUTPUTSENTRY']._serialized_start=1661
|
60
|
+
_globals['_MODELDEFINITION_OUTPUTSENTRY']._serialized_end=1744
|
61
|
+
_globals['_MODELDEFINITION_STATICATTRIBUTESENTRY']._serialized_start=1746
|
62
|
+
_globals['_MODELDEFINITION_STATICATTRIBUTESENTRY']._serialized_end=1826
|
63
63
|
# @@protoc_insertion_point(module_scope)
|
@@ -27,7 +27,7 @@ class ModelParameter(_message.Message):
|
|
27
27
|
def __init__(self, paramType: _Optional[_Union[_type_pb2.TypeDescriptor, _Mapping]] = ..., label: _Optional[str] = ..., defaultValue: _Optional[_Union[_type_pb2.Value, _Mapping]] = ..., paramProps: _Optional[_Mapping[str, _type_pb2.Value]] = ...) -> None: ...
|
28
28
|
|
29
29
|
class ModelInputSchema(_message.Message):
|
30
|
-
__slots__ = ("schema", "label", "optional", "inputProps")
|
30
|
+
__slots__ = ("schema", "label", "optional", "dynamic", "inputProps")
|
31
31
|
class InputPropsEntry(_message.Message):
|
32
32
|
__slots__ = ("key", "value")
|
33
33
|
KEY_FIELD_NUMBER: _ClassVar[int]
|
@@ -38,15 +38,17 @@ class ModelInputSchema(_message.Message):
|
|
38
38
|
SCHEMA_FIELD_NUMBER: _ClassVar[int]
|
39
39
|
LABEL_FIELD_NUMBER: _ClassVar[int]
|
40
40
|
OPTIONAL_FIELD_NUMBER: _ClassVar[int]
|
41
|
+
DYNAMIC_FIELD_NUMBER: _ClassVar[int]
|
41
42
|
INPUTPROPS_FIELD_NUMBER: _ClassVar[int]
|
42
43
|
schema: _data_pb2.SchemaDefinition
|
43
44
|
label: str
|
44
45
|
optional: bool
|
46
|
+
dynamic: bool
|
45
47
|
inputProps: _containers.MessageMap[str, _type_pb2.Value]
|
46
|
-
def __init__(self, schema: _Optional[_Union[_data_pb2.SchemaDefinition, _Mapping]] = ..., label: _Optional[str] = ..., optional: bool = ..., inputProps: _Optional[_Mapping[str, _type_pb2.Value]] = ...) -> None: ...
|
48
|
+
def __init__(self, schema: _Optional[_Union[_data_pb2.SchemaDefinition, _Mapping]] = ..., label: _Optional[str] = ..., optional: bool = ..., dynamic: bool = ..., inputProps: _Optional[_Mapping[str, _type_pb2.Value]] = ...) -> None: ...
|
47
49
|
|
48
50
|
class ModelOutputSchema(_message.Message):
|
49
|
-
__slots__ = ("schema", "label", "optional", "outputProps")
|
51
|
+
__slots__ = ("schema", "label", "optional", "dynamic", "outputProps")
|
50
52
|
class OutputPropsEntry(_message.Message):
|
51
53
|
__slots__ = ("key", "value")
|
52
54
|
KEY_FIELD_NUMBER: _ClassVar[int]
|
@@ -57,12 +59,14 @@ class ModelOutputSchema(_message.Message):
|
|
57
59
|
SCHEMA_FIELD_NUMBER: _ClassVar[int]
|
58
60
|
LABEL_FIELD_NUMBER: _ClassVar[int]
|
59
61
|
OPTIONAL_FIELD_NUMBER: _ClassVar[int]
|
62
|
+
DYNAMIC_FIELD_NUMBER: _ClassVar[int]
|
60
63
|
OUTPUTPROPS_FIELD_NUMBER: _ClassVar[int]
|
61
64
|
schema: _data_pb2.SchemaDefinition
|
62
65
|
label: str
|
63
66
|
optional: bool
|
67
|
+
dynamic: bool
|
64
68
|
outputProps: _containers.MessageMap[str, _type_pb2.Value]
|
65
|
-
def __init__(self, schema: _Optional[_Union[_data_pb2.SchemaDefinition, _Mapping]] = ..., label: _Optional[str] = ..., optional: bool = ..., outputProps: _Optional[_Mapping[str, _type_pb2.Value]] = ...) -> None: ...
|
69
|
+
def __init__(self, schema: _Optional[_Union[_data_pb2.SchemaDefinition, _Mapping]] = ..., label: _Optional[str] = ..., optional: bool = ..., dynamic: bool = ..., outputProps: _Optional[_Mapping[str, _type_pb2.Value]] = ...) -> None: ...
|
66
70
|
|
67
71
|
class ModelDefinition(_message.Message):
|
68
72
|
__slots__ = ("language", "repository", "packageGroup", "package", "version", "entryPoint", "path", "parameters", "inputs", "outputs", "staticAttributes")
|
tracdap/rt/_impl/static_api.py
CHANGED
@@ -154,33 +154,49 @@ class StaticApiImpl(_StaticApiHook):
|
|
154
154
|
|
155
155
|
def define_input_table(
|
156
156
|
self, *fields: _tp.Union[_meta.FieldSchema, _tp.List[_meta.FieldSchema]],
|
157
|
-
label: _tp.Optional[str] = None,
|
158
|
-
optional: bool = False,
|
157
|
+
label: _tp.Optional[str] = None, optional: bool = False, dynamic: bool = False,
|
159
158
|
input_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) \
|
160
159
|
-> _meta.ModelInputSchema:
|
161
160
|
|
162
161
|
_val.validate_signature(
|
163
162
|
self.define_input_table, *fields,
|
164
|
-
label=label, optional=optional,
|
163
|
+
label=label, optional=optional, dynamic=dynamic,
|
165
164
|
input_props=input_props)
|
166
165
|
|
167
|
-
|
168
|
-
|
166
|
+
# Do not define details for dynamic schemas
|
167
|
+
|
168
|
+
if dynamic:
|
169
|
+
schema_def = _meta.SchemaDefinition(_meta.SchemaType.TABLE)
|
170
|
+
else:
|
171
|
+
schema_def = self.define_schema(*fields, schema_type=_meta.SchemaType.TABLE)
|
172
|
+
|
173
|
+
return _meta.ModelInputSchema(
|
174
|
+
schema=schema_def, label=label,
|
175
|
+
optional=optional, dynamic=dynamic,
|
176
|
+
inputProps=input_props)
|
169
177
|
|
170
178
|
def define_output_table(
|
171
179
|
self, *fields: _tp.Union[_meta.FieldSchema, _tp.List[_meta.FieldSchema]],
|
172
|
-
label: _tp.Optional[str] = None,
|
173
|
-
optional: bool = False,
|
180
|
+
label: _tp.Optional[str] = None, optional: bool = False, dynamic: bool = False,
|
174
181
|
output_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) \
|
175
182
|
-> _meta.ModelOutputSchema:
|
176
183
|
|
177
184
|
_val.validate_signature(
|
178
185
|
self.define_output_table, *fields,
|
179
|
-
label=label, optional=optional,
|
186
|
+
label=label, optional=optional, dynamic=dynamic,
|
180
187
|
output_props=output_props)
|
181
188
|
|
182
|
-
|
183
|
-
|
189
|
+
# Do not define details for dynamic schemas
|
190
|
+
|
191
|
+
if dynamic:
|
192
|
+
schema_def = _meta.SchemaDefinition(_meta.SchemaType.TABLE)
|
193
|
+
else:
|
194
|
+
schema_def = self.define_schema(*fields, schema_type=_meta.SchemaType.TABLE)
|
195
|
+
|
196
|
+
return _meta.ModelOutputSchema(
|
197
|
+
schema=schema_def, label=label,
|
198
|
+
optional=optional, dynamic=dynamic,
|
199
|
+
outputProps=output_props)
|
184
200
|
|
185
201
|
@staticmethod
|
186
202
|
def _build_named_dict(
|
tracdap/rt/_impl/validation.py
CHANGED
@@ -38,7 +38,7 @@ def check_type(expected_type: tp.Type, value: tp.Any) -> bool:
|
|
38
38
|
|
39
39
|
|
40
40
|
def quick_validate_model_def(model_def: meta.ModelDefinition):
|
41
|
-
|
41
|
+
StaticValidator.quick_validate_model_def(model_def)
|
42
42
|
|
43
43
|
|
44
44
|
class _TypeValidator:
|
@@ -233,7 +233,7 @@ class _TypeValidator:
|
|
233
233
|
return type_var.__name__
|
234
234
|
|
235
235
|
|
236
|
-
class
|
236
|
+
class StaticValidator:
|
237
237
|
|
238
238
|
__identifier_pattern = re.compile("\\A[a-zA-Z_]\\w*\\Z", re.ASCII)
|
239
239
|
__reserved_identifier_pattern = re.compile("\\A(_|trac_)", re.ASCII)
|
@@ -301,6 +301,28 @@ class _StaticValidator:
|
|
301
301
|
cls._check_inputs_or_outputs(model_def.inputs)
|
302
302
|
cls._check_inputs_or_outputs(model_def.outputs)
|
303
303
|
|
304
|
+
@classmethod
|
305
|
+
def quick_validate_schema(cls, schema: meta.SchemaDefinition):
|
306
|
+
|
307
|
+
if schema.schemaType != meta.SchemaType.TABLE:
|
308
|
+
cls._fail(f"Unsupported schema type [{schema.schemaType}]")
|
309
|
+
|
310
|
+
if schema.partType != meta.PartType.PART_ROOT:
|
311
|
+
cls._fail(f"Unsupported partition type [{schema.partType}]")
|
312
|
+
|
313
|
+
if schema.table is None or schema.table.fields is None or len(schema.table.fields) == 0:
|
314
|
+
cls._fail(f"Table schema does not define any fields")
|
315
|
+
|
316
|
+
fields = schema.table.fields
|
317
|
+
field_names = list(map(lambda f: f.fieldName, fields))
|
318
|
+
property_type = f"field"
|
319
|
+
|
320
|
+
cls._valid_identifiers(field_names, property_type)
|
321
|
+
cls._case_insensitive_duplicates(field_names, property_type)
|
322
|
+
|
323
|
+
for field in fields:
|
324
|
+
cls._check_single_field(field, property_type)
|
325
|
+
|
304
326
|
@classmethod
|
305
327
|
def _check_label(cls, label, param_name):
|
306
328
|
if label is not None:
|
@@ -330,10 +352,20 @@ class _StaticValidator:
|
|
330
352
|
|
331
353
|
cls._log.info(f"Checking {input_name}")
|
332
354
|
|
355
|
+
if input_schema.dynamic:
|
356
|
+
if input_schema.schema and input_schema.schema.table:
|
357
|
+
error = "Dynamic schemas must have schema.table = None"
|
358
|
+
cls._fail(f"Invalid schema for [{input_name}]: {error}")
|
359
|
+
else:
|
360
|
+
continue
|
361
|
+
|
333
362
|
fields = input_schema.schema.table.fields
|
334
363
|
field_names = list(map(lambda f: f.fieldName, fields))
|
335
364
|
property_type = f"field in [{input_name}]"
|
336
365
|
|
366
|
+
if len(fields) == 0:
|
367
|
+
cls._fail(f"Invalid schema for [{input_name}]: No fields defined")
|
368
|
+
|
337
369
|
cls._valid_identifiers(field_names, property_type)
|
338
370
|
cls._case_insensitive_duplicates(field_names, property_type)
|
339
371
|
|
@@ -375,8 +407,9 @@ class _StaticValidator:
|
|
375
407
|
if field.categorical and field.fieldType != meta.BasicType.STRING:
|
376
408
|
cls._fail(f"Invalid {property_type}: [{field.fieldName}] fieldType {field.fieldType} used as categorical")
|
377
409
|
|
378
|
-
|
379
|
-
|
410
|
+
# Do not require notNull = True for business keys here
|
411
|
+
# Instead setting businessKey = True will cause notNull = True to be set during normalization
|
412
|
+
# This agrees with the semantics in platform API and CSV schema loader
|
380
413
|
|
381
414
|
@classmethod
|
382
415
|
def _valid_identifiers(cls, keys, property_type):
|
tracdap/rt/_version.py
CHANGED
tracdap/rt/api/hook.py
CHANGED
@@ -121,8 +121,7 @@ class _StaticApiHook:
|
|
121
121
|
@_abc.abstractmethod
|
122
122
|
def define_input_table(
|
123
123
|
self, *fields: _tp.Union[_meta.FieldSchema, _tp.List[_meta.FieldSchema]],
|
124
|
-
label: _tp.Optional[str] = None,
|
125
|
-
optional: bool = False,
|
124
|
+
label: _tp.Optional[str] = None, optional: bool = False, dynamic: bool = False,
|
126
125
|
input_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) \
|
127
126
|
-> _meta.ModelInputSchema:
|
128
127
|
|
@@ -131,8 +130,7 @@ class _StaticApiHook:
|
|
131
130
|
@_abc.abstractmethod
|
132
131
|
def define_output_table(
|
133
132
|
self, *fields: _tp.Union[_meta.FieldSchema, _tp.List[_meta.FieldSchema]],
|
134
|
-
label: _tp.Optional[str] = None,
|
135
|
-
optional: bool = False,
|
133
|
+
label: _tp.Optional[str] = None, optional: bool = False, dynamic: bool = False,
|
136
134
|
output_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) \
|
137
135
|
-> _meta.ModelOutputSchema:
|
138
136
|
|
tracdap/rt/api/model_api.py
CHANGED
@@ -100,13 +100,26 @@ class TracContext:
|
|
100
100
|
"""
|
101
101
|
Get the schema of a model input or output
|
102
102
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
103
|
+
Use this method to get the :py:class:`SchemaDefinition <tracdap.rt.metadata.SchemaDefinition>`
|
104
|
+
for any input or output of the current model.
|
105
|
+
For datasets with static schemas, this will be the same schema that was defined in the
|
106
|
+
:py:class:`TracModel <tracdap.rt.api.TracModel>` methods
|
107
|
+
:py:meth:`define_inputs() <tracdap.rt.api.TracModel.define_inputs>` and
|
108
|
+
:py:meth:`define_outputs() <tracdap.rt.api.TracModel.define_outputs>`.
|
109
|
+
|
110
|
+
For inputs with dynamic schemas, the schema of the provided input dataset will be returned.
|
111
|
+
For outputs with dynamic schemas the schema must be set by calling
|
112
|
+
:py:meth:`put_schema() <tracdap.rt.api.TracContext.put_schema>`, after which this method
|
113
|
+
will return that schema. Calling :py:meth:`get_schema() <tracdap.rt.api.TracContext.get_schema>`
|
114
|
+
for a dynamic output before the schema is set will result in a runtime validation error.
|
115
|
+
|
116
|
+
For optional inputs, use :py:meth:`has_dataset() <tracdap.rt.api.TracContext.has_dataset>`
|
117
|
+
to check whether the input was provided. Calling :py:meth:`get_schema() <tracdap.rt.api.TracContext.get_schema>`
|
118
|
+
for an optional input that was not provided will always result in a validation error,
|
119
|
+
regardless of whether the input using a static or dynamic schema. For optional outputs
|
120
|
+
:py:meth:`get_schema() <tracdap.rt.api.TracContext.get_schema>` can be called, with the
|
121
|
+
normal proviso that dynamic schemas must first be set by calling
|
122
|
+
:py:meth:`put_schema() <tracdap.rt.api.TracContext.put_schema>`.
|
110
123
|
|
111
124
|
Attempting to retrieve the schema for a dataset that is not defined as a model input or output
|
112
125
|
will result in a runtime validation error, even if that dataset exists in the job config and
|
@@ -152,6 +165,36 @@ class TracContext:
|
|
152
165
|
"""
|
153
166
|
pass
|
154
167
|
|
168
|
+
@_abc.abstractmethod
|
169
|
+
def put_schema(self, dataset_name: str, schema: SchemaDefinition):
|
170
|
+
|
171
|
+
"""
|
172
|
+
Set the schema of a dynamic model output
|
173
|
+
|
174
|
+
For outputs marked as dynamic, a :py:class:`SchemaDefinition <tracdap.rt.metadata.SchemaDefinition>`
|
175
|
+
must be supplied before attempting to save the data. TRAC API functions are available to help with
|
176
|
+
building schemas, such as :py:func:`trac.F() <tracdap.rt.api.F>` to define fields or
|
177
|
+
:py:func:`load_schema() <tracdap.rt.api.load_schema>` to load predefined schemas.
|
178
|
+
Once a schema has been set, it can be retrieved by calling
|
179
|
+
:py:meth:`get_schema() <tracdap.rt.api.TracContext.get_schema>` as normal.
|
180
|
+
If :py:meth:`put_schema() <tracdap.rt.api.TracContext.put_schema>` is called for an optional
|
181
|
+
output the model must also supply data for that output, otherwise TRAC will report a runtime
|
182
|
+
validation error after the model completes.
|
183
|
+
|
184
|
+
Each schema can only be set once and the schema will be validated using the normal
|
185
|
+
validation rules. If validation fails this method will raise
|
186
|
+
:py:class:`ERuntimeValidation <tracdap.rt.exceptions.ERuntimeValidation>`.
|
187
|
+
Attempting to set the schema for a dataset that is not defined as a dynamic model output
|
188
|
+
for the current model will result in a runtime validation error.
|
189
|
+
|
190
|
+
:param dataset_name: The name of the output to set the schema for
|
191
|
+
:param schema: A TRAC schema definition to use for the named output
|
192
|
+
:type schema: :py:class:`SchemaDefinition <tracdap.rt.metadata.SchemaDefinition>`
|
193
|
+
:raises: :py:class:`ERuntimeValidation <tracdap.rt.exceptions.ERuntimeValidation>`
|
194
|
+
"""
|
195
|
+
|
196
|
+
pass
|
197
|
+
|
155
198
|
@_abc.abstractmethod
|
156
199
|
def put_pandas_table(self, dataset_name: str, dataset: pandas.DataFrame):
|
157
200
|
|
tracdap/rt/api/static_api.py
CHANGED
@@ -451,8 +451,7 @@ def load_schema(
|
|
451
451
|
|
452
452
|
def define_input_table(
|
453
453
|
*fields: _tp.Union[FieldSchema, _tp.List[FieldSchema]],
|
454
|
-
label: _tp.Optional[str] = None,
|
455
|
-
optional: bool = False,
|
454
|
+
label: _tp.Optional[str] = None, optional: bool = False, dynamic: bool = False,
|
456
455
|
input_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) \
|
457
456
|
-> ModelInputSchema:
|
458
457
|
|
@@ -469,6 +468,7 @@ def define_input_table(
|
|
469
468
|
:param fields: A set of fields to make up a :py:class:`TableSchema <tracdap.rt.metadata.TableSchema>`
|
470
469
|
:param label: An optional label (of type str) for a model input schema. Default value: None.
|
471
470
|
:param optional: Mark this input as an optional model input
|
471
|
+
:param dynamic: Mark this input as a dynamic model input (the list of fields must be empty)
|
472
472
|
:param input_props: Associate key-value properties with this input (not used by the TRAC engine)
|
473
473
|
:return: A model input schema, suitable for returning from :py:meth:`TracModel.define_inputs`
|
474
474
|
|
@@ -476,12 +476,16 @@ def define_input_table(
|
|
476
476
|
List[:py:class:`FieldSchema <tracdap.rt.metadata.FieldSchema>`]
|
477
477
|
:type label: Optional[str]
|
478
478
|
:type optional: bool
|
479
|
+
:type dynamic: bool
|
479
480
|
:type input_props: Optional[Dict[str, Any]]
|
480
481
|
:rtype: :py:class:`ModelInputSchema <tracdap.rt.metadata.ModelInputSchema>`
|
481
482
|
"""
|
482
483
|
|
483
484
|
sa = _StaticApiHook.get_instance()
|
484
|
-
|
485
|
+
|
486
|
+
return sa.define_input_table(
|
487
|
+
*fields, label=label, optional=optional, dynamic=dynamic,
|
488
|
+
input_props=input_props)
|
485
489
|
|
486
490
|
|
487
491
|
def declare_input_table(
|
@@ -507,8 +511,7 @@ def declare_input_table(
|
|
507
511
|
|
508
512
|
def define_output_table(
|
509
513
|
*fields: _tp.Union[FieldSchema, _tp.List[FieldSchema]],
|
510
|
-
label: _tp.Optional[str] = None,
|
511
|
-
optional: bool = False,
|
514
|
+
label: _tp.Optional[str] = None, optional: bool = False, dynamic: bool = False,
|
512
515
|
output_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) \
|
513
516
|
-> ModelOutputSchema:
|
514
517
|
|
@@ -525,6 +528,7 @@ def define_output_table(
|
|
525
528
|
:param fields: A set of fields to make up a :py:class:`TableSchema <tracdap.rt.metadata.TableSchema>`
|
526
529
|
:param label: An optional label (of type str) for a model output schema. Default value: None.
|
527
530
|
:param optional: Mark this output as an optional model output
|
531
|
+
:param dynamic: Mark this output as a dynamic model output (the list of fields must be empty)
|
528
532
|
:param output_props: Associate key-value properties with this output (not used by the TRAC engine)
|
529
533
|
:return: A model output schema, suitable for returning from :py:meth:`TracModel.define_outputs`
|
530
534
|
|
@@ -532,12 +536,16 @@ def define_output_table(
|
|
532
536
|
List[:py:class:`FieldSchema <tracdap.rt.metadata.FieldSchema>`]
|
533
537
|
:type label: Optional[str]
|
534
538
|
:type optional: bool
|
539
|
+
:type dynamic: bool
|
535
540
|
:type output_props: Optional[Dict[str, Any]]
|
536
541
|
:rtype: :py:class:`ModelOutputSchema <tracdap.rt.metadata.ModelOutputSchema>`
|
537
542
|
"""
|
538
543
|
|
539
544
|
sa = _StaticApiHook.get_instance()
|
540
|
-
|
545
|
+
|
546
|
+
return sa.define_output_table(
|
547
|
+
*fields, label=label, optional=optional, dynamic=dynamic,
|
548
|
+
output_props=output_props)
|
541
549
|
|
542
550
|
|
543
551
|
def declare_output_table(
|