diff --git a/core/wren-core-py/Cargo.toml b/core/wren-core-py/Cargo.toml index 43785d191..70b55f014 100644 --- a/core/wren-core-py/Cargo.toml +++ b/core/wren-core-py/Cargo.toml @@ -2,6 +2,9 @@ name = "wren-core-py" version = "0.1.0" edition = "2021" +description = "Python bindings for Wren Engine semantic layer (wren-core)" +license = "Apache-2.0" +repository = "https://github.com/Canner/wren-engine" include = ["/src", "pyproject.toml", "Cargo.toml", "Cargo.lock"] [lib] diff --git a/core/wren-core-py/README.md b/core/wren-core-py/README.md index 57ef83dde..fd31b7cf4 100644 --- a/core/wren-core-py/README.md +++ b/core/wren-core-py/README.md @@ -1,6 +1,32 @@ -# Wren Core Python binding +# Wren Core Python Binding -This is a python binding for [wren-core](../wren-core). It uses [PyO3](https://github.com/PyO3/pyo3) to build the required wheel for [ibis-server](../ibis-server/). +Python bindings for [wren-core](../wren-core), the Rust semantic engine behind [Wren Engine](https://github.com/Canner/wren-engine). Built with [PyO3](https://github.com/PyO3/pyo3) and [Maturin](https://github.com/PyO3/maturin). + +Wren Engine translates SQL queries through a semantic layer (MDL - Modeling Definition Language) and executes them against 22+ data sources (PostgreSQL, BigQuery, Snowflake, etc.). + +## Installation + +```bash +pip install wren-core-py +``` + +Requires Python >= 3.11. + +## Quick Start + +```python +from wren_core import SessionContext, to_manifest + +# Load an MDL manifest from a base64-encoded JSON string +base64_mdl_json = "" +manifest = to_manifest(base64_mdl_json) + +# Create a session context for query planning +ctx = SessionContext(manifest, remote_functions=[]) + +# Transform a SQL query through the semantic layer +planned_sql = ctx.transform_sql("SELECT * FROM my_model") +``` ## Developer Guide @@ -11,14 +37,31 @@ This is a python binding for [wren-core](../wren-core). It uses [PyO3](https://g - Install [poetry](https://github.com/python-poetry/poetry) - Install [casey/just](https://github.com/casey/just) -### Test and build -After install `casey/just`, you can use the following command to build or test: -- Execute `just install` to create Python venv and install dependencies. -- **Important**: Before testing Python, you need to build the Rust package by running `just develop`. -- Use `just test-rs` to test Rust only, and `just test-py` to test Python only. -- Use `just test` to test Rust and Python. -- Execute `just build` to build the Python package. You can find the wheel in the `target/wheels/` directory. +### Test and Build + +After installing `casey/just`, you can use the following commands: + +- `just install` — Create Python venv and install dependencies. +- `just develop` — Build the Rust package for local development (**required before running Python tests**). +- `just test-rs` — Run Rust tests only. +- `just test-py` — Run Python tests only. +- `just test` — Run both Rust and Python tests. +- `just build` — Build the Python wheel. Output goes to `target/wheels/`. ### Coding Style -Format via `just format` +Format via `just format`. + +### Publishing + +See `scripts/publish.sh` for local publishing to PyPI/TestPyPI: + +```bash +./scripts/publish.sh --build # Build wheel only +./scripts/publish.sh --test # Build + publish to TestPyPI +./scripts/publish.sh # Build + publish to PyPI +``` + +## License + +Apache-2.0 diff --git a/core/wren-core-py/poetry.lock b/core/wren-core-py/poetry.lock index 16310bf4c..9976d6104 100644 --- a/core/wren-core-py/poetry.lock +++ b/core/wren-core-py/poetry.lock @@ -150,4 +150,4 @@ files = [ [metadata] lock-version = "2.1" python-versions = ">=3.11" -content-hash = "038d17d7d6e90435edd346fa7552b6dcc7193d0f4b1a257e8b0da8c2720fe2bd" +content-hash = "3560f376f36040614abcd7694537b1de69e8fda39be75a63b213c2c2c857541f" diff --git a/core/wren-core-py/pyproject.toml b/core/wren-core-py/pyproject.toml index f5d27b9e5..81be99a8b 100644 --- a/core/wren-core-py/pyproject.toml +++ b/core/wren-core-py/pyproject.toml @@ -1,13 +1,34 @@ [project] name = "wren-core-py" -classifiers = ["Programming Language :: Python :: 3.11"] version = "0.1.0" +description = "Python bindings for Wren Engine semantic layer (wren-core)" +readme = "README.md" +requires-python = ">=3.11" +license = { text = "Apache-2.0" } +authors = [{ name = "Wren AI", email = "contact@getwren.ai" }] +keywords = ["sql", "semantic-layer", "data-modeling", "analytics", "wren", "wrenai", "datafusion"] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Rust", + "Topic :: Database", + "Topic :: Software Development :: Libraries :: Python Modules", +] + +[project.urls] +Homepage = "https://www.getwren.ai/" +Repository = "https://github.com/Canner/wren-engine" +Issues = "https://github.com/Canner/wren-engine/issues" [tool.poetry] name = "wren-core-py" version = "0.1.0" -description = "" -authors = ["Canner "] +description = "Python bindings for Wren Engine semantic layer (wren-core)" +authors = ["Wren AI "] [tool.poetry.dependencies] python = ">=3.11" diff --git a/core/wren-core-py/scripts/publish.sh b/core/wren-core-py/scripts/publish.sh new file mode 100755 index 000000000..962c71c31 --- /dev/null +++ b/core/wren-core-py/scripts/publish.sh @@ -0,0 +1,124 @@ +#!/usr/bin/env bash +# +# Build and publish wren-core-py to PyPI or TestPyPI. +# +# Usage: +# ./scripts/publish.sh # build + publish to PyPI +# ./scripts/publish.sh --test # build + publish to TestPyPI +# ./scripts/publish.sh --build # build only (no publish) +# +# Prerequisites: +# - Rust toolchain (rustup, cargo) +# - maturin (pip install maturin) +# - twine (pip install twine) +# +# Environment variables (optional): +# MATURIN_ARGS — extra args passed to maturin build (e.g. "--target x86_64-unknown-linux-gnu") +# +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +DIST_DIR="$PROJECT_DIR/dist" + +MODE="publish" # publish | test | build +REPOSITORY="pypi" + +while [[ $# -gt 0 ]]; do + case "$1" in + --test) + MODE="test" + REPOSITORY="testpypi" + shift + ;; + --build) + MODE="build" + shift + ;; + -h|--help) + echo "Usage: $0 [--test | --build | -h]" + echo "" + echo " (no flag) Build and publish to PyPI" + echo " --test Build and publish to TestPyPI" + echo " --build Build only, no publish" + echo " -h, --help Show this help" + exit 0 + ;; + *) + echo "Unknown option: $1" >&2 + exit 1 + ;; + esac +done + +cd "$PROJECT_DIR" + +# --- Check prerequisites --- +for cmd in cargo maturin; do + if ! command -v "$cmd" &>/dev/null; then + echo "Error: '$cmd' is not installed." >&2 + exit 1 + fi +done + +if [[ "$MODE" != "build" ]]; then + if ! command -v twine &>/dev/null; then + echo "Error: 'twine' is not installed. Run: pip install twine" >&2 + exit 1 + fi +fi + +# --- Read version from Cargo.toml --- +VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/') +echo "==> Building wren-core-py v${VERSION}" + +# --- Clean previous dist --- +rm -rf "$DIST_DIR" +mkdir -p "$DIST_DIR" + +# --- Build wheel --- +echo "==> Running maturin build --release" +maturin build --release --out "$DIST_DIR" ${MATURIN_ARGS:-} + +# --- Build sdist --- +echo "==> Running maturin sdist" +maturin sdist --out "$DIST_DIR" + +# --- List artifacts --- +echo "" +echo "==> Built artifacts:" +ls -lh "$DIST_DIR" + +# --- Validate --- +echo "" +echo "==> Validating with twine check" +if command -v twine &>/dev/null; then + twine check "$DIST_DIR"/* +elif [[ "$MODE" == "build" ]]; then + echo "Warning: twine not installed; skipping validation in build-only mode" +else + echo "Error: 'twine' is not installed. Run: pip install twine" >&2 + exit 1 +fi + +if [[ "$MODE" == "build" ]]; then + echo "" + echo "==> Build complete. Artifacts in: $DIST_DIR" + exit 0 +fi + +# --- Publish --- +echo "" +if [[ "$REPOSITORY" == "testpypi" ]]; then + echo "==> Publishing to TestPyPI" + echo " After upload, install with:" + echo " pip install --index-url https://test.pypi.org/simple/ wren-core-py" +else + echo "==> Publishing to PyPI" +fi +echo "" + +twine upload --repository "$REPOSITORY" "$DIST_DIR"/* + +echo "" +echo "==> Done! Published wren-core-py v${VERSION} to ${REPOSITORY}"