Skip to content

Commit e634d97

Browse files
committed
Dataframe/Polars: Add test wrapper and CI configuration
1 parent 7163302 commit e634d97

File tree

7 files changed

+200
-0
lines changed

7 files changed

+200
-0
lines changed

.github/dependabot.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ updates:
3333
schedule:
3434
interval: "daily"
3535

36+
- directory: "/by-dataframe/polars"
37+
package-ecosystem: "pip"
38+
schedule:
39+
interval: "daily"
40+
3641
- directory: "/by-language/csharp-efcore"
3742
package-ecosystem: "nuget"
3843
schedule:
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: Polars
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- '.github/workflows/dataframe-polars.yml'
7+
- 'by-dataframe/polars/**'
8+
- '/requirements.txt'
9+
push:
10+
branches: [ main ]
11+
paths:
12+
- '.github/workflows/dataframe-polars.yml'
13+
- 'by-dataframe/polars/**'
14+
- '/requirements.txt'
15+
16+
# Allow job to be triggered manually.
17+
workflow_dispatch:
18+
19+
# Run job each night after CrateDB nightly has been published.
20+
schedule:
21+
- cron: '0 3 * * *'
22+
23+
# Cancel in-progress jobs when pushing to the same branch.
24+
concurrency:
25+
cancel-in-progress: true
26+
group: ${{ github.workflow }}-${{ github.ref }}
27+
28+
jobs:
29+
test:
30+
name: "
31+
Python: ${{ matrix.python-version }}
32+
CrateDB: ${{ matrix.cratedb-version }}
33+
on ${{ matrix.os }}"
34+
runs-on: ${{ matrix.os }}
35+
strategy:
36+
fail-fast: false
37+
matrix:
38+
os: [ 'ubuntu-latest' ]
39+
python-version: [
40+
'3.10',
41+
'3.13',
42+
]
43+
cratedb-version: [ 'nightly' ]
44+
45+
services:
46+
cratedb:
47+
image: crate/crate:${{ matrix.cratedb-version }}
48+
ports:
49+
- 4200:4200
50+
- 5432:5432
51+
env:
52+
CRATE_HEAP_SIZE: 4g
53+
54+
steps:
55+
56+
- name: Acquire sources
57+
uses: actions/checkout@v5
58+
59+
- name: Set up Python
60+
uses: actions/setup-python@v6
61+
with:
62+
python-version: ${{ matrix.python-version }}
63+
architecture: x64
64+
cache: 'pip'
65+
cache-dependency-path: |
66+
by-dataframe/polars/requirements.txt
67+
by-dataframe/polars/requirements-dev.txt
68+
69+
- name: Set up uv
70+
uses: astral-sh/setup-uv@v7
71+
72+
- name: Validate by-dataframe/polars
73+
run: |
74+
uv run --with=pueblo ngr test --accept-no-venv by-dataframe/polars

by-dataframe/polars/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Connect to CrateDB and CrateDB Cloud using Polars
2+
3+
## About
4+
5+
Example programs demonstrating connectivity with [Polars] and [CrateDB].
6+
7+
## Usage
8+
9+
```shell
10+
python read_pg.py
11+
python read_sqlalchemy.py
12+
python write_pg.py
13+
python write_sqlalchemy.py
14+
python write_adbc.py
15+
python one_db_to_another.py
16+
```
17+
18+
> [!TIP]
19+
> For more information, please refer to the header sections of each of the
20+
provided example programs.
21+
22+
## Tests
23+
24+
To test the accompanied example programs all at once, invoke the software tests:
25+
```shell
26+
pytest
27+
```
28+
29+
30+
[CrateDB]: https://github.com/crate/crate
31+
[CrateDB Cloud]: https://console.cratedb.cloud/
32+
[Polars]: https://pola.rs/

by-dataframe/polars/pyproject.toml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[tool.pytest.ini_options]
2+
minversion = "2.0"
3+
addopts = """
4+
-rfEX -p pytester --strict-markers --verbosity=3
5+
--cov --cov-report=term-missing
6+
--capture=no
7+
"""
8+
log_level = "DEBUG"
9+
log_cli_level = "DEBUG"
10+
testpaths = ["*.py"]
11+
xfail_strict = true
12+
markers = [
13+
]
14+
15+
16+
[tool.coverage.run]
17+
branch = false
18+
omit = [
19+
"test*",
20+
]
21+
22+
[tool.coverage.report]
23+
fail_under = 0
24+
show_missing = true
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pytest<9
2+
pytest-cov<8
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
adbc-driver-postgresql<1.9
2+
connectorx>=0.4.5a1
3+
pandas<2.4
4+
polars<1.36
5+
pyarrow<23
6+
sqlalchemy-cratedb>=0.42.0.dev2

by-dataframe/polars/test.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import shlex
2+
import subprocess
3+
import pytest
4+
import sqlalchemy as sa
5+
6+
7+
DBURI = "crate://localhost:4200"
8+
9+
10+
def run(command: str):
11+
subprocess.check_call(shlex.split(command))
12+
13+
14+
def test_read_pg():
15+
cmd = "time python read_pg.py"
16+
run(cmd)
17+
18+
19+
def test_read_sqlalchemy():
20+
cmd = "time python read_sqlalchemy.py"
21+
run(cmd)
22+
23+
24+
@pytest.mark.skip
25+
def test_write_adbc(reset_table):
26+
cmd = "time python write_adbc.py"
27+
run(cmd)
28+
assert get_table_cardinality() == 20
29+
30+
31+
def test_write_sqlalchemy(reset_table):
32+
cmd = "time python write_sqlalchemy.py"
33+
run(cmd)
34+
assert get_table_cardinality() == 20
35+
36+
37+
@pytest.fixture
38+
def reset_table():
39+
"""Drop database tables used for testing."""
40+
engine = get_engine()
41+
with engine.connect() as conn:
42+
conn.exec_driver_sql("DROP TABLE IF EXISTS testdrive_polars;")
43+
44+
45+
def get_engine():
46+
"""Provide an SQLAlchemy `engine` instance."""
47+
return sa.create_engine(DBURI)
48+
49+
50+
def get_table_cardinality():
51+
"""Get number of records in table used for testing."""
52+
engine = get_engine()
53+
with engine.connect() as conn:
54+
conn.exec_driver_sql("REFRESH TABLE testdrive_polars;")
55+
result = conn.exec_driver_sql("SELECT COUNT(*) FROM testdrive_polars;")
56+
table_size = result.scalar_one()
57+
return table_size

0 commit comments

Comments
 (0)