zendt 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.
zendt-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SPLOR/SEPLAG/MG
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.
zendt-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,200 @@
1
+ Metadata-Version: 2.4
2
+ Name: zendt
3
+ Version: 0.1.0
4
+ Summary: CLI for applying business rules built in the GoRules tool model to data tables.
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Author: Laura Dilly
8
+ Author-email: laura.dgm06@gmail.com
9
+ Requires-Python: >=3.13,<4.0
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Requires-Dist: openpyxl (>=3.1.5,<4.0.0)
14
+ Requires-Dist: pandas (>=3.0.5,<4.0.0)
15
+ Requires-Dist: prompt-toolkit (>=3.0.0,<4)
16
+ Requires-Dist: python-dotenv (>=1.2.2,<2)
17
+ Requires-Dist: pyyaml (>=6.0.0,<7.0.0)
18
+ Requires-Dist: requests (>=2.34.2,<3)
19
+ Requires-Dist: typer (>=0.15.0)
20
+ Requires-Dist: zen-engine (>=2.0.2,<3.0.0)
21
+ Description-Content-Type: text/markdown
22
+
23
+ # zendt [Zen Engine for Data Tables]
24
+
25
+ ![Coverage](coverage.svg)
26
+
27
+
28
+ Apply [GoRules](https://gorules.io/) business rules to a table from the terminal. Rules are JSON graphs in the [JDM standard](https://docs.gorules.io/developers/jdm/standard). Tables are CSV, gzip-compressed CSV, Excel (`.xlsx`), or JSON.
29
+
30
+ ```bash
31
+ pip install zendt
32
+ zendt apply student_discount -s ./rules -i customers.csv -o customers-out.csv
33
+ ```
34
+
35
+ The command keeps every input column and appends the columns each rule creates. Each rule sees the original rows, not columns produced by an earlier rule in the same command.
36
+
37
+ Python 3.13 or newer is required.
38
+
39
+ ## Commands
40
+
41
+ ```bash
42
+ zendt list -s ./rules
43
+ zendt list -s source_one -f discount
44
+ zendt apply student_discount age_discount -s ./rules -i customers.csv -o customers-out.csv
45
+ zendt apply student_discount -s https://github.com/user/rules/tree/main/rules -a GH_TOKEN -v 1.2.1 -i customers.csv
46
+ zendt flow financedata -i customers.csv -o customers-out.csv --printhead
47
+ zendt config --create
48
+ zendt config --edit
49
+ ```
50
+
51
+ | Command | What it does |
52
+ | --- | --- |
53
+ | `list` | Print the rule names in a source. Does not run them. |
54
+ | `apply` | Run one or more rules on a table. |
55
+ | `flow` | Run a named pipeline from `zendt.json`. |
56
+ | `config --create` | Write `zendt.json` by answering prompts. |
57
+ | `config --edit` | Edit that file by answering prompts. |
58
+
59
+
60
+ ### Flags
61
+
62
+ | Flag | Short | Use |
63
+ | --- | --- | --- |
64
+ | `--source` | `-s` | GitHub URL, local file or directory, or a source id from the config. `list` and `apply`. |
65
+ | `--find` | `-f` | On `list`, keep names that contain this text. |
66
+ | `--version` | `-v` | Git tag, branch, or other ref. `list` and `apply`. |
67
+ | `--authentication` | `-a` | Name of the environment variable that holds a GitHub token. Not the token. |
68
+ | `--input` | `-i` | Input file. Omitted means stdin. |
69
+ | `--output` | `-o` | Output file. Omitted writes CSV to stdout only when stdout is a pipe or a redirect. |
70
+ | `--printhead` | `-ph` | Print the first five result rows. On `apply` and `flow` this is not help; use `--help`. |
71
+ | `--create` | `-c` | Create `zendt.json`. |
72
+ | `--edit` | `-e` | Edit `zendt.json`. |
73
+
74
+ ## A local folder of rules
75
+
76
+ ```bash
77
+ zendt list -s ./rules
78
+ zendt apply student_discount -s ./rules -i customers.csv -o customers-out.csv
79
+ ```
80
+
81
+ `student_discount` is the file `rules/student_discount.json`. Nested files are listed by their stem as well. A decision node inside a graph calls another file by its path relative to the folder, without `.json` (`discounts/student_discount`).
82
+
83
+ `list` prints one name per line. A file named `zendt.json` inside the rules folder is skipped.
84
+
85
+ ## GitHub
86
+
87
+ ```bash
88
+ export GH_TOKEN=github_pat_...
89
+ zendt apply student_discount \
90
+ -s https://github.com/user/rules/tree/main/rules \
91
+ -a GH_TOKEN \
92
+ -v 1.2.1 \
93
+ -i customers.csv \
94
+ -o customers-out.csv
95
+ ```
96
+
97
+ The URL must be GitHub: a repository, a `tree` URL of the rules folder, a `blob` URL of one JSON file, or a `raw.githubusercontent.com` URL. Other hosts are rejected.
98
+
99
+ `-v` is the git ref sent to GitHub. If you omit it, the ref in the URL is used, or `HEAD` when the URL has none. zendt does not look up the latest tag. `-a` is the name of the environment variable that stores the token for a private repository. You can also put the token in a `.env` file in the current directory. Values already set in the environment are left as they are.
100
+
101
+
102
+ ## Configuration and flows
103
+
104
+ When you omit `--source`, zendt looks for `zendt.json` in the current directory, then the `config` (or `CONFIG`) environment variable, which stores the path to a config file (json or yaml), then `sources` (or `SOURCES`) env variable. `sources` is one source object or a JSON array of sources. Flows, if any, go in env variable `flows` (or `FLOWS`).
105
+
106
+ ```json
107
+ {
108
+ "sources": [
109
+ {
110
+ "id": "source_one",
111
+ "source": "https://github.com/user/rules_repo",
112
+ "authentication": "GH_TOKEN",
113
+ "version": "1.2.1"
114
+ },
115
+ {
116
+ "id": "source_two",
117
+ "source": "rules"
118
+ }
119
+ ],
120
+ "flows": [
121
+ {
122
+ "id": "financedata",
123
+ "description": "finance team flow for discount purposes",
124
+ "input": "data-raw/finance.csv.gz",
125
+ "rules": ["student_discount", "source_two/age_discount"],
126
+ "output": "data/finance.csv"
127
+ }
128
+ ]
129
+ }
130
+ ```
131
+
132
+ ```bash
133
+ zendt list
134
+ zendt list -s source_one
135
+ zendt apply source_one/student_discount -i customers.csv -o customers-out.csv
136
+ zendt flow financedata
137
+ zendt flow financedata -i other.csv -o other-out.csv
138
+ ```
139
+
140
+ `id` cannot contain `/`. `authentication` is an environment-variable name. `version` is a git ref. `description` is for self organization; the command does not print it.
141
+
142
+ `zendt flow financedata` uses every source in the file, with each source's own token variable and ref. It does not take `-s`, `-v`, or `-a`. The flow can store an input and an output which are overriden by `-i` and `-o` flags if provided for that run.
143
+
144
+ The same file stem may exist in two sources. The short name works only when it is unique. Otherwise the command refuses and tells you to use `source_id/name`. `list` prints those qualified names. Two files with the same stem inside one source are an error, even in different subfolders.
145
+
146
+ JSON and YAML files may hold other project keys. zendt reads `sources` and `flows` only. Those keys may also sit under `zendt_config`. Point `config` env variable at that file.
147
+
148
+ `zendt config --create` and `zendt config --edit` always edit `zendt.json` in the current directory in a interactive way through the terminal. Use that to guide you through creation or editing of the config file.
149
+
150
+ ## Input and output
151
+
152
+ Accepted suffixes: `.csv`, `.csv.gz`, `.json`, `.xlsx`.
153
+
154
+ CSV delimiters are detected from the header and limited to comma and semicolon. The same delimiter is used when the result is written as CSV. JSON input is one object (one row) or an array of objects. `.xlsx` uses openpyxl.
155
+
156
+ ```bash
157
+ cat customers.csv | zendt apply student_discount -s ./rules > customers-out.csv
158
+ ```
159
+
160
+ A terminal with no `--input` fails instead of waiting for typed rows. An empty pipe fails with `Stdin is empty.` On a terminal, omitting `--output` writes nothing; pass `--printhead` to see the first five rows, or pass `--output` / redirect stdout to get the table. In a pipe, `--printhead` prints the preview on stderr so the CSV on stdout stays intact.
161
+
162
+ zendt does not validate columns. Enforce the shape in the pipeline (before running zendt rules application) or with an input schema inside the JDM graph.
163
+
164
+ ## How rules are applied
165
+
166
+ Named rules run in order, each on the original table. New fields are appended. Fields the rule returns that already exist on the input stay as they were. If two rules in one command create the same new column, the command stops. A row the engine rejects stops the command and names the rule and the 1-based row number.
167
+
168
+ Decision nodes load the called graph from the same source. The key is the file's path relative to the source, without `.json`. Only those graphs are downloaded and compiled.
169
+
170
+ Below 10,000 rows the command evaluates in the current process, in batches of 20,000. At 10,000 rows or more it uses up to eight processes, and never more than the machine's cores. The full table is still loaded in the parent process.
171
+
172
+ ## Errors
173
+
174
+ | Exit | When |
175
+ | --- | --- |
176
+ | 0 | The command finished. |
177
+ | 1 | Config, source, authentication, input, missing rule, ambiguous name, invalid graph, or engine failure. The reason is on stderr. |
178
+ | 2 | Usage error: unknown flag, missing argument, or `zendt` with no command. |
179
+
180
+ Common cases: no config and no `--source`; `--version` on a local folder; a rule name that is not in the source; a name that exists in two sources; GitHub 401 or 403; a file that is not a JDM object (`nodes` and `edges`).
181
+
182
+ ## Documentation
183
+
184
+ The `docs/` directory is the full reference (commands, configuration, rule names, input and output, evaluation, errors). It is a [Zensical](https://zensical.org/) site. From a checkout:
185
+
186
+ ```bash
187
+ zensical serve
188
+ ```
189
+
190
+ ## Development
191
+
192
+ This repository uses Poetry. The dev group includes pytest.
193
+
194
+ ```bash
195
+ poetry install
196
+ poetry run pytest
197
+ ```
198
+
199
+ The tests live in `tests/` and cover the CLI, config editor, catalog, GitHub listing, input and output, and rule evaluation.
200
+
zendt-0.1.0/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # zendt [Zen Engine for Data Tables]
2
+
3
+ ![Coverage](coverage.svg)
4
+
5
+
6
+ Apply [GoRules](https://gorules.io/) business rules to a table from the terminal. Rules are JSON graphs in the [JDM standard](https://docs.gorules.io/developers/jdm/standard). Tables are CSV, gzip-compressed CSV, Excel (`.xlsx`), or JSON.
7
+
8
+ ```bash
9
+ pip install zendt
10
+ zendt apply student_discount -s ./rules -i customers.csv -o customers-out.csv
11
+ ```
12
+
13
+ The command keeps every input column and appends the columns each rule creates. Each rule sees the original rows, not columns produced by an earlier rule in the same command.
14
+
15
+ Python 3.13 or newer is required.
16
+
17
+ ## Commands
18
+
19
+ ```bash
20
+ zendt list -s ./rules
21
+ zendt list -s source_one -f discount
22
+ zendt apply student_discount age_discount -s ./rules -i customers.csv -o customers-out.csv
23
+ zendt apply student_discount -s https://github.com/user/rules/tree/main/rules -a GH_TOKEN -v 1.2.1 -i customers.csv
24
+ zendt flow financedata -i customers.csv -o customers-out.csv --printhead
25
+ zendt config --create
26
+ zendt config --edit
27
+ ```
28
+
29
+ | Command | What it does |
30
+ | --- | --- |
31
+ | `list` | Print the rule names in a source. Does not run them. |
32
+ | `apply` | Run one or more rules on a table. |
33
+ | `flow` | Run a named pipeline from `zendt.json`. |
34
+ | `config --create` | Write `zendt.json` by answering prompts. |
35
+ | `config --edit` | Edit that file by answering prompts. |
36
+
37
+
38
+ ### Flags
39
+
40
+ | Flag | Short | Use |
41
+ | --- | --- | --- |
42
+ | `--source` | `-s` | GitHub URL, local file or directory, or a source id from the config. `list` and `apply`. |
43
+ | `--find` | `-f` | On `list`, keep names that contain this text. |
44
+ | `--version` | `-v` | Git tag, branch, or other ref. `list` and `apply`. |
45
+ | `--authentication` | `-a` | Name of the environment variable that holds a GitHub token. Not the token. |
46
+ | `--input` | `-i` | Input file. Omitted means stdin. |
47
+ | `--output` | `-o` | Output file. Omitted writes CSV to stdout only when stdout is a pipe or a redirect. |
48
+ | `--printhead` | `-ph` | Print the first five result rows. On `apply` and `flow` this is not help; use `--help`. |
49
+ | `--create` | `-c` | Create `zendt.json`. |
50
+ | `--edit` | `-e` | Edit `zendt.json`. |
51
+
52
+ ## A local folder of rules
53
+
54
+ ```bash
55
+ zendt list -s ./rules
56
+ zendt apply student_discount -s ./rules -i customers.csv -o customers-out.csv
57
+ ```
58
+
59
+ `student_discount` is the file `rules/student_discount.json`. Nested files are listed by their stem as well. A decision node inside a graph calls another file by its path relative to the folder, without `.json` (`discounts/student_discount`).
60
+
61
+ `list` prints one name per line. A file named `zendt.json` inside the rules folder is skipped.
62
+
63
+ ## GitHub
64
+
65
+ ```bash
66
+ export GH_TOKEN=github_pat_...
67
+ zendt apply student_discount \
68
+ -s https://github.com/user/rules/tree/main/rules \
69
+ -a GH_TOKEN \
70
+ -v 1.2.1 \
71
+ -i customers.csv \
72
+ -o customers-out.csv
73
+ ```
74
+
75
+ The URL must be GitHub: a repository, a `tree` URL of the rules folder, a `blob` URL of one JSON file, or a `raw.githubusercontent.com` URL. Other hosts are rejected.
76
+
77
+ `-v` is the git ref sent to GitHub. If you omit it, the ref in the URL is used, or `HEAD` when the URL has none. zendt does not look up the latest tag. `-a` is the name of the environment variable that stores the token for a private repository. You can also put the token in a `.env` file in the current directory. Values already set in the environment are left as they are.
78
+
79
+
80
+ ## Configuration and flows
81
+
82
+ When you omit `--source`, zendt looks for `zendt.json` in the current directory, then the `config` (or `CONFIG`) environment variable, which stores the path to a config file (json or yaml), then `sources` (or `SOURCES`) env variable. `sources` is one source object or a JSON array of sources. Flows, if any, go in env variable `flows` (or `FLOWS`).
83
+
84
+ ```json
85
+ {
86
+ "sources": [
87
+ {
88
+ "id": "source_one",
89
+ "source": "https://github.com/user/rules_repo",
90
+ "authentication": "GH_TOKEN",
91
+ "version": "1.2.1"
92
+ },
93
+ {
94
+ "id": "source_two",
95
+ "source": "rules"
96
+ }
97
+ ],
98
+ "flows": [
99
+ {
100
+ "id": "financedata",
101
+ "description": "finance team flow for discount purposes",
102
+ "input": "data-raw/finance.csv.gz",
103
+ "rules": ["student_discount", "source_two/age_discount"],
104
+ "output": "data/finance.csv"
105
+ }
106
+ ]
107
+ }
108
+ ```
109
+
110
+ ```bash
111
+ zendt list
112
+ zendt list -s source_one
113
+ zendt apply source_one/student_discount -i customers.csv -o customers-out.csv
114
+ zendt flow financedata
115
+ zendt flow financedata -i other.csv -o other-out.csv
116
+ ```
117
+
118
+ `id` cannot contain `/`. `authentication` is an environment-variable name. `version` is a git ref. `description` is for self organization; the command does not print it.
119
+
120
+ `zendt flow financedata` uses every source in the file, with each source's own token variable and ref. It does not take `-s`, `-v`, or `-a`. The flow can store an input and an output which are overriden by `-i` and `-o` flags if provided for that run.
121
+
122
+ The same file stem may exist in two sources. The short name works only when it is unique. Otherwise the command refuses and tells you to use `source_id/name`. `list` prints those qualified names. Two files with the same stem inside one source are an error, even in different subfolders.
123
+
124
+ JSON and YAML files may hold other project keys. zendt reads `sources` and `flows` only. Those keys may also sit under `zendt_config`. Point `config` env variable at that file.
125
+
126
+ `zendt config --create` and `zendt config --edit` always edit `zendt.json` in the current directory in a interactive way through the terminal. Use that to guide you through creation or editing of the config file.
127
+
128
+ ## Input and output
129
+
130
+ Accepted suffixes: `.csv`, `.csv.gz`, `.json`, `.xlsx`.
131
+
132
+ CSV delimiters are detected from the header and limited to comma and semicolon. The same delimiter is used when the result is written as CSV. JSON input is one object (one row) or an array of objects. `.xlsx` uses openpyxl.
133
+
134
+ ```bash
135
+ cat customers.csv | zendt apply student_discount -s ./rules > customers-out.csv
136
+ ```
137
+
138
+ A terminal with no `--input` fails instead of waiting for typed rows. An empty pipe fails with `Stdin is empty.` On a terminal, omitting `--output` writes nothing; pass `--printhead` to see the first five rows, or pass `--output` / redirect stdout to get the table. In a pipe, `--printhead` prints the preview on stderr so the CSV on stdout stays intact.
139
+
140
+ zendt does not validate columns. Enforce the shape in the pipeline (before running zendt rules application) or with an input schema inside the JDM graph.
141
+
142
+ ## How rules are applied
143
+
144
+ Named rules run in order, each on the original table. New fields are appended. Fields the rule returns that already exist on the input stay as they were. If two rules in one command create the same new column, the command stops. A row the engine rejects stops the command and names the rule and the 1-based row number.
145
+
146
+ Decision nodes load the called graph from the same source. The key is the file's path relative to the source, without `.json`. Only those graphs are downloaded and compiled.
147
+
148
+ Below 10,000 rows the command evaluates in the current process, in batches of 20,000. At 10,000 rows or more it uses up to eight processes, and never more than the machine's cores. The full table is still loaded in the parent process.
149
+
150
+ ## Errors
151
+
152
+ | Exit | When |
153
+ | --- | --- |
154
+ | 0 | The command finished. |
155
+ | 1 | Config, source, authentication, input, missing rule, ambiguous name, invalid graph, or engine failure. The reason is on stderr. |
156
+ | 2 | Usage error: unknown flag, missing argument, or `zendt` with no command. |
157
+
158
+ Common cases: no config and no `--source`; `--version` on a local folder; a rule name that is not in the source; a name that exists in two sources; GitHub 401 or 403; a file that is not a JDM object (`nodes` and `edges`).
159
+
160
+ ## Documentation
161
+
162
+ The `docs/` directory is the full reference (commands, configuration, rule names, input and output, evaluation, errors). It is a [Zensical](https://zensical.org/) site. From a checkout:
163
+
164
+ ```bash
165
+ zensical serve
166
+ ```
167
+
168
+ ## Development
169
+
170
+ This repository uses Poetry. The dev group includes pytest.
171
+
172
+ ```bash
173
+ poetry install
174
+ poetry run pytest
175
+ ```
176
+
177
+ The tests live in `tests/` and cover the CLI, config editor, catalog, GitHub listing, input and output, and rule evaluation.
@@ -0,0 +1,76 @@
1
+ [project]
2
+ name = "zendt"
3
+ version = "0.1.0"
4
+ license = "MIT"
5
+ description = "CLI for applying business rules built in the GoRules tool model to data tables."
6
+ authors = [
7
+ {name = "Laura Dilly", email = "laura.dgm06@gmail.com"},
8
+ {name = "Gabriel Dornas", email = "gabrielbdornas@gmail.com"}
9
+ ]
10
+ readme = "README.md"
11
+ requires-python = ">=3.13,<4.0"
12
+ dependencies = [
13
+ "requests>=2.34.2,<3",
14
+ "python-dotenv>=1.2.2,<2",
15
+ "prompt-toolkit>=3.0.0,<4",
16
+ "typer>=0.15.0",
17
+ "zen-engine (>=2.0.2,<3.0.0)",
18
+ "pandas (>=3.0.5,<4.0.0)",
19
+ "openpyxl (>=3.1.5,<4.0.0)",
20
+ "pyyaml (>=6.0.0,<7.0.0)",
21
+ ]
22
+
23
+ [dependency-groups]
24
+ dev = [
25
+ "pytest (>=9.1.1,<10.0.0)",
26
+ "genbadge[coverage] (>=1.1.3,<2.0.0)",
27
+ "pytest-cov (>=7.1.0,<8.0.0)",
28
+ "ruff (>=0.16.9,<0.17.0)",
29
+ "zensical (>=0.0.67,<0.0.68)",
30
+ "taskipy (>=1.14.1,<2.0.0)",
31
+ "commitizen (>=4.19.0,<5.0.0)",
32
+ "python-dotenv (>=1.2.4,<2.0.0)"
33
+ ]
34
+
35
+ [project.scripts]
36
+ zendt = "zendt.cli:app"
37
+
38
+ [build-system]
39
+ requires = ["poetry-core>=2.0.0"]
40
+ build-backend = "poetry.core.masonry.api"
41
+
42
+ [tool.poetry]
43
+ packages = [{include = "zendt", from = "src"}]
44
+
45
+ [tool.ruff]
46
+ line-length = 79
47
+
48
+ [tool.ruff.lint]
49
+ preview = true
50
+ select = ['I', 'F', 'E', 'W', 'PL', 'PT']
51
+
52
+ [tool.ruff.format]
53
+ preview = true
54
+ quote-style = 'single'
55
+
56
+
57
+ [tool.commitizen]
58
+ name = 'cz_conventional_commits'
59
+ tag_format = '$version'
60
+ version_scheme = 'pep440'
61
+ version_provider = 'pep621'
62
+ update_changelog_on_bump = true
63
+ major_version_zero = true
64
+
65
+
66
+ [tool.taskipy.tasks]
67
+ list = { cmd = 'task --list', help = 'Lists all tasks.' }
68
+ lint = { cmd = 'ruff check', help = 'Checks for good coding practices in Python.' }
69
+ pre_format = { cmd = 'ruff check --fix', help = 'Makes some best practice corrections.' }
70
+ format = { cmd = 'ruff format', help = 'Formats code according to code style conventions.' }
71
+ test = { cmd = 'pytest -vv --cov=zendt --cov-report=term-missing --cov-report=xml', help = 'Runs unit tests with coverage.' }
72
+ test_debug = { cmd = 'pytest -s -x -vv', help = 'Runs unit tests in debug mode.' }
73
+ coverage_badge = { cmd = 'genbadge coverage -i coverage.xml -o coverage.svg --local', help = 'Generates the README coverage badge.' }
74
+ check = { cmd = 'task lint && task test', help = 'Runs lint and tests.' }
75
+ bump = { cmd = 'cz bump', help = 'Bumps project version.' }
76
+ publish = { cmd = 'task bump && dotenv run poetry publish --build -n && git push origin main --tags', help = 'Bumps version and publish the package on Pypi.' }
@@ -0,0 +1,3 @@
1
+ from zendt.main import apply, flow, rules_list
2
+
3
+ __all__ = ['apply', 'flow', 'rules_list']
@@ -0,0 +1,4 @@
1
+ from zendt.cli import app
2
+
3
+ if __name__ == '__main__':
4
+ app()
@@ -0,0 +1,167 @@
1
+ import sys
2
+ from typing import Annotated
3
+
4
+ import pandas as pd
5
+ import typer
6
+
7
+ from zendt.config.create import create_config
8
+ from zendt.config.edit import edit_config
9
+ from zendt.engine.output import write_output
10
+ from zendt.errors import ZendtError
11
+ from zendt.main import apply, flow, rules_list
12
+
13
+ app = typer.Typer(
14
+ name='zendt',
15
+ help='Apply JDM (GoRules) rules to data from the terminal.',
16
+ no_args_is_help=True,
17
+ )
18
+
19
+ SourceOption = typer.Option(
20
+ None,
21
+ '--source',
22
+ '-s',
23
+ help='GitHub URL, local path, or id of a configured source.',
24
+ )
25
+
26
+ FindOption = typer.Option(
27
+ None,
28
+ '--find',
29
+ '-f',
30
+ help='Search for rules whose name contains the specified word.',
31
+ )
32
+
33
+ VersionOption = typer.Option(
34
+ None,
35
+ '--version',
36
+ '-v',
37
+ help='Rule version to apply for git repositories.',
38
+ )
39
+
40
+ AuthOption = typer.Option(
41
+ None,
42
+ '--authentication',
43
+ '-a',
44
+ help=(
45
+ 'Name of the environment variable that holds the token '
46
+ '(private repositories).'
47
+ ),
48
+ )
49
+
50
+ InputOption = typer.Option(
51
+ None,
52
+ '--input',
53
+ '-i',
54
+ help='Input file to process.',
55
+ )
56
+
57
+ OutputOption = typer.Option(
58
+ None,
59
+ '--output',
60
+ '-o',
61
+ help='Output file to save.',
62
+ )
63
+
64
+ PrintHeadOption = typer.Option(
65
+ False,
66
+ '--printhead',
67
+ '-ph',
68
+ help='Print a preview of the result on screen.',
69
+ )
70
+
71
+ CreateConfigOption = typer.Option(
72
+ False,
73
+ '--create',
74
+ '-c',
75
+ help='Create a zendt.json configuration file.',
76
+ )
77
+
78
+ EditConfigOption = typer.Option(
79
+ False,
80
+ '--edit',
81
+ '-e',
82
+ help='Edit the zendt.json configuration file.',
83
+ )
84
+
85
+
86
+ def echo_head(frame: pd.DataFrame) -> None:
87
+ """Preview on the terminal.
88
+
89
+ Keep it off stdout when that stream carries the csv.
90
+ """
91
+ typer.echo(frame.head(), err=not sys.stdout.isatty())
92
+
93
+
94
+ @app.command('config')
95
+ def config(
96
+ create: bool = CreateConfigOption,
97
+ edit: bool = EditConfigOption,
98
+ ) -> None:
99
+ """Manage the zendt.json configuration file."""
100
+ if create:
101
+ create_config()
102
+ elif edit:
103
+ edit_config()
104
+
105
+
106
+ @app.command('list')
107
+ def list_rules_command(
108
+ source: str = SourceOption,
109
+ find: str = FindOption,
110
+ version: str = VersionOption,
111
+ authentication: str = AuthOption,
112
+ ) -> None:
113
+ """List the JDM rules found in SOURCE."""
114
+ try:
115
+ names = rules_list(source, find, version, authentication)
116
+ except ZendtError as exc:
117
+ typer.echo(str(exc), err=True)
118
+ raise typer.Exit(code=exc.exit_code) from exc
119
+
120
+ typer.echo('Rules found in provided sources:')
121
+ for name in names:
122
+ typer.echo(name)
123
+
124
+
125
+ @app.command('apply')
126
+ def apply_command(
127
+ rules: Annotated[
128
+ list[str], typer.Argument(help='Names of the rules to apply.')
129
+ ],
130
+ source: str = SourceOption,
131
+ authentication: str = AuthOption,
132
+ version: str = VersionOption,
133
+ input: str = InputOption,
134
+ output: str = OutputOption,
135
+ printhead: bool = PrintHeadOption,
136
+ ) -> None:
137
+ """Apply the JDM rules passed as arguments."""
138
+ try:
139
+ result = apply(rules, source, authentication, version, input)
140
+ write_output(result, output)
141
+ if printhead:
142
+ echo_head(result)
143
+ except ZendtError as exc:
144
+ typer.echo(str(exc), err=True)
145
+ raise typer.Exit(code=exc.exit_code) from exc
146
+
147
+
148
+ @app.command('flow')
149
+ def flow_command(
150
+ flow_id: Annotated[str, typer.Argument(help='Configured flow ID.')],
151
+ input: str = InputOption,
152
+ output: str = OutputOption,
153
+ printhead: bool = PrintHeadOption,
154
+ ) -> None:
155
+ """Apply a pre-configured flow."""
156
+ try:
157
+ result = flow(flow_id, input)
158
+ except ZendtError as exc:
159
+ typer.echo(str(exc), err=True)
160
+ raise typer.Exit(code=exc.exit_code) from exc
161
+
162
+ destination = output
163
+ if destination is None:
164
+ destination = result.attrs.get('output')
165
+ write_output(result, destination)
166
+ if printhead:
167
+ echo_head(result)
File without changes