tracdap-runtime 0.7.0rc1__tar.gz → 0.8.0b1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/PKG-INFO +3 -3
  2. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/setup.cfg +2 -2
  3. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_exec/context.py +140 -64
  4. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_exec/dev_mode.py +144 -69
  5. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_exec/engine.py +9 -7
  6. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_exec/functions.py +95 -33
  7. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_exec/graph.py +22 -15
  8. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_exec/graph_builder.py +221 -98
  9. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_exec/runtime.py +19 -6
  10. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/data.py +86 -13
  11. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/file_pb2.py +3 -1
  12. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/file_pb2.pyi +8 -0
  13. tracdap_runtime-0.8.0b1/src/tracdap/rt/_impl/grpc/tracdap/metadata/model_pb2.py +67 -0
  14. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/model_pb2.pyi +14 -4
  15. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/models.py +9 -7
  16. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/static_api.py +53 -33
  17. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/util.py +1 -1
  18. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/validation.py +54 -28
  19. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_version.py +1 -1
  20. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/api/__init__.py +6 -3
  21. tracdap_runtime-0.8.0b1/src/tracdap/rt/api/file_types.py +29 -0
  22. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/api/hook.py +15 -7
  23. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/api/model_api.py +16 -0
  24. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/api/static_api.py +211 -125
  25. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/config/common.py +11 -1
  26. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/config/platform.py +4 -6
  27. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/launch/launch.py +9 -11
  28. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/__init__.py +10 -9
  29. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/file.py +8 -0
  30. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/model.py +12 -2
  31. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/tracdap_runtime.egg-info/PKG-INFO +3 -3
  32. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/tracdap_runtime.egg-info/SOURCES.txt +1 -0
  33. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/tracdap_runtime.egg-info/requires.txt +1 -1
  34. tracdap_runtime-0.7.0rc1/src/tracdap/rt/_impl/grpc/tracdap/metadata/model_pb2.py +0 -65
  35. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/LICENSE +0 -0
  36. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/README.md +0 -0
  37. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/pyproject.toml +0 -0
  38. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/__init__.py +0 -0
  39. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_exec/__init__.py +0 -0
  40. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_exec/actors.py +0 -0
  41. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_exec/server.py +0 -0
  42. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/__init__.py +0 -0
  43. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/config_parser.py +0 -0
  44. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/ext/__init__.py +0 -0
  45. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/ext/sql.py +0 -0
  46. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/ext/storage.py +0 -0
  47. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/__init__.py +0 -0
  48. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/codec.py +0 -0
  49. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/api/internal/runtime_pb2.py +0 -0
  50. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/api/internal/runtime_pb2.pyi +0 -0
  51. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/api/internal/runtime_pb2_grpc.py +0 -0
  52. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/common_pb2.py +0 -0
  53. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/common_pb2.pyi +0 -0
  54. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/custom_pb2.py +0 -0
  55. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/custom_pb2.pyi +0 -0
  56. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/data_pb2.py +0 -0
  57. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/data_pb2.pyi +0 -0
  58. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/flow_pb2.py +0 -0
  59. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/flow_pb2.pyi +0 -0
  60. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/job_pb2.py +0 -0
  61. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/job_pb2.pyi +0 -0
  62. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/object_id_pb2.py +0 -0
  63. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/object_id_pb2.pyi +0 -0
  64. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/object_pb2.py +0 -0
  65. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/object_pb2.pyi +0 -0
  66. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/resource_pb2.py +0 -0
  67. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/resource_pb2.pyi +0 -0
  68. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/search_pb2.py +0 -0
  69. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/search_pb2.pyi +0 -0
  70. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/stoarge_pb2.py +0 -0
  71. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/stoarge_pb2.pyi +0 -0
  72. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/tag_pb2.py +0 -0
  73. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/tag_pb2.pyi +0 -0
  74. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/tag_update_pb2.py +0 -0
  75. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/tag_update_pb2.pyi +0 -0
  76. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/type_pb2.py +0 -0
  77. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/grpc/tracdap/metadata/type_pb2.pyi +0 -0
  78. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/guard_rails.py +0 -0
  79. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/repos.py +0 -0
  80. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/schemas.py +0 -0
  81. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/shim.py +0 -0
  82. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/storage.py +0 -0
  83. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_impl/type_system.py +0 -0
  84. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_plugins/__init__.py +0 -0
  85. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_plugins/_helpers.py +0 -0
  86. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_plugins/config_local.py +0 -0
  87. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_plugins/format_arrow.py +0 -0
  88. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_plugins/format_csv.py +0 -0
  89. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_plugins/format_parquet.py +0 -0
  90. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_plugins/repo_git.py +0 -0
  91. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_plugins/repo_local.py +0 -0
  92. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_plugins/repo_pypi.py +0 -0
  93. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_plugins/storage_aws.py +0 -0
  94. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_plugins/storage_azure.py +0 -0
  95. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_plugins/storage_gcp.py +0 -0
  96. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_plugins/storage_local.py +0 -0
  97. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_plugins/storage_sql.py +0 -0
  98. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/_plugins/storage_sql_dialects.py +0 -0
  99. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/api/experimental.py +0 -0
  100. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/config/__init__.py +6 -6
  101. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/config/job.py +0 -0
  102. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/config/result.py +0 -0
  103. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/config/runtime.py +0 -0
  104. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/exceptions.py +0 -0
  105. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/ext/__init__.py +0 -0
  106. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/ext/config.py +0 -0
  107. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/ext/embed.py +0 -0
  108. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/ext/plugins.py +0 -0
  109. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/ext/repos.py +0 -0
  110. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/ext/storage.py +0 -0
  111. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/launch/__init__.py +0 -0
  112. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/launch/__main__.py +0 -0
  113. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/launch/cli.py +0 -0
  114. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/common.py +0 -0
  115. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/custom.py +0 -0
  116. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/data.py +0 -0
  117. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/flow.py +0 -0
  118. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/job.py +0 -0
  119. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/object.py +0 -0
  120. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/object_id.py +0 -0
  121. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/resource.py +0 -0
  122. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/search.py +0 -0
  123. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/stoarge.py +0 -0
  124. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/tag.py +0 -0
  125. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/tag_update.py +0 -0
  126. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/src/tracdap/rt/metadata/type.py +0 -0
  127. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/tracdap_runtime.egg-info/dependency_links.txt +0 -0
  128. {tracdap_runtime-0.7.0rc1 → tracdap_runtime-0.8.0b1}/tracdap_runtime.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tracdap-runtime
3
- Version: 0.7.0rc1
3
+ Version: 0.8.0b1
4
4
  Summary: Runtime package for building models on the TRAC Data & Analytics Platform
5
5
  Home-page: https://tracdap.finos.org/
6
6
  Author: Martin Traverse
@@ -28,8 +28,8 @@ Requires-Dist: grpcio==1.66.1; extra == "grpc"
28
28
  Requires-Dist: grpcio-status==1.66.1; extra == "grpc"
29
29
  Provides-Extra: polars
30
30
  Requires-Dist: polars<2.0.0,>=1.0.0; extra == "polars"
31
- Provides-Extra: spark
32
- Requires-Dist: pyspark<3.6.0,>=3.0.0; extra == "spark"
31
+ Provides-Extra: pyspark
32
+ Requires-Dist: pyspark<3.6.0,>=3.0.0; extra == "pyspark"
33
33
  Provides-Extra: sql
34
34
  Requires-Dist: sqlalchemy<2.1.0,>=2.0.0; extra == "sql"
35
35
  Provides-Extra: aws
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = tracdap-runtime
3
- version = 0.7.0rc1
3
+ version = 0.8.0b1
4
4
  description = Runtime package for building models on the TRAC Data & Analytics Platform
5
5
  long_description = file: README.md
6
6
  long_description_content_type = text/markdown
@@ -54,7 +54,7 @@ grpc =
54
54
  grpcio-status == 1.66.1
55
55
  polars =
56
56
  polars >= 1.0.0, < 2.0.0
57
- spark =
57
+ pyspark =
58
58
  pyspark >= 3.0.0, < 3.6.0
59
59
  sql =
60
60
  sqlalchemy >= 2.0.0, < 2.1.0
@@ -13,7 +13,9 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
+ import contextlib
16
17
  import copy
18
+ import io
17
19
  import logging
18
20
  import pathlib
19
21
  import typing as tp
@@ -82,9 +84,9 @@ class TracContextImpl(_api.TracContext):
82
84
 
83
85
  _val.validate_signature(self.get_parameter, parameter_name)
84
86
 
85
- self.__val.check_param_valid_identifier(parameter_name)
86
- self.__val.check_param_defined_in_model(parameter_name)
87
- self.__val.check_param_available_in_context(parameter_name)
87
+ self.__val.check_item_valid_identifier(parameter_name, TracContextValidator.PARAMETER)
88
+ self.__val.check_item_defined_in_model(parameter_name, TracContextValidator.PARAMETER)
89
+ self.__val.check_item_available_in_context(parameter_name, TracContextValidator.PARAMETER)
88
90
 
89
91
  value: _meta.Value = self.__local_ctx.get(parameter_name)
90
92
 
@@ -96,8 +98,8 @@ class TracContextImpl(_api.TracContext):
96
98
 
97
99
  _val.validate_signature(self.has_dataset, dataset_name)
98
100
 
99
- self.__val.check_dataset_valid_identifier(dataset_name)
100
- self.__val.check_dataset_defined_in_model(dataset_name)
101
+ self.__val.check_item_valid_identifier(dataset_name, TracContextValidator.DATASET)
102
+ self.__val.check_item_defined_in_model(dataset_name, TracContextValidator.DATASET)
101
103
 
102
104
  data_view: _data.DataView = self.__local_ctx.get(dataset_name)
103
105
 
@@ -105,6 +107,7 @@ class TracContextImpl(_api.TracContext):
105
107
  return False
106
108
 
107
109
  self.__val.check_context_object_type(dataset_name, data_view, _data.DataView)
110
+ self.__val.check_context_data_view_type(dataset_name, data_view, _meta.ObjectType.DATA)
108
111
 
109
112
  return not data_view.is_empty()
110
113
 
@@ -112,9 +115,9 @@ class TracContextImpl(_api.TracContext):
112
115
 
113
116
  _val.validate_signature(self.get_schema, dataset_name)
114
117
 
115
- self.__val.check_dataset_valid_identifier(dataset_name)
116
- self.__val.check_dataset_defined_in_model(dataset_name)
117
- self.__val.check_dataset_available_in_context(dataset_name)
118
+ self.__val.check_item_valid_identifier(dataset_name, TracContextValidator.DATASET)
119
+ self.__val.check_item_defined_in_model(dataset_name, TracContextValidator.DATASET)
120
+ self.__val.check_item_available_in_context(dataset_name, TracContextValidator.DATASET)
118
121
 
119
122
  static_schema = self.__get_static_schema(self.__model_def, dataset_name)
120
123
  data_view: _data.DataView = self.__local_ctx.get(dataset_name)
@@ -123,6 +126,7 @@ class TracContextImpl(_api.TracContext):
123
126
  # This ensures errors are always reported and is consistent with get_pandas_table()
124
127
 
125
128
  self.__val.check_context_object_type(dataset_name, data_view, _data.DataView)
129
+ self.__val.check_context_data_view_type(dataset_name, data_view, _meta.ObjectType.DATA)
126
130
  self.__val.check_dataset_schema_defined(dataset_name, data_view)
127
131
 
128
132
  # If a static schema exists, that takes priority
@@ -138,9 +142,9 @@ class TracContextImpl(_api.TracContext):
138
142
  _val.validate_signature(self.get_table, dataset_name, framework)
139
143
  _val.require_package(framework.protocol_name, framework.api_type)
140
144
 
141
- self.__val.check_dataset_valid_identifier(dataset_name)
142
- self.__val.check_dataset_defined_in_model(dataset_name)
143
- self.__val.check_dataset_available_in_context(dataset_name)
145
+ self.__val.check_item_valid_identifier(dataset_name, TracContextValidator.DATASET)
146
+ self.__val.check_item_defined_in_model(dataset_name, TracContextValidator.DATASET)
147
+ self.__val.check_item_available_in_context(dataset_name, TracContextValidator.DATASET)
144
148
  self.__val.check_data_framework_args(framework, framework_args)
145
149
 
146
150
  static_schema = self.__get_static_schema(self.__model_def, dataset_name)
@@ -150,6 +154,7 @@ class TracContextImpl(_api.TracContext):
150
154
  converter = _data.DataConverter.for_framework(framework, **framework_args)
151
155
 
152
156
  self.__val.check_context_object_type(dataset_name, data_view, _data.DataView)
157
+ self.__val.check_context_data_view_type(dataset_name, data_view, _meta.ObjectType.DATA)
153
158
  self.__val.check_dataset_schema_defined(dataset_name, data_view)
154
159
  self.__val.check_dataset_part_present(dataset_name, data_view, part_key)
155
160
 
@@ -173,6 +178,27 @@ class TracContextImpl(_api.TracContext):
173
178
  def get_polars_table(self, dataset_name: str) -> "_data.polars.DataFrame":
174
179
 
175
180
  return self.get_table(dataset_name, _eapi.POLARS)
181
+
182
+ def get_file(self, file_name: str) -> bytes:
183
+
184
+ _val.validate_signature(self.get_file, file_name)
185
+
186
+ self.__val.check_item_valid_identifier(file_name, TracContextValidator.FILE)
187
+ self.__val.check_item_defined_in_model(file_name, TracContextValidator.FILE)
188
+ self.__val.check_item_available_in_context(file_name, TracContextValidator.FILE)
189
+
190
+ file_view: _data.DataView = self.__local_ctx.get(file_name)
191
+
192
+ self.__val.check_context_object_type(file_name, file_view, _data.DataView)
193
+ self.__val.check_context_data_view_type(file_name, file_view, _meta.ObjectType.FILE)
194
+ self.__val.check_file_content_present(file_name, file_view)
195
+
196
+ return file_view.file_item.raw_bytes
197
+
198
+ def get_file_stream(self, file_name: str) -> tp.ContextManager[tp.BinaryIO]:
199
+
200
+ buffer = self.get_file(file_name)
201
+ return contextlib.closing(io.BytesIO(buffer))
176
202
 
177
203
  def put_schema(self, dataset_name: str, schema: _meta.SchemaDefinition):
178
204
 
@@ -182,7 +208,7 @@ class TracContextImpl(_api.TracContext):
182
208
  # If field ordering is not assigned by the model, assign it here (model code will not see the numbers)
183
209
  schema_copy = self.__assign_field_order(copy.deepcopy(schema))
184
210
 
185
- self.__val.check_dataset_valid_identifier(dataset_name)
211
+ self.__val.check_item_valid_identifier(dataset_name, TracContextValidator.DATASET)
186
212
  self.__val.check_dataset_is_dynamic_output(dataset_name)
187
213
  self.__val.check_provided_schema_is_valid(dataset_name, schema_copy)
188
214
 
@@ -197,6 +223,7 @@ class TracContextImpl(_api.TracContext):
197
223
 
198
224
  # If there is a prior view it must contain nothing and will be replaced
199
225
  self.__val.check_context_object_type(dataset_name, data_view, _data.DataView)
226
+ self.__val.check_context_data_view_type(dataset_name, data_view, _meta.ObjectType.DATA)
200
227
  self.__val.check_dataset_schema_not_defined(dataset_name, data_view)
201
228
  self.__val.check_dataset_is_empty(dataset_name, data_view)
202
229
 
@@ -216,8 +243,8 @@ class TracContextImpl(_api.TracContext):
216
243
 
217
244
  _val.require_package(framework.protocol_name, framework.api_type)
218
245
 
219
- self.__val.check_dataset_valid_identifier(dataset_name)
220
- self.__val.check_dataset_is_model_output(dataset_name)
246
+ self.__val.check_item_valid_identifier(dataset_name, TracContextValidator.DATASET)
247
+ self.__val.check_item_is_model_output(dataset_name, TracContextValidator.DATASET)
221
248
  self.__val.check_provided_dataset_type(dataset, framework.api_type)
222
249
  self.__val.check_data_framework_args(framework, framework_args)
223
250
 
@@ -234,6 +261,7 @@ class TracContextImpl(_api.TracContext):
234
261
  data_view = _data.DataView.create_empty()
235
262
 
236
263
  self.__val.check_context_object_type(dataset_name, data_view, _data.DataView)
264
+ self.__val.check_context_data_view_type(dataset_name, data_view, _meta.ObjectType.DATA)
237
265
  self.__val.check_dataset_schema_defined(dataset_name, data_view)
238
266
  self.__val.check_dataset_part_not_present(dataset_name, data_view, part_key)
239
267
 
@@ -246,7 +274,7 @@ class TracContextImpl(_api.TracContext):
246
274
 
247
275
  # Data conformance is applied automatically inside the converter, if schema != None
248
276
  table = converter.to_internal(dataset, schema)
249
- item = _data.DataItem(schema, table)
277
+ item = _data.DataItem(_meta.ObjectType.DATA, schema, table)
250
278
 
251
279
  updated_view = _data.DataMapping.add_item_to_view(data_view, part_key, item)
252
280
 
@@ -259,6 +287,46 @@ class TracContextImpl(_api.TracContext):
259
287
  def put_polars_table(self, dataset_name: str, dataset: "_data.polars.DataFrame"):
260
288
 
261
289
  self.put_table(dataset_name, dataset, _eapi.POLARS)
290
+
291
+ def put_file(self, file_name: str, file_content: tp.Union[bytes, bytearray]):
292
+
293
+ _val.validate_signature(self.put_file, file_name, file_content)
294
+
295
+ self.__val.check_item_valid_identifier(file_name, TracContextValidator.FILE)
296
+ self.__val.check_item_is_model_output(file_name, TracContextValidator.FILE)
297
+
298
+ file_view: _data.DataView = self.__local_ctx.get(file_name)
299
+
300
+ if file_view is None:
301
+ file_view = _data.DataView.create_empty(_meta.ObjectType.FILE)
302
+
303
+ self.__val.check_context_object_type(file_name, file_view, _data.DataView)
304
+ self.__val.check_context_data_view_type(file_name, file_view, _meta.ObjectType.FILE)
305
+ self.__val.check_file_content_not_present(file_name, file_view)
306
+
307
+ if isinstance(file_content, bytearray):
308
+ file_content = bytes(bytearray)
309
+
310
+ file_item = _data.DataItem.for_file_content(file_content)
311
+ self.__local_ctx[file_name] = file_view.with_file_item(file_item)
312
+
313
+ def put_file_stream(self, file_name: str) -> tp.ContextManager[tp.BinaryIO]:
314
+
315
+ _val.validate_signature(self.put_file_stream, file_name)
316
+
317
+ self.__val.check_item_valid_identifier(file_name, TracContextValidator.FILE)
318
+ self.__val.check_item_is_model_output(file_name, TracContextValidator.FILE)
319
+
320
+ @contextlib.contextmanager
321
+ def memory_stream(stream: io.BytesIO):
322
+ try:
323
+ yield stream
324
+ buffer = stream.getbuffer().tobytes()
325
+ self.put_file(file_name, buffer)
326
+ finally:
327
+ stream.close()
328
+
329
+ return memory_stream(io.BytesIO())
262
330
 
263
331
  def log(self) -> logging.Logger:
264
332
 
@@ -310,7 +378,7 @@ class TracDataContextImpl(TracContextImpl, _eapi.TracDataContext):
310
378
  self.__storage_map = storage_map
311
379
  self.__checkout_directory = checkout_directory
312
380
 
313
- self.__val = self._TracContextImpl__val # noqa
381
+ self.__val: TracContextValidator = self._TracContextImpl__val # noqa
314
382
 
315
383
  def get_file_storage(self, storage_key: str) -> _eapi.TracFileStorage:
316
384
 
@@ -348,9 +416,9 @@ class TracDataContextImpl(TracContextImpl, _eapi.TracDataContext):
348
416
 
349
417
  _val.validate_signature(self.add_data_import, dataset_name)
350
418
 
351
- self.__val.check_dataset_valid_identifier(dataset_name)
352
- self.__val.check_dataset_not_defined_in_model(dataset_name)
353
- self.__val.check_dataset_not_available_in_context(dataset_name)
419
+ self.__val.check_item_valid_identifier(dataset_name, TracContextValidator.DATASET)
420
+ self.__val.check_item_not_defined_in_model(dataset_name, TracContextValidator.DATASET)
421
+ self.__val.check_item_not_available_in_context(dataset_name, TracContextValidator.DATASET)
354
422
 
355
423
  self.__local_ctx[dataset_name] = _data.DataView.create_empty()
356
424
  self.__dynamic_outputs.append(dataset_name)
@@ -359,8 +427,8 @@ class TracDataContextImpl(TracContextImpl, _eapi.TracDataContext):
359
427
 
360
428
  _val.validate_signature(self.set_source_metadata, dataset_name, storage_key, source_info)
361
429
 
362
- self.__val.check_dataset_valid_identifier(dataset_name)
363
- self.__val.check_dataset_available_in_context(dataset_name)
430
+ self.__val.check_item_valid_identifier(dataset_name, TracContextValidator.DATASET)
431
+ self.__val.check_item_available_in_context(dataset_name, TracContextValidator.DATASET)
364
432
  self.__val.check_storage_valid_identifier(storage_key)
365
433
  self.__val.check_storage_available(self.__storage_map, storage_key)
366
434
 
@@ -368,11 +436,11 @@ class TracDataContextImpl(TracContextImpl, _eapi.TracDataContext):
368
436
 
369
437
  if isinstance(storage, _eapi.TracFileStorage):
370
438
  if not isinstance(source_info, _eapi.FileStat):
371
- self.__val.report_public_error(f"Expected storage_info to be a FileStat, [{storage_key}] refers to file storage")
439
+ self.__val.report_public_error(_ex.ERuntimeValidation(f"Expected storage_info to be a FileStat, [{storage_key}] refers to file storage"))
372
440
 
373
441
  if isinstance(storage, _eapi.TracDataStorage):
374
442
  if not isinstance(source_info, str):
375
- self.__val.report_public_error(f"Expected storage_info to be a table name, [{storage_key}] refers to dadta storage")
443
+ self.__val.report_public_error(_ex.ERuntimeValidation(f"Expected storage_info to be a table name, [{storage_key}] refers to dadta storage"))
376
444
 
377
445
  pass # Not implemented yet, only required when imports are sent back to the platform
378
446
 
@@ -684,6 +752,10 @@ class TracContextErrorReporter:
684
752
 
685
753
  class TracContextValidator(TracContextErrorReporter):
686
754
 
755
+ PARAMETER = "Parameter"
756
+ DATASET = "Dataset"
757
+ FILE = "File"
758
+
687
759
  def __init__(
688
760
  self, log: logging.Logger,
689
761
  model_def: _meta.ModelDefinition,
@@ -697,49 +769,45 @@ class TracContextValidator(TracContextErrorReporter):
697
769
  self.__local_ctx = local_ctx
698
770
  self.__dynamic_outputs = dynamic_outputs
699
771
 
700
- def check_param_valid_identifier(self, param_name: str):
701
-
702
- if param_name is None:
703
- self._report_error(f"Parameter name is null")
704
-
705
- if not self._VALID_IDENTIFIER.match(param_name):
706
- self._report_error(f"Parameter name {param_name} is not a valid identifier")
707
-
708
- def check_param_defined_in_model(self, param_name: str):
772
+ def check_item_valid_identifier(self, item_name: str, item_type: str):
709
773
 
710
- if param_name not in self.__model_def.parameters:
711
- self._report_error(f"Parameter {param_name} is not defined in the model")
774
+ if item_name is None:
775
+ self._report_error(f"{item_type} name is null")
712
776
 
713
- def check_param_available_in_context(self, param_name: str):
777
+ if not self._VALID_IDENTIFIER.match(item_name):
778
+ self._report_error(f"{item_type} name {item_name} is not a valid identifier")
714
779
 
715
- if param_name not in self.__local_ctx:
716
- self._report_error(f"Parameter {param_name} is not available in the current context")
780
+ def check_item_defined_in_model(self, item_name: str, item_type: str):
717
781
 
718
- def check_dataset_valid_identifier(self, dataset_name: str):
782
+ if item_type == self.PARAMETER:
783
+ if item_name not in self.__model_def.parameters:
784
+ self._report_error(f"{item_type} {item_name} is not defined in the model")
785
+ else:
786
+ if item_name not in self.__model_def.inputs and item_name not in self.__model_def.outputs:
787
+ self._report_error(f"{item_type} {item_name} is not defined in the model")
719
788
 
720
- if dataset_name is None:
721
- self._report_error(f"Dataset name is null")
789
+ def check_item_not_defined_in_model(self, item_name: str, item_type: str):
722
790
 
723
- if not self._VALID_IDENTIFIER.match(dataset_name):
724
- self._report_error(f"Dataset name {dataset_name} is not a valid identifier")
791
+ if item_name in self.__model_def.inputs or item_name in self.__model_def.outputs:
792
+ self._report_error(f"{item_type} {item_name} is already defined in the model")
725
793
 
726
- def check_dataset_not_defined_in_model(self, dataset_name: str):
794
+ if item_name in self.__model_def.parameters:
795
+ self._report_error(f"{item_name} name {item_name} is already in use as a model parameter")
727
796
 
728
- if dataset_name in self.__model_def.inputs or dataset_name in self.__model_def.outputs:
729
- self._report_error(f"Dataset {dataset_name} is already defined in the model")
797
+ def check_item_is_model_output(self, item_name: str, item_type: str):
730
798
 
731
- if dataset_name in self.__model_def.parameters:
732
- self._report_error(f"Dataset name {dataset_name} is already in use as a model parameter")
799
+ if item_name not in self.__model_def.outputs and item_name not in self.__dynamic_outputs:
800
+ self._report_error(f"{item_type} {item_name} is not defined as a model output")
733
801
 
734
- def check_dataset_defined_in_model(self, dataset_name: str):
802
+ def check_item_available_in_context(self, item_name: str, item_type: str):
735
803
 
736
- if dataset_name not in self.__model_def.inputs and dataset_name not in self.__model_def.outputs:
737
- self._report_error(f"Dataset {dataset_name} is not defined in the model")
804
+ if item_name not in self.__local_ctx:
805
+ self._report_error(f"{item_type} {item_name} is not available in the current context")
738
806
 
739
- def check_dataset_is_model_output(self, dataset_name: str):
807
+ def check_item_not_available_in_context(self, item_name: str, item_type: str):
740
808
 
741
- if dataset_name not in self.__model_def.outputs and dataset_name not in self.__dynamic_outputs:
742
- self._report_error(f"Dataset {dataset_name} is not defined as a model output")
809
+ if item_name in self.__local_ctx:
810
+ self._report_error(f"{item_type} {item_name} already exists in the current context")
743
811
 
744
812
  def check_dataset_is_dynamic_output(self, dataset_name: str):
745
813
 
@@ -752,16 +820,6 @@ class TracContextValidator(TracContextErrorReporter):
752
820
  if model_output and not model_output.dynamic:
753
821
  self._report_error(f"Model output {dataset_name} is not a dynamic output")
754
822
 
755
- def check_dataset_available_in_context(self, item_name: str):
756
-
757
- if item_name not in self.__local_ctx:
758
- self._report_error(f"Dataset {item_name} is not available in the current context")
759
-
760
- def check_dataset_not_available_in_context(self, item_name: str):
761
-
762
- if item_name in self.__local_ctx:
763
- self._report_error(f"Dataset {item_name} already exists in the current context")
764
-
765
823
  def check_dataset_schema_defined(self, dataset_name: str, data_view: _data.DataView):
766
824
 
767
825
  schema = data_view.trac_schema if data_view is not None else None
@@ -834,6 +892,14 @@ class TracContextValidator(TracContextErrorReporter):
834
892
  f"The object referenced by [{item_name}] in the current context has the wrong type" +
835
893
  f" (expected {expected_type_name}, got {actual_type_name})")
836
894
 
895
+ def check_context_data_view_type(self, item_name: str, data_vew: _data.DataView, expected_type: _meta.ObjectType):
896
+
897
+ if data_vew.object_type != expected_type:
898
+
899
+ self._report_error(
900
+ f"The object referenced by [{item_name}] in the current context has the wrong type" +
901
+ f" (expected {expected_type.name}, got {data_vew.object_type.name})")
902
+
837
903
  def check_data_framework_args(self, framework: _eapi.DataFramework, framework_args: tp.Dict[str, tp.Any]):
838
904
 
839
905
  expected_args = _data.DataConverter.get_framework_args(framework)
@@ -861,6 +927,16 @@ class TracContextValidator(TracContextErrorReporter):
861
927
  f"Using [{framework}], argument [{arg_name}] has the wrong type" +
862
928
  f" (expected {expected_type_name}, got {actual_type_name})")
863
929
 
930
+ def check_file_content_present(self, file_name: str, file_view: _data.DataView):
931
+
932
+ if file_view.file_item is None or not file_view.file_item.raw_bytes:
933
+ self._report_error(f"File content is missing or empty for [{file_name}] in the current context")
934
+
935
+ def check_file_content_not_present(self, file_name: str, file_view: _data.DataView):
936
+
937
+ if file_view.file_item is not None and file_view.file_item.raw_bytes:
938
+ self._report_error(f"File content is already present for [{file_name}] in the current context")
939
+
864
940
  def check_storage_valid_identifier(self, storage_key):
865
941
 
866
942
  if storage_key is None:
@@ -878,7 +954,7 @@ class TracContextValidator(TracContextErrorReporter):
878
954
 
879
955
  def check_storage_type(
880
956
  self, storage_map: tp.Dict, storage_key: str,
881
- storage_type: tp.Union[_eapi.TracFileStorage.__class__]):
957
+ storage_type: tp.Union[_eapi.TracFileStorage.__class__, _eapi.TracDataStorage.__class__]):
882
958
 
883
959
  storage_instance = storage_map.get(storage_key)
884
960