chronix-client 0.2.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.
@@ -0,0 +1,52 @@
1
+ # Generated by Cargo
2
+ # will have compiled files and executables
3
+ debug
4
+ target
5
+
6
+ # Internal-only documents (not published) — the architecture notes and the backlog
7
+ /concepts/
8
+
9
+ # Third-party specifications, protocol definitions and papers (copyrighted;
10
+ # indexed with retrieval URLs in concepts/REFERENCES.md so the folder can be rebuilt).
11
+ /specs/
12
+
13
+ # Feedback for sibling crates (bug reports / feature requests; always internal — sent to their teams)
14
+ *_FEEDBACK.md
15
+
16
+ # macOS
17
+ .DS_Store
18
+
19
+ # These are backup files generated by rustfmt
20
+ **/*.rs.bk
21
+
22
+ # MSVC Windows builds of rustc generate these, which store debugging information
23
+ *.pdb
24
+
25
+ # Generated by cargo mutants
26
+ # Contains mutation testing data
27
+ **/mutants.out*/
28
+
29
+ # RustRover
30
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
31
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
32
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
33
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
34
+ #.idea/
35
+
36
+ # Zola build output for the documentation site.
37
+ site/public/
38
+
39
+ # Staged by .github/actions/setup-cross so the cross container can see it.
40
+ .protoc/
41
+
42
+ # Python SDK working files. The compiled bytecode and the local virtualenv
43
+ # were committed once; nothing reads them and they go stale on every edit.
44
+ __pycache__/
45
+ *.py[cod]
46
+ .pytest_cache/
47
+ sdks/python/.venv/
48
+ # `python -m build` output, produced by the release workflow and by anyone
49
+ # testing the package locally.
50
+ sdks/python/dist/
51
+ sdks/python/build/
52
+ *.egg-info/
@@ -0,0 +1,200 @@
1
+ Metadata-Version: 2.5
2
+ Name: chronix-client
3
+ Version: 0.2.0
4
+ Summary: Python client for Chronix time-series database
5
+ Author: Chronix Authors
6
+ License-Expression: Apache-2.0
7
+ Keywords: chronix,client,database,timeseries
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Database
17
+ Classifier: Topic :: Scientific/Engineering
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: adbc-driver-flightsql>=1.0
21
+ Requires-Dist: httpx<1,>=0.27
22
+ Requires-Dist: pyarrow>=17
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
25
+ Requires-Dist: pytest>=8; extra == 'dev'
26
+ Requires-Dist: respx>=0.21; extra == 'dev'
27
+ Provides-Extra: pandas
28
+ Requires-Dist: pandas>=2; extra == 'pandas'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # chronix-client (Python)
32
+
33
+ Async Python client for the [Chronix](https://github.com/hupe1980/chronix) time-series database.
34
+
35
+ ## Features
36
+
37
+ - **Async-first** — built on `httpx` for non-blocking I/O
38
+ - **JSON + Line Protocol writes** — both formats supported
39
+ - **Structured queries + SQL** — first-class support for both query APIs
40
+ - **PromQL** — instant & range queries via Prometheus-compatible endpoints
41
+ - **Arrow Flight SQL** — zero-copy queries via ADBC driver
42
+ - **Schema introspection** — list measurements, get column schemas
43
+ - **Multi-tenant** — namespace header support
44
+ - **Typed** — full type annotations with `py.typed` marker
45
+
46
+ ## Installation
47
+
48
+ ```bash
49
+ pip install chronix-client
50
+ ```
51
+
52
+ With pandas support:
53
+
54
+ ```bash
55
+ pip install "chronix-client[pandas]"
56
+ ```
57
+
58
+ ## Quick Start
59
+
60
+ ```python
61
+ import asyncio
62
+ from chronix_client import ChronixClient, Point, TimeRange
63
+
64
+ async def main():
65
+ async with ChronixClient("http://localhost:5555") as client:
66
+ # Write
67
+ await client.write([
68
+ Point("cpu", {"usage": 42.5}, tags={"host": "a"})
69
+ ])
70
+
71
+ # Query
72
+ result = await client.query(
73
+ "cpu",
74
+ TimeRange(start=0, end=2**63 - 1),
75
+ tag_filters={"host": "a"},
76
+ )
77
+ for row in result:
78
+ print(row)
79
+
80
+ # SQL
81
+ result = await client.sql("SELECT * FROM cpu ORDER BY _time DESC LIMIT 10")
82
+ df = result.to_dataframe() # requires pandas extra
83
+
84
+ asyncio.run(main())
85
+ ```
86
+
87
+ ## Line Protocol Writes
88
+
89
+ ```python
90
+ await client.write_line_protocol([
91
+ "cpu,host=a usage=42.5 1700000000000000000",
92
+ "mem,host=a total=16384i,used=8192i 1700000000000000000",
93
+ ])
94
+ ```
95
+
96
+ ## PromQL Queries
97
+
98
+ ```python
99
+ # Instant query
100
+ result = await client.prom_query('cpu_usage{host="server-1"}')
101
+
102
+ # Range query
103
+ result = await client.prom_query_range(
104
+ 'rate(cpu_usage[5m])',
105
+ start="2024-01-01T00:00:00Z",
106
+ end="2024-01-02T00:00:00Z",
107
+ step="60s",
108
+ )
109
+
110
+ # Label discovery
111
+ labels = await client.prom_labels()
112
+ values = await client.prom_label_values("host")
113
+ ```
114
+
115
+ ## Arrow Flight SQL (Zero-Copy)
116
+
117
+ For high-throughput analytical queries, use Arrow Flight SQL via ADBC:
118
+
119
+ ```python
120
+ import adbc_driver_flightsql.dbapi
121
+
122
+ uri = ChronixClient.flight_sql_uri("localhost", 5557)
123
+ conn = adbc_driver_flightsql.dbapi.connect(uri)
124
+ cursor = conn.cursor()
125
+ cursor.execute("SELECT * FROM cpu WHERE _time > now() - INTERVAL '1 hour'")
126
+ table = cursor.fetch_arrow_table()
127
+ df = table.to_pandas()
128
+ ```
129
+
130
+ ## Authentication & Multi-Tenancy
131
+
132
+ ```python
133
+ client = ChronixClient(
134
+ "http://localhost:5555",
135
+ api_key="your-api-key",
136
+ namespace="production",
137
+ )
138
+ ```
139
+
140
+ ## Idempotent Writes
141
+
142
+ ```python
143
+ await client.write(
144
+ [Point("cpu", {"usage": 42.5})],
145
+ idempotency_key="batch-2024-01-15-001",
146
+ )
147
+ # Second call with same key → WriteError (HTTP 409)
148
+ ```
149
+
150
+ ## API Reference
151
+
152
+ ### `ChronixClient`
153
+
154
+ | Method | Description |
155
+ |--------|-------------|
156
+ | `health()` | Health check |
157
+ | `ready()` | Readiness check |
158
+ | `server_info()` | Server metadata |
159
+ | `write(points, *, idempotency_key)` | Write points (JSON) |
160
+ | `write_line_protocol(lines, *, idempotency_key)` | Write (line protocol) |
161
+ | `query(measurement, time_range, *, tag_filters, field_columns, limit)` | Structured query |
162
+ | `sql(query)` | SQL query |
163
+ | `explain(measurement, time_range)` | Explain query plan |
164
+ | `list_measurements()` | List measurements |
165
+ | `get_schema(measurement)` | Get column schema |
166
+ | `drop_measurement(measurement)` | Drop measurement |
167
+ | `delete(measurement, time_range=None, *, tags)` | Delete data; returns a `DeleteResult` — check `.complete` |
168
+ | `prom_query(query, *, time)` | PromQL instant query |
169
+ | `prom_query_range(query, start, end, step)` | PromQL range query |
170
+ | `prom_labels()` | List Prometheus labels |
171
+ | `prom_label_values(label)` | Label values |
172
+ | `prom_series(match)` | Find series |
173
+ | `list_rollups()` | List rollup rules |
174
+ | `list_connectors()` | List connectors |
175
+ | `openapi_spec()` | Fetch OpenAPI spec |
176
+ | `flight_sql_uri(host, port)` | Build Flight SQL URI |
177
+
178
+ ### Models
179
+
180
+ | Type | Description |
181
+ |------|-------------|
182
+ | `Point` | Data point with measurement, tags, fields, timestamp |
183
+ | `TimeRange` | Half-open `[start, end)` in nanoseconds |
184
+ | `QueryResult` | Query result with `.rows`, `.to_dataframe()` |
185
+ | `ColumnSchema` | Column metadata (name, role, data_type) |
186
+ | `MeasurementInfo` | Measurement summary (name) |
187
+ | `ServerInfo` | Server metadata (version, uptime, measurement_count) |
188
+
189
+ ### Exceptions
190
+
191
+ | Exception | When |
192
+ |-----------|------|
193
+ | `ChronixError` | Base exception (server errors) |
194
+ | `ConnectionError` | Cannot reach server |
195
+ | `WriteError` | Write failure (including idempotency conflict) |
196
+ | `QueryError` | Query/client error (4xx) |
197
+
198
+ ## License
199
+
200
+ Apache-2.0 — same as Chronix.
@@ -0,0 +1,170 @@
1
+ # chronix-client (Python)
2
+
3
+ Async Python client for the [Chronix](https://github.com/hupe1980/chronix) time-series database.
4
+
5
+ ## Features
6
+
7
+ - **Async-first** — built on `httpx` for non-blocking I/O
8
+ - **JSON + Line Protocol writes** — both formats supported
9
+ - **Structured queries + SQL** — first-class support for both query APIs
10
+ - **PromQL** — instant & range queries via Prometheus-compatible endpoints
11
+ - **Arrow Flight SQL** — zero-copy queries via ADBC driver
12
+ - **Schema introspection** — list measurements, get column schemas
13
+ - **Multi-tenant** — namespace header support
14
+ - **Typed** — full type annotations with `py.typed` marker
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ pip install chronix-client
20
+ ```
21
+
22
+ With pandas support:
23
+
24
+ ```bash
25
+ pip install "chronix-client[pandas]"
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ```python
31
+ import asyncio
32
+ from chronix_client import ChronixClient, Point, TimeRange
33
+
34
+ async def main():
35
+ async with ChronixClient("http://localhost:5555") as client:
36
+ # Write
37
+ await client.write([
38
+ Point("cpu", {"usage": 42.5}, tags={"host": "a"})
39
+ ])
40
+
41
+ # Query
42
+ result = await client.query(
43
+ "cpu",
44
+ TimeRange(start=0, end=2**63 - 1),
45
+ tag_filters={"host": "a"},
46
+ )
47
+ for row in result:
48
+ print(row)
49
+
50
+ # SQL
51
+ result = await client.sql("SELECT * FROM cpu ORDER BY _time DESC LIMIT 10")
52
+ df = result.to_dataframe() # requires pandas extra
53
+
54
+ asyncio.run(main())
55
+ ```
56
+
57
+ ## Line Protocol Writes
58
+
59
+ ```python
60
+ await client.write_line_protocol([
61
+ "cpu,host=a usage=42.5 1700000000000000000",
62
+ "mem,host=a total=16384i,used=8192i 1700000000000000000",
63
+ ])
64
+ ```
65
+
66
+ ## PromQL Queries
67
+
68
+ ```python
69
+ # Instant query
70
+ result = await client.prom_query('cpu_usage{host="server-1"}')
71
+
72
+ # Range query
73
+ result = await client.prom_query_range(
74
+ 'rate(cpu_usage[5m])',
75
+ start="2024-01-01T00:00:00Z",
76
+ end="2024-01-02T00:00:00Z",
77
+ step="60s",
78
+ )
79
+
80
+ # Label discovery
81
+ labels = await client.prom_labels()
82
+ values = await client.prom_label_values("host")
83
+ ```
84
+
85
+ ## Arrow Flight SQL (Zero-Copy)
86
+
87
+ For high-throughput analytical queries, use Arrow Flight SQL via ADBC:
88
+
89
+ ```python
90
+ import adbc_driver_flightsql.dbapi
91
+
92
+ uri = ChronixClient.flight_sql_uri("localhost", 5557)
93
+ conn = adbc_driver_flightsql.dbapi.connect(uri)
94
+ cursor = conn.cursor()
95
+ cursor.execute("SELECT * FROM cpu WHERE _time > now() - INTERVAL '1 hour'")
96
+ table = cursor.fetch_arrow_table()
97
+ df = table.to_pandas()
98
+ ```
99
+
100
+ ## Authentication & Multi-Tenancy
101
+
102
+ ```python
103
+ client = ChronixClient(
104
+ "http://localhost:5555",
105
+ api_key="your-api-key",
106
+ namespace="production",
107
+ )
108
+ ```
109
+
110
+ ## Idempotent Writes
111
+
112
+ ```python
113
+ await client.write(
114
+ [Point("cpu", {"usage": 42.5})],
115
+ idempotency_key="batch-2024-01-15-001",
116
+ )
117
+ # Second call with same key → WriteError (HTTP 409)
118
+ ```
119
+
120
+ ## API Reference
121
+
122
+ ### `ChronixClient`
123
+
124
+ | Method | Description |
125
+ |--------|-------------|
126
+ | `health()` | Health check |
127
+ | `ready()` | Readiness check |
128
+ | `server_info()` | Server metadata |
129
+ | `write(points, *, idempotency_key)` | Write points (JSON) |
130
+ | `write_line_protocol(lines, *, idempotency_key)` | Write (line protocol) |
131
+ | `query(measurement, time_range, *, tag_filters, field_columns, limit)` | Structured query |
132
+ | `sql(query)` | SQL query |
133
+ | `explain(measurement, time_range)` | Explain query plan |
134
+ | `list_measurements()` | List measurements |
135
+ | `get_schema(measurement)` | Get column schema |
136
+ | `drop_measurement(measurement)` | Drop measurement |
137
+ | `delete(measurement, time_range=None, *, tags)` | Delete data; returns a `DeleteResult` — check `.complete` |
138
+ | `prom_query(query, *, time)` | PromQL instant query |
139
+ | `prom_query_range(query, start, end, step)` | PromQL range query |
140
+ | `prom_labels()` | List Prometheus labels |
141
+ | `prom_label_values(label)` | Label values |
142
+ | `prom_series(match)` | Find series |
143
+ | `list_rollups()` | List rollup rules |
144
+ | `list_connectors()` | List connectors |
145
+ | `openapi_spec()` | Fetch OpenAPI spec |
146
+ | `flight_sql_uri(host, port)` | Build Flight SQL URI |
147
+
148
+ ### Models
149
+
150
+ | Type | Description |
151
+ |------|-------------|
152
+ | `Point` | Data point with measurement, tags, fields, timestamp |
153
+ | `TimeRange` | Half-open `[start, end)` in nanoseconds |
154
+ | `QueryResult` | Query result with `.rows`, `.to_dataframe()` |
155
+ | `ColumnSchema` | Column metadata (name, role, data_type) |
156
+ | `MeasurementInfo` | Measurement summary (name) |
157
+ | `ServerInfo` | Server metadata (version, uptime, measurement_count) |
158
+
159
+ ### Exceptions
160
+
161
+ | Exception | When |
162
+ |-----------|------|
163
+ | `ChronixError` | Base exception (server errors) |
164
+ | `ConnectionError` | Cannot reach server |
165
+ | `WriteError` | Write failure (including idempotency conflict) |
166
+ | `QueryError` | Query/client error (4xx) |
167
+
168
+ ## License
169
+
170
+ Apache-2.0 — same as Chronix.
@@ -0,0 +1,41 @@
1
+ """Chronix Python client — async-first SDK for Chronix time-series database."""
2
+
3
+ from chronix_client.client import ChronixClient
4
+ from chronix_client.exceptions import (
5
+ BackpressureError,
6
+ ChronixError,
7
+ ConnectionError,
8
+ DeadlineExceeded,
9
+ QueryError,
10
+ WriteError,
11
+ )
12
+ from chronix_client.models import (
13
+ ColumnSchema,
14
+ FieldValue,
15
+ MeasurementInfo,
16
+ Point,
17
+ QueryResult,
18
+ DeleteResult,
19
+ ServerInfo,
20
+ TimeRange,
21
+ )
22
+
23
+ __all__ = [
24
+ "BackpressureError",
25
+ "ChronixClient",
26
+ "ChronixError",
27
+ "ColumnSchema",
28
+ "ConnectionError",
29
+ "DeadlineExceeded",
30
+ "DeleteResult",
31
+ "FieldValue",
32
+ "MeasurementInfo",
33
+ "Point",
34
+ "QueryError",
35
+ "QueryResult",
36
+ "ServerInfo",
37
+ "TimeRange",
38
+ "WriteError",
39
+ ]
40
+
41
+ __version__ = "0.2.0"