tracdap-runtime 0.7.0rc1__py3-none-any.whl → 0.8.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.
- tracdap/rt/_impl/core/__init__.py +14 -0
- tracdap/rt/_impl/{config_parser.py → core/config_parser.py} +61 -36
- tracdap/rt/_impl/{data.py → core/data.py} +136 -32
- tracdap/rt/_impl/core/logging.py +195 -0
- tracdap/rt/_impl/{models.py → core/models.py} +15 -12
- tracdap/rt/_impl/{repos.py → core/repos.py} +12 -3
- tracdap/rt/_impl/{schemas.py → core/schemas.py} +5 -5
- tracdap/rt/_impl/{shim.py → core/shim.py} +5 -4
- tracdap/rt/_impl/{storage.py → core/storage.py} +21 -10
- tracdap/rt/_impl/core/struct.py +547 -0
- tracdap/rt/_impl/{type_system.py → core/type_system.py} +73 -33
- tracdap/rt/_impl/{util.py → core/util.py} +1 -111
- tracdap/rt/_impl/{validation.py → core/validation.py} +99 -31
- tracdap/rt/_impl/exec/__init__.py +14 -0
- tracdap/rt/{_exec → _impl/exec}/actors.py +12 -14
- tracdap/rt/{_exec → _impl/exec}/context.py +228 -82
- tracdap/rt/{_exec → _impl/exec}/dev_mode.py +176 -89
- tracdap/rt/{_exec → _impl/exec}/engine.py +230 -105
- tracdap/rt/{_exec → _impl/exec}/functions.py +191 -100
- tracdap/rt/{_exec → _impl/exec}/graph.py +24 -36
- tracdap/rt/{_exec → _impl/exec}/graph_builder.py +252 -115
- tracdap/rt/_impl/grpc/codec.py +1 -1
- tracdap/rt/{_exec → _impl/grpc}/server.py +7 -6
- tracdap/rt/_impl/grpc/tracdap/api/internal/runtime_pb2.py +3 -3
- tracdap/rt/_impl/grpc/tracdap/api/internal/runtime_pb2_grpc.py +1 -1
- tracdap/rt/_impl/grpc/tracdap/metadata/common_pb2.py +1 -1
- tracdap/rt/_impl/grpc/tracdap/metadata/config_pb2.py +40 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/config_pb2.pyi +62 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/custom_pb2.py +1 -1
- tracdap/rt/_impl/grpc/tracdap/metadata/data_pb2.py +32 -20
- tracdap/rt/_impl/grpc/tracdap/metadata/data_pb2.pyi +48 -2
- tracdap/rt/_impl/grpc/tracdap/metadata/file_pb2.py +4 -2
- tracdap/rt/_impl/grpc/tracdap/metadata/file_pb2.pyi +8 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/flow_pb2.py +1 -1
- tracdap/rt/_impl/grpc/tracdap/metadata/job_pb2.py +65 -63
- tracdap/rt/_impl/grpc/tracdap/metadata/job_pb2.pyi +16 -2
- tracdap/rt/_impl/grpc/tracdap/metadata/model_pb2.py +28 -26
- tracdap/rt/_impl/grpc/tracdap/metadata/model_pb2.pyi +14 -4
- tracdap/rt/_impl/grpc/tracdap/metadata/object_id_pb2.py +4 -4
- tracdap/rt/_impl/grpc/tracdap/metadata/object_id_pb2.pyi +6 -0
- tracdap/rt/_impl/grpc/tracdap/metadata/object_pb2.py +9 -7
- tracdap/rt/_impl/grpc/tracdap/metadata/object_pb2.pyi +12 -4
- tracdap/rt/_impl/grpc/tracdap/metadata/resource_pb2.py +18 -5
- tracdap/rt/_impl/grpc/tracdap/metadata/resource_pb2.pyi +42 -2
- tracdap/rt/_impl/grpc/tracdap/metadata/search_pb2.py +1 -1
- tracdap/rt/_impl/grpc/tracdap/metadata/{stoarge_pb2.py → storage_pb2.py} +4 -4
- tracdap/rt/_impl/grpc/tracdap/metadata/tag_pb2.py +1 -1
- tracdap/rt/_impl/grpc/tracdap/metadata/tag_update_pb2.py +1 -1
- tracdap/rt/_impl/grpc/tracdap/metadata/type_pb2.py +1 -1
- tracdap/rt/{_exec → _impl}/runtime.py +32 -18
- tracdap/rt/_impl/static_api.py +66 -38
- tracdap/rt/_plugins/format_csv.py +1 -1
- tracdap/rt/_plugins/repo_git.py +56 -11
- tracdap/rt/_plugins/storage_sql.py +13 -6
- tracdap/rt/_version.py +1 -1
- tracdap/rt/api/__init__.py +5 -24
- tracdap/rt/api/constants.py +57 -0
- tracdap/rt/api/experimental.py +32 -0
- tracdap/rt/api/hook.py +26 -7
- tracdap/rt/api/model_api.py +16 -0
- tracdap/rt/api/static_api.py +265 -127
- tracdap/rt/config/__init__.py +11 -11
- tracdap/rt/config/common.py +2 -26
- tracdap/rt/config/dynamic.py +28 -0
- tracdap/rt/config/platform.py +17 -31
- tracdap/rt/config/runtime.py +2 -0
- tracdap/rt/ext/embed.py +2 -2
- tracdap/rt/ext/plugins.py +3 -3
- tracdap/rt/launch/launch.py +12 -14
- tracdap/rt/metadata/__init__.py +31 -21
- tracdap/rt/metadata/config.py +95 -0
- tracdap/rt/metadata/data.py +40 -0
- tracdap/rt/metadata/file.py +10 -0
- tracdap/rt/metadata/job.py +16 -0
- tracdap/rt/metadata/model.py +12 -2
- tracdap/rt/metadata/object.py +9 -1
- tracdap/rt/metadata/object_id.py +6 -0
- tracdap/rt/metadata/resource.py +41 -1
- {tracdap_runtime-0.7.0rc1.dist-info → tracdap_runtime-0.8.0.dist-info}/METADATA +33 -27
- tracdap_runtime-0.8.0.dist-info/RECORD +129 -0
- {tracdap_runtime-0.7.0rc1.dist-info → tracdap_runtime-0.8.0.dist-info}/WHEEL +1 -1
- tracdap/rt/_exec/__init__.py +0 -0
- tracdap_runtime-0.7.0rc1.dist-info/RECORD +0 -121
- /tracdap/rt/_impl/{guard_rails.py → core/guard_rails.py} +0 -0
- /tracdap/rt/_impl/grpc/tracdap/metadata/{stoarge_pb2.pyi → storage_pb2.pyi} +0 -0
- /tracdap/rt/metadata/{stoarge.py → storage.py} +0 -0
- {tracdap_runtime-0.7.0rc1.dist-info → tracdap_runtime-0.8.0.dist-info/licenses}/LICENSE +0 -0
- {tracdap_runtime-0.7.0rc1.dist-info → tracdap_runtime-0.8.0.dist-info}/top_level.txt +0 -0
tracdap/rt/_impl/static_api.py
CHANGED
@@ -19,10 +19,11 @@ import types as _ts
|
|
19
19
|
import tracdap.rt.api.experimental as _api
|
20
20
|
import tracdap.rt.metadata as _meta
|
21
21
|
import tracdap.rt.exceptions as _ex
|
22
|
-
import tracdap.rt._impl.data as _data
|
23
|
-
import tracdap.rt._impl.schemas as _schemas
|
24
|
-
import tracdap.rt._impl.
|
25
|
-
import tracdap.rt._impl.
|
22
|
+
import tracdap.rt._impl.core.data as _data
|
23
|
+
import tracdap.rt._impl.core.schemas as _schemas
|
24
|
+
import tracdap.rt._impl.core.struct as _struct
|
25
|
+
import tracdap.rt._impl.core.type_system as _type_system
|
26
|
+
import tracdap.rt._impl.core.validation as _val
|
26
27
|
|
27
28
|
# Import hook interfaces into this module namespace
|
28
29
|
from tracdap.rt.api.hook import _StaticApiHook # noqa
|
@@ -55,7 +56,7 @@ class StaticApiImpl(_StaticApiHook):
|
|
55
56
|
if not _val.is_primitive_type(entry_type):
|
56
57
|
raise _ex.EModelValidation(f"Maps can only contain primitive types, [{entry_type}] is not primitive")
|
57
58
|
|
58
|
-
return _meta.TypeDescriptor(_meta.BasicType.MAP,
|
59
|
+
return _meta.TypeDescriptor(_meta.BasicType.MAP, mapType=_meta.TypeDescriptor(entry_type))
|
59
60
|
|
60
61
|
def define_attribute(
|
61
62
|
self, attr_name: str, attr_value: _tp.Any,
|
@@ -150,16 +151,27 @@ class StaticApiImpl(_StaticApiHook):
|
|
150
151
|
notNull=not_null,
|
151
152
|
formatCode=format_code)
|
152
153
|
|
154
|
+
def define_struct(self, python_type: type[_api.STRUCT_TYPE]):
|
155
|
+
|
156
|
+
_val.validate_signature(self.define_struct, python_type)
|
157
|
+
|
158
|
+
struct_schema = _struct.StructProcessor.define_struct(python_type)
|
159
|
+
return _meta.SchemaDefinition(schemaType=_meta.SchemaType.STRUCT, struct=struct_schema)
|
160
|
+
|
153
161
|
def define_schema(
|
154
162
|
self, *fields: _tp.Union[_meta.FieldSchema, _tp.List[_meta.FieldSchema]],
|
155
|
-
schema_type: _meta.SchemaType = _meta.SchemaType.TABLE) \
|
163
|
+
schema_type: _meta.SchemaType = _meta.SchemaType.TABLE, dynamic: bool = False) \
|
156
164
|
-> _meta.SchemaDefinition:
|
157
165
|
|
158
|
-
_val.validate_signature(self.define_schema, *fields, schema_type=schema_type)
|
166
|
+
_val.validate_signature(self.define_schema, *fields, schema_type=schema_type, dynamic=dynamic)
|
159
167
|
|
160
168
|
if schema_type == _meta.SchemaType.TABLE:
|
161
169
|
|
162
|
-
|
170
|
+
if dynamic and not fields:
|
171
|
+
table_schema = None
|
172
|
+
else:
|
173
|
+
table_schema = self._build_table_schema(*fields)
|
174
|
+
|
163
175
|
return _meta.SchemaDefinition(_meta.SchemaType.TABLE, table=table_schema)
|
164
176
|
|
165
177
|
raise _ex.ERuntimeValidation(f"Invalid schema type [{schema_type.name}]")
|
@@ -182,51 +194,67 @@ class StaticApiImpl(_StaticApiHook):
|
|
182
194
|
|
183
195
|
return converter.infer_schema(dataset)
|
184
196
|
|
185
|
-
def
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
197
|
+
def define_file_type(self, extension: str, mime_type: str) -> _meta.FileType:
|
198
|
+
|
199
|
+
_val.validate_signature(self.define_file_type, extension, mime_type)
|
200
|
+
|
201
|
+
return _meta.FileType(extension=extension, mimeType=mime_type)
|
202
|
+
|
203
|
+
def define_input(
|
204
|
+
self, requirement: _tp.Union[_meta.SchemaDefinition, _meta.FileType], *,
|
205
|
+
label: _tp.Optional[str] = None,
|
206
|
+
optional: bool = False, dynamic: bool = False,
|
207
|
+
input_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None):
|
190
208
|
|
191
209
|
_val.validate_signature(
|
192
|
-
self.
|
210
|
+
self.define_input, requirement,
|
193
211
|
label=label, optional=optional, dynamic=dynamic,
|
194
212
|
input_props=input_props)
|
195
213
|
|
196
|
-
|
214
|
+
if isinstance(requirement, _meta.SchemaDefinition):
|
197
215
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
216
|
+
return _meta.ModelInputSchema(
|
217
|
+
objectType=_meta.ObjectType.DATA, schema=requirement,
|
218
|
+
label=label, optional=optional, dynamic=dynamic,
|
219
|
+
inputProps=input_props)
|
202
220
|
|
203
|
-
|
204
|
-
schema=schema_def, label=label,
|
205
|
-
optional=optional, dynamic=dynamic,
|
206
|
-
inputProps=input_props)
|
221
|
+
elif isinstance(requirement, _meta.FileType):
|
207
222
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
223
|
+
return _meta.ModelInputSchema(
|
224
|
+
objectType=_meta.ObjectType.FILE, fileType=requirement,
|
225
|
+
label=label, optional=optional, dynamic=dynamic,
|
226
|
+
inputProps=input_props)
|
227
|
+
|
228
|
+
else:
|
229
|
+
raise _ex.EUnexpected()
|
230
|
+
|
231
|
+
def define_output(
|
232
|
+
self, requirement: _tp.Union[_meta.SchemaDefinition, _meta.FileType], *,
|
233
|
+
label: _tp.Optional[str] = None,
|
234
|
+
optional: bool = False, dynamic: bool = False,
|
235
|
+
output_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None):
|
213
236
|
|
214
237
|
_val.validate_signature(
|
215
|
-
self.
|
238
|
+
self.define_output, requirement,
|
216
239
|
label=label, optional=optional, dynamic=dynamic,
|
217
240
|
output_props=output_props)
|
218
241
|
|
219
|
-
|
242
|
+
if isinstance(requirement, _meta.SchemaDefinition):
|
220
243
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
244
|
+
return _meta.ModelOutputSchema(
|
245
|
+
objectType=_meta.ObjectType.DATA, schema=requirement,
|
246
|
+
label=label, optional=optional, dynamic=dynamic,
|
247
|
+
outputProps=output_props)
|
248
|
+
|
249
|
+
elif isinstance(requirement, _meta.FileType):
|
225
250
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
251
|
+
return _meta.ModelOutputSchema(
|
252
|
+
objectType=_meta.ObjectType.FILE, fileType=requirement,
|
253
|
+
label=label, optional=optional, dynamic=dynamic,
|
254
|
+
outputProps=output_props)
|
255
|
+
|
256
|
+
else:
|
257
|
+
raise _ex.EUnexpected()
|
230
258
|
|
231
259
|
@staticmethod
|
232
260
|
def _build_named_dict(
|
tracdap/rt/_plugins/repo_git.py
CHANGED
@@ -23,6 +23,7 @@ import time
|
|
23
23
|
import dulwich.repo as git_repo
|
24
24
|
import dulwich.client as git_client
|
25
25
|
import dulwich.index as git_index
|
26
|
+
import urllib3.exceptions # noqa
|
26
27
|
|
27
28
|
import tracdap.rt.metadata as meta
|
28
29
|
import tracdap.rt.exceptions as ex
|
@@ -75,20 +76,45 @@ class GitRepository(IModelRepository):
|
|
75
76
|
|
76
77
|
def do_checkout(self, model_def: meta.ModelDefinition, checkout_dir: pathlib.Path) -> pathlib.Path:
|
77
78
|
|
78
|
-
|
79
|
-
f"Git checkout: repo = [{model_def.repository}], " +
|
80
|
-
f"group = [{model_def.packageGroup}], package = [{model_def.package}], version = [{model_def.version}]")
|
79
|
+
try:
|
81
80
|
|
82
|
-
|
81
|
+
self._log.info(
|
82
|
+
f"Git checkout: repo = [{model_def.repository}], " +
|
83
|
+
f"group = [{model_def.packageGroup}], package = [{model_def.package}], version = [{model_def.version}]")
|
83
84
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
85
|
+
self._log.info(f"Checkout location: [{checkout_dir}]")
|
86
|
+
|
87
|
+
if self._native_git:
|
88
|
+
package_path = self._do_native_checkout(model_def, checkout_dir)
|
89
|
+
else:
|
90
|
+
package_path = self._do_python_checkout(model_def, checkout_dir)
|
91
|
+
|
92
|
+
self._log.info(f"Git checkout succeeded for {model_def.package} {model_def.version}")
|
93
|
+
|
94
|
+
return package_path
|
95
|
+
|
96
|
+
except Exception as e:
|
97
|
+
|
98
|
+
error = e
|
99
|
+
|
100
|
+
# For retry failures, try to find the original cause
|
101
|
+
while e.__cause__ is not None:
|
102
|
+
if isinstance(e, urllib3.exceptions.MaxRetryError):
|
103
|
+
error = e.__cause__
|
104
|
+
break
|
105
|
+
else:
|
106
|
+
e = e.__cause__
|
107
|
+
|
108
|
+
# Try to sanitize error messages from urllib3
|
109
|
+
if isinstance(error, urllib3.exceptions.HTTPError):
|
110
|
+
detail = self._clean_urllib3_error(error)
|
111
|
+
else:
|
112
|
+
detail = str(error)
|
88
113
|
|
89
|
-
|
114
|
+
message = f"Failed to check out [{model_def.repository}]: {detail}"
|
90
115
|
|
91
|
-
|
116
|
+
self._log.error(message)
|
117
|
+
raise ex.EModelRepo(message) from error
|
92
118
|
|
93
119
|
def _do_native_checkout(self, model_def: meta.ModelDefinition, checkout_dir: pathlib.Path) -> pathlib.Path:
|
94
120
|
|
@@ -150,10 +176,15 @@ class GitRepository(IModelRepository):
|
|
150
176
|
for line in cmd_err:
|
151
177
|
self._log.info(line)
|
152
178
|
|
153
|
-
|
179
|
+
elif cmd_err:
|
180
|
+
|
154
181
|
for line in cmd_err:
|
155
182
|
self._log.error(line)
|
156
183
|
|
184
|
+
raise ex.EModelRepo(cmd_err[-1])
|
185
|
+
|
186
|
+
else:
|
187
|
+
|
157
188
|
error_msg = f"Git checkout failed for {model_def.package} {model_def.version}"
|
158
189
|
self._log.error(error_msg)
|
159
190
|
raise ex.EModelRepo(error_msg)
|
@@ -265,6 +296,20 @@ class GitRepository(IModelRepository):
|
|
265
296
|
def _ref_key(key):
|
266
297
|
return bytes(key, "ascii")
|
267
298
|
|
299
|
+
@classmethod
|
300
|
+
def _clean_urllib3_error(cls, error: urllib3.exceptions.HTTPError):
|
301
|
+
|
302
|
+
match = cls._URLLIB3_ERROR_PATTERN.match(str(error))
|
303
|
+
|
304
|
+
# Best efforts to clean up the message, fall back on str(error)
|
305
|
+
if match:
|
306
|
+
return match.group(1)
|
307
|
+
else:
|
308
|
+
return str(error)
|
309
|
+
|
310
|
+
# Error message format is like this:
|
311
|
+
# <pkg.ClassName object at 0xXXXXXXX>: Message
|
312
|
+
_URLLIB3_ERROR_PATTERN = re.compile(r"<[^>]*>: (.*)")
|
268
313
|
|
269
314
|
# Register plugin
|
270
315
|
plugins.PluginManager.register_plugin(IModelRepository, GitRepository, ["git"])
|
@@ -30,7 +30,7 @@ from tracdap.rt._impl.ext.sql import * # noqa
|
|
30
30
|
import tracdap.rt._plugins._helpers as _helpers
|
31
31
|
|
32
32
|
# TODO: Remove internal references
|
33
|
-
import tracdap.rt._impl.data as _data
|
33
|
+
import tracdap.rt._impl.core.data as _data
|
34
34
|
|
35
35
|
|
36
36
|
class SqlDataStorage(IDataStorageBase[pa.Table, pa.Schema]):
|
@@ -268,10 +268,18 @@ plugins.PluginManager.register_plugin(IStorageProvider, SqlStorageProvider, ["SQ
|
|
268
268
|
|
269
269
|
|
270
270
|
try:
|
271
|
-
|
272
271
|
import sqlalchemy as sqla # noqa
|
273
272
|
import sqlalchemy.exc as sqla_exc # noqa
|
274
273
|
|
274
|
+
# Only 2.x versions of SQL Alchemy are currently supported
|
275
|
+
sqla_supported = sqla.__version__.startswith("2.")
|
276
|
+
|
277
|
+
except ModuleNotFoundError:
|
278
|
+
sqla = None
|
279
|
+
sqla_supported = False
|
280
|
+
|
281
|
+
if sqla_supported:
|
282
|
+
|
275
283
|
class SqlAlchemyDriver(ISqlDriver):
|
276
284
|
|
277
285
|
def __init__(self, properties: tp.Dict[str, str]):
|
@@ -336,7 +344,7 @@ try:
|
|
336
344
|
|
337
345
|
class ConnectionWrapper(DbApiWrapper.Connection):
|
338
346
|
|
339
|
-
def __init__(self, conn: sqla.Connection):
|
347
|
+
def __init__(self, conn: "sqla.Connection"):
|
340
348
|
self.__conn = conn
|
341
349
|
|
342
350
|
def close(self):
|
@@ -355,7 +363,7 @@ try:
|
|
355
363
|
|
356
364
|
arraysize: int = 1000
|
357
365
|
|
358
|
-
def __init__(self, conn: sqla.Connection):
|
366
|
+
def __init__(self, conn: "sqla.Connection"):
|
359
367
|
self.__conn = conn
|
360
368
|
self.__result: tp.Optional[sqla.CursorResult] = None
|
361
369
|
|
@@ -414,5 +422,4 @@ try:
|
|
414
422
|
|
415
423
|
plugins.PluginManager.register_plugin(ISqlDriver, SqlAlchemyDriver, ["alchemy"])
|
416
424
|
|
417
|
-
|
418
|
-
pass
|
425
|
+
|
tracdap/rt/_version.py
CHANGED
tracdap/rt/api/__init__.py
CHANGED
@@ -17,32 +17,13 @@
|
|
17
17
|
TRAC model API for Python
|
18
18
|
"""
|
19
19
|
|
20
|
-
from .model_api import *
|
21
|
-
from .static_api import *
|
22
|
-
|
23
20
|
# Make metadata classes available to client code when importing the API package
|
24
21
|
# Remove this import when generating docs, so metadata classes are only documented once
|
25
22
|
from tracdap.rt.metadata import * # noqa DOCGEN_REMOVE
|
26
23
|
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
INTEGER = BasicType.INTEGER
|
33
|
-
"""Synonym for :py:attr:`BasicType.INTEGER <tracdap.rt.metadata.BasicType.INTEGER>`"""
|
34
|
-
|
35
|
-
FLOAT = BasicType.FLOAT
|
36
|
-
"""Synonym for :py:attr:`BasicType.FLOAT <tracdap.rt.metadata.BasicType.FLOAT>`"""
|
37
|
-
|
38
|
-
DECIMAL = BasicType.DECIMAL
|
39
|
-
"""Synonym for :py:attr:`BasicType.DECIMAL <tracdap.rt.metadata.BasicType.DECIMAL>`"""
|
40
|
-
|
41
|
-
STRING = BasicType.STRING
|
42
|
-
"""Synonym for :py:attr:`BasicType.STRING <tracdap.rt.metadata.BasicType.STRING>`"""
|
43
|
-
|
44
|
-
DATE = BasicType.DATE
|
45
|
-
"""Synonym for :py:attr:`BasicType.DATE <tracdap.rt.metadata.BasicType.DATE>`"""
|
24
|
+
# static_api overrides some metadata types for backwards compatibility with pre-0.8 versions
|
25
|
+
# Make sure it is last in the list
|
26
|
+
from .constants import *
|
27
|
+
from .model_api import *
|
28
|
+
from .static_api import *
|
46
29
|
|
47
|
-
DATETIME = BasicType.DATETIME
|
48
|
-
"""Synonym for :py:attr:`BasicType.DATETIME <tracdap.rt.metadata.BasicType.DATETIME>`"""
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Licensed to the Fintech Open Source Foundation (FINOS) under one or
|
2
|
+
# more contributor license agreements. See the NOTICE file distributed
|
3
|
+
# with this work for additional information regarding copyright ownership.
|
4
|
+
# FINOS licenses this file to you under the Apache License, Version 2.0
|
5
|
+
# (the "License"); you may not use this file except in compliance with the
|
6
|
+
# License. You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
import tracdap.rt.metadata
|
17
|
+
|
18
|
+
|
19
|
+
class CommonFileTypes:
|
20
|
+
|
21
|
+
"""
|
22
|
+
A collection of common :py:class:`FileTypes <tracdap.rt.metadata.FileType>` to use as model inputs and outputs
|
23
|
+
"""
|
24
|
+
|
25
|
+
TXT = tracdap.rt.metadata.FileType("txt", "text/plain")
|
26
|
+
|
27
|
+
JPG = tracdap.rt.metadata.FileType("jpg", "image/jpeg")
|
28
|
+
PNG = tracdap.rt.metadata.FileType("png", "image/png")
|
29
|
+
SVG = tracdap.rt.metadata.FileType("svg", "image/svg+xml")
|
30
|
+
|
31
|
+
WORD = tracdap.rt.metadata.FileType("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
|
32
|
+
EXCEL = tracdap.rt.metadata.FileType("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
33
|
+
POWERPOINT = tracdap.rt.metadata.FileType("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation")
|
34
|
+
|
35
|
+
|
36
|
+
# Map basic types into the root of the API package
|
37
|
+
|
38
|
+
BOOLEAN = tracdap.rt.metadata.BasicType.BOOLEAN
|
39
|
+
"""Synonym for :py:attr:`BasicType.BOOLEAN <tracdap.rt.metadata.BasicType.BOOLEAN>`"""
|
40
|
+
|
41
|
+
INTEGER = tracdap.rt.metadata.BasicType.INTEGER
|
42
|
+
"""Synonym for :py:attr:`BasicType.INTEGER <tracdap.rt.metadata.BasicType.INTEGER>`"""
|
43
|
+
|
44
|
+
FLOAT = tracdap.rt.metadata.BasicType.FLOAT
|
45
|
+
"""Synonym for :py:attr:`BasicType.FLOAT <tracdap.rt.metadata.BasicType.FLOAT>`"""
|
46
|
+
|
47
|
+
DECIMAL = tracdap.rt.metadata.BasicType.DECIMAL
|
48
|
+
"""Synonym for :py:attr:`BasicType.DECIMAL <tracdap.rt.metadata.BasicType.DECIMAL>`"""
|
49
|
+
|
50
|
+
STRING = tracdap.rt.metadata.BasicType.STRING
|
51
|
+
"""Synonym for :py:attr:`BasicType.STRING <tracdap.rt.metadata.BasicType.STRING>`"""
|
52
|
+
|
53
|
+
DATE = tracdap.rt.metadata.BasicType.DATE
|
54
|
+
"""Synonym for :py:attr:`BasicType.DATE <tracdap.rt.metadata.BasicType.DATE>`"""
|
55
|
+
|
56
|
+
DATETIME = tracdap.rt.metadata.BasicType.DATETIME
|
57
|
+
"""Synonym for :py:attr:`BasicType.DATETIME <tracdap.rt.metadata.BasicType.DATETIME>`"""
|
tracdap/rt/api/experimental.py
CHANGED
@@ -70,6 +70,8 @@ PANDAS = DataFramework.pandas()
|
|
70
70
|
POLARS = DataFramework.polars()
|
71
71
|
"""Data framework constant for the Polars data library"""
|
72
72
|
|
73
|
+
STRUCT_TYPE = _tp.TypeVar('STRUCT_TYPE')
|
74
|
+
|
73
75
|
|
74
76
|
class TracContext(TracContext):
|
75
77
|
|
@@ -83,6 +85,14 @@ class TracContext(TracContext):
|
|
83
85
|
|
84
86
|
pass
|
85
87
|
|
88
|
+
def get_struct(self, struct_name: str, python_class: _tp.Type[STRUCT_TYPE]) -> STRUCT_TYPE:
|
89
|
+
|
90
|
+
pass
|
91
|
+
|
92
|
+
def put_struct(self, struct_name: str, struct_data: STRUCT_TYPE):
|
93
|
+
|
94
|
+
pass
|
95
|
+
|
86
96
|
|
87
97
|
def init_static():
|
88
98
|
"""Ensure TRAC's static model API is available to use (for static definitions at module or class scope)"""
|
@@ -108,6 +118,28 @@ def map_type(entry_type: BasicType) -> TypeDescriptor:
|
|
108
118
|
return sa.map_type(entry_type)
|
109
119
|
|
110
120
|
|
121
|
+
def define_struct(python_type: _tp.Type[STRUCT_TYPE]) -> SchemaDefinition:
|
122
|
+
"""Build schema definition for a STRUCT"""
|
123
|
+
sa = _StaticApiHook.get_instance()
|
124
|
+
return sa.define_struct(python_type)
|
125
|
+
|
126
|
+
def define_input_struct(
|
127
|
+
python_type: _tp.Type[STRUCT_TYPE], *,
|
128
|
+
label: _tp.Optional[str] = None, optional: bool = False,
|
129
|
+
input_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) -> ModelInputSchema:
|
130
|
+
|
131
|
+
schema = define_struct(python_type)
|
132
|
+
return define_input(schema, label=label, optional=optional, input_props=input_props)
|
133
|
+
|
134
|
+
def define_output_struct(
|
135
|
+
python_type: _tp.Type[STRUCT_TYPE], *,
|
136
|
+
label: _tp.Optional[str] = None, optional: bool = False,
|
137
|
+
output_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) -> ModelOutputSchema:
|
138
|
+
|
139
|
+
schema = define_struct(python_type)
|
140
|
+
return define_output(schema, label=label, optional=optional, output_props=output_props)
|
141
|
+
|
142
|
+
|
111
143
|
class FileType(_enum.Enum):
|
112
144
|
|
113
145
|
FILE = 1
|
tracdap/rt/api/hook.py
CHANGED
@@ -116,11 +116,16 @@ class _StaticApiHook:
|
|
116
116
|
@_abc.abstractmethod
|
117
117
|
def define_schema(
|
118
118
|
self, *fields: _tp.Union[_meta.FieldSchema, _tp.List[_meta.FieldSchema]],
|
119
|
-
schema_type: _meta.SchemaType = _meta.SchemaType.TABLE) \
|
119
|
+
schema_type: _meta.SchemaType = _meta.SchemaType.TABLE, dynamic: bool = False) \
|
120
120
|
-> _meta.SchemaDefinition:
|
121
121
|
|
122
122
|
pass
|
123
123
|
|
124
|
+
@_abc.abstractmethod
|
125
|
+
def define_struct(self, python_type: type) -> _meta.SchemaDefinition:
|
126
|
+
|
127
|
+
pass
|
128
|
+
|
124
129
|
@_abc.abstractmethod
|
125
130
|
def load_schema(
|
126
131
|
self, package: _tp.Union[_ts.ModuleType, str], schema_file: str,
|
@@ -131,22 +136,36 @@ class _StaticApiHook:
|
|
131
136
|
|
132
137
|
@_abc.abstractmethod
|
133
138
|
def infer_schema(self, dataset: _tp.Any) -> _meta.SchemaDefinition:
|
139
|
+
|
134
140
|
pass
|
135
141
|
|
136
142
|
@_abc.abstractmethod
|
137
|
-
def
|
138
|
-
|
139
|
-
|
143
|
+
def define_file_type(self, extension: str, mime_type: str) -> _meta.FileType:
|
144
|
+
|
145
|
+
pass
|
146
|
+
|
147
|
+
@_abc.abstractmethod
|
148
|
+
def define_input(
|
149
|
+
self, requirement: _tp.Union[_meta.SchemaDefinition, _meta.FileType], *,
|
150
|
+
label: _tp.Optional[str] = None,
|
151
|
+
optional: bool = False, dynamic: bool = False,
|
140
152
|
input_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) \
|
141
153
|
-> _meta.ModelInputSchema:
|
142
154
|
|
143
155
|
pass
|
144
156
|
|
145
157
|
@_abc.abstractmethod
|
146
|
-
def
|
147
|
-
self,
|
148
|
-
label: _tp.Optional[str] = None,
|
158
|
+
def define_output(
|
159
|
+
self, requirement: _tp.Union[_meta.SchemaDefinition, _meta.FileType], *,
|
160
|
+
label: _tp.Optional[str] = None,
|
161
|
+
optional: bool = False, dynamic: bool = False,
|
149
162
|
output_props: _tp.Optional[_tp.Dict[str, _tp.Any]] = None) \
|
150
163
|
-> _meta.ModelOutputSchema:
|
151
164
|
|
152
165
|
pass
|
166
|
+
|
167
|
+
X = _tp.TypeVar("X")
|
168
|
+
|
169
|
+
def do_x(x: type[X]) -> X:
|
170
|
+
|
171
|
+
return x.__new__(x)
|
tracdap/rt/api/model_api.py
CHANGED
@@ -194,6 +194,14 @@ class TracContext(metaclass=_abc.ABCMeta):
|
|
194
194
|
|
195
195
|
pass
|
196
196
|
|
197
|
+
def get_file(self, file_name: str) -> bytes:
|
198
|
+
|
199
|
+
pass
|
200
|
+
|
201
|
+
def get_file_stream(self, file_name: str) -> _tp.ContextManager[_tp.BinaryIO]:
|
202
|
+
|
203
|
+
pass
|
204
|
+
|
197
205
|
def put_schema(self, dataset_name: str, schema: SchemaDefinition):
|
198
206
|
|
199
207
|
"""
|
@@ -283,6 +291,14 @@ class TracContext(metaclass=_abc.ABCMeta):
|
|
283
291
|
|
284
292
|
pass
|
285
293
|
|
294
|
+
def put_file(self, file_name: str, file_content: _tp.Union[bytes, bytearray]):
|
295
|
+
|
296
|
+
pass
|
297
|
+
|
298
|
+
def put_file_stream(self, file_name: str) -> _tp.ContextManager[_tp.BinaryIO]:
|
299
|
+
|
300
|
+
pass
|
301
|
+
|
286
302
|
def log(self) -> _logging.Logger:
|
287
303
|
|
288
304
|
"""
|