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.
- duckgresql-1.4.4.0/.env.example +21 -0
- duckgresql-1.4.4.0/.env.prod.example +11 -0
- duckgresql-1.4.4.0/.github/workflows/check.yml +50 -0
- duckgresql-1.4.4.0/.github/workflows/release.yml +89 -0
- duckgresql-1.4.4.0/.gitignore +68 -0
- duckgresql-1.4.4.0/.python-version +1 -0
- duckgresql-1.4.4.0/CONTRIBUTING.md +70 -0
- duckgresql-1.4.4.0/LICENSE +21 -0
- duckgresql-1.4.4.0/Makefile +55 -0
- duckgresql-1.4.4.0/PKG-INFO +160 -0
- duckgresql-1.4.4.0/README.md +122 -0
- duckgresql-1.4.4.0/RELEASING.md +192 -0
- duckgresql-1.4.4.0/example/.env.example +18 -0
- duckgresql-1.4.4.0/example/run_query.py +67 -0
- duckgresql-1.4.4.0/pyproject.toml +80 -0
- duckgresql-1.4.4.0/scripts/inject_release_defaults.py +101 -0
- duckgresql-1.4.4.0/src/duckgresql/__init__.py +123 -0
- duckgresql-1.4.4.0/src/duckgresql/_config.py +13 -0
- duckgresql-1.4.4.0/src/duckgresql/_flight.py +152 -0
- duckgresql-1.4.4.0/src/duckgresql/_rest.py +125 -0
- duckgresql-1.4.4.0/src/duckgresql/_rest_async.py +119 -0
- duckgresql-1.4.4.0/src/duckgresql/_types.py +35 -0
- duckgresql-1.4.4.0/src/duckgresql/_version.py +1 -0
- duckgresql-1.4.4.0/src/duckgresql/async_connection.py +173 -0
- duckgresql-1.4.4.0/src/duckgresql/async_job.py +154 -0
- duckgresql-1.4.4.0/src/duckgresql/connection.py +172 -0
- duckgresql-1.4.4.0/src/duckgresql/exceptions.py +27 -0
- duckgresql-1.4.4.0/src/duckgresql/py.typed +0 -0
- duckgresql-1.4.4.0/src/duckgresql/result.py +128 -0
- duckgresql-1.4.4.0/tests/__init__.py +0 -0
- duckgresql-1.4.4.0/tests/conftest.py +67 -0
- duckgresql-1.4.4.0/tests/test_async_connection.py +77 -0
- duckgresql-1.4.4.0/tests/test_async_job.py +133 -0
- duckgresql-1.4.4.0/tests/test_config.py +174 -0
- duckgresql-1.4.4.0/tests/test_connection.py +132 -0
- duckgresql-1.4.4.0/tests/test_flight.py +67 -0
- duckgresql-1.4.4.0/tests/test_rest.py +117 -0
- duckgresql-1.4.4.0/tests/test_result.py +118 -0
- 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.
|