kenze 0.3.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.
- kenze-0.3.0/LICENSE +21 -0
- kenze-0.3.0/PKG-INFO +153 -0
- kenze-0.3.0/README.md +131 -0
- kenze-0.3.0/pyproject.toml +35 -0
- kenze-0.3.0/setup.cfg +4 -0
- kenze-0.3.0/src/kenze/__init__.py +70 -0
- kenze-0.3.0/src/kenze/__main__.py +4 -0
- kenze-0.3.0/src/kenze/cli.py +294 -0
- kenze-0.3.0/src/kenze/engine.py +128 -0
- kenze-0.3.0/src/kenze/ops.py +727 -0
- kenze-0.3.0/src/kenze/recipe.py +124 -0
- kenze-0.3.0/src/kenze.egg-info/PKG-INFO +153 -0
- kenze-0.3.0/src/kenze.egg-info/SOURCES.txt +15 -0
- kenze-0.3.0/src/kenze.egg-info/dependency_links.txt +1 -0
- kenze-0.3.0/src/kenze.egg-info/entry_points.txt +2 -0
- kenze-0.3.0/src/kenze.egg-info/requires.txt +5 -0
- kenze-0.3.0/src/kenze.egg-info/top_level.txt +1 -0
kenze-0.3.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ken
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
kenze-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kenze
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Big-file data prep that never runs out of memory — no SQL required. Powered by DuckDB.
|
|
5
|
+
Author: Ken
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://pypi.org/project/kenze/
|
|
8
|
+
Keywords: duckdb,data,csv,parquet,etl,cli,big-data,dataframe,data-cleaning
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering
|
|
12
|
+
Classifier: Topic :: Utilities
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: duckdb>=0.10
|
|
18
|
+
Requires-Dist: psutil>=5.9
|
|
19
|
+
Provides-Extra: cloud
|
|
20
|
+
Requires-Dist: duckdb>=0.10; extra == "cloud"
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
# kenze
|
|
24
|
+
|
|
25
|
+
**Big-file data prep that never runs out of memory — no SQL required.**
|
|
26
|
+
|
|
27
|
+
`kenze` is a tiny command-line tool for cleaning and reshaping data files
|
|
28
|
+
(CSV, Parquet, JSON) that are too big for pandas. It's a friendly front-end
|
|
29
|
+
over [DuckDB](https://duckdb.org): DuckDB does the heavy lifting (streaming,
|
|
30
|
+
disk-spill, all your CPU cores) and `kenze` makes it a one-liner — and
|
|
31
|
+
auto-configures memory so your job doesn't crash.
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install kenze
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
One name for everything: `pip install kenze` → the `kenze` command → `import kenze`.
|
|
38
|
+
|
|
39
|
+
## Why
|
|
40
|
+
|
|
41
|
+
- **It doesn't OOM.** Memory is capped to a fraction of *free* RAM and DuckDB
|
|
42
|
+
spills to disk instead of dying. Point it at a file bigger than your RAM; it's fine.
|
|
43
|
+
- **No SQL, no pandas.** Simple verbs, or a readable recipe file.
|
|
44
|
+
- **One streaming pass.** A whole recipe compiles to a single query — no
|
|
45
|
+
intermediate files, so it's fast and light.
|
|
46
|
+
- **Any format, local or cloud.** CSV / Parquet / JSON, plain or `.gz`,
|
|
47
|
+
on disk or on `s3://` / `gs://` / `https://` — auto-detected.
|
|
48
|
+
|
|
49
|
+
## One-liners
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
kenze profile sales.parquet # schema + row count, instantly
|
|
53
|
+
kenze peek sales.parquet # first rows + types + null counts
|
|
54
|
+
kenze stats sales.parquet # per-column min/max/nulls/unique
|
|
55
|
+
kenze check sales.csv # is the file valid? any bad rows?
|
|
56
|
+
|
|
57
|
+
kenze keep sales.parquet --cols id,city,amount -o small.csv
|
|
58
|
+
kenze drop users.csv --cols email,phone -o clean.parquet
|
|
59
|
+
kenze filter sales.parquet --where "amount > 100" -o big.csv
|
|
60
|
+
kenze rename sales.csv --map "amount:total" -o out.csv
|
|
61
|
+
kenze cast users.csv --types "zip:VARCHAR" -o out.parquet # keep leading zeros
|
|
62
|
+
kenze fillna users.csv --with "city:Unknown" -o out.csv
|
|
63
|
+
kenze mask users.csv --cols email,ssn --method hash -o safe.csv
|
|
64
|
+
kenze dedup users.csv --on id -o unique.parquet
|
|
65
|
+
kenze sample sales.parquet --n 50000 -o sample.csv
|
|
66
|
+
kenze clip points.parquet --bbox -10,35,5,45 -o region.parquet
|
|
67
|
+
|
|
68
|
+
kenze join orders.csv users.parquet --on user_id -o joined.parquet
|
|
69
|
+
kenze diff old.csv new.csv --on id # added / removed / changed
|
|
70
|
+
kenze pivot sales.csv --on city --values amount --agg sum --group region -o wide.csv
|
|
71
|
+
kenze split sales.parquet --by city -o by_city/ # one file per value
|
|
72
|
+
kenze partition sales.parquet --by year -o lake/ # hive year=2026/ folders
|
|
73
|
+
kenze convert sales.parquet -o sales.csv # just change format
|
|
74
|
+
|
|
75
|
+
kenze sql "SELECT *, lag(amount) OVER (ORDER BY ts) FROM 'sales.parquet'" -o out.csv
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Read or write the cloud directly (nothing to download first):
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
kenze filter s3://bucket/huge.parquet --where "amount > 0" -o local.csv
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Pipe like any Unix tool (use `-` for stdin/stdout):
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
cat data.csv | kenze filter - --where "x > 1" -o - | gzip > out.csv.gz
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Recipes
|
|
91
|
+
|
|
92
|
+
Chain steps in a readable `.dq` file — they run as one streaming pass:
|
|
93
|
+
|
|
94
|
+
```yaml
|
|
95
|
+
# clean.dq
|
|
96
|
+
input: data/sales_${DAY}.parquet # ${DAY} filled from --set or the environment
|
|
97
|
+
keep: [id, city, amount]
|
|
98
|
+
types: zip:VARCHAR
|
|
99
|
+
filter: amount > 0
|
|
100
|
+
fillna: city:Unknown
|
|
101
|
+
dedup: id
|
|
102
|
+
sample: 50000
|
|
103
|
+
output: out/clean.csv
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
kenze run clean.dq --set DAY=2026-07-14
|
|
108
|
+
kenze recipe # show every valid recipe step
|
|
109
|
+
kenze eject clean.dq --to sql # print the raw DuckDB SQL (no lock-in)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## From Python
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
import kenze
|
|
116
|
+
kenze.sift("big.parquet", "clean.csv", keep=["id", "city"], filter="amount > 0", sample=50000)
|
|
117
|
+
rows = kenze.sql("SELECT city, count(*) FROM 'big.parquet' GROUP BY 1")
|
|
118
|
+
kenze.profile("big.parquet")
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Handy flags
|
|
122
|
+
|
|
123
|
+
- `--memory-limit 8` — pin the RAM budget (GB) for reproducible / SLA runs.
|
|
124
|
+
- `--temp-dir D:/spill` — put disk-spill where there's room.
|
|
125
|
+
- `--skip-bad-lines` — ignore malformed rows in a dirty CSV.
|
|
126
|
+
- `--log run.json` — write a run manifest (inputs, rows, timing).
|
|
127
|
+
- Writes are **atomic** — a cancelled run never leaves a half-written file.
|
|
128
|
+
|
|
129
|
+
## Commands
|
|
130
|
+
|
|
131
|
+
`profile` · `peek` · `stats` · `check` · `validate` · `keep` · `drop` · `rename` · `cast` ·
|
|
132
|
+
`fillna` · `mask` · `filter` · `dedup` · `sample` · `head` · `clip` · `convert` · `join` ·
|
|
133
|
+
`diff` · `pivot` · `split` · `partition` · `sql` · `eject` · `run` · `recipe`
|
|
134
|
+
|
|
135
|
+
## Where it stops (on purpose)
|
|
136
|
+
|
|
137
|
+
kenze is one dependency and one machine — that's the whole point. It maxes out
|
|
138
|
+
your cores and spills to disk so a single laptop or VM can chew through files far
|
|
139
|
+
bigger than its RAM. It does **not** run a cluster. If you've genuinely outgrown
|
|
140
|
+
one machine (multi-terabyte, distributed pipelines with SLAs and lineage
|
|
141
|
+
tracking), reach for Spark/Dask — kenze is the tool you use *before* you need those.
|
|
142
|
+
|
|
143
|
+
## Troubleshooting
|
|
144
|
+
|
|
145
|
+
**`'kenze' is not recognized` / `kenze: command not found`?**
|
|
146
|
+
`pip` installed kenze correctly — the command just landed in a folder that isn't on
|
|
147
|
+
your PATH (this affects every pip-installed CLI). Options:
|
|
148
|
+
|
|
149
|
+
- **Use it now, no setup:** `python -m kenze --help`
|
|
150
|
+
- **Fix it for good:** reinstall Python from [python.org](https://www.python.org/downloads/)
|
|
151
|
+
with **"Add python.exe to PATH"** ticked, or use `python -m pipx install kenze`.
|
|
152
|
+
|
|
153
|
+
MIT licensed.
|
kenze-0.3.0/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# kenze
|
|
2
|
+
|
|
3
|
+
**Big-file data prep that never runs out of memory — no SQL required.**
|
|
4
|
+
|
|
5
|
+
`kenze` is a tiny command-line tool for cleaning and reshaping data files
|
|
6
|
+
(CSV, Parquet, JSON) that are too big for pandas. It's a friendly front-end
|
|
7
|
+
over [DuckDB](https://duckdb.org): DuckDB does the heavy lifting (streaming,
|
|
8
|
+
disk-spill, all your CPU cores) and `kenze` makes it a one-liner — and
|
|
9
|
+
auto-configures memory so your job doesn't crash.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install kenze
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
One name for everything: `pip install kenze` → the `kenze` command → `import kenze`.
|
|
16
|
+
|
|
17
|
+
## Why
|
|
18
|
+
|
|
19
|
+
- **It doesn't OOM.** Memory is capped to a fraction of *free* RAM and DuckDB
|
|
20
|
+
spills to disk instead of dying. Point it at a file bigger than your RAM; it's fine.
|
|
21
|
+
- **No SQL, no pandas.** Simple verbs, or a readable recipe file.
|
|
22
|
+
- **One streaming pass.** A whole recipe compiles to a single query — no
|
|
23
|
+
intermediate files, so it's fast and light.
|
|
24
|
+
- **Any format, local or cloud.** CSV / Parquet / JSON, plain or `.gz`,
|
|
25
|
+
on disk or on `s3://` / `gs://` / `https://` — auto-detected.
|
|
26
|
+
|
|
27
|
+
## One-liners
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
kenze profile sales.parquet # schema + row count, instantly
|
|
31
|
+
kenze peek sales.parquet # first rows + types + null counts
|
|
32
|
+
kenze stats sales.parquet # per-column min/max/nulls/unique
|
|
33
|
+
kenze check sales.csv # is the file valid? any bad rows?
|
|
34
|
+
|
|
35
|
+
kenze keep sales.parquet --cols id,city,amount -o small.csv
|
|
36
|
+
kenze drop users.csv --cols email,phone -o clean.parquet
|
|
37
|
+
kenze filter sales.parquet --where "amount > 100" -o big.csv
|
|
38
|
+
kenze rename sales.csv --map "amount:total" -o out.csv
|
|
39
|
+
kenze cast users.csv --types "zip:VARCHAR" -o out.parquet # keep leading zeros
|
|
40
|
+
kenze fillna users.csv --with "city:Unknown" -o out.csv
|
|
41
|
+
kenze mask users.csv --cols email,ssn --method hash -o safe.csv
|
|
42
|
+
kenze dedup users.csv --on id -o unique.parquet
|
|
43
|
+
kenze sample sales.parquet --n 50000 -o sample.csv
|
|
44
|
+
kenze clip points.parquet --bbox -10,35,5,45 -o region.parquet
|
|
45
|
+
|
|
46
|
+
kenze join orders.csv users.parquet --on user_id -o joined.parquet
|
|
47
|
+
kenze diff old.csv new.csv --on id # added / removed / changed
|
|
48
|
+
kenze pivot sales.csv --on city --values amount --agg sum --group region -o wide.csv
|
|
49
|
+
kenze split sales.parquet --by city -o by_city/ # one file per value
|
|
50
|
+
kenze partition sales.parquet --by year -o lake/ # hive year=2026/ folders
|
|
51
|
+
kenze convert sales.parquet -o sales.csv # just change format
|
|
52
|
+
|
|
53
|
+
kenze sql "SELECT *, lag(amount) OVER (ORDER BY ts) FROM 'sales.parquet'" -o out.csv
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Read or write the cloud directly (nothing to download first):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
kenze filter s3://bucket/huge.parquet --where "amount > 0" -o local.csv
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Pipe like any Unix tool (use `-` for stdin/stdout):
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
cat data.csv | kenze filter - --where "x > 1" -o - | gzip > out.csv.gz
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Recipes
|
|
69
|
+
|
|
70
|
+
Chain steps in a readable `.dq` file — they run as one streaming pass:
|
|
71
|
+
|
|
72
|
+
```yaml
|
|
73
|
+
# clean.dq
|
|
74
|
+
input: data/sales_${DAY}.parquet # ${DAY} filled from --set or the environment
|
|
75
|
+
keep: [id, city, amount]
|
|
76
|
+
types: zip:VARCHAR
|
|
77
|
+
filter: amount > 0
|
|
78
|
+
fillna: city:Unknown
|
|
79
|
+
dedup: id
|
|
80
|
+
sample: 50000
|
|
81
|
+
output: out/clean.csv
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
kenze run clean.dq --set DAY=2026-07-14
|
|
86
|
+
kenze recipe # show every valid recipe step
|
|
87
|
+
kenze eject clean.dq --to sql # print the raw DuckDB SQL (no lock-in)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## From Python
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
import kenze
|
|
94
|
+
kenze.sift("big.parquet", "clean.csv", keep=["id", "city"], filter="amount > 0", sample=50000)
|
|
95
|
+
rows = kenze.sql("SELECT city, count(*) FROM 'big.parquet' GROUP BY 1")
|
|
96
|
+
kenze.profile("big.parquet")
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Handy flags
|
|
100
|
+
|
|
101
|
+
- `--memory-limit 8` — pin the RAM budget (GB) for reproducible / SLA runs.
|
|
102
|
+
- `--temp-dir D:/spill` — put disk-spill where there's room.
|
|
103
|
+
- `--skip-bad-lines` — ignore malformed rows in a dirty CSV.
|
|
104
|
+
- `--log run.json` — write a run manifest (inputs, rows, timing).
|
|
105
|
+
- Writes are **atomic** — a cancelled run never leaves a half-written file.
|
|
106
|
+
|
|
107
|
+
## Commands
|
|
108
|
+
|
|
109
|
+
`profile` · `peek` · `stats` · `check` · `validate` · `keep` · `drop` · `rename` · `cast` ·
|
|
110
|
+
`fillna` · `mask` · `filter` · `dedup` · `sample` · `head` · `clip` · `convert` · `join` ·
|
|
111
|
+
`diff` · `pivot` · `split` · `partition` · `sql` · `eject` · `run` · `recipe`
|
|
112
|
+
|
|
113
|
+
## Where it stops (on purpose)
|
|
114
|
+
|
|
115
|
+
kenze is one dependency and one machine — that's the whole point. It maxes out
|
|
116
|
+
your cores and spills to disk so a single laptop or VM can chew through files far
|
|
117
|
+
bigger than its RAM. It does **not** run a cluster. If you've genuinely outgrown
|
|
118
|
+
one machine (multi-terabyte, distributed pipelines with SLAs and lineage
|
|
119
|
+
tracking), reach for Spark/Dask — kenze is the tool you use *before* you need those.
|
|
120
|
+
|
|
121
|
+
## Troubleshooting
|
|
122
|
+
|
|
123
|
+
**`'kenze' is not recognized` / `kenze: command not found`?**
|
|
124
|
+
`pip` installed kenze correctly — the command just landed in a folder that isn't on
|
|
125
|
+
your PATH (this affects every pip-installed CLI). Options:
|
|
126
|
+
|
|
127
|
+
- **Use it now, no setup:** `python -m kenze --help`
|
|
128
|
+
- **Fix it for good:** reinstall Python from [python.org](https://www.python.org/downloads/)
|
|
129
|
+
with **"Add python.exe to PATH"** ticked, or use `python -m pipx install kenze`.
|
|
130
|
+
|
|
131
|
+
MIT licensed.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "kenze"
|
|
7
|
+
version = "0.3.0"
|
|
8
|
+
description = "Big-file data prep that never runs out of memory — no SQL required. Powered by DuckDB."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Ken" }]
|
|
13
|
+
keywords = ["duckdb", "data", "csv", "parquet", "etl", "cli", "big-data", "dataframe", "data-cleaning"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Topic :: Scientific/Engineering",
|
|
18
|
+
"Topic :: Utilities",
|
|
19
|
+
"Environment :: Console",
|
|
20
|
+
]
|
|
21
|
+
# psutil is core: the never-OOM memory sizing is the headline feature, so it
|
|
22
|
+
# ships by default rather than hiding behind an optional extra.
|
|
23
|
+
dependencies = ["duckdb>=0.10", "psutil>=5.9"]
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
cloud = ["duckdb>=0.10"] # S3/GCS/Azure work out of the box via DuckDB httpfs
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://pypi.org/project/kenze/"
|
|
30
|
+
|
|
31
|
+
[project.scripts]
|
|
32
|
+
kenze = "kenze.cli:main"
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.packages.find]
|
|
35
|
+
where = ["src"]
|
kenze-0.3.0/setup.cfg
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""kenze - big-file data prep that never runs out of memory.
|
|
2
|
+
|
|
3
|
+
One `pip install`, then simple commands. DuckDB does the heavy lifting under
|
|
4
|
+
the hood (streaming, disk-spill, all cores); kenze just makes it a one-liner
|
|
5
|
+
and auto-configures memory so it doesn't OOM.
|
|
6
|
+
|
|
7
|
+
You can also use it from Python:
|
|
8
|
+
|
|
9
|
+
import kenze
|
|
10
|
+
kenze.sift("big.parquet", "clean.csv", keep=["id", "city"],
|
|
11
|
+
filter="amount > 0", sample=50000)
|
|
12
|
+
rows = kenze.sql("SELECT city, count(*) FROM 'big.parquet' GROUP BY 1")
|
|
13
|
+
kenze.profile("big.parquet")
|
|
14
|
+
"""
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from .engine import connect
|
|
18
|
+
from .ops import (
|
|
19
|
+
build_query,
|
|
20
|
+
check,
|
|
21
|
+
diff,
|
|
22
|
+
join,
|
|
23
|
+
partition,
|
|
24
|
+
peek,
|
|
25
|
+
pivot,
|
|
26
|
+
profile,
|
|
27
|
+
run_spec,
|
|
28
|
+
run_sql,
|
|
29
|
+
split,
|
|
30
|
+
stats,
|
|
31
|
+
validate,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
__version__ = "0.3.0"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def sift(input, output, con=None, quiet=True, **steps):
|
|
38
|
+
"""Run one streaming pass. steps = keep/drop/filter/bbox/types/fillna/
|
|
39
|
+
mask/rename/dedup/sample/head (same words as the recipe / CLI)."""
|
|
40
|
+
spec = {"input": input, "output": output, **steps}
|
|
41
|
+
return run_spec(spec, con=con, quiet=quiet)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def run(recipe_path, variables=None, con=None, quiet=True):
|
|
45
|
+
"""Run a .dq recipe file from Python."""
|
|
46
|
+
from .recipe import parse
|
|
47
|
+
|
|
48
|
+
with open(recipe_path, encoding="utf-8") as f:
|
|
49
|
+
spec = parse(f.read(), variables=variables)
|
|
50
|
+
return run_spec(spec, con=con, quiet=quiet)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def sql(query, con=None):
|
|
54
|
+
"""Run any DuckDB SQL and get the rows back (window functions, aggregates)."""
|
|
55
|
+
own = con is None
|
|
56
|
+
con = con or connect()
|
|
57
|
+
try:
|
|
58
|
+
return con.execute(query).fetchall()
|
|
59
|
+
finally:
|
|
60
|
+
if own:
|
|
61
|
+
con.close()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
__all__ = [
|
|
65
|
+
"connect", "sift", "run", "sql",
|
|
66
|
+
"run_spec", "build_query", "run_sql",
|
|
67
|
+
"profile", "stats", "peek", "check", "validate",
|
|
68
|
+
"join", "diff", "split", "partition", "pivot",
|
|
69
|
+
"__version__",
|
|
70
|
+
]
|