deltex 1.3.1__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,35 @@
1
+ /target
2
+ **/*.rs.bk
3
+ /bin
4
+ /pkg
5
+ *.wasm
6
+ *.tar.gzclaudecode-linux-x64
7
+ edgedb-docs.zip
8
+ fastly-api.toml
9
+ claudecode-linux-x64
10
+
11
+ # Web build artifacts
12
+ web/node_modules/
13
+ web/dist/
14
+ redis.env
15
+ *.pem
16
+ dashboard/node_modules/
17
+ dashboard/dist/
18
+ dashboard/.env.local
19
+ dashboard/test-results/
20
+ benchmarks/__pycache__/
21
+
22
+ # SDK build artifacts
23
+ sdk/rust/target/
24
+ sdk/typescript/node_modules/
25
+ sdk/typescript/dist/
26
+ sdk/typescript/build/
27
+ sdk/python/__pycache__/
28
+ sdk/python/*.egg-info/
29
+ sdk/python/build/
30
+ sdk/python/dist/
31
+ sdk/python/.eggs/
32
+ sdk/python/**/__pycache__/
33
+ sdk/go/bin/
34
+ sdk/go/vendor/
35
+ sdk/rust/Cargo.lock
deltex-1.3.1/PKG-INFO ADDED
@@ -0,0 +1,207 @@
1
+ Metadata-Version: 2.4
2
+ Name: deltex
3
+ Version: 1.3.1
4
+ Summary: Official Python client for Deltex — edge-native SQL database
5
+ Project-URL: Homepage, https://deltex.dev
6
+ Project-URL: Repository, https://github.com/deltex/deltex-python
7
+ License: MIT
8
+ Keywords: database,deltex,edge,sql
9
+ Requires-Python: >=3.8
10
+ Description-Content-Type: text/markdown
11
+
12
+ # deltex — Python client
13
+
14
+ Official Python client for [Deltex](https://deltex.dev) — edge-native SQL database.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ pip install deltex
20
+ ```
21
+
22
+ ## Quick start
23
+
24
+ ```python
25
+ import deltex
26
+
27
+ # Auto-reads DELTEX_API_KEY from environment
28
+ db = deltex.connect()
29
+
30
+ # Query
31
+ users = db.query("SELECT * FROM users WHERE active = $1", [True])
32
+ user = db.query_one("SELECT * FROM users WHERE id = $1", [42])
33
+
34
+ # Mutation
35
+ n = db.execute("INSERT INTO events (type, ts) VALUES ($1, NOW())", ["pageview"])
36
+
37
+ # Full result with commit status
38
+ result = db.execute_raw("INSERT INTO orders (amount) VALUES ($1)", [99.99])
39
+ print(result.commit_status) # "edge-accepted" | "committed"
40
+ print(result.execution_ms) # server-side execution time
41
+ ```
42
+
43
+ ## API
44
+
45
+ ### `deltex.connect(api_key=None, endpoint=None, write_mode="sync", ...)`
46
+
47
+ | Param | Default | Description |
48
+ |-------|---------|-------------|
49
+ | `api_key` | `DELTEX_API_KEY` env | Bearer token |
50
+ | `endpoint` | `DELTEX_ENDPOINT` or `https://db.deltex.dev` | Engine URL |
51
+ | `write_mode` | `"sync"` | `"sync"` / `"edge"` / `"async"` |
52
+ | `timeout` | `30.0` | Request timeout (seconds) |
53
+ | `max_retries` | `3` | Auto-retry on 429 |
54
+ | `tag` | `None` | X-Query-Tag for analytics |
55
+
56
+ ### Methods
57
+
58
+ ```python
59
+ db.query(sql, params=[]) → list[dict]
60
+ db.query_one(sql, params=[]) → dict | None
61
+ db.execute(sql, params=[]) → int (rows affected)
62
+ db.execute_raw(sql, params=[]) → QueryResult
63
+
64
+ db.transaction(fn) # BEGIN → fn(tx) → COMMIT
65
+ db.batch(statements) # atomic multi-statement, one round-trip → int
66
+
67
+ db.with_write_mode("sync") → Client (per-client write mode)
68
+ db.strong → Client (X-Consistency: strong)
69
+ db.with_idempotency_key(key) → Client (safe retry deduplication)
70
+ db.with_tag(tag) → Client (X-Query-Tag)
71
+ ```
72
+
73
+ ## Async
74
+
75
+ ```python
76
+ import asyncio
77
+ import deltex
78
+
79
+ async def main():
80
+ async with deltex.async_connect() as db:
81
+ users = await db.query("SELECT * FROM users LIMIT 10")
82
+ print(users)
83
+
84
+ asyncio.run(main())
85
+ ```
86
+
87
+ ## Transaction
88
+
89
+ ```python
90
+ def transfer(tx):
91
+ tx.execute("UPDATE accounts SET balance = balance - $1 WHERE id = $2", [100, 1])
92
+ tx.execute("UPDATE accounts SET balance = balance + $1 WHERE id = $2", [100, 2])
93
+
94
+ db.transaction(transfer)
95
+ ```
96
+
97
+ ## Batch — fastest bulk write
98
+
99
+ `batch()` applies a list of SQL statements in **one round-trip**, committed
100
+ atomically, and returns total rows affected:
101
+
102
+ ```python
103
+ n = db.batch([
104
+ "INSERT INTO products (name, price) VALUES ('Apple', 0.99)",
105
+ "INSERT INTO products (name, price) VALUES ('Banana', 0.59)",
106
+ ]) # n == 2
107
+ ```
108
+
109
+ Each durable write has a ~300ms Fastly-KV commit floor, so looping `execute`
110
+ costs ~N × 300ms. `batch()` (and a single multi-row `INSERT`) coalesce into one
111
+ durable commit — O(1) instead of O(N): 78 separate writes ≈ 54s, the same 78 in
112
+ a `batch()` ≈ 2s. `batch()` takes raw SQL (no binding) — for untrusted values,
113
+ build statements safely or use `transaction`.
114
+
115
+ ## CLI
116
+
117
+ ```bash
118
+ export DELTEX_API_KEY="dtx_k_..."
119
+
120
+ deltex query "SELECT * FROM users LIMIT 5"
121
+ deltex tables
122
+ deltex schema orders
123
+ deltex exec "DELETE FROM sessions WHERE expires_at < NOW()"
124
+ deltex health
125
+ deltex bench --samples 30
126
+ ```
127
+
128
+ ## Write Modes
129
+
130
+ | Mode | Latency | Use when |
131
+ |------|---------|----------|
132
+ | `sync` (default) | ~340ms | Everything by default; durable, never loses an acked write (batch to amortize) |
133
+ | `edge` | ~10ms | Caches, sessions, idempotent upserts — eventual durability |
134
+ | `async` | ~5ms | High-volume telemetry, fire-and-forget |
135
+
136
+ ## Error handling
137
+
138
+ ```python
139
+ from deltex import DeltexError, RateLimitError
140
+
141
+ try:
142
+ db.query("SELECT * FROM nonexistent")
143
+ except RateLimitError as e:
144
+ print(f"Rate limited, retry after {e.retry_after}s")
145
+ except DeltexError as e:
146
+ print(f"Error {e.status}: {e.engine_message}")
147
+ print(f"SQL: {e.sql}")
148
+ ```
149
+
150
+ ## License
151
+
152
+ MIT
153
+
154
+ ---
155
+
156
+ ## Common Patterns
157
+
158
+ ### Error handling
159
+
160
+ ```python
161
+ import time
162
+ from deltex import connect, RateLimitError, DeltexError
163
+
164
+ db = connect()
165
+ try:
166
+ result = db.query("SELECT * FROM users WHERE id = $1", [42])
167
+ except RateLimitError as e:
168
+ time.sleep(e.retry_after)
169
+ result = db.query("SELECT * FROM users WHERE id = $1", [42])
170
+ except DeltexError as e:
171
+ print(f"Query failed: {e}")
172
+ raise
173
+ ```
174
+
175
+ ### Async client (non-blocking)
176
+
177
+ ```python
178
+ import deltex
179
+
180
+ async def main():
181
+ db = deltex.async_connect()
182
+ rows = await db.query("SELECT * FROM products WHERE price < $1", [50.0])
183
+ for row in rows:
184
+ print(row["name"], row["price"])
185
+ ```
186
+
187
+ ### CLI usage
188
+
189
+ ```bash
190
+ # Run a query
191
+ deltex query "SELECT COUNT(*) FROM users"
192
+
193
+ # Migrate
194
+ deltex migrate --file migrations/001_create_users.sql
195
+
196
+ # Backup
197
+ deltex backup --output backup.json
198
+
199
+ # Manage API keys
200
+ deltex keys list
201
+ deltex keys create --name "production"
202
+ deltex keys revoke --id key_id_here
203
+ ```
204
+
205
+ ## SDK Version
206
+
207
+ `v1.3.1` — see [CHANGELOG.md](../../CHANGELOG.md) for history.
deltex-1.3.1/README.md ADDED
@@ -0,0 +1,196 @@
1
+ # deltex — Python client
2
+
3
+ Official Python client for [Deltex](https://deltex.dev) — edge-native SQL database.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install deltex
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ ```python
14
+ import deltex
15
+
16
+ # Auto-reads DELTEX_API_KEY from environment
17
+ db = deltex.connect()
18
+
19
+ # Query
20
+ users = db.query("SELECT * FROM users WHERE active = $1", [True])
21
+ user = db.query_one("SELECT * FROM users WHERE id = $1", [42])
22
+
23
+ # Mutation
24
+ n = db.execute("INSERT INTO events (type, ts) VALUES ($1, NOW())", ["pageview"])
25
+
26
+ # Full result with commit status
27
+ result = db.execute_raw("INSERT INTO orders (amount) VALUES ($1)", [99.99])
28
+ print(result.commit_status) # "edge-accepted" | "committed"
29
+ print(result.execution_ms) # server-side execution time
30
+ ```
31
+
32
+ ## API
33
+
34
+ ### `deltex.connect(api_key=None, endpoint=None, write_mode="sync", ...)`
35
+
36
+ | Param | Default | Description |
37
+ |-------|---------|-------------|
38
+ | `api_key` | `DELTEX_API_KEY` env | Bearer token |
39
+ | `endpoint` | `DELTEX_ENDPOINT` or `https://db.deltex.dev` | Engine URL |
40
+ | `write_mode` | `"sync"` | `"sync"` / `"edge"` / `"async"` |
41
+ | `timeout` | `30.0` | Request timeout (seconds) |
42
+ | `max_retries` | `3` | Auto-retry on 429 |
43
+ | `tag` | `None` | X-Query-Tag for analytics |
44
+
45
+ ### Methods
46
+
47
+ ```python
48
+ db.query(sql, params=[]) → list[dict]
49
+ db.query_one(sql, params=[]) → dict | None
50
+ db.execute(sql, params=[]) → int (rows affected)
51
+ db.execute_raw(sql, params=[]) → QueryResult
52
+
53
+ db.transaction(fn) # BEGIN → fn(tx) → COMMIT
54
+ db.batch(statements) # atomic multi-statement, one round-trip → int
55
+
56
+ db.with_write_mode("sync") → Client (per-client write mode)
57
+ db.strong → Client (X-Consistency: strong)
58
+ db.with_idempotency_key(key) → Client (safe retry deduplication)
59
+ db.with_tag(tag) → Client (X-Query-Tag)
60
+ ```
61
+
62
+ ## Async
63
+
64
+ ```python
65
+ import asyncio
66
+ import deltex
67
+
68
+ async def main():
69
+ async with deltex.async_connect() as db:
70
+ users = await db.query("SELECT * FROM users LIMIT 10")
71
+ print(users)
72
+
73
+ asyncio.run(main())
74
+ ```
75
+
76
+ ## Transaction
77
+
78
+ ```python
79
+ def transfer(tx):
80
+ tx.execute("UPDATE accounts SET balance = balance - $1 WHERE id = $2", [100, 1])
81
+ tx.execute("UPDATE accounts SET balance = balance + $1 WHERE id = $2", [100, 2])
82
+
83
+ db.transaction(transfer)
84
+ ```
85
+
86
+ ## Batch — fastest bulk write
87
+
88
+ `batch()` applies a list of SQL statements in **one round-trip**, committed
89
+ atomically, and returns total rows affected:
90
+
91
+ ```python
92
+ n = db.batch([
93
+ "INSERT INTO products (name, price) VALUES ('Apple', 0.99)",
94
+ "INSERT INTO products (name, price) VALUES ('Banana', 0.59)",
95
+ ]) # n == 2
96
+ ```
97
+
98
+ Each durable write has a ~300ms Fastly-KV commit floor, so looping `execute`
99
+ costs ~N × 300ms. `batch()` (and a single multi-row `INSERT`) coalesce into one
100
+ durable commit — O(1) instead of O(N): 78 separate writes ≈ 54s, the same 78 in
101
+ a `batch()` ≈ 2s. `batch()` takes raw SQL (no binding) — for untrusted values,
102
+ build statements safely or use `transaction`.
103
+
104
+ ## CLI
105
+
106
+ ```bash
107
+ export DELTEX_API_KEY="dtx_k_..."
108
+
109
+ deltex query "SELECT * FROM users LIMIT 5"
110
+ deltex tables
111
+ deltex schema orders
112
+ deltex exec "DELETE FROM sessions WHERE expires_at < NOW()"
113
+ deltex health
114
+ deltex bench --samples 30
115
+ ```
116
+
117
+ ## Write Modes
118
+
119
+ | Mode | Latency | Use when |
120
+ |------|---------|----------|
121
+ | `sync` (default) | ~340ms | Everything by default; durable, never loses an acked write (batch to amortize) |
122
+ | `edge` | ~10ms | Caches, sessions, idempotent upserts — eventual durability |
123
+ | `async` | ~5ms | High-volume telemetry, fire-and-forget |
124
+
125
+ ## Error handling
126
+
127
+ ```python
128
+ from deltex import DeltexError, RateLimitError
129
+
130
+ try:
131
+ db.query("SELECT * FROM nonexistent")
132
+ except RateLimitError as e:
133
+ print(f"Rate limited, retry after {e.retry_after}s")
134
+ except DeltexError as e:
135
+ print(f"Error {e.status}: {e.engine_message}")
136
+ print(f"SQL: {e.sql}")
137
+ ```
138
+
139
+ ## License
140
+
141
+ MIT
142
+
143
+ ---
144
+
145
+ ## Common Patterns
146
+
147
+ ### Error handling
148
+
149
+ ```python
150
+ import time
151
+ from deltex import connect, RateLimitError, DeltexError
152
+
153
+ db = connect()
154
+ try:
155
+ result = db.query("SELECT * FROM users WHERE id = $1", [42])
156
+ except RateLimitError as e:
157
+ time.sleep(e.retry_after)
158
+ result = db.query("SELECT * FROM users WHERE id = $1", [42])
159
+ except DeltexError as e:
160
+ print(f"Query failed: {e}")
161
+ raise
162
+ ```
163
+
164
+ ### Async client (non-blocking)
165
+
166
+ ```python
167
+ import deltex
168
+
169
+ async def main():
170
+ db = deltex.async_connect()
171
+ rows = await db.query("SELECT * FROM products WHERE price < $1", [50.0])
172
+ for row in rows:
173
+ print(row["name"], row["price"])
174
+ ```
175
+
176
+ ### CLI usage
177
+
178
+ ```bash
179
+ # Run a query
180
+ deltex query "SELECT COUNT(*) FROM users"
181
+
182
+ # Migrate
183
+ deltex migrate --file migrations/001_create_users.sql
184
+
185
+ # Backup
186
+ deltex backup --output backup.json
187
+
188
+ # Manage API keys
189
+ deltex keys list
190
+ deltex keys create --name "production"
191
+ deltex keys revoke --id key_id_here
192
+ ```
193
+
194
+ ## SDK Version
195
+
196
+ `v1.3.1` — see [CHANGELOG.md](../../CHANGELOG.md) for history.
@@ -0,0 +1,35 @@
1
+ """
2
+ deltex — Official Python client for Deltex edge-native SQL database.
3
+
4
+ Usage:
5
+ import deltex
6
+
7
+ db = deltex.connect() # reads DELTEX_API_KEY from env
8
+
9
+ # Query
10
+ users = db.query("SELECT * FROM users WHERE active = $1", [True])
11
+ user = db.query_one("SELECT * FROM users WHERE id = $1", [42])
12
+
13
+ # Execute (INSERT/UPDATE/DELETE)
14
+ n = db.execute("INSERT INTO events (type, ts) VALUES ($1, NOW())", ["click"])
15
+
16
+ # Async
17
+ import asyncio
18
+ async def main():
19
+ async with deltex.async_connect() as db:
20
+ users = await db.query("SELECT * FROM users")
21
+ """
22
+
23
+ from .client import connect, Client, DeltexError, RateLimitError, QueryResult
24
+ from .async_client import async_connect, AsyncClient
25
+
26
+ __version__ = "1.3.1"
27
+ __all__ = [
28
+ "connect",
29
+ "async_connect",
30
+ "Client",
31
+ "AsyncClient",
32
+ "DeltexError",
33
+ "RateLimitError",
34
+ "QueryResult",
35
+ ]
@@ -0,0 +1,215 @@
1
+ """
2
+ Deltex asyncio client.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import os
8
+ import json
9
+ import asyncio
10
+ import urllib.request
11
+ import urllib.error
12
+ from typing import Any, Dict, List, Optional, Sequence
13
+
14
+ from .client import (
15
+ _bind, _format_param, _TIMING_RE, _COMMIT_STATUS_VALUES,
16
+ DeltexError, RateLimitError, QueryResult, Row, Param,
17
+ )
18
+
19
+
20
+ async def _run_query_async(
21
+ sql: str,
22
+ url: str,
23
+ headers: Dict[str, str],
24
+ timeout: float,
25
+ max_retries: int,
26
+ ) -> QueryResult:
27
+ """Async HTTP execution using urllib in a thread (no external deps)."""
28
+ from .client import _run_query
29
+ loop = asyncio.get_event_loop()
30
+ return await loop.run_in_executor(
31
+ None,
32
+ lambda: _run_query(sql, url, headers, timeout, max_retries),
33
+ )
34
+
35
+
36
+ class AsyncClient:
37
+ """
38
+ Deltex asyncio SQL client.
39
+
40
+ Example:
41
+ async with deltex.async_connect() as db:
42
+ users = await db.query("SELECT * FROM users WHERE active = $1", [True])
43
+ user = await db.query_one("SELECT * FROM users WHERE id = $1", [42])
44
+ """
45
+
46
+ def __init__(
47
+ self,
48
+ api_key: Optional[str] = None,
49
+ endpoint: Optional[str] = None,
50
+ write_mode: str = "sync",
51
+ timeout: float = 30.0,
52
+ max_retries: int = 3,
53
+ tag: Optional[str] = None,
54
+ ):
55
+ self._api_key = api_key or os.environ.get("DELTEX_API_KEY", "")
56
+ if not self._api_key:
57
+ raise DeltexError("No API key. Set DELTEX_API_KEY env var or pass api_key=")
58
+
59
+ ep = (endpoint or os.environ.get("DELTEX_ENDPOINT") or "https://db.deltex.dev").rstrip("/")
60
+ self._url = f"{ep}/v1/query"
61
+ self._write_mode = write_mode
62
+ self._timeout = timeout
63
+ self._max_retries = max_retries
64
+
65
+ self._headers: Dict[str, str] = {
66
+ "Content-Type": "application/json",
67
+ "Authorization": f"Bearer {self._api_key}",
68
+ "X-Write-Mode": write_mode,
69
+ }
70
+ if tag:
71
+ self._headers["X-Query-Tag"] = tag
72
+
73
+ async def __aenter__(self) -> "AsyncClient":
74
+ return self
75
+
76
+ async def __aexit__(self, *args: Any) -> None:
77
+ pass
78
+
79
+ async def query(self, sql: str, params: Sequence[Param] = ()) -> List[Row]:
80
+ """Execute SQL, return all rows."""
81
+ result = await _run_query_async(_bind(sql, params), self._url, self._headers, self._timeout, self._max_retries)
82
+ return result.rows
83
+
84
+ async def query_one(self, sql: str, params: Sequence[Param] = ()) -> Optional[Row]:
85
+ """Execute SQL, return first row or None."""
86
+ rows = (await _run_query_async(_bind(sql, params), self._url, self._headers, self._timeout, self._max_retries)).rows
87
+ return rows[0] if rows else None
88
+
89
+ async def execute(self, sql: str, params: Sequence[Param] = ()) -> int:
90
+ """Execute a mutation, return rows affected."""
91
+ return (await _run_query_async(_bind(sql, params), self._url, self._headers, self._timeout, self._max_retries)).rows_affected
92
+
93
+ async def execute_raw(self, sql: str, params: Sequence[Param] = ()) -> QueryResult:
94
+ """Execute SQL, return full QueryResult."""
95
+ return await _run_query_async(_bind(sql, params), self._url, self._headers, self._timeout, self._max_retries)
96
+
97
+ async def transaction(self, fn):
98
+ """
99
+ Execute an atomic transaction via Deltex's /transaction endpoint.
100
+
101
+ Mutating statements (``execute``/``execute_raw``) are collected and sent
102
+ atomically in a single round-trip; reads (``query``/``query_one``) execute
103
+ live. If ``fn`` raises before returning, no statements are sent — the
104
+ transaction is effectively rolled back.
105
+
106
+ Example:
107
+ async def do_transfer(tx):
108
+ await tx.execute("UPDATE accounts SET balance = balance - $1 WHERE id = $2", [100, 1])
109
+ await tx.execute("UPDATE accounts SET balance = balance + $1 WHERE id = $2", [100, 2])
110
+
111
+ await db.transaction(do_transfer)
112
+ """
113
+ statements: list = []
114
+ outer = self
115
+
116
+ class CollectingClient:
117
+ async def query(self_inner, sql: str, params: Sequence[Param] = ()) -> List[Row]:
118
+ return await outer.query(sql, params)
119
+
120
+ async def query_one(self_inner, sql: str, params: Sequence[Param] = ()) -> Optional[Row]:
121
+ return await outer.query_one(sql, params)
122
+
123
+ async def execute(self_inner, sql: str, params: Sequence[Param] = ()) -> int:
124
+ statements.append(_bind(sql, params))
125
+ return 0
126
+
127
+ async def execute_raw(self_inner, sql: str, params: Sequence[Param] = ()) -> QueryResult:
128
+ statements.append(_bind(sql, params))
129
+ return QueryResult(rows=[], columns=[], rows_affected=0)
130
+
131
+ tx = CollectingClient()
132
+ user_result = await fn(tx)
133
+
134
+ if not statements:
135
+ return user_result
136
+
137
+ tx_url = self._url.replace("/v1/query", "/v1/transaction")
138
+ body = json.dumps({"statements": statements, "isolation": "SERIALIZABLE"}).encode()
139
+
140
+ def _send() -> None:
141
+ req = urllib.request.Request(tx_url, data=body, method="POST", headers=self._headers)
142
+ try:
143
+ with urllib.request.urlopen(req, timeout=self._timeout) as resp:
144
+ data = json.loads(resp.read())
145
+ except urllib.error.HTTPError as e:
146
+ data = json.loads(e.read())
147
+ raise DeltexError(data.get("message", str(e)), e.code, "; ".join(statements))
148
+ if data.get("success") is False:
149
+ raise DeltexError(data.get("message", "Transaction failed"), 500, "; ".join(statements))
150
+
151
+ loop = asyncio.get_event_loop()
152
+ await loop.run_in_executor(None, _send)
153
+ return user_result
154
+
155
+ def with_write_mode(self, mode: str) -> "AsyncClient":
156
+ c = AsyncClient.__new__(AsyncClient)
157
+ c._api_key = self._api_key
158
+ c._url = self._url
159
+ c._write_mode = mode
160
+ c._timeout = self._timeout
161
+ c._max_retries = self._max_retries
162
+ c._headers = {**self._headers, "X-Write-Mode": mode}
163
+ return c
164
+
165
+ @property
166
+ def strong(self) -> "AsyncClient":
167
+ c = AsyncClient.__new__(AsyncClient)
168
+ c._api_key = self._api_key
169
+ c._url = self._url
170
+ c._write_mode = self._write_mode
171
+ c._timeout = self._timeout
172
+ c._max_retries = self._max_retries
173
+ c._headers = {**self._headers, "X-Consistency": "strong"}
174
+ return c
175
+
176
+ def with_tag(self, tag: str) -> "AsyncClient":
177
+ c = AsyncClient.__new__(AsyncClient)
178
+ c._api_key = self._api_key
179
+ c._url = self._url
180
+ c._write_mode = self._write_mode
181
+ c._timeout = self._timeout
182
+ c._max_retries = self._max_retries
183
+ c._headers = {**self._headers, "X-Query-Tag": tag}
184
+ return c
185
+
186
+ def with_idempotency_key(self, key: str) -> "AsyncClient":
187
+ c = AsyncClient.__new__(AsyncClient)
188
+ c._api_key = self._api_key
189
+ c._url = self._url
190
+ c._write_mode = self._write_mode
191
+ c._timeout = self._timeout
192
+ c._max_retries = self._max_retries
193
+ c._headers = {**self._headers, "X-Idempotency-Key": key}
194
+ return c
195
+
196
+
197
+ def async_connect(
198
+ api_key: Optional[str] = None,
199
+ endpoint: Optional[str] = None,
200
+ write_mode: str = "sync",
201
+ timeout: float = 30.0,
202
+ max_retries: int = 3,
203
+ tag: Optional[str] = None,
204
+ ) -> AsyncClient:
205
+ """
206
+ Create an async Deltex client.
207
+
208
+ Example:
209
+ async with deltex.async_connect() as db:
210
+ users = await db.query("SELECT * FROM users")
211
+ """
212
+ return AsyncClient(
213
+ api_key=api_key, endpoint=endpoint, write_mode=write_mode,
214
+ timeout=timeout, max_retries=max_retries, tag=tag,
215
+ )