Skip to content

Commit fcc9551

Browse files
singaraionaclaude
andcommitted
Add PyPI packaging: scikit-build-core, cibuildwheel CI, MIT license
- pyproject.toml: scikit-build-core backend, teide v0.1.0 metadata - CMakeLists.txt: TEIDE_PORTABLE option (-mtune=generic), install() target - __init__.py: __version__, wheel-first lib discovery, re-export high-level API - wheels.yml: cibuildwheel for manylinux + macOS, PyPI publish on v* tags - LICENSE, README.md, MANIFEST.in Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 835dc63 commit fcc9551

7 files changed

Lines changed: 230 additions & 14 deletions

File tree

.github/workflows/wheels.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Build wheels
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
workflow_dispatch:
8+
9+
jobs:
10+
build_wheels:
11+
name: Build ${{ matrix.os }} ${{ matrix.arch }}
12+
runs-on: ${{ matrix.os }}
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
include:
17+
- os: ubuntu-latest
18+
arch: x86_64
19+
- os: ubuntu-latest
20+
arch: aarch64
21+
- os: macos-13
22+
arch: x86_64
23+
- os: macos-14
24+
arch: arm64
25+
26+
steps:
27+
- uses: actions/checkout@v4
28+
29+
- name: Set up QEMU (aarch64)
30+
if: matrix.arch == 'aarch64'
31+
uses: docker/setup-qemu-action@v3
32+
with:
33+
platforms: arm64
34+
35+
- name: Build wheels
36+
uses: pypa/cibuildwheel@v2.21
37+
env:
38+
CIBW_ARCHS: ${{ matrix.arch }}
39+
CIBW_SKIP: "pp* *-musllinux_*"
40+
CIBW_TEST_COMMAND: >
41+
python -c "from teide import Context; print('OK')"
42+
43+
- uses: actions/upload-artifact@v4
44+
with:
45+
name: wheels-${{ matrix.os }}-${{ matrix.arch }}
46+
path: wheelhouse/*.whl
47+
48+
build_sdist:
49+
name: Build sdist
50+
runs-on: ubuntu-latest
51+
steps:
52+
- uses: actions/checkout@v4
53+
- name: Build sdist
54+
run: pipx run build --sdist
55+
- uses: actions/upload-artifact@v4
56+
with:
57+
name: sdist
58+
path: dist/*.tar.gz
59+
60+
publish:
61+
name: Publish to PyPI
62+
needs: [build_wheels, build_sdist]
63+
runs-on: ubuntu-latest
64+
if: startsWith(github.ref, 'refs/tags/v')
65+
permissions:
66+
id-token: write
67+
steps:
68+
- uses: actions/download-artifact@v4
69+
with:
70+
path: dist
71+
merge-multiple: true
72+
- uses: pypa/gh-action-pypi-publish@release/v1

CMakeLists.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ set(CMAKE_C_STANDARD 17)
55
set(CMAKE_C_STANDARD_REQUIRED ON)
66
set(CMAKE_C_EXTENSIONS OFF)
77

8+
option(TEIDE_PORTABLE "Build portable binary (no -march=native)" OFF)
9+
810
# Collect all source files under src/
911
file(GLOB_RECURSE TEIDE_SOURCES "src/**/*.c")
1012

@@ -25,7 +27,11 @@ if(MSVC)
2527
else()
2628
set(TEIDE_WARNINGS -Wall -Wextra -Wpedantic -Werror)
2729
set(TEIDE_DEBUG_FLAGS -O0 -g -fsanitize=address,undefined)
28-
set(TEIDE_RELEASE_FLAGS -O3 -march=native -DNDEBUG)
30+
if(TEIDE_PORTABLE)
31+
set(TEIDE_RELEASE_FLAGS -O3 -mtune=generic -DNDEBUG)
32+
else()
33+
set(TEIDE_RELEASE_FLAGS -O3 -march=native -DNDEBUG)
34+
endif()
2935
endif()
3036

3137
# Apply flags to both library targets
@@ -71,3 +77,6 @@ if(TEST_SOURCES)
7177
endif()
7278
add_test(NAME test_teide COMMAND test_teide)
7379
endif()
80+
81+
# Install target for scikit-build wheel packaging
82+
install(TARGETS teide LIBRARY DESTINATION teide)

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Teide Contributors
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.

MANIFEST.in

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
include CMakeLists.txt
2+
include LICENSE
3+
include README.md
4+
recursive-include src *.c *.h
5+
recursive-include include *.h
6+
recursive-include bindings/python/teide *.py
7+
prune build
8+
prune build_release
9+
prune build_debug_noasan
10+
prune build_tsan

README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Teide
2+
3+
Fast columnar dataframe library for Python, powered by a zero-dependency C17 engine with lazy fusion execution.
4+
5+
## Install
6+
7+
```bash
8+
pip install teide
9+
```
10+
11+
> **Note:** v0.1.0 supports Linux and macOS only. Windows support is planned.
12+
13+
## Quick Start
14+
15+
```python
16+
from teide import Context, col
17+
18+
with Context() as ctx:
19+
df = ctx.read_csv("data.csv")
20+
21+
result = (
22+
df.filter(col("price") > 0)
23+
.group_by("category")
24+
.agg(col("price").sum(), col("price").mean())
25+
.sort("price_sum", descending=True)
26+
.collect()
27+
)
28+
29+
print(result)
30+
```
31+
32+
## Features
33+
34+
- **Lazy evaluation** with automatic query optimization (predicate pushdown, CSE, operator fusion)
35+
- **Morsel-driven parallel execution** across all cores
36+
- **Zero-copy** NumPy interop for numeric columns
37+
- **Fast CSV reader** — parallel parsing, mmap I/O
38+
- **Columnar storage** — splayed tables, date-partitioned datasets
39+
- **Pure C17 engine** — no external dependencies, minimal memory overhead
40+
41+
## License
42+
43+
MIT

bindings/python/teide/__init__.py

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
"""
2-
Teide — Low-level ctypes wrapper for libteide.
2+
Teide — Fast columnar dataframe library for Python.
33
44
Usage:
5-
from teide import TeideLib
6-
lib = TeideLib() # loads libteide.so
7-
lib.sym_init()
8-
# ... use the C API ...
9-
lib.sym_destroy()
10-
lib.arena_destroy_all()
5+
from teide import Context, col, lit
6+
7+
with Context() as ctx:
8+
df = ctx.read_csv("data.csv")
9+
result = df.group_by("id1").agg(col("v1").sum()).collect()
10+
print(result)
1111
"""
1212

13+
__version__ = "0.1.0"
14+
1315
import ctypes
1416
import os
1517
import sys
@@ -21,24 +23,42 @@
2123

2224

2325
def _find_lib():
24-
"""Find libteide.so, checking TEIDE_LIB env var first."""
26+
"""Find libteide shared library.
27+
28+
Search order:
29+
1. Same directory as this __init__.py (wheel-bundled layout)
30+
2. TEIDE_LIB environment variable
31+
3. Common build directories relative to source tree
32+
"""
33+
_pkg_dir = os.path.dirname(__file__)
34+
_lib_names = ["libteide.so", "libteide.dylib"]
35+
36+
# 1. Wheel-bundled: libteide.so sits next to __init__.py
37+
for name in _lib_names:
38+
path = os.path.join(_pkg_dir, name)
39+
if os.path.exists(path):
40+
return os.path.abspath(path)
41+
42+
# 2. Explicit env var
2543
env_path = os.environ.get("TEIDE_LIB")
2644
if env_path and os.path.exists(env_path):
2745
return env_path
2846

29-
# Search common locations
47+
# 3. Source-tree build directories
3048
search_dirs = [
31-
os.path.join(os.path.dirname(__file__), "..", "..", "..", "build_release"),
32-
os.path.join(os.path.dirname(__file__), "..", "..", "..", "build"),
49+
os.path.join(_pkg_dir, "..", "..", "..", "build_release"),
50+
os.path.join(_pkg_dir, "..", "..", "..", "build"),
3351
".",
3452
]
3553
for d in search_dirs:
36-
for name in ["libteide.so", "libteide.dylib"]:
54+
for name in _lib_names:
3755
path = os.path.join(d, name)
3856
if os.path.exists(path):
3957
return os.path.abspath(path)
4058

41-
raise OSError("Cannot find libteide.so. Set TEIDE_LIB environment variable.")
59+
raise OSError(
60+
"Cannot find libteide.so. Install via 'pip install teide' or set TEIDE_LIB."
61+
)
4262

4363

4464
class TeideLib:
@@ -422,3 +442,6 @@ def part_load(self, db_root, table_name):
422442
OP_AVG = 55
423443
OP_FIRST = 56
424444
OP_LAST = 57
445+
446+
# Re-export high-level API so users can do: from teide import Context, col, lit
447+
from teide.api import Context, col, lit, Expr, Table, Series, Query # noqa: E402,F401

pyproject.toml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[build-system]
2+
requires = ["scikit-build-core>=0.5"]
3+
build-backend = "scikit_build_core.build"
4+
5+
[project]
6+
name = "teide"
7+
version = "0.1.0"
8+
description = "Fast columnar dataframe library for Python, powered by a zero-dependency C17 engine"
9+
readme = "README.md"
10+
license = "MIT"
11+
requires-python = ">=3.8"
12+
authors = [{ name = "Teide Contributors" }]
13+
classifiers = [
14+
"Development Status :: 3 - Alpha",
15+
"Intended Audience :: Developers",
16+
"Intended Audience :: Science/Research",
17+
"License :: OSI Approved :: MIT License",
18+
"Operating System :: POSIX :: Linux",
19+
"Operating System :: MacOS",
20+
"Programming Language :: C",
21+
"Programming Language :: Python :: 3",
22+
"Programming Language :: Python :: 3.8",
23+
"Programming Language :: Python :: 3.9",
24+
"Programming Language :: Python :: 3.10",
25+
"Programming Language :: Python :: 3.11",
26+
"Programming Language :: Python :: 3.12",
27+
"Programming Language :: Python :: 3.13",
28+
"Topic :: Scientific/Engineering",
29+
]
30+
31+
[project.urls]
32+
Homepage = "https://github.com/teide-project/teide"
33+
Issues = "https://github.com/teide-project/teide/issues"
34+
35+
[tool.scikit-build]
36+
wheel.packages = ["bindings/python/teide"]
37+
cmake.build-type = "Release"
38+
cmake.args = ["-DTEIDE_PORTABLE=ON"]

0 commit comments

Comments
 (0)