Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
108 changes: 108 additions & 0 deletions .github/workflows/pr_build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: PR build validation

on:
pull_request:
branches: [master, "stable-[0-9]+.[0-9]+"]
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
name: Build PyMEOS CFFI on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-13, macos-14]
include:
- ld_prefix: "/usr/local"
- os: macos-14
ld_prefix: "/opt/homebrew"

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Derive MEOS branch from package version
id: meos_branch
shell: bash
run: |
python_version=$(sed -nE 's/^__version__ = "([^"]+)".*/\1/p' pymeos_cffi/__init__.py)
major_minor=$(echo "$python_version" | sed -nE 's/^([0-9]+\.[0-9]+).*/\1/p')
candidate="stable-${major_minor}"
if git ls-remote --exit-code https://github.com/MobilityDB/MobilityDB "$candidate" >/dev/null 2>&1; then
meos_branch=$candidate
else
meos_branch="master"
fi
echo "Package version $python_version => MEOS branch $meos_branch"
echo "meos_branch=$meos_branch" >> "$GITHUB_OUTPUT"

- name: Install MEOS build deps (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake postgresql-server-dev-16 \
libproj-dev libgeos-dev libgsl-dev libjson-c-dev

- name: Install MEOS build deps (macOS)
if: runner.os == 'macOS'
uses: tecolicom/actions-use-homebrew-tools@v1
with:
tools: cmake libpq proj json-c gsl geos

- name: Build and install MEOS
shell: bash
run: |
git clone --depth 1 --branch ${{ steps.meos_branch.outputs.meos_branch }} \
https://github.com/MobilityDB/MobilityDB
mkdir MobilityDB/build
cd MobilityDB/build
if [ "${{ runner.os }}" = "macOS" ]; then
export MACOSX_DEPLOYMENT_TARGET="${{ matrix.os == 'macos-14' && 14 || 13.6 }}"
fi
cmake .. -DMEOS=ON -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${{ matrix.ld_prefix }}
make -j
sudo make install

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"

- name: Install build dependencies
run: |
python -m pip install --upgrade pip
python -m pip install build cffi setuptools

- name: Build sdist
run: |
python -m build -s
ls -l dist

- name: Install from sdist
shell: bash
run: |
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${{ matrix.ld_prefix }}/lib
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:${{ matrix.ld_prefix }}/lib
pip install dist/pymeos_cffi-*.tar.gz

- name: Smoke-test CFFI binding
shell: bash
run: |
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${{ matrix.ld_prefix }}/lib
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:${{ matrix.ld_prefix }}/lib
python -c "
import pymeos_cffi
from pymeos_cffi import meos_initialize, meos_finalize
meos_initialize('UTC')
# Confirm a representative C function resolves
assert callable(pymeos_cffi.tstzspan_make), 'tstzspan_make missing'
meos_finalize()
print('PyMEOS CFFI build + smoke test OK on ${{ matrix.os }}')
"
2 changes: 1 addition & 1 deletion builder/build_header.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def get_defined_functions(library_path):

def remove_undefined_functions(content, so_path):
defined = get_defined_functions(so_path)
undefined_types = ["json_object"]
undefined_types = ["json_object", "GEOSContextHandle_t"]

def remove_if_not_defined(m):
function = m.group(0).split("(")[0].strip().split(" ")[-1].strip("*")
Expand Down
4 changes: 3 additions & 1 deletion builder/build_pymeos_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,9 @@ def is_result_parameter(function: str, parameter: Parameter) -> bool:
def is_output_parameter(function: str, parameter: Parameter) -> bool:
if parameter.name.endswith("_out"):
return True
if parameter.name == "count" and parameter.ptype.endswith("*'"):
# ``int *count`` is the canonical trailing-output pattern that returns
# an array's length; auto-detect it on name + raw ctype.
if parameter.name == "count" and parameter.ctype == "int *":
return True
return (function, parameter.name) in output_parameters

Expand Down
11 changes: 7 additions & 4 deletions builder/build_pymeos_functions_modifiers.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ def custom_array_modifier(function: str) -> str:

def textset_make_modifier(function: str) -> str:
function = array_parameter_modifier("values", "count")(function)
return function.replace("_ffi.cast('const text *', x)", "cstring2text(x)").replace(
"'list[const text]'", "list[str]"
return (
function.replace("_ffi.cast('const text *', x)", "cstring2text(x)")
.replace("_ffi.cast('text *', x)", "cstring2text(x)")
.replace("'list[const text]'", "list[str]")
.replace("'list[text]'", "list[str]")
)


Expand Down Expand Up @@ -77,8 +80,8 @@ def text2cstring_modifier(_: str) -> str:


def from_wkb_modifier(function: str, return_type: str) -> Callable[[str], str]:
return (
lambda _: f"""def {function}(wkb: bytes) -> '{return_type} *':
return lambda _: (
f"""def {function}(wkb: bytes) -> '{return_type} *':
wkb_converted = _ffi.new('uint8_t []', wkb)
result = _lib.{function}(wkb_converted, len(wkb))
return result if result != _ffi.NULL else None"""
Expand Down
Loading
Loading