keboola-query-service 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.
@@ -0,0 +1,32 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+ *.egg
11
+
12
+ # Virtual environments
13
+ .venv/
14
+ venv/
15
+ ENV/
16
+
17
+ # IDE
18
+ .idea/
19
+ .vscode/
20
+ *.swp
21
+ *.swo
22
+
23
+ # Testing
24
+ .pytest_cache/
25
+ .coverage
26
+ htmlcov/
27
+
28
+ # mypy
29
+ .mypy_cache/
30
+
31
+ # MISC
32
+ .env
@@ -0,0 +1,229 @@
1
+ Metadata-Version: 2.4
2
+ Name: keboola-query-service
3
+ Version: 0.1.0
4
+ Summary: Python SDK for Keboola Query Service API
5
+ Project-URL: Homepage, https://github.com/keboola/query-service-python-sdk
6
+ Project-URL: Documentation, https://developers.keboola.com/
7
+ Project-URL: Repository, https://github.com/keboola/query-service-python-sdk
8
+ Project-URL: Issues, https://github.com/keboola/query-service-python-sdk/issues
9
+ Author-email: Keboola <support@keboola.com>
10
+ License-Expression: MIT
11
+ Keywords: bigquery,data,keboola,query,snowflake,sql
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Database
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: httpx>=0.25.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: mypy>=1.0.0; extra == 'dev'
27
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
28
+ Requires-Dist: pytest-httpx>=0.22.0; extra == 'dev'
29
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
30
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # Keboola Query Service Python SDK
34
+
35
+ Python client for [Keboola Query Service API](https://query.keboola.com/api/v1/documentation).
36
+
37
+ ## Installation
38
+
39
+ ```bash
40
+ pip install keboola-query-service
41
+ ```
42
+
43
+ ## Quick Start
44
+
45
+ ```python
46
+ from keboola_query_service import Client
47
+
48
+ # Initialize client
49
+ client = Client(
50
+ base_url="https://query.keboola.com",
51
+ token="your-storage-api-token"
52
+ )
53
+
54
+ # Execute a query and wait for results
55
+ results = client.execute_query(
56
+ branch_id="123",
57
+ workspace_id="456",
58
+ statements=["SELECT * FROM my_table LIMIT 10"]
59
+ )
60
+
61
+ # Access results
62
+ for row in results[0].data:
63
+ print(row)
64
+ ```
65
+
66
+ ## Features
67
+
68
+ - **Sync and async support** - Both synchronous and async (asyncio) APIs
69
+ - **Automatic retries** - Configurable retry logic for transient failures
70
+ - **Job polling** - Built-in exponential backoff for waiting on job completion
71
+ - **Streaming** - NDJSON streaming for large result sets
72
+ - **Type hints** - Full type annotations for IDE support
73
+
74
+ ## Usage
75
+
76
+ ### Basic Query Execution
77
+
78
+ ```python
79
+ from keboola_query_service import Client
80
+
81
+ with Client(base_url="https://query.keboola.com", token="...") as client:
82
+ # Execute query and wait for results
83
+ results = client.execute_query(
84
+ branch_id="123",
85
+ workspace_id="456",
86
+ statements=[
87
+ "SELECT * FROM orders WHERE date > '2024-01-01'",
88
+ "SELECT COUNT(*) FROM customers"
89
+ ],
90
+ transactional=True # Execute in a transaction
91
+ )
92
+
93
+ # Results is a list - one QueryResult per statement
94
+ orders_result = results[0]
95
+ count_result = results[1]
96
+
97
+ print(f"Columns: {[c.name for c in orders_result.columns]}")
98
+ print(f"Rows: {len(orders_result.data)}")
99
+ ```
100
+
101
+ ### Async Usage
102
+
103
+ ```python
104
+ import asyncio
105
+ from keboola_query_service import Client
106
+
107
+ async def main():
108
+ async with Client(base_url="...", token="...") as client:
109
+ results = await client.execute_query_async(
110
+ branch_id="123",
111
+ workspace_id="456",
112
+ statements=["SELECT 1"]
113
+ )
114
+ print(results[0].data)
115
+
116
+ asyncio.run(main())
117
+ ```
118
+
119
+ ### Low-Level API
120
+
121
+ For more control, use the low-level methods:
122
+
123
+ ```python
124
+ # Submit job without waiting
125
+ job_id = client.submit_job(
126
+ branch_id="123",
127
+ workspace_id="456",
128
+ statements=["SELECT * FROM large_table"]
129
+ )
130
+
131
+ # Check status
132
+ status = client.get_job_status(job_id)
133
+ print(f"Status: {status.status}") # created, enqueued, processing, completed, failed
134
+
135
+ # Wait for completion
136
+ final_status = client.wait_for_job(job_id, max_wait_time=300)
137
+
138
+ # Get results for specific statement
139
+ result = client.get_job_results(job_id, final_status.statements[0].id)
140
+ ```
141
+
142
+ ### Streaming Large Results
143
+
144
+ ```python
145
+ # Stream results as NDJSON for large datasets
146
+ for row in client.stream_results(job_id, statement_id):
147
+ process_row(row)
148
+ ```
149
+
150
+ ### Error Handling
151
+
152
+ ```python
153
+ from keboola_query_service import (
154
+ Client,
155
+ AuthenticationError,
156
+ ValidationError,
157
+ JobError,
158
+ TimeoutError,
159
+ )
160
+
161
+ try:
162
+ results = client.execute_query(...)
163
+ except AuthenticationError:
164
+ print("Invalid token")
165
+ except ValidationError as e:
166
+ print(f"Invalid request: {e.message}")
167
+ except JobError as e:
168
+ print(f"Query failed: {e.message}")
169
+ for stmt in e.failed_statements:
170
+ print(f" Statement {stmt['id']}: {stmt['error']}")
171
+ except TimeoutError as e:
172
+ print(f"Job {e.job_id} timed out")
173
+ ```
174
+
175
+ ### Query History
176
+
177
+ ```python
178
+ history = client.get_query_history(
179
+ branch_id="123",
180
+ workspace_id="456",
181
+ page_size=100
182
+ )
183
+
184
+ for stmt in history.statements:
185
+ print(f"{stmt.query_job_id}: {stmt.query[:50]}... ({stmt.status})")
186
+ ```
187
+
188
+ ## Configuration
189
+
190
+ ```python
191
+ client = Client(
192
+ base_url="https://query.keboola.com",
193
+ token="your-token",
194
+ timeout=120.0, # Request timeout (seconds)
195
+ connect_timeout=10.0, # Connection timeout (seconds)
196
+ max_retries=3, # Max retry attempts
197
+ user_agent="my-app/1.0", # Custom user agent
198
+ )
199
+ ```
200
+
201
+ ## API Reference
202
+
203
+ ### Client Methods
204
+
205
+ | Method | Description |
206
+ |--------|-------------|
207
+ | `execute_query()` | Submit query, wait for completion, return results |
208
+ | `submit_job()` | Submit query job without waiting |
209
+ | `get_job_status()` | Get current job status |
210
+ | `get_job_results()` | Get results for a statement |
211
+ | `wait_for_job()` | Wait for job to complete |
212
+ | `cancel_job()` | Cancel a running job |
213
+ | `get_query_history()` | Get query history for workspace |
214
+ | `stream_results()` | Stream results as NDJSON |
215
+
216
+ All methods have async variants with `_async` suffix.
217
+
218
+ ### Models
219
+
220
+ - `JobStatus` - Job status with statements
221
+ - `QueryResult` - Query results with columns and data
222
+ - `Statement` - Individual SQL statement info
223
+ - `Column` - Column metadata
224
+ - `JobState` - Enum: created, enqueued, processing, completed, failed, canceled
225
+ - `StatementState` - Enum: waiting, processing, completed, failed, canceled, notExecuted
226
+
227
+ ## License
228
+
229
+ MIT
@@ -0,0 +1,197 @@
1
+ # Keboola Query Service Python SDK
2
+
3
+ Python client for [Keboola Query Service API](https://query.keboola.com/api/v1/documentation).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install keboola-query-service
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```python
14
+ from keboola_query_service import Client
15
+
16
+ # Initialize client
17
+ client = Client(
18
+ base_url="https://query.keboola.com",
19
+ token="your-storage-api-token"
20
+ )
21
+
22
+ # Execute a query and wait for results
23
+ results = client.execute_query(
24
+ branch_id="123",
25
+ workspace_id="456",
26
+ statements=["SELECT * FROM my_table LIMIT 10"]
27
+ )
28
+
29
+ # Access results
30
+ for row in results[0].data:
31
+ print(row)
32
+ ```
33
+
34
+ ## Features
35
+
36
+ - **Sync and async support** - Both synchronous and async (asyncio) APIs
37
+ - **Automatic retries** - Configurable retry logic for transient failures
38
+ - **Job polling** - Built-in exponential backoff for waiting on job completion
39
+ - **Streaming** - NDJSON streaming for large result sets
40
+ - **Type hints** - Full type annotations for IDE support
41
+
42
+ ## Usage
43
+
44
+ ### Basic Query Execution
45
+
46
+ ```python
47
+ from keboola_query_service import Client
48
+
49
+ with Client(base_url="https://query.keboola.com", token="...") as client:
50
+ # Execute query and wait for results
51
+ results = client.execute_query(
52
+ branch_id="123",
53
+ workspace_id="456",
54
+ statements=[
55
+ "SELECT * FROM orders WHERE date > '2024-01-01'",
56
+ "SELECT COUNT(*) FROM customers"
57
+ ],
58
+ transactional=True # Execute in a transaction
59
+ )
60
+
61
+ # Results is a list - one QueryResult per statement
62
+ orders_result = results[0]
63
+ count_result = results[1]
64
+
65
+ print(f"Columns: {[c.name for c in orders_result.columns]}")
66
+ print(f"Rows: {len(orders_result.data)}")
67
+ ```
68
+
69
+ ### Async Usage
70
+
71
+ ```python
72
+ import asyncio
73
+ from keboola_query_service import Client
74
+
75
+ async def main():
76
+ async with Client(base_url="...", token="...") as client:
77
+ results = await client.execute_query_async(
78
+ branch_id="123",
79
+ workspace_id="456",
80
+ statements=["SELECT 1"]
81
+ )
82
+ print(results[0].data)
83
+
84
+ asyncio.run(main())
85
+ ```
86
+
87
+ ### Low-Level API
88
+
89
+ For more control, use the low-level methods:
90
+
91
+ ```python
92
+ # Submit job without waiting
93
+ job_id = client.submit_job(
94
+ branch_id="123",
95
+ workspace_id="456",
96
+ statements=["SELECT * FROM large_table"]
97
+ )
98
+
99
+ # Check status
100
+ status = client.get_job_status(job_id)
101
+ print(f"Status: {status.status}") # created, enqueued, processing, completed, failed
102
+
103
+ # Wait for completion
104
+ final_status = client.wait_for_job(job_id, max_wait_time=300)
105
+
106
+ # Get results for specific statement
107
+ result = client.get_job_results(job_id, final_status.statements[0].id)
108
+ ```
109
+
110
+ ### Streaming Large Results
111
+
112
+ ```python
113
+ # Stream results as NDJSON for large datasets
114
+ for row in client.stream_results(job_id, statement_id):
115
+ process_row(row)
116
+ ```
117
+
118
+ ### Error Handling
119
+
120
+ ```python
121
+ from keboola_query_service import (
122
+ Client,
123
+ AuthenticationError,
124
+ ValidationError,
125
+ JobError,
126
+ TimeoutError,
127
+ )
128
+
129
+ try:
130
+ results = client.execute_query(...)
131
+ except AuthenticationError:
132
+ print("Invalid token")
133
+ except ValidationError as e:
134
+ print(f"Invalid request: {e.message}")
135
+ except JobError as e:
136
+ print(f"Query failed: {e.message}")
137
+ for stmt in e.failed_statements:
138
+ print(f" Statement {stmt['id']}: {stmt['error']}")
139
+ except TimeoutError as e:
140
+ print(f"Job {e.job_id} timed out")
141
+ ```
142
+
143
+ ### Query History
144
+
145
+ ```python
146
+ history = client.get_query_history(
147
+ branch_id="123",
148
+ workspace_id="456",
149
+ page_size=100
150
+ )
151
+
152
+ for stmt in history.statements:
153
+ print(f"{stmt.query_job_id}: {stmt.query[:50]}... ({stmt.status})")
154
+ ```
155
+
156
+ ## Configuration
157
+
158
+ ```python
159
+ client = Client(
160
+ base_url="https://query.keboola.com",
161
+ token="your-token",
162
+ timeout=120.0, # Request timeout (seconds)
163
+ connect_timeout=10.0, # Connection timeout (seconds)
164
+ max_retries=3, # Max retry attempts
165
+ user_agent="my-app/1.0", # Custom user agent
166
+ )
167
+ ```
168
+
169
+ ## API Reference
170
+
171
+ ### Client Methods
172
+
173
+ | Method | Description |
174
+ |--------|-------------|
175
+ | `execute_query()` | Submit query, wait for completion, return results |
176
+ | `submit_job()` | Submit query job without waiting |
177
+ | `get_job_status()` | Get current job status |
178
+ | `get_job_results()` | Get results for a statement |
179
+ | `wait_for_job()` | Wait for job to complete |
180
+ | `cancel_job()` | Cancel a running job |
181
+ | `get_query_history()` | Get query history for workspace |
182
+ | `stream_results()` | Stream results as NDJSON |
183
+
184
+ All methods have async variants with `_async` suffix.
185
+
186
+ ### Models
187
+
188
+ - `JobStatus` - Job status with statements
189
+ - `QueryResult` - Query results with columns and data
190
+ - `Statement` - Individual SQL statement info
191
+ - `Column` - Column metadata
192
+ - `JobState` - Enum: created, enqueued, processing, completed, failed, canceled
193
+ - `StatementState` - Enum: waiting, processing, completed, failed, canceled, notExecuted
194
+
195
+ ## License
196
+
197
+ MIT
@@ -0,0 +1,71 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "keboola-query-service"
7
+ version = "0.1.0"
8
+ description = "Python SDK for Keboola Query Service API"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "Keboola", email = "support@keboola.com" }
14
+ ]
15
+ keywords = ["keboola", "query", "sql", "data", "snowflake", "bigquery"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Topic :: Database",
26
+ "Topic :: Software Development :: Libraries :: Python Modules",
27
+ "Typing :: Typed",
28
+ ]
29
+ dependencies = [
30
+ "httpx>=0.25.0",
31
+ ]
32
+
33
+ [project.optional-dependencies]
34
+ dev = [
35
+ "pytest>=7.0.0",
36
+ "pytest-asyncio>=0.21.0",
37
+ "pytest-httpx>=0.22.0",
38
+ "ruff>=0.1.0",
39
+ "mypy>=1.0.0",
40
+ ]
41
+
42
+ [project.urls]
43
+ Homepage = "https://github.com/keboola/query-service-python-sdk"
44
+ Documentation = "https://developers.keboola.com/"
45
+ Repository = "https://github.com/keboola/query-service-python-sdk"
46
+ Issues = "https://github.com/keboola/query-service-python-sdk/issues"
47
+
48
+ [tool.hatch.build.targets.sdist]
49
+ include = [
50
+ "/src",
51
+ ]
52
+
53
+ [tool.hatch.build.targets.wheel]
54
+ packages = ["src/keboola_query_service"]
55
+
56
+ [tool.pytest.ini_options]
57
+ asyncio_mode = "auto"
58
+ testpaths = ["tests"]
59
+
60
+ [tool.ruff]
61
+ target-version = "py310"
62
+ line-length = 88
63
+
64
+ [tool.ruff.lint]
65
+ select = ["E", "F", "I", "UP", "B", "SIM"]
66
+
67
+ [tool.mypy]
68
+ python_version = "3.10"
69
+ strict = true
70
+ warn_return_any = true
71
+ warn_unused_configs = true
@@ -0,0 +1,38 @@
1
+ """Keboola Query Service Python SDK."""
2
+
3
+ from ._version import __version__
4
+ from .client import Client
5
+ from .models import (
6
+ ActorType,
7
+ JobState,
8
+ StatementState,
9
+ Column,
10
+ Statement,
11
+ JobStatus,
12
+ QueryResult,
13
+ QueryHistory,
14
+ )
15
+ from .exceptions import (
16
+ QueryServiceError,
17
+ AuthenticationError,
18
+ ValidationError,
19
+ JobError,
20
+ JobTimeoutError,
21
+ )
22
+
23
+ __all__ = [
24
+ "Client",
25
+ "ActorType",
26
+ "JobState",
27
+ "StatementState",
28
+ "Column",
29
+ "Statement",
30
+ "JobStatus",
31
+ "QueryResult",
32
+ "QueryHistory",
33
+ "QueryServiceError",
34
+ "AuthenticationError",
35
+ "ValidationError",
36
+ "JobError",
37
+ "JobTimeoutError",
38
+ ]
@@ -0,0 +1,3 @@
1
+ """Version information for Keboola Query Service SDK."""
2
+
3
+ __version__ = "0.1.0"