chops 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.
- chops-0.1.0/.github/workflows/ci.yml +36 -0
- chops-0.1.0/.github/workflows/publish.yml +31 -0
- chops-0.1.0/.gitignore +11 -0
- chops-0.1.0/LICENSE +21 -0
- chops-0.1.0/PKG-INFO +141 -0
- chops-0.1.0/README.md +107 -0
- chops-0.1.0/pyproject.toml +62 -0
- chops-0.1.0/src/chops/__init__.py +3 -0
- chops-0.1.0/src/chops/cli.py +70 -0
- chops-0.1.0/src/chops/client.py +40 -0
- chops-0.1.0/src/chops/commands/__init__.py +1 -0
- chops-0.1.0/src/chops/commands/dq.py +345 -0
- chops-0.1.0/src/chops/commands/health.py +297 -0
- chops-0.1.0/tests/__init__.py +0 -0
- chops-0.1.0/tests/test_cli.py +35 -0
- chops-0.1.0/uv.lock +692 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: pip install -e ".[dev]"
|
|
26
|
+
|
|
27
|
+
- name: Lint
|
|
28
|
+
run: |
|
|
29
|
+
ruff check src/ tests/
|
|
30
|
+
ruff format --check src/ tests/
|
|
31
|
+
|
|
32
|
+
- name: Type check
|
|
33
|
+
run: mypy src/
|
|
34
|
+
|
|
35
|
+
- name: Test
|
|
36
|
+
run: pytest -v
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
id-token: write
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
environment:
|
|
14
|
+
name: pypi
|
|
15
|
+
url: https://pypi.org/p/chops
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.12"
|
|
23
|
+
|
|
24
|
+
- name: Install build tools
|
|
25
|
+
run: pip install build
|
|
26
|
+
|
|
27
|
+
- name: Build package
|
|
28
|
+
run: python -m build
|
|
29
|
+
|
|
30
|
+
- name: Publish to PyPI
|
|
31
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
chops-0.1.0/.gitignore
ADDED
chops-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Antonio Mello
|
|
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.
|
chops-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: chops
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: ClickHouse Operations CLI — health checks, data quality profiling, and observability
|
|
5
|
+
Project-URL: Homepage, https://github.com/antonio-mello-ai/chops
|
|
6
|
+
Project-URL: Repository, https://github.com/antonio-mello-ai/chops
|
|
7
|
+
Project-URL: Issues, https://github.com/antonio-mello-ai/chops/issues
|
|
8
|
+
Author-email: Antonio Mello <antonio.mello@felhen.com.br>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: cli,clickhouse,data-quality,database,observability,operations
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: System Administrators
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Database
|
|
23
|
+
Classifier: Topic :: System :: Monitoring
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: clickhouse-connect>=0.7
|
|
26
|
+
Requires-Dist: rich>=13.0
|
|
27
|
+
Requires-Dist: typer>=0.12
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: mypy>=1.11; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-asyncio>=1.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# chops
|
|
36
|
+
|
|
37
|
+
ClickHouse Operations CLI — health checks, data quality profiling, and observability from your terminal.
|
|
38
|
+
|
|
39
|
+
No more copy-pasting system table queries. One command to check cluster health, profile data quality, or find slow queries.
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Run directly with uvx (no install needed)
|
|
45
|
+
uvx chops health summary
|
|
46
|
+
|
|
47
|
+
# Or install with pip
|
|
48
|
+
pip install chops
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Configuration
|
|
52
|
+
|
|
53
|
+
Set environment variables or pass flags:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
export CLICKHOUSE_HOST=localhost
|
|
57
|
+
export CLICKHOUSE_PORT=8123
|
|
58
|
+
export CLICKHOUSE_USER=default
|
|
59
|
+
export CLICKHOUSE_PASSWORD=
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Or use flags: `chops --host myserver --user admin health summary`
|
|
63
|
+
|
|
64
|
+
## Commands
|
|
65
|
+
|
|
66
|
+
### Health & Observability
|
|
67
|
+
|
|
68
|
+
| Command | Description |
|
|
69
|
+
|---------|-------------|
|
|
70
|
+
| `chops health summary` | Cluster overview: version, uptime, databases, tables, parts, merges, queries |
|
|
71
|
+
| `chops health table-sizes` | Disk usage by table, sorted by size |
|
|
72
|
+
| `chops health slow-queries` | Top N slowest queries from query log |
|
|
73
|
+
| `chops health merges` | Currently running merge operations |
|
|
74
|
+
| `chops health running-queries` | Active queries with elapsed time and memory |
|
|
75
|
+
|
|
76
|
+
### Data Quality
|
|
77
|
+
|
|
78
|
+
| Command | Description |
|
|
79
|
+
|---------|-------------|
|
|
80
|
+
| `chops dq profile <table>` | Column-level profiling: null rates, cardinality, min/max |
|
|
81
|
+
| `chops dq check <table>` | Run quality checks with configurable thresholds (CI-friendly exit codes) |
|
|
82
|
+
| `chops dq freshness <table>` | Time since last row — OK/WARNING/CRITICAL with exit codes |
|
|
83
|
+
|
|
84
|
+
## Examples
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Quick cluster health check
|
|
88
|
+
chops health summary
|
|
89
|
+
|
|
90
|
+
# Find which tables are eating disk
|
|
91
|
+
chops health table-sizes --limit 10
|
|
92
|
+
|
|
93
|
+
# Slowest queries in the last 6 hours
|
|
94
|
+
chops health slow-queries --hours 6
|
|
95
|
+
|
|
96
|
+
# Profile a table's data quality
|
|
97
|
+
chops dq profile mydb.events
|
|
98
|
+
|
|
99
|
+
# Run quality checks in CI (non-zero exit on failure)
|
|
100
|
+
chops dq check mydb.events --max-null-pct 5 --min-rows 1000
|
|
101
|
+
|
|
102
|
+
# Check if a streaming table is still receiving data
|
|
103
|
+
chops dq freshness mydb.events --warn 60 --critical 1440
|
|
104
|
+
|
|
105
|
+
# JSON output for automation
|
|
106
|
+
chops dq profile mydb.events --output json
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## CI/CD Integration
|
|
110
|
+
|
|
111
|
+
`chops dq check` and `chops dq freshness` return non-zero exit codes on failure, making them usable in CI pipelines:
|
|
112
|
+
|
|
113
|
+
```yaml
|
|
114
|
+
- name: Data quality gate
|
|
115
|
+
run: |
|
|
116
|
+
chops dq check production.orders --max-null-pct 2 --min-rows 10000
|
|
117
|
+
chops dq freshness production.orders --warn 30 --critical 120
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Development
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
git clone https://github.com/antonio-mello-ai/chops.git
|
|
124
|
+
cd chops
|
|
125
|
+
python -m venv .venv
|
|
126
|
+
source .venv/bin/activate
|
|
127
|
+
pip install -e ".[dev]"
|
|
128
|
+
|
|
129
|
+
# Run tests
|
|
130
|
+
pytest
|
|
131
|
+
|
|
132
|
+
# Lint
|
|
133
|
+
ruff check src/ tests/
|
|
134
|
+
|
|
135
|
+
# Type check
|
|
136
|
+
mypy src/
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## License
|
|
140
|
+
|
|
141
|
+
MIT
|
chops-0.1.0/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# chops
|
|
2
|
+
|
|
3
|
+
ClickHouse Operations CLI — health checks, data quality profiling, and observability from your terminal.
|
|
4
|
+
|
|
5
|
+
No more copy-pasting system table queries. One command to check cluster health, profile data quality, or find slow queries.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Run directly with uvx (no install needed)
|
|
11
|
+
uvx chops health summary
|
|
12
|
+
|
|
13
|
+
# Or install with pip
|
|
14
|
+
pip install chops
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Configuration
|
|
18
|
+
|
|
19
|
+
Set environment variables or pass flags:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
export CLICKHOUSE_HOST=localhost
|
|
23
|
+
export CLICKHOUSE_PORT=8123
|
|
24
|
+
export CLICKHOUSE_USER=default
|
|
25
|
+
export CLICKHOUSE_PASSWORD=
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or use flags: `chops --host myserver --user admin health summary`
|
|
29
|
+
|
|
30
|
+
## Commands
|
|
31
|
+
|
|
32
|
+
### Health & Observability
|
|
33
|
+
|
|
34
|
+
| Command | Description |
|
|
35
|
+
|---------|-------------|
|
|
36
|
+
| `chops health summary` | Cluster overview: version, uptime, databases, tables, parts, merges, queries |
|
|
37
|
+
| `chops health table-sizes` | Disk usage by table, sorted by size |
|
|
38
|
+
| `chops health slow-queries` | Top N slowest queries from query log |
|
|
39
|
+
| `chops health merges` | Currently running merge operations |
|
|
40
|
+
| `chops health running-queries` | Active queries with elapsed time and memory |
|
|
41
|
+
|
|
42
|
+
### Data Quality
|
|
43
|
+
|
|
44
|
+
| Command | Description |
|
|
45
|
+
|---------|-------------|
|
|
46
|
+
| `chops dq profile <table>` | Column-level profiling: null rates, cardinality, min/max |
|
|
47
|
+
| `chops dq check <table>` | Run quality checks with configurable thresholds (CI-friendly exit codes) |
|
|
48
|
+
| `chops dq freshness <table>` | Time since last row — OK/WARNING/CRITICAL with exit codes |
|
|
49
|
+
|
|
50
|
+
## Examples
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Quick cluster health check
|
|
54
|
+
chops health summary
|
|
55
|
+
|
|
56
|
+
# Find which tables are eating disk
|
|
57
|
+
chops health table-sizes --limit 10
|
|
58
|
+
|
|
59
|
+
# Slowest queries in the last 6 hours
|
|
60
|
+
chops health slow-queries --hours 6
|
|
61
|
+
|
|
62
|
+
# Profile a table's data quality
|
|
63
|
+
chops dq profile mydb.events
|
|
64
|
+
|
|
65
|
+
# Run quality checks in CI (non-zero exit on failure)
|
|
66
|
+
chops dq check mydb.events --max-null-pct 5 --min-rows 1000
|
|
67
|
+
|
|
68
|
+
# Check if a streaming table is still receiving data
|
|
69
|
+
chops dq freshness mydb.events --warn 60 --critical 1440
|
|
70
|
+
|
|
71
|
+
# JSON output for automation
|
|
72
|
+
chops dq profile mydb.events --output json
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## CI/CD Integration
|
|
76
|
+
|
|
77
|
+
`chops dq check` and `chops dq freshness` return non-zero exit codes on failure, making them usable in CI pipelines:
|
|
78
|
+
|
|
79
|
+
```yaml
|
|
80
|
+
- name: Data quality gate
|
|
81
|
+
run: |
|
|
82
|
+
chops dq check production.orders --max-null-pct 2 --min-rows 10000
|
|
83
|
+
chops dq freshness production.orders --warn 30 --critical 120
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Development
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
git clone https://github.com/antonio-mello-ai/chops.git
|
|
90
|
+
cd chops
|
|
91
|
+
python -m venv .venv
|
|
92
|
+
source .venv/bin/activate
|
|
93
|
+
pip install -e ".[dev]"
|
|
94
|
+
|
|
95
|
+
# Run tests
|
|
96
|
+
pytest
|
|
97
|
+
|
|
98
|
+
# Lint
|
|
99
|
+
ruff check src/ tests/
|
|
100
|
+
|
|
101
|
+
# Type check
|
|
102
|
+
mypy src/
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
MIT
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "chops"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "ClickHouse Operations CLI — health checks, data quality profiling, and observability"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{ name = "Antonio Mello", email = "antonio.mello@felhen.com.br" }]
|
|
13
|
+
keywords = ["clickhouse", "cli", "data-quality", "observability", "database", "operations"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Intended Audience :: System Administrators",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Topic :: Database",
|
|
26
|
+
"Topic :: System :: Monitoring",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"clickhouse-connect>=0.7",
|
|
30
|
+
"rich>=13.0",
|
|
31
|
+
"typer>=0.12",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.scripts]
|
|
35
|
+
chops = "chops.cli:app"
|
|
36
|
+
|
|
37
|
+
[project.urls]
|
|
38
|
+
Homepage = "https://github.com/antonio-mello-ai/chops"
|
|
39
|
+
Repository = "https://github.com/antonio-mello-ai/chops"
|
|
40
|
+
Issues = "https://github.com/antonio-mello-ai/chops/issues"
|
|
41
|
+
|
|
42
|
+
[project.optional-dependencies]
|
|
43
|
+
dev = [
|
|
44
|
+
"pytest>=8.0",
|
|
45
|
+
"pytest-asyncio>=1.0",
|
|
46
|
+
"mypy>=1.11",
|
|
47
|
+
"ruff>=0.6",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[tool.ruff]
|
|
51
|
+
target-version = "py310"
|
|
52
|
+
line-length = 100
|
|
53
|
+
|
|
54
|
+
[tool.ruff.lint]
|
|
55
|
+
select = ["E", "F", "I", "N", "W", "UP", "SIM", "B", "A", "C4", "RET", "PIE"]
|
|
56
|
+
|
|
57
|
+
[tool.mypy]
|
|
58
|
+
strict = true
|
|
59
|
+
python_version = "3.10"
|
|
60
|
+
|
|
61
|
+
[tool.pytest.ini_options]
|
|
62
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""CLI entry point for chops."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from chops import __version__
|
|
8
|
+
from chops.commands import dq, health
|
|
9
|
+
|
|
10
|
+
app = typer.Typer(
|
|
11
|
+
name="chops",
|
|
12
|
+
help="ClickHouse Operations CLI — health checks, data quality, and observability.",
|
|
13
|
+
no_args_is_help=True,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
app.add_typer(health.app, name="health", help="Cluster health and observability commands.")
|
|
17
|
+
app.add_typer(dq.app, name="dq", help="Data quality profiling and checks.")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@app.command()
|
|
21
|
+
def version() -> None:
|
|
22
|
+
"""Show chops version."""
|
|
23
|
+
typer.echo(f"chops {__version__}")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@app.callback()
|
|
27
|
+
def main(
|
|
28
|
+
ctx: typer.Context,
|
|
29
|
+
host: str | None = typer.Option(
|
|
30
|
+
None,
|
|
31
|
+
"--host",
|
|
32
|
+
"-h",
|
|
33
|
+
envvar="CLICKHOUSE_HOST",
|
|
34
|
+
help="ClickHouse host",
|
|
35
|
+
),
|
|
36
|
+
port: int | None = typer.Option(
|
|
37
|
+
None,
|
|
38
|
+
"--port",
|
|
39
|
+
"-p",
|
|
40
|
+
envvar="CLICKHOUSE_PORT",
|
|
41
|
+
help="ClickHouse HTTP port",
|
|
42
|
+
),
|
|
43
|
+
user: str | None = typer.Option(
|
|
44
|
+
None,
|
|
45
|
+
"--user",
|
|
46
|
+
"-u",
|
|
47
|
+
envvar="CLICKHOUSE_USER",
|
|
48
|
+
help="ClickHouse user",
|
|
49
|
+
),
|
|
50
|
+
password: str | None = typer.Option(
|
|
51
|
+
None,
|
|
52
|
+
"--password",
|
|
53
|
+
envvar="CLICKHOUSE_PASSWORD",
|
|
54
|
+
help="ClickHouse password",
|
|
55
|
+
),
|
|
56
|
+
database: str | None = typer.Option(
|
|
57
|
+
None,
|
|
58
|
+
"--database",
|
|
59
|
+
"-d",
|
|
60
|
+
envvar="CLICKHOUSE_DATABASE",
|
|
61
|
+
help="Default database",
|
|
62
|
+
),
|
|
63
|
+
) -> None:
|
|
64
|
+
"""Global connection options."""
|
|
65
|
+
ctx.ensure_object(dict)
|
|
66
|
+
ctx.obj["host"] = host
|
|
67
|
+
ctx.obj["port"] = port
|
|
68
|
+
ctx.obj["user"] = user
|
|
69
|
+
ctx.obj["password"] = password
|
|
70
|
+
ctx.obj["database"] = database
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""ClickHouse connection client."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import clickhouse_connect
|
|
9
|
+
from clickhouse_connect.driver.client import Client
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_client(
|
|
13
|
+
host: str | None = None,
|
|
14
|
+
port: int | None = None,
|
|
15
|
+
user: str | None = None,
|
|
16
|
+
password: str | None = None,
|
|
17
|
+
database: str | None = None,
|
|
18
|
+
secure: bool | None = None,
|
|
19
|
+
) -> Client:
|
|
20
|
+
"""Create a ClickHouse client from explicit args or environment variables."""
|
|
21
|
+
return clickhouse_connect.get_client(
|
|
22
|
+
host=host or os.getenv("CLICKHOUSE_HOST", "localhost"),
|
|
23
|
+
port=port or int(os.getenv("CLICKHOUSE_PORT", "8123")),
|
|
24
|
+
username=user or os.getenv("CLICKHOUSE_USER", "default"),
|
|
25
|
+
password=password if password is not None else os.getenv("CLICKHOUSE_PASSWORD", ""),
|
|
26
|
+
database=database if database is not None else os.getenv("CLICKHOUSE_DATABASE", "default"),
|
|
27
|
+
secure=(
|
|
28
|
+
secure
|
|
29
|
+
if secure is not None
|
|
30
|
+
else os.getenv("CLICKHOUSE_SECURE", "false").lower() == "true"
|
|
31
|
+
),
|
|
32
|
+
connect_timeout=10,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def query(client: Client, sql: str, params: dict[str, Any] | None = None) -> list[dict[str, Any]]:
|
|
37
|
+
"""Execute a query and return results as list of dicts."""
|
|
38
|
+
result = client.query(sql, parameters=params or {})
|
|
39
|
+
columns = result.column_names
|
|
40
|
+
return [dict(zip(columns, row, strict=False)) for row in result.result_rows]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""chops CLI commands."""
|