Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d61f9fe
stub expr crate
paleolimbot May 20, 2026
be81a2f
fix test
paleolimbot May 20, 2026
c69c873
prototype
paleolimbot May 29, 2026
9de055f
generate the build
paleolimbot May 29, 2026
d332e3a
maybe fix ci
paleolimbot May 29, 2026
793c82e
see if this works to fix test collection
paleolimbot May 29, 2026
f6cb718
more specific pytest invocation
paleolimbot Jun 2, 2026
66e9130
fix build option
paleolimbot Jun 2, 2026
626e908
fix some generated function issues
paleolimbot Jun 2, 2026
d4e9107
maybe fix doctest command
paleolimbot Jun 2, 2026
e816251
missing args
paleolimbot Jun 2, 2026
5617b32
context aware expressions
paleolimbot Jun 2, 2026
1b7f6b2
nicer error for when _ctx is None
paleolimbot Jun 2, 2026
9e00aa0
fix the function names
paleolimbot Jun 2, 2026
bb269c9
formatting
paleolimbot Jun 8, 2026
bc2826d
make pythonic
paleolimbot Jun 8, 2026
b29d9e7
add the builder
paleolimbot Jun 8, 2026
617865e
imports
paleolimbot Jun 8, 2026
d33e288
add toods
paleolimbot Jun 8, 2026
5dad2c7
versions and basic testing
paleolimbot Jun 9, 2026
27d8b6e
format, tidy
paleolimbot Jun 9, 2026
0e62690
tests
paleolimbot Jun 9, 2026
17268c8
fix circular import on build
paleolimbot Jun 9, 2026
20fcb24
no doctests yet
paleolimbot Jun 9, 2026
d7ca4e3
better readme
paleolimbot Jun 9, 2026
eb0f733
fix test
paleolimbot Jun 9, 2026
a3e6e33
add utils test
paleolimbot Jun 9, 2026
c2bfdfd
less weird mock factory
paleolimbot Jun 9, 2026
bafc9ec
Merge remote-tracking branch 'upstream/main' into python-expr
paleolimbot Jun 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,18 @@ jobs:
# Update this key to force a new cache (sync with packaging.yml)
prefix-key: "python-v3"

- name: Install
- name: Install sedonadb-expr
run: |
pip install -e "python/sedonadb-expr" -vv

- name: Install sedonadb
run: |
# Keep this export in sync with the export in dev/release/verify-release-candidate.sh
export MATURIN_PEP517_ARGS="--features s2geography"
pip install -e "python/sedonadb/[test]" -vv
# Unset so `--features s2geography` (sedonadb-only) doesn't
# carry into the plugin install.
unset MATURIN_PEP517_ARGS

- name: Install sedonadb-zarr
run: |
pip install -e "python/sedonadb-zarr/[test]" -vv

- name: Download minimal geoarrow-data assets
Expand All @@ -132,18 +136,23 @@ jobs:
run: |
docker compose up --wait --detach postgis

- name: Run tests
- name: Run tests (sedonadb)
env:
# Ensure that we don't skip tests that we didn't intend to
SEDONADB_PYTHON_NO_SKIP_TESTS: "true"
run: |
cd python
cd python/sedonadb
python -m pytest -vv

- name: Run doctests
- name: Run doctests (sedonadb)
run: |
cd python
python -m pytest --doctest-modules
cd python/sedonadb
python -m pytest --doctest-modules python/

- name: Run tests (sedonadb-expr)
run: |
cd python/sedonadb-expr
python -m pytest -vv

- name: Shutdown docker compose services
if: always()
Expand Down
76 changes: 76 additions & 0 deletions python/sedonadb-expr/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

# Generated files
python/sedonadb_expr/_version.py
python/sedonadb_expr/_generated/

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
*.egg

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# IDE
.idea/
.vscode/
*.swp
*.swo
38 changes: 38 additions & 0 deletions python/sedonadb-expr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!---
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->

# SedonaDB Expr

A standalone Python package for SedonaDB expressions. This is an optional
dependency of the `sedonadb` package that powers the type-specific accessors
without bloating the core package for non-interactive usage.

## Installation

```shell
pip install sedonadb-expr
```

## Example

```python
import sedonadb_expr

print(sedonadb_expr.__version__)
```
47 changes: 47 additions & 0 deletions python/sedonadb-expr/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

"""
Version source for hatchling - reads from workspace Cargo.toml.

This file is used by hatchling at build time to determine the version.
The build hook then generates a static _version.py inside the package.
"""

import re
from pathlib import Path


def get_version() -> str:
"""Read version from the workspace root Cargo.toml."""
here = Path(__file__).parent
cargo_toml = here.parent.parent / "Cargo.toml"

if not cargo_toml.exists():
raise FileNotFoundError(f"Could not find workspace Cargo.toml at {cargo_toml}")

content = cargo_toml.read_text()

match = re.search(
r'\[workspace\.package\].*?version\s*=\s*"([^"]+)"',
content,
re.DOTALL,
)
if match:
return match.group(1)

raise ValueError("Could not find workspace.package.version in Cargo.toml")
89 changes: 89 additions & 0 deletions python/sedonadb-expr/hatch_build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

"""
Hatch build hook for sedonadb-expr.

This hook runs during sdist and wheel builds to generate Python source
files from the docs/reference/sql documentation files.
"""

from __future__ import annotations

from pathlib import Path
from typing import Any

from hatchling.builders.hooks.plugin.interface import BuildHookInterface


class CustomBuildHook(BuildHookInterface):
"""Custom build hook that generates Python sources from SQL docs."""

PLUGIN_NAME = "custom"

def initialize(self, version: str, build_data: dict[str, Any]) -> None:
"""
Called before the build process starts.

Args:
version: The version being built
build_data: Mutable dict to modify build behavior
"""
# Import the _codegen module directly to avoid triggering __init__.py,
# which imports from _generated (which doesn't exist yet).
import importlib.util

here = Path(__file__).parent
codegen_path = here / "python" / "sedonadb_expr" / "_codegen.py"
spec = importlib.util.spec_from_file_location("_codegen", codegen_path)
codegen_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(codegen_module)

self._generate_version(version, codegen_module.LICENSE_HEADER)
self._generate_sources(codegen_module, here)

def _generate_version(self, version: str, license_header: str) -> None:
"""Generate _version.py with the static version string."""
here = Path(__file__).parent
version_file = here / "python" / "sedonadb_expr" / "_version.py"

content = f'''{license_header}
# Auto-generated at build time - do not edit
__version__ = "{version}"
'''
version_file.write_text(content)
self.app.display_info(f"Generated _version.py with version {version}")

def _generate_sources(self, codegen_module: Any, here: Path) -> None:
"""Generate Python source files from docs/reference/sql."""
generate_sources = codegen_module.generate_sources

docs_sql = here.parent.parent / "docs" / "reference" / "sql"
output_dir = here / "python" / "sedonadb_expr" / "_generated"

result = generate_sources(docs_sql, output_dir)

if result.total_functions == 0 and not docs_sql.exists():
self.app.display_warning(
f"docs/reference/sql not found at {docs_sql}, skipping generation"
)
return

self.app.display_info(
f"Generated {result.total_functions} functions total, "
f"{result.geo_method_count} geo methods"
)
56 changes: 56 additions & 0 deletions python/sedonadb-expr/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

[build-system]
requires = ["hatchling", "pyyaml"]
build-backend = "hatchling.build"

[project]
name = "sedonadb-expr"
readme = "README.md"
requires-python = ">=3.9"
classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
]
dynamic = ["version"]

[project.optional-dependencies]
test = [
"pytest",
"pyyaml",
]

[tool.hatch.version]
source = "code"
path = "_version.py"
expression = "get_version()"

[tool.hatch.build.targets.wheel]
packages = ["python/sedonadb_expr"]

[tool.hatch.build.targets.wheel.hooks.custom]
path = "hatch_build.py"

[tool.hatch.build.targets.sdist.hooks.custom]
path = "hatch_build.py"
26 changes: 26 additions & 0 deletions python/sedonadb-expr/python/sedonadb_expr/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

from sedonadb_expr._version import __version__
from sedonadb_expr._generated.geo_functions import GeoFunctions
from sedonadb_expr._generated.geo_methods import GeoMethods

__all__ = [
"__version__",
"GeoFunctions",
"GeoMethods",
]
Loading