deltacat-io-core 0.1.0__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.
- deltacat_io_core-0.1.0/.gitignore +222 -0
- deltacat_io_core-0.1.0/PKG-INFO +153 -0
- deltacat_io_core-0.1.0/README.md +122 -0
- deltacat_io_core-0.1.0/__init__.py +40 -0
- deltacat_io_core-0.1.0/bucket_task_support.py +101 -0
- deltacat_io_core-0.1.0/catalog_read_support.py +538 -0
- deltacat_io_core-0.1.0/catalog_schemaless_support.py +161 -0
- deltacat_io_core-0.1.0/catalog_write_policy.py +646 -0
- deltacat_io_core-0.1.0/catalog_write_support.py +1117 -0
- deltacat_io_core-0.1.0/chunk_dedupe.py +56 -0
- deltacat_io_core-0.1.0/compact_partition_params_support.py +183 -0
- deltacat_io_core-0.1.0/compaction_audit_model.py +701 -0
- deltacat_io_core-0.1.0/compaction_support.py +1134 -0
- deltacat_io_core-0.1.0/compactor_base_models.py +218 -0
- deltacat_io_core-0.1.0/compactor_locator_models.py +204 -0
- deltacat_io_core-0.1.0/compactor_session_models.py +38 -0
- deltacat_io_core-0.1.0/compactor_task_models.py +288 -0
- deltacat_io_core-0.1.0/delete_models.py +147 -0
- deltacat_io_core-0.1.0/delete_support.py +109 -0
- deltacat_io_core-0.1.0/delimited_options.py +135 -0
- deltacat_io_core-0.1.0/delta_annotation_support.py +278 -0
- deltacat_io_core-0.1.0/delta_file_support.py +151 -0
- deltacat_io_core-0.1.0/deps.py +123 -0
- deltacat_io_core-0.1.0/envelope_models.py +160 -0
- deltacat_io_core-0.1.0/errors.py +9 -0
- deltacat_io_core-0.1.0/execution.py +2333 -0
- deltacat_io_core-0.1.0/filesystem_support.py +214 -0
- deltacat_io_core-0.1.0/filtering.py +743 -0
- deltacat_io_core-0.1.0/lance_support.py +440 -0
- deltacat_io_core-0.1.0/log_constants.py +51 -0
- deltacat_io_core-0.1.0/logs.py +423 -0
- deltacat_io_core-0.1.0/manifest_builder_support.py +323 -0
- deltacat_io_core-0.1.0/manifest_distributed_execution.py +150 -0
- deltacat_io_core-0.1.0/manifest_distributed_support.py +47 -0
- deltacat_io_core-0.1.0/manifest_download_support.py +115 -0
- deltacat_io_core-0.1.0/manifest_entry_support.py +172 -0
- deltacat_io_core-0.1.0/manifest_path_support.py +140 -0
- deltacat_io_core-0.1.0/manifest_wrapper.py +127 -0
- deltacat_io_core-0.1.0/manifest_write_replica.py +80 -0
- deltacat_io_core-0.1.0/merge_file_group_models.py +128 -0
- deltacat_io_core-0.1.0/merge_file_group_support.py +82 -0
- deltacat_io_core-0.1.0/merge_key_support.py +55 -0
- deltacat_io_core-0.1.0/merge_table_support.py +332 -0
- deltacat_io_core-0.1.0/merge_task_support.py +567 -0
- deltacat_io_core-0.1.0/models.py +778 -0
- deltacat_io_core-0.1.0/mor_support.py +808 -0
- deltacat_io_core-0.1.0/performance_support.py +15 -0
- deltacat_io_core-0.1.0/pk_hash_support.py +131 -0
- deltacat_io_core-0.1.0/polars_support.py +153 -0
- deltacat_io_core-0.1.0/pyarrow_read_support.py +411 -0
- deltacat_io_core-0.1.0/pyarrow_write_support.py +203 -0
- deltacat_io_core-0.1.0/pyproject.toml +62 -0
- deltacat_io_core-0.1.0/resource_metrics.py +73 -0
- deltacat_io_core-0.1.0/round_completion_support.py +101 -0
- deltacat_io_core-0.1.0/schema_support.py +255 -0
- deltacat_io_core-0.1.0/sort_key_validation.py +63 -0
- deltacat_io_core-0.1.0/sort_support.py +165 -0
- deltacat_io_core-0.1.0/storage_delta_support.py +163 -0
- deltacat_io_core-0.1.0/storage_read_support.py +275 -0
- deltacat_io_core-0.1.0/storage_write_support.py +190 -0
- deltacat_io_core-0.1.0/system_columns.py +275 -0
- deltacat_io_core-0.1.0/table_conversion.py +280 -0
- deltacat_io_core-0.1.0/table_dispatch.py +544 -0
- deltacat_io_core-0.1.0/table_ops.py +180 -0
- deltacat_io_core-0.1.0/table_version_schema_support.py +52 -0
- deltacat_io_core-0.1.0/table_write_replica.py +155 -0
- deltacat_io_core-0.1.0/table_write_strategy.py +79 -0
- deltacat_io_core-0.1.0/write_capture.py +418 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# uv
|
|
2
|
+
.venv/
|
|
3
|
+
|
|
4
|
+
# Byte-compiled / optimized / DLL files
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*$py.class
|
|
8
|
+
|
|
9
|
+
# C extensions
|
|
10
|
+
*.so
|
|
11
|
+
|
|
12
|
+
# Distribution / packaging
|
|
13
|
+
.Python
|
|
14
|
+
build/
|
|
15
|
+
develop-eggs/
|
|
16
|
+
dist/
|
|
17
|
+
downloads/
|
|
18
|
+
eggs/
|
|
19
|
+
.eggs/
|
|
20
|
+
lib/
|
|
21
|
+
lib64/
|
|
22
|
+
parts/
|
|
23
|
+
sdist/
|
|
24
|
+
var/
|
|
25
|
+
wheels/
|
|
26
|
+
share/python-wheels/
|
|
27
|
+
*.egg-info/
|
|
28
|
+
.installed.cfg
|
|
29
|
+
*.egg
|
|
30
|
+
*.egg-info
|
|
31
|
+
MANIFEST
|
|
32
|
+
package-lock.json
|
|
33
|
+
*.db
|
|
34
|
+
pyvenv.cfg
|
|
35
|
+
**/.deltacat
|
|
36
|
+
.deltacat_memory/
|
|
37
|
+
|
|
38
|
+
# Generated Files
|
|
39
|
+
**/.riv-meta-*
|
|
40
|
+
**/*.parquet
|
|
41
|
+
**/*.feather
|
|
42
|
+
**/*.json
|
|
43
|
+
|
|
44
|
+
# PyInstaller
|
|
45
|
+
# Usually these files are written by a python script from a template
|
|
46
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
47
|
+
*.manifest
|
|
48
|
+
*.spec
|
|
49
|
+
|
|
50
|
+
# Installer logs
|
|
51
|
+
pip-log.txt
|
|
52
|
+
pip-delete-this-directory.txt
|
|
53
|
+
|
|
54
|
+
# Unit test / coverage reports
|
|
55
|
+
htmlcov/
|
|
56
|
+
.tox/
|
|
57
|
+
.nox/
|
|
58
|
+
.coverage
|
|
59
|
+
.coverage.*
|
|
60
|
+
.cache
|
|
61
|
+
nosetests.xml
|
|
62
|
+
coverage.xml
|
|
63
|
+
*.cover
|
|
64
|
+
*.py,cover
|
|
65
|
+
.hypothesis/
|
|
66
|
+
.pytest_cache/
|
|
67
|
+
cover/
|
|
68
|
+
|
|
69
|
+
# Translations
|
|
70
|
+
*.mo
|
|
71
|
+
*.pot
|
|
72
|
+
|
|
73
|
+
# Django stuff:
|
|
74
|
+
*.log
|
|
75
|
+
local_settings.py
|
|
76
|
+
db.sqlite3
|
|
77
|
+
db.sqlite3-journal
|
|
78
|
+
|
|
79
|
+
# Flask stuff:
|
|
80
|
+
instance/
|
|
81
|
+
.webassets-cache
|
|
82
|
+
|
|
83
|
+
# Scrapy stuff:
|
|
84
|
+
.scrapy
|
|
85
|
+
|
|
86
|
+
# Sphinx documentation
|
|
87
|
+
docs/_build/
|
|
88
|
+
|
|
89
|
+
# PyBuilder
|
|
90
|
+
.pybuilder/
|
|
91
|
+
target/
|
|
92
|
+
|
|
93
|
+
# Jupyter Notebook
|
|
94
|
+
.ipynb_checkpoints
|
|
95
|
+
|
|
96
|
+
# IPython
|
|
97
|
+
profile_default/
|
|
98
|
+
ipython_config.py
|
|
99
|
+
|
|
100
|
+
# pyenv
|
|
101
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
102
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
103
|
+
.python-version
|
|
104
|
+
|
|
105
|
+
# pipenv
|
|
106
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
107
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
108
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
109
|
+
# install all needed dependencies.
|
|
110
|
+
#Pipfile.lock
|
|
111
|
+
|
|
112
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
113
|
+
__pypackages__/
|
|
114
|
+
|
|
115
|
+
# Celery stuff
|
|
116
|
+
celerybeat-schedule
|
|
117
|
+
celerybeat.pid
|
|
118
|
+
|
|
119
|
+
# SageMath parsed files
|
|
120
|
+
*.sage.py
|
|
121
|
+
|
|
122
|
+
# Environments
|
|
123
|
+
.env
|
|
124
|
+
.venv
|
|
125
|
+
env/
|
|
126
|
+
venv/
|
|
127
|
+
ENV/
|
|
128
|
+
env.bak/
|
|
129
|
+
venv.bak/
|
|
130
|
+
|
|
131
|
+
# Spyder project settings
|
|
132
|
+
.spyderproject
|
|
133
|
+
.spyproject
|
|
134
|
+
|
|
135
|
+
# Rope project settings
|
|
136
|
+
.ropeproject
|
|
137
|
+
|
|
138
|
+
# mkdocs documentation
|
|
139
|
+
/site
|
|
140
|
+
|
|
141
|
+
# mypy
|
|
142
|
+
.mypy_cache/
|
|
143
|
+
.dmypy.json
|
|
144
|
+
dmypy.json
|
|
145
|
+
|
|
146
|
+
# Pyre type checker
|
|
147
|
+
.pyre/
|
|
148
|
+
|
|
149
|
+
# pytype static type analyzer
|
|
150
|
+
.pytype/
|
|
151
|
+
|
|
152
|
+
# Cython debug symbols
|
|
153
|
+
cython_debug/
|
|
154
|
+
|
|
155
|
+
# Vi
|
|
156
|
+
*.swp
|
|
157
|
+
|
|
158
|
+
##############################
|
|
159
|
+
## JetBrains
|
|
160
|
+
##############################
|
|
161
|
+
out/
|
|
162
|
+
.idea/
|
|
163
|
+
.idea_modules/
|
|
164
|
+
*.iml
|
|
165
|
+
*.ipr
|
|
166
|
+
*.iws
|
|
167
|
+
|
|
168
|
+
##############################
|
|
169
|
+
## Eclipse
|
|
170
|
+
##############################
|
|
171
|
+
.settings/
|
|
172
|
+
bin/
|
|
173
|
+
tmp/
|
|
174
|
+
.metadata
|
|
175
|
+
.classpath
|
|
176
|
+
.project
|
|
177
|
+
*.tmp
|
|
178
|
+
*.bak
|
|
179
|
+
*.swp
|
|
180
|
+
*~.nib
|
|
181
|
+
local.properties
|
|
182
|
+
.loadpath
|
|
183
|
+
.factorypath
|
|
184
|
+
/eclipse-bin/
|
|
185
|
+
/eclipse-bin/*
|
|
186
|
+
|
|
187
|
+
##############################
|
|
188
|
+
## NetBeans
|
|
189
|
+
##############################
|
|
190
|
+
nbproject/private/
|
|
191
|
+
build/
|
|
192
|
+
nbbuild/
|
|
193
|
+
dist/
|
|
194
|
+
nbdist/
|
|
195
|
+
nbactions.xml
|
|
196
|
+
nb-configuration.xml
|
|
197
|
+
|
|
198
|
+
##############################
|
|
199
|
+
## Visual Studio Code
|
|
200
|
+
##############################
|
|
201
|
+
.vscode/
|
|
202
|
+
.code-workspace
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
##############################
|
|
206
|
+
## Cursor
|
|
207
|
+
##############################
|
|
208
|
+
.cursor/
|
|
209
|
+
|
|
210
|
+
##############################
|
|
211
|
+
## OS X
|
|
212
|
+
##############################
|
|
213
|
+
.DS_Store
|
|
214
|
+
|
|
215
|
+
# Iceberg Examples
|
|
216
|
+
iceberg_warehouse
|
|
217
|
+
|
|
218
|
+
# Analysis reports (large CSVs, not code)
|
|
219
|
+
reports/
|
|
220
|
+
|
|
221
|
+
# Local coding transcripts/scratch notes
|
|
222
|
+
claude-coding-session-*.txt
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: deltacat-io-core
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Shared local IO execution layer for DeltaCAT read/write clients.
|
|
5
|
+
Author: Ray Team
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Requires-Python: <3.11,>=3.10
|
|
13
|
+
Requires-Dist: fsspec
|
|
14
|
+
Requires-Dist: msgpack~=1.0.7
|
|
15
|
+
Requires-Dist: numpy==1.23.2
|
|
16
|
+
Requires-Dist: pyarrow==17.0.0
|
|
17
|
+
Provides-Extra: all
|
|
18
|
+
Requires-Dist: fastavro; extra == 'all'
|
|
19
|
+
Requires-Dist: pandas==2.2.3; extra == 'all'
|
|
20
|
+
Requires-Dist: polars==1.28.1; extra == 'all'
|
|
21
|
+
Requires-Dist: pylance>=0.37.0; extra == 'all'
|
|
22
|
+
Provides-Extra: io
|
|
23
|
+
Requires-Dist: fastavro; extra == 'io'
|
|
24
|
+
Provides-Extra: lance
|
|
25
|
+
Requires-Dist: pylance>=0.37.0; extra == 'lance'
|
|
26
|
+
Provides-Extra: pandas
|
|
27
|
+
Requires-Dist: pandas==2.2.3; extra == 'pandas'
|
|
28
|
+
Provides-Extra: polars
|
|
29
|
+
Requires-Dist: polars==1.28.1; extra == 'polars'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# deltacat-io-core
|
|
33
|
+
|
|
34
|
+
`deltacat-io-core` is the shared local execution layer for DeltaCAT reads and
|
|
35
|
+
writes.
|
|
36
|
+
|
|
37
|
+
It is used by both:
|
|
38
|
+
|
|
39
|
+
- `deltacat-client` for direct thin-plan execution
|
|
40
|
+
- `deltacat` for shared local execution and compatibility wrappers
|
|
41
|
+
|
|
42
|
+
## Naming
|
|
43
|
+
|
|
44
|
+
- distribution/package name: `deltacat-io-core`
|
|
45
|
+
- Python import module: `deltacat_io_core`
|
|
46
|
+
|
|
47
|
+
The distribution uses dashes for consistency with `deltacat-client`. The import
|
|
48
|
+
module keeps underscores because Python module names cannot contain `-`.
|
|
49
|
+
|
|
50
|
+
## Scope
|
|
51
|
+
|
|
52
|
+
`deltacat-io-core` owns the code that should behave the same regardless of
|
|
53
|
+
whether the caller is using the thin client or the thick DeltaCAT package.
|
|
54
|
+
|
|
55
|
+
Today that includes:
|
|
56
|
+
|
|
57
|
+
- direct execution of thin `Plan` objects
|
|
58
|
+
- MOR execution for thin and thick paths
|
|
59
|
+
- local file materialization and manifest building
|
|
60
|
+
- schema alignment and table conversion helpers
|
|
61
|
+
- sort-aware file ordering and manifest handling
|
|
62
|
+
- shared compaction/MOR helper layers and model types
|
|
63
|
+
- format-specific local readers/writers
|
|
64
|
+
|
|
65
|
+
## Non-Goals
|
|
66
|
+
|
|
67
|
+
`deltacat-io-core` does not own:
|
|
68
|
+
|
|
69
|
+
- server routes or REST/MCP request handling
|
|
70
|
+
- authoritative catalog/storage mutations
|
|
71
|
+
- native Ray job orchestration surfaces
|
|
72
|
+
- public end-user API shape for `deltacat` or `deltacat-client`
|
|
73
|
+
|
|
74
|
+
It is a shared implementation layer, not the top-level user product.
|
|
75
|
+
|
|
76
|
+
## Architecture
|
|
77
|
+
|
|
78
|
+
The current read architecture is:
|
|
79
|
+
|
|
80
|
+
1. The server resolves a thin `Plan`.
|
|
81
|
+
2. `client.catalog.read(plan=...)` executes that plan directly through
|
|
82
|
+
`deltacat-io-core`.
|
|
83
|
+
3. `dc.read_table(plan=...)` for thin plans also executes through the same
|
|
84
|
+
shared path.
|
|
85
|
+
|
|
86
|
+
There is no longer a runtime bridge back into thick DeltaCAT for thin plan
|
|
87
|
+
execution. The plan contract is expected to carry the metadata required for
|
|
88
|
+
direct execution.
|
|
89
|
+
|
|
90
|
+
The current write architecture is:
|
|
91
|
+
|
|
92
|
+
1. The client stages local files or materializes local data through shared
|
|
93
|
+
helpers.
|
|
94
|
+
2. The authoritative commit still happens through DeltaCAT server/native
|
|
95
|
+
boundaries.
|
|
96
|
+
3. Shared write-preparation and manifest logic lives in `deltacat-io-core`.
|
|
97
|
+
|
|
98
|
+
## Installation
|
|
99
|
+
|
|
100
|
+
Base install:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
uv pip install deltacat-io-core
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Optional extras:
|
|
107
|
+
|
|
108
|
+
- `deltacat-io-core[io]` for local file readers/writers (`pyarrow`, `fastavro`)
|
|
109
|
+
- `deltacat-io-core[pandas]` for Pandas conversions
|
|
110
|
+
- `deltacat-io-core[polars]` for Polars conversions and lazy scan helpers
|
|
111
|
+
- `deltacat-io-core[lance]` for Lance dataset support
|
|
112
|
+
- `deltacat-io-core[all]` for the full local IO stack
|
|
113
|
+
|
|
114
|
+
## Read Capabilities
|
|
115
|
+
|
|
116
|
+
The shared read executor currently handles:
|
|
117
|
+
|
|
118
|
+
- schema-table reads
|
|
119
|
+
- schemaless manifest-table reads
|
|
120
|
+
- MOR reads
|
|
121
|
+
- direct `pyarrow`, `pandas`, `polars`, `numpy`, `daft`, and `ray_dataset`
|
|
122
|
+
outputs where supported
|
|
123
|
+
- lazy `pyarrow_parquet`
|
|
124
|
+
- lazy `lance`
|
|
125
|
+
|
|
126
|
+
It also enforces direct validation for unsupported combinations, for example:
|
|
127
|
+
|
|
128
|
+
- schemaless + `pyarrow_parquet`
|
|
129
|
+
- schemaless + `lance`
|
|
130
|
+
- mixed-content lazy plans for format-specific readers
|
|
131
|
+
- unknown content types in the shared path
|
|
132
|
+
|
|
133
|
+
## Write Capabilities
|
|
134
|
+
|
|
135
|
+
The shared write layer currently covers:
|
|
136
|
+
|
|
137
|
+
- write input normalization
|
|
138
|
+
- local data materialization
|
|
139
|
+
- manifest construction for existing files and datasets
|
|
140
|
+
- schema/read compatibility helpers
|
|
141
|
+
- standard catalog write orchestration slices
|
|
142
|
+
|
|
143
|
+
Authoritative catalog mutation, commit, retention, and compaction boundaries
|
|
144
|
+
still remain on the native/server side where they belong.
|
|
145
|
+
|
|
146
|
+
## Relationship To Other Packages
|
|
147
|
+
|
|
148
|
+
Use `deltacat-client` when you want the public thin client.
|
|
149
|
+
|
|
150
|
+
Use `deltacat` when you want the thick/native package.
|
|
151
|
+
|
|
152
|
+
Use `deltacat-io-core` directly only if you are intentionally building against
|
|
153
|
+
the shared execution layer itself.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# deltacat-io-core
|
|
2
|
+
|
|
3
|
+
`deltacat-io-core` is the shared local execution layer for DeltaCAT reads and
|
|
4
|
+
writes.
|
|
5
|
+
|
|
6
|
+
It is used by both:
|
|
7
|
+
|
|
8
|
+
- `deltacat-client` for direct thin-plan execution
|
|
9
|
+
- `deltacat` for shared local execution and compatibility wrappers
|
|
10
|
+
|
|
11
|
+
## Naming
|
|
12
|
+
|
|
13
|
+
- distribution/package name: `deltacat-io-core`
|
|
14
|
+
- Python import module: `deltacat_io_core`
|
|
15
|
+
|
|
16
|
+
The distribution uses dashes for consistency with `deltacat-client`. The import
|
|
17
|
+
module keeps underscores because Python module names cannot contain `-`.
|
|
18
|
+
|
|
19
|
+
## Scope
|
|
20
|
+
|
|
21
|
+
`deltacat-io-core` owns the code that should behave the same regardless of
|
|
22
|
+
whether the caller is using the thin client or the thick DeltaCAT package.
|
|
23
|
+
|
|
24
|
+
Today that includes:
|
|
25
|
+
|
|
26
|
+
- direct execution of thin `Plan` objects
|
|
27
|
+
- MOR execution for thin and thick paths
|
|
28
|
+
- local file materialization and manifest building
|
|
29
|
+
- schema alignment and table conversion helpers
|
|
30
|
+
- sort-aware file ordering and manifest handling
|
|
31
|
+
- shared compaction/MOR helper layers and model types
|
|
32
|
+
- format-specific local readers/writers
|
|
33
|
+
|
|
34
|
+
## Non-Goals
|
|
35
|
+
|
|
36
|
+
`deltacat-io-core` does not own:
|
|
37
|
+
|
|
38
|
+
- server routes or REST/MCP request handling
|
|
39
|
+
- authoritative catalog/storage mutations
|
|
40
|
+
- native Ray job orchestration surfaces
|
|
41
|
+
- public end-user API shape for `deltacat` or `deltacat-client`
|
|
42
|
+
|
|
43
|
+
It is a shared implementation layer, not the top-level user product.
|
|
44
|
+
|
|
45
|
+
## Architecture
|
|
46
|
+
|
|
47
|
+
The current read architecture is:
|
|
48
|
+
|
|
49
|
+
1. The server resolves a thin `Plan`.
|
|
50
|
+
2. `client.catalog.read(plan=...)` executes that plan directly through
|
|
51
|
+
`deltacat-io-core`.
|
|
52
|
+
3. `dc.read_table(plan=...)` for thin plans also executes through the same
|
|
53
|
+
shared path.
|
|
54
|
+
|
|
55
|
+
There is no longer a runtime bridge back into thick DeltaCAT for thin plan
|
|
56
|
+
execution. The plan contract is expected to carry the metadata required for
|
|
57
|
+
direct execution.
|
|
58
|
+
|
|
59
|
+
The current write architecture is:
|
|
60
|
+
|
|
61
|
+
1. The client stages local files or materializes local data through shared
|
|
62
|
+
helpers.
|
|
63
|
+
2. The authoritative commit still happens through DeltaCAT server/native
|
|
64
|
+
boundaries.
|
|
65
|
+
3. Shared write-preparation and manifest logic lives in `deltacat-io-core`.
|
|
66
|
+
|
|
67
|
+
## Installation
|
|
68
|
+
|
|
69
|
+
Base install:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
uv pip install deltacat-io-core
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Optional extras:
|
|
76
|
+
|
|
77
|
+
- `deltacat-io-core[io]` for local file readers/writers (`pyarrow`, `fastavro`)
|
|
78
|
+
- `deltacat-io-core[pandas]` for Pandas conversions
|
|
79
|
+
- `deltacat-io-core[polars]` for Polars conversions and lazy scan helpers
|
|
80
|
+
- `deltacat-io-core[lance]` for Lance dataset support
|
|
81
|
+
- `deltacat-io-core[all]` for the full local IO stack
|
|
82
|
+
|
|
83
|
+
## Read Capabilities
|
|
84
|
+
|
|
85
|
+
The shared read executor currently handles:
|
|
86
|
+
|
|
87
|
+
- schema-table reads
|
|
88
|
+
- schemaless manifest-table reads
|
|
89
|
+
- MOR reads
|
|
90
|
+
- direct `pyarrow`, `pandas`, `polars`, `numpy`, `daft`, and `ray_dataset`
|
|
91
|
+
outputs where supported
|
|
92
|
+
- lazy `pyarrow_parquet`
|
|
93
|
+
- lazy `lance`
|
|
94
|
+
|
|
95
|
+
It also enforces direct validation for unsupported combinations, for example:
|
|
96
|
+
|
|
97
|
+
- schemaless + `pyarrow_parquet`
|
|
98
|
+
- schemaless + `lance`
|
|
99
|
+
- mixed-content lazy plans for format-specific readers
|
|
100
|
+
- unknown content types in the shared path
|
|
101
|
+
|
|
102
|
+
## Write Capabilities
|
|
103
|
+
|
|
104
|
+
The shared write layer currently covers:
|
|
105
|
+
|
|
106
|
+
- write input normalization
|
|
107
|
+
- local data materialization
|
|
108
|
+
- manifest construction for existing files and datasets
|
|
109
|
+
- schema/read compatibility helpers
|
|
110
|
+
- standard catalog write orchestration slices
|
|
111
|
+
|
|
112
|
+
Authoritative catalog mutation, commit, retention, and compaction boundaries
|
|
113
|
+
still remain on the native/server side where they belong.
|
|
114
|
+
|
|
115
|
+
## Relationship To Other Packages
|
|
116
|
+
|
|
117
|
+
Use `deltacat-client` when you want the public thin client.
|
|
118
|
+
|
|
119
|
+
Use `deltacat` when you want the thick/native package.
|
|
120
|
+
|
|
121
|
+
Use `deltacat-io-core` directly only if you are intentionally building against
|
|
122
|
+
the shared execution layer itself.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Shared local IO execution helpers for DeltaCAT thin and thick read/write paths."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
__version__ = "0.1.0"
|
|
8
|
+
|
|
9
|
+
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"__version__",
|
|
13
|
+
"build_entries_for_local_paths",
|
|
14
|
+
"coerce_write_input",
|
|
15
|
+
"execute_read_plan",
|
|
16
|
+
"materialize_arrow_write",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def __getattr__(name: str):
|
|
21
|
+
if name in {
|
|
22
|
+
"build_entries_for_local_paths",
|
|
23
|
+
"coerce_write_input",
|
|
24
|
+
"execute_read_plan",
|
|
25
|
+
"materialize_arrow_write",
|
|
26
|
+
}:
|
|
27
|
+
from deltacat_io_core.execution import (
|
|
28
|
+
build_entries_for_local_paths,
|
|
29
|
+
coerce_write_input,
|
|
30
|
+
execute_read_plan,
|
|
31
|
+
materialize_arrow_write,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
"build_entries_for_local_paths": build_entries_for_local_paths,
|
|
36
|
+
"coerce_write_input": coerce_write_input,
|
|
37
|
+
"execute_read_plan": execute_read_plan,
|
|
38
|
+
"materialize_arrow_write": materialize_arrow_write,
|
|
39
|
+
}[name]
|
|
40
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Shared helpers for hash/range bucket task execution."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def execute_bucket_grouping(
|
|
11
|
+
*,
|
|
12
|
+
input: Any,
|
|
13
|
+
load_delta_file_envelope_groups_fn,
|
|
14
|
+
group_hash_bucket_indices_fn,
|
|
15
|
+
current_process_peak_memory_fn,
|
|
16
|
+
hash_bucket_result_factory,
|
|
17
|
+
wall_time_fn,
|
|
18
|
+
log_info_fn,
|
|
19
|
+
peak_memory_log_message: str,
|
|
20
|
+
) -> Any:
|
|
21
|
+
"""Execute the common bucket-task core shared by hash and range bucketing."""
|
|
22
|
+
(
|
|
23
|
+
delta_file_envelope_groups,
|
|
24
|
+
total_record_count,
|
|
25
|
+
total_size_bytes,
|
|
26
|
+
) = load_delta_file_envelope_groups_fn()
|
|
27
|
+
hash_bucket_group_to_obj_id_tuple = group_hash_bucket_indices_fn(
|
|
28
|
+
hash_bucket_object_groups=delta_file_envelope_groups,
|
|
29
|
+
num_buckets=input.num_hash_buckets,
|
|
30
|
+
num_groups=input.num_hash_groups,
|
|
31
|
+
object_store=input.object_store,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
peak_memory_usage_bytes = current_process_peak_memory_fn()
|
|
35
|
+
log_info_fn(
|
|
36
|
+
peak_memory_log_message.format(peak_memory_usage_bytes=peak_memory_usage_bytes)
|
|
37
|
+
)
|
|
38
|
+
return hash_bucket_result_factory(
|
|
39
|
+
hash_bucket_group_to_obj_id_tuple,
|
|
40
|
+
np.int64(total_size_bytes),
|
|
41
|
+
np.int64(total_record_count),
|
|
42
|
+
np.double(peak_memory_usage_bytes),
|
|
43
|
+
np.double(0.0),
|
|
44
|
+
np.double(wall_time_fn()),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def execute_bucket_task(
|
|
49
|
+
*,
|
|
50
|
+
input: Any,
|
|
51
|
+
task_fn,
|
|
52
|
+
task_fn_kwargs: dict[str, Any],
|
|
53
|
+
process_utilization_context_factory,
|
|
54
|
+
timed_invocation_fn,
|
|
55
|
+
emit_timer_metrics_fn,
|
|
56
|
+
metrics_name: str,
|
|
57
|
+
hash_bucket_result_factory,
|
|
58
|
+
bytes_per_gibibyte: float,
|
|
59
|
+
log_info_fn,
|
|
60
|
+
log_debug_fn,
|
|
61
|
+
started_message: str,
|
|
62
|
+
finished_message: str,
|
|
63
|
+
) -> Any:
|
|
64
|
+
"""Execute the common outer wrapper shared by hash/range bucket tasks."""
|
|
65
|
+
with process_utilization_context_factory() as process_util:
|
|
66
|
+
log_info_fn(started_message)
|
|
67
|
+
|
|
68
|
+
def log_peak_memory():
|
|
69
|
+
log_debug_fn(
|
|
70
|
+
"Process peak memory utilization so far: %s bytes (%s GB)",
|
|
71
|
+
process_util.max_memory,
|
|
72
|
+
process_util.max_memory / bytes_per_gibibyte,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
if input.memory_logs_enabled:
|
|
76
|
+
process_util.schedule_callback(log_peak_memory, 10)
|
|
77
|
+
|
|
78
|
+
bucket_result, duration = timed_invocation_fn(
|
|
79
|
+
func=task_fn,
|
|
80
|
+
**task_fn_kwargs,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
emit_metrics_time = 0.0
|
|
84
|
+
if input.metrics_config:
|
|
85
|
+
_, latency = timed_invocation_fn(
|
|
86
|
+
func=emit_timer_metrics_fn,
|
|
87
|
+
metrics_name=metrics_name,
|
|
88
|
+
value=duration,
|
|
89
|
+
metrics_config=input.metrics_config,
|
|
90
|
+
)
|
|
91
|
+
emit_metrics_time = latency
|
|
92
|
+
|
|
93
|
+
log_info_fn(finished_message)
|
|
94
|
+
return hash_bucket_result_factory(
|
|
95
|
+
bucket_result[0],
|
|
96
|
+
bucket_result[1],
|
|
97
|
+
bucket_result[2],
|
|
98
|
+
bucket_result[3],
|
|
99
|
+
np.double(emit_metrics_time),
|
|
100
|
+
bucket_result[5],
|
|
101
|
+
)
|