duckgresql 1.4.4.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.
Files changed (39) hide show
  1. duckgresql-1.4.4.0/.env.example +21 -0
  2. duckgresql-1.4.4.0/.env.prod.example +11 -0
  3. duckgresql-1.4.4.0/.github/workflows/check.yml +50 -0
  4. duckgresql-1.4.4.0/.github/workflows/release.yml +89 -0
  5. duckgresql-1.4.4.0/.gitignore +68 -0
  6. duckgresql-1.4.4.0/.python-version +1 -0
  7. duckgresql-1.4.4.0/CONTRIBUTING.md +70 -0
  8. duckgresql-1.4.4.0/LICENSE +21 -0
  9. duckgresql-1.4.4.0/Makefile +55 -0
  10. duckgresql-1.4.4.0/PKG-INFO +160 -0
  11. duckgresql-1.4.4.0/README.md +122 -0
  12. duckgresql-1.4.4.0/RELEASING.md +192 -0
  13. duckgresql-1.4.4.0/example/.env.example +18 -0
  14. duckgresql-1.4.4.0/example/run_query.py +67 -0
  15. duckgresql-1.4.4.0/pyproject.toml +80 -0
  16. duckgresql-1.4.4.0/scripts/inject_release_defaults.py +101 -0
  17. duckgresql-1.4.4.0/src/duckgresql/__init__.py +123 -0
  18. duckgresql-1.4.4.0/src/duckgresql/_config.py +13 -0
  19. duckgresql-1.4.4.0/src/duckgresql/_flight.py +152 -0
  20. duckgresql-1.4.4.0/src/duckgresql/_rest.py +125 -0
  21. duckgresql-1.4.4.0/src/duckgresql/_rest_async.py +119 -0
  22. duckgresql-1.4.4.0/src/duckgresql/_types.py +35 -0
  23. duckgresql-1.4.4.0/src/duckgresql/_version.py +1 -0
  24. duckgresql-1.4.4.0/src/duckgresql/async_connection.py +173 -0
  25. duckgresql-1.4.4.0/src/duckgresql/async_job.py +154 -0
  26. duckgresql-1.4.4.0/src/duckgresql/connection.py +172 -0
  27. duckgresql-1.4.4.0/src/duckgresql/exceptions.py +27 -0
  28. duckgresql-1.4.4.0/src/duckgresql/py.typed +0 -0
  29. duckgresql-1.4.4.0/src/duckgresql/result.py +128 -0
  30. duckgresql-1.4.4.0/tests/__init__.py +0 -0
  31. duckgresql-1.4.4.0/tests/conftest.py +67 -0
  32. duckgresql-1.4.4.0/tests/test_async_connection.py +77 -0
  33. duckgresql-1.4.4.0/tests/test_async_job.py +133 -0
  34. duckgresql-1.4.4.0/tests/test_config.py +174 -0
  35. duckgresql-1.4.4.0/tests/test_connection.py +132 -0
  36. duckgresql-1.4.4.0/tests/test_flight.py +67 -0
  37. duckgresql-1.4.4.0/tests/test_rest.py +117 -0
  38. duckgresql-1.4.4.0/tests/test_result.py +118 -0
  39. duckgresql-1.4.4.0/uv.lock +613 -0
@@ -0,0 +1,21 @@
1
+ # DuckGresQL Python SDK — example environment variables
2
+ # Copy to .env and set values. Do not commit .env.
3
+
4
+ # -----------------------------------------------------------------------------
5
+ # Runtime (used by the SDK when connecting to a server)
6
+ # -----------------------------------------------------------------------------
7
+ DUCKGRESQL_HOST=localhost
8
+ DUCKGRESQL_FLIGHT_PORT=47470
9
+ DUCKGRESQL_REST_PORT=3100
10
+ DUCKGRESQL_USE_TLS=false
11
+ DUCKGRESQL_REST_SCHEME=http
12
+
13
+ # -----------------------------------------------------------------------------
14
+ # Release build (only for `make py-sdk-inject-defaults` / building for PyPI)
15
+ # Set in GitHub repo variables for CI, or here for local release testing.
16
+ # -----------------------------------------------------------------------------
17
+ # DUCKGRESQL_RELEASE_HOST=api.duckgresql.com
18
+ # DUCKGRESQL_RELEASE_FLIGHT_PORT=47470
19
+ # DUCKGRESQL_RELEASE_REST_PORT=3100
20
+ # DUCKGRESQL_RELEASE_USE_TLS=true
21
+ # DUCKGRESQL_RELEASE_REST_SCHEME=https
@@ -0,0 +1,11 @@
1
+ # Production release defaults — used by `make test-pypi-install-prod`
2
+ # Copy to .env.prod and fill in values. Do not commit .env.prod.
3
+
4
+ DUCKGRESQL_RELEASE_HOST=api.duckgresql.io
5
+ DUCKGRESQL_RELEASE_FLIGHT_PORT=47470
6
+ DUCKGRESQL_RELEASE_REST_PORT=443
7
+ DUCKGRESQL_RELEASE_USE_TLS=false
8
+ DUCKGRESQL_RELEASE_REST_SCHEME=https
9
+
10
+ DUCKGRESQL_TOKEN=dkgql_your_token_here
11
+ DUCKGRESQL_DATABASE=your_database_name_or_uuid
@@ -0,0 +1,50 @@
1
+ name: Python SDK
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: sdk-python-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ test:
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ matrix:
18
+ python-version: ['3.11', '3.12', '3.13']
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - name: Set up Python ${{ matrix.python-version }}
23
+ uses: actions/setup-python@v5
24
+ with:
25
+ python-version: ${{ matrix.python-version }}
26
+ cache: pip
27
+ cache-dependency-path: pyproject.toml
28
+
29
+ - name: Install dependencies
30
+ run: |
31
+ python -m pip install --upgrade pip
32
+ pip install -e ".[dev,all]"
33
+
34
+ - name: Lint
35
+ run: ruff check src/ tests/
36
+
37
+ - name: Type check
38
+ run: mypy src/duckgresql/
39
+
40
+ - name: Test
41
+ run: pytest tests/ -v --tb=short
42
+
43
+ - name: Install build tools
44
+ run: pip install build twine
45
+
46
+ - name: Build package
47
+ run: python -m build
48
+
49
+ - name: Check package
50
+ run: twine check dist/*
@@ -0,0 +1,89 @@
1
+ name: Python SDK Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ permissions:
9
+ contents: write # create GitHub Release
10
+ id-token: write # required for PyPI trusted publishing (OIDC)
11
+
12
+ jobs:
13
+ release:
14
+ runs-on: ubuntu-latest
15
+ environment:
16
+ name: pypi
17
+ url: https://pypi.org/p/duckgresql
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Set up Python
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: '3.13'
25
+
26
+ - name: Install build dependencies
27
+ run: |
28
+ python -m pip install --upgrade pip
29
+ pip install build twine
30
+
31
+ - name: Extract version from tag
32
+ id: version
33
+ run: |
34
+ TAG_VERSION="${GITHUB_REF#refs/tags/v}"
35
+ echo "version=$TAG_VERSION" >> $GITHUB_OUTPUT
36
+ echo "Releasing version: $TAG_VERSION"
37
+
38
+ - name: Verify version matches pyproject.toml
39
+ run: |
40
+ PACKAGE_VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])" 2>/dev/null || python -c "exec(open('src/duckgresql/_version.py').read()); print(__version__)")
41
+ if [ "$PACKAGE_VERSION" != "${{ steps.version.outputs.version }}" ]; then
42
+ echo "Error: Tag version (${{ steps.version.outputs.version }}) does not match package version ($PACKAGE_VERSION)"
43
+ exit 1
44
+ fi
45
+
46
+ - name: Install dependencies and run tests
47
+ run: |
48
+ pip install -e ".[dev,all]"
49
+ ruff check src/ tests/
50
+ mypy src/duckgresql/
51
+ pytest tests/ -v
52
+
53
+ - name: Inject release defaults
54
+ env:
55
+ DUCKGRESQL_RELEASE_HOST: ${{ vars.DUCKGRESQL_RELEASE_HOST }}
56
+ DUCKGRESQL_RELEASE_FLIGHT_PORT: ${{ vars.DUCKGRESQL_RELEASE_FLIGHT_PORT }}
57
+ DUCKGRESQL_RELEASE_REST_PORT: ${{ vars.DUCKGRESQL_RELEASE_REST_PORT }}
58
+ DUCKGRESQL_RELEASE_USE_TLS: ${{ vars.DUCKGRESQL_RELEASE_USE_TLS }}
59
+ DUCKGRESQL_RELEASE_REST_SCHEME: ${{ vars.DUCKGRESQL_RELEASE_REST_SCHEME }}
60
+ run: python scripts/inject_release_defaults.py
61
+
62
+ - name: Build package
63
+ run: python -m build
64
+
65
+ - name: Check package
66
+ run: twine check dist/*
67
+
68
+ - name: Publish to PyPI
69
+ uses: pypa/gh-action-pypi-publish@release/v1
70
+ with:
71
+ packages-dir: dist/
72
+ skip-existing: false
73
+ verbose: true
74
+
75
+ - name: Create GitHub Release
76
+ uses: softprops/action-gh-release@v2
77
+ with:
78
+ name: Python SDK v${{ steps.version.outputs.version }}
79
+ body: |
80
+ ## Python SDK v${{ steps.version.outputs.version }}
81
+
82
+ Install from PyPI:
83
+ ```bash
84
+ pip install duckgresql==${{ steps.version.outputs.version }}
85
+ ```
86
+
87
+ [View on PyPI](https://pypi.org/project/duckgresql/${{ steps.version.outputs.version }}/)
88
+ files: |
89
+ dist/*
@@ -0,0 +1,68 @@
1
+ # Virtual environments
2
+ .venv/
3
+ .venv-pypi-test/
4
+ venv/
5
+ env/
6
+ .env/
7
+
8
+ # Python
9
+ __pycache__/
10
+ *.py[cod]
11
+ *$py.class
12
+ *.so
13
+ .Python
14
+ *.egg
15
+ *.egg-info/
16
+ .eggs/
17
+ dist/
18
+ build/
19
+ *.manifest
20
+ *.spec
21
+
22
+ # Hatch
23
+ .hatch/
24
+
25
+ # Installer
26
+ *.whl
27
+ *.tar.gz
28
+
29
+ # Testing / coverage
30
+ .pytest_cache/
31
+ .coverage
32
+ htmlcov/
33
+ .tox/
34
+ .nox/
35
+ coverage.xml
36
+ *.cover
37
+ .hypothesis/
38
+
39
+ # Type checkers / linters
40
+ .mypy_cache/
41
+ .dmypy.json
42
+ dmypy.json
43
+ .ruff_cache/
44
+
45
+ # IDE
46
+ .idea/
47
+ .vscode/
48
+ *.swp
49
+ *.swo
50
+ *~
51
+
52
+ # OS
53
+ .DS_Store
54
+ Thumbs.db
55
+
56
+ # Local env / secrets
57
+ .env
58
+ .env.prod
59
+ .env.local
60
+ .env.*.local
61
+ *.local
62
+
63
+ # Jupyter
64
+ .ipynb_checkpoints/
65
+
66
+ # Distribution / packaging (keep dist out; built in CI)
67
+ *.egg-info/
68
+ *.egg
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,70 @@
1
+ # Contributing to the DuckGresQL Python SDK
2
+
3
+ This document is for **developers of the SDK** (contributors and maintainers). For using the library, see [README.md](README.md).
4
+
5
+ ## Prerequisites
6
+
7
+ - **Python 3.13+** (SDK development; end users can install with Python 3.11+)
8
+ - [uv](https://docs.astral.sh/uv/) for installs and scripts
9
+ - `.python-version` in the repo pins Python 3.13
10
+
11
+ ## Development Setup
12
+
13
+ ```bash
14
+ make install # uv sync (editable install + dev + all extras)
15
+ make test # pytest
16
+ make lint # ruff check
17
+ make typecheck # mypy
18
+ make build # build wheel + sdist
19
+ ```
20
+
21
+ Other targets: `make format`, `make inject-defaults`, `make publish`, `make help`.
22
+
23
+ ## Testing the Package as if Installed from PyPI
24
+
25
+ To verify the library works the same way end users get it (from a built wheel, not editable):
26
+
27
+ 1. **Install tools and build the package**
28
+ ```bash
29
+ make install
30
+ make build
31
+ ```
32
+
33
+ 2. **Create a clean environment and install only the wheel** (no repo code)
34
+ ```bash
35
+ uv venv .venv-pypi-test --python 3.13
36
+ uv pip install --python .venv-pypi-test/bin/python dist/duckgresql-*.whl
37
+ ```
38
+
39
+ 3. **Use it like a normal install**
40
+ ```bash
41
+ .venv-pypi-test/bin/python -c "
42
+ import duckgresql
43
+ print('Version:', duckgresql.__version__)
44
+ # Optional: connect if you have a running DuckGresQL server
45
+ # conn = duckgresql.connect(token='dkgql_...', database='mydb')
46
+ # print(conn.execute('SELECT 1').fetchone())
47
+ "
48
+ ```
49
+ Or run your own script: `.venv-pypi-test/bin/python your_script.py`
50
+
51
+ 4. **Optional: match production defaults before building**
52
+ If you want the same defaults as the published package, set release env vars and inject before building:
53
+ ```bash
54
+ export DUCKGRESQL_RELEASE_HOST=api.duckgresql.com
55
+ export DUCKGRESQL_RELEASE_FLIGHT_PORT=47470
56
+ export DUCKGRESQL_RELEASE_REST_PORT=3100
57
+ make inject-defaults
58
+ make build
59
+ ```
60
+ Then repeat steps 2–3 with the new `dist/` wheel.
61
+
62
+ You can also run **`make test-pypi-install`** to build, create `.venv-pypi-test`, install the wheel, and run a quick import/version check.
63
+
64
+ ## Version Scheme
65
+
66
+ The SDK version (`1.4.4.0`) tracks DuckDB version `1.4.4`, with the last digit as the SDK patch version.
67
+
68
+ ## Publishing
69
+
70
+ See [RELEASING.md](RELEASING.md) for instructions on publishing new versions to PyPI.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DuckGresQL Team
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.
@@ -0,0 +1,55 @@
1
+ .PHONY: help install test lint format typecheck inject-defaults build publish test-pypi-install
2
+
3
+ # Default target
4
+ .DEFAULT_GOAL := help
5
+
6
+ # UV uses .python-version (3.13) and installs that Python if missing. No need to choose a version.
7
+ UV ?= uv
8
+
9
+ ##@ Python SDK
10
+
11
+ help: ## Display this help message
12
+ @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
13
+
14
+ install: ## Sync deps with UV (editable install + dev + all extras; uses .python-version; UV installs Python 3.13 if needed)
15
+ $(UV) sync --extra dev --extra all
16
+
17
+ test: ## Run unit tests
18
+ $(UV) run pytest tests/ -v
19
+
20
+ lint: ## Lint code
21
+ $(UV) run ruff check src/ tests/
22
+
23
+ format: ## Format code
24
+ $(UV) run ruff format src/ tests/
25
+
26
+ typecheck: ## Type-check with mypy
27
+ $(UV) run mypy src/duckgresql/
28
+
29
+ inject-defaults: ## Inject release defaults into _config.py (requires DUCKGRESQL_RELEASE_* env vars)
30
+ $(UV) run python scripts/inject_release_defaults.py
31
+
32
+ build: ## Build package
33
+ $(UV) run python -m build
34
+
35
+ publish: ## Publish to PyPI (requires TWINE_PASSWORD or trusted publishing)
36
+ $(UV) run python -m twine upload dist/*
37
+
38
+ test-pypi-install: ## Build, install wheel into .venv-pypi-test, and verify (simulate PyPI install)
39
+ $(UV) run python -m build
40
+ $(UV) venv .venv-pypi-test --python 3.13
41
+ $(UV) pip install --python .venv-pypi-test/bin/python dist/duckgresql-*.whl
42
+ @echo "--- Done. Use: .venv-pypi-test/bin/python your_script.py <sql_query> ---"
43
+
44
+ test-pypi-install-prod: ## Like test-pypi-install but with production defaults from .env.prod. Usage: make test-pypi-install-prod Q="SELECT 1"
45
+ @test -f .env.prod || { echo "Error: .env.prod not found. Copy .env.prod.example and fill in values."; exit 1; }
46
+ @test -n "$(Q)" || { echo "Error: query required. Usage: make test-pypi-install-prod Q=\"SELECT 1\""; exit 1; }
47
+ @# Load .env.prod, inject production config, build, restore dev config, then install
48
+ set -a && . ./.env.prod && set +a && $(UV) run python scripts/inject_release_defaults.py
49
+ $(UV) run python -m build
50
+ git checkout src/duckgresql/_config.py
51
+ rm -rf .venv-pypi-test
52
+ $(UV) venv .venv-pypi-test --python 3.13
53
+ $(UV) pip install --python .venv-pypi-test/bin/python dist/duckgresql-*.whl
54
+ $(UV) pip install --python .venv-pypi-test/bin/python python-dotenv
55
+ .venv-pypi-test/bin/python example/run_query.py --env .env.prod "$(Q)"
@@ -0,0 +1,160 @@
1
+ Metadata-Version: 2.4
2
+ Name: duckgresql
3
+ Version: 1.4.4.0
4
+ Summary: Python SDK for DuckGresQL — DuckDB-compatible API for remote databases
5
+ Project-URL: Homepage, https://github.com/duckgresql/duckgresql
6
+ Project-URL: Documentation, https://github.com/duckgresql/duckgresql/tree/main/sdk/python
7
+ Project-URL: Repository, https://github.com/duckgresql/duckgresql
8
+ Author: DuckGresQL Team
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Database
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: httpx>=0.28
22
+ Requires-Dist: pyarrow>=18.0.0
23
+ Requires-Dist: python-dotenv>=1.0.0
24
+ Provides-Extra: all
25
+ Requires-Dist: numpy>=1.26; extra == 'all'
26
+ Requires-Dist: pandas>=2.0; extra == 'all'
27
+ Provides-Extra: dev
28
+ Requires-Dist: build; extra == 'dev'
29
+ Requires-Dist: mypy>=1.13; extra == 'dev'
30
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
31
+ Requires-Dist: pytest>=8.0; extra == 'dev'
32
+ Requires-Dist: ruff>=0.8; extra == 'dev'
33
+ Provides-Extra: numpy
34
+ Requires-Dist: numpy>=1.26; extra == 'numpy'
35
+ Provides-Extra: pandas
36
+ Requires-Dist: pandas>=2.0; extra == 'pandas'
37
+ Description-Content-Type: text/markdown
38
+
39
+ # DuckGresQL Python SDK
40
+
41
+ Python client for [DuckGresQL](https://github.com/jjballano/duckgresql) — a DuckDB-compatible API for remote databases. Uses **Arrow Flight SQL** for fast query execution and a REST API for async job management.
42
+
43
+ ## Installation
44
+
45
+ Requires Python 3.11+
46
+
47
+ ```bash
48
+ pip install duckgresql
49
+ ```
50
+
51
+ With optional extras:
52
+
53
+ ```bash
54
+ pip install duckgresql[pandas] # adds fetchdf() support
55
+ pip install duckgresql[all] # pandas + numpy
56
+ ```
57
+
58
+ ## Quick Start
59
+
60
+ ### Synchronous
61
+
62
+ ```python
63
+ import duckgresql
64
+
65
+ conn = duckgresql.connect(
66
+ token="dkgql_your_api_token",
67
+ database="my_database",
68
+ )
69
+
70
+ # Execute a query
71
+ result = conn.execute("SELECT * FROM users LIMIT 10")
72
+ print(result.fetchall())
73
+
74
+ # Get a pandas DataFrame
75
+ df = conn.execute("SELECT * FROM sales").fetchdf()
76
+
77
+ # DML
78
+ result = conn.execute("INSERT INTO users (name) VALUES ('Alice')")
79
+ print(result.rowcount) # affected rows
80
+
81
+ conn.close()
82
+ ```
83
+
84
+ ### Async
85
+
86
+ ```python
87
+ import asyncio
88
+ import duckgresql
89
+
90
+ async def main():
91
+ conn = await duckgresql.connect_async(
92
+ token="dkgql_your_api_token",
93
+ database="my_database",
94
+ )
95
+
96
+ result = await conn.execute("SELECT * FROM users")
97
+ print(result.fetchall())
98
+
99
+ await conn.close()
100
+
101
+ asyncio.run(main())
102
+ ```
103
+
104
+ ### Context Manager
105
+
106
+ ```python
107
+ with duckgresql.connect(token="...", database="...") as conn:
108
+ result = conn.execute("SELECT 1")
109
+ print(result.fetchone())
110
+ ```
111
+
112
+ ### Async Jobs (Long-Running Queries)
113
+
114
+ ```python
115
+ conn = duckgresql.connect(token="...", database="...")
116
+
117
+ job = conn.execute_async("SELECT * FROM very_large_table")
118
+ print(f"Job submitted: {job.job_id}")
119
+
120
+ # Poll until done (with exponential backoff)
121
+ result = job.result(timeout=600)
122
+ print(result.fetchall())
123
+ ```
124
+
125
+ ## Connection Parameters
126
+
127
+ | Parameter | Default | Description |
128
+ |-----------|---------|-------------|
129
+ | `token` | *required* | API token (`dkgql_…`) |
130
+ | `database` | *required* | Database name or UUID |
131
+
132
+ ## Result Methods
133
+
134
+ | Method | Returns | Description |
135
+ |--------|---------|-------------|
136
+ | `fetchone()` | `tuple \| None` | Next row |
137
+ | `fetchmany(size)` | `list[tuple]` | Up to *size* rows |
138
+ | `fetchall()` | `list[tuple]` | All remaining rows |
139
+ | `fetchdf()` | `DataFrame` | Pandas DataFrame (requires `pandas`) |
140
+ | `fetchnumpy()` | `dict[str, ndarray]` | NumPy arrays (requires `numpy`) |
141
+ | `fetch_arrow_table()` | `pyarrow.Table` | Zero-copy Arrow table |
142
+
143
+ ## Result Properties
144
+
145
+ | Property | Type | Description |
146
+ |----------|------|-------------|
147
+ | `description` | `list \| None` | DB-API 2.0 column metadata |
148
+ | `rowcount` | `int` | Row count or affected rows |
149
+ | `columns` | `list[str]` | Column names |
150
+
151
+ ## Architecture
152
+
153
+ - **Arrow Flight SQL (gRPC)** — Primary transport for `execute()`. Fast, columnar, zero-copy.
154
+ - **REST API** — Used only for `execute_async()` (job submission/polling), since Flight SQL has no native job queue pattern.
155
+
156
+ Both transports authenticate via the same API token. Flight SQL uses BasicAuth handshake; REST uses the `/connect` endpoint to exchange the token for a session token.
157
+
158
+ ---
159
+
160
+ **Developing the SDK?** See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, testing, building, and publishing.
@@ -0,0 +1,122 @@
1
+ # DuckGresQL Python SDK
2
+
3
+ Python client for [DuckGresQL](https://github.com/jjballano/duckgresql) — a DuckDB-compatible API for remote databases. Uses **Arrow Flight SQL** for fast query execution and a REST API for async job management.
4
+
5
+ ## Installation
6
+
7
+ Requires Python 3.11+
8
+
9
+ ```bash
10
+ pip install duckgresql
11
+ ```
12
+
13
+ With optional extras:
14
+
15
+ ```bash
16
+ pip install duckgresql[pandas] # adds fetchdf() support
17
+ pip install duckgresql[all] # pandas + numpy
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ### Synchronous
23
+
24
+ ```python
25
+ import duckgresql
26
+
27
+ conn = duckgresql.connect(
28
+ token="dkgql_your_api_token",
29
+ database="my_database",
30
+ )
31
+
32
+ # Execute a query
33
+ result = conn.execute("SELECT * FROM users LIMIT 10")
34
+ print(result.fetchall())
35
+
36
+ # Get a pandas DataFrame
37
+ df = conn.execute("SELECT * FROM sales").fetchdf()
38
+
39
+ # DML
40
+ result = conn.execute("INSERT INTO users (name) VALUES ('Alice')")
41
+ print(result.rowcount) # affected rows
42
+
43
+ conn.close()
44
+ ```
45
+
46
+ ### Async
47
+
48
+ ```python
49
+ import asyncio
50
+ import duckgresql
51
+
52
+ async def main():
53
+ conn = await duckgresql.connect_async(
54
+ token="dkgql_your_api_token",
55
+ database="my_database",
56
+ )
57
+
58
+ result = await conn.execute("SELECT * FROM users")
59
+ print(result.fetchall())
60
+
61
+ await conn.close()
62
+
63
+ asyncio.run(main())
64
+ ```
65
+
66
+ ### Context Manager
67
+
68
+ ```python
69
+ with duckgresql.connect(token="...", database="...") as conn:
70
+ result = conn.execute("SELECT 1")
71
+ print(result.fetchone())
72
+ ```
73
+
74
+ ### Async Jobs (Long-Running Queries)
75
+
76
+ ```python
77
+ conn = duckgresql.connect(token="...", database="...")
78
+
79
+ job = conn.execute_async("SELECT * FROM very_large_table")
80
+ print(f"Job submitted: {job.job_id}")
81
+
82
+ # Poll until done (with exponential backoff)
83
+ result = job.result(timeout=600)
84
+ print(result.fetchall())
85
+ ```
86
+
87
+ ## Connection Parameters
88
+
89
+ | Parameter | Default | Description |
90
+ |-----------|---------|-------------|
91
+ | `token` | *required* | API token (`dkgql_…`) |
92
+ | `database` | *required* | Database name or UUID |
93
+
94
+ ## Result Methods
95
+
96
+ | Method | Returns | Description |
97
+ |--------|---------|-------------|
98
+ | `fetchone()` | `tuple \| None` | Next row |
99
+ | `fetchmany(size)` | `list[tuple]` | Up to *size* rows |
100
+ | `fetchall()` | `list[tuple]` | All remaining rows |
101
+ | `fetchdf()` | `DataFrame` | Pandas DataFrame (requires `pandas`) |
102
+ | `fetchnumpy()` | `dict[str, ndarray]` | NumPy arrays (requires `numpy`) |
103
+ | `fetch_arrow_table()` | `pyarrow.Table` | Zero-copy Arrow table |
104
+
105
+ ## Result Properties
106
+
107
+ | Property | Type | Description |
108
+ |----------|------|-------------|
109
+ | `description` | `list \| None` | DB-API 2.0 column metadata |
110
+ | `rowcount` | `int` | Row count or affected rows |
111
+ | `columns` | `list[str]` | Column names |
112
+
113
+ ## Architecture
114
+
115
+ - **Arrow Flight SQL (gRPC)** — Primary transport for `execute()`. Fast, columnar, zero-copy.
116
+ - **REST API** — Used only for `execute_async()` (job submission/polling), since Flight SQL has no native job queue pattern.
117
+
118
+ Both transports authenticate via the same API token. Flight SQL uses BasicAuth handshake; REST uses the `/connect` endpoint to exchange the token for a session token.
119
+
120
+ ---
121
+
122
+ **Developing the SDK?** See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, testing, building, and publishing.