Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unpin Cython version #46

Merged
merged 5 commits into from
Aug 31, 2023
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/python.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
run: |
sudo apt-get install -y lcov
pip uninstall --yes geoarrow
pip install pytest-cov "Cython <= 0.29.36"
pip install pytest-cov Cython
pushd python

# Build with Cython + gcc coverage options
Expand Down
2 changes: 1 addition & 1 deletion python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ repository = "https://github.com/geoarrow/geoarrow-c"
requires = [
"setuptools >= 61.0.0",
"setuptools-scm",
"Cython <= 0.29.36"
"Cython"
]
build-backend = "setuptools.build_meta"
46 changes: 27 additions & 19 deletions python/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,50 +27,58 @@
# checkout or copy from ../dist if the caller doesn't have cmake available.
# Note that bootstrap.py won't exist if building from sdist.
this_dir = os.path.dirname(__file__)
bootstrap_py = os.path.join(this_dir, 'bootstrap.py')
bootstrap_py = os.path.join(this_dir, "bootstrap.py")
if os.path.exists(bootstrap_py):
subprocess.run([sys.executable, bootstrap_py])

vendor_dir = os.path.join(this_dir, 'src', 'geoarrow', 'geoarrow')
vendor_dir = os.path.join(this_dir, "src", "geoarrow", "geoarrow")
vendored_files = os.listdir(vendor_dir)
sources = [f'src/geoarrow/geoarrow/{f}' for f in vendored_files if f.endswith('.c')]
sources = [f"src/geoarrow/geoarrow/{f}" for f in vendored_files if f.endswith(".c")]


# Workaround because setuptools has no easy way to mix C and C++ sources
# if extra flags are required (e.g., -std=c++11 like we need here).
class build_ext_subclass(build_ext):
def build_extensions(self):
original__compile = self.compiler._compile

def new__compile(obj, src, ext, cc_args, extra_postargs, pp_opts):
if src.endswith('.c'):
if src.endswith(".c"):
extra_postargs = [s for s in extra_postargs if s != "-std=c++11"]
return original__compile(obj, src, ext, cc_args, extra_postargs, pp_opts)

self.compiler._compile = new__compile
try:
build_ext.build_extensions(self)
finally:
del self.compiler._compile


# Set some extra flags for compiling with coverage support
if os.getenv('GEOARROW_COVERAGE') == "1":
coverage_compile_args = ['--coverage']
coverage_link_args = ['--coverage']
coverage_define_macros = [("CYTHON_TRACE", 1)]
if os.getenv("GEOARROW_COVERAGE") == "1":
extra_compile_args = ["--coverage"]
extra_link_args = ["--coverage"]
extra_define_macros = [("CYTHON_TRACE", 1)]
elif os.getenv("GEOARROW_DEBUG_EXTENSION") == "1":
extra_compile_args = ["-g", "-O0"]
extra_link_args = []
extra_define_macros = []
else:
coverage_compile_args = []
coverage_link_args = []
coverage_define_macros = []
extra_compile_args = []
extra_link_args = []
extra_define_macros = []

setup(
ext_modules=[
Extension(
name='geoarrow._lib',
include_dirs=['src/geoarrow/geoarrow', 'src/geoarrow/geoarrow_python'],
language='c++',
sources=['src/geoarrow/_lib.pyx'] + sources,
extra_compile_args = ['-std=c++11'] + coverage_compile_args,
extra_link_args = [] + coverage_link_args,
define_macros= [] + coverage_define_macros
name="geoarrow._lib",
include_dirs=["src/geoarrow/geoarrow", "src/geoarrow/geoarrow_python"],
language="c++",
sources=["src/geoarrow/_lib.pyx"] + sources,
extra_compile_args=["-std=c++11"] + extra_compile_args,
extra_link_args=[] + extra_link_args,
define_macros=[] + extra_define_macros,
)
],
cmdclass = {"build_ext": build_ext_subclass}
cmdclass={"build_ext": build_ext_subclass},
)
94 changes: 62 additions & 32 deletions python/src/geoarrow/_lib.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,33 @@
const string& metadata)


class GeoArrowCException(RuntimeError):

def __init__(self, what, code, message=""):
self.what = what
self.code = code
self.message = message

if self.message == "":
super().__init__(f"{self.what} failed ({self.code})")
else:
super().__init__(f"{self.what} failed ({self.code}): {self.message}")


cdef class Error:
cdef GeoArrowError c_error

def __cinit__(self):
self.c_error.message[0] = 0

def raise_message(self, what, code):
raise GeoArrowCException(what, code, self.c_error.message.decode("UTF-8"))

@staticmethod
def raise_error(what, code):
raise GeoArrowCException(what, code, "")


cdef class SchemaHolder:
cdef ArrowSchema c_schema

Expand Down Expand Up @@ -394,61 +421,64 @@

cdef class CKernel:
cdef GeoArrowKernel c_kernel
cdef object cname_str

def __init__(self, const char* name):
cdef const char* cname = <const char*>name
self.cname_str = cname.decode("UTF-8")
cdef int result = GeoArrowKernelInit(&self.c_kernel, cname, NULL)
if result != GEOARROW_OK:
raise ValueError('GeoArrowKernelInit() failed')
Error.raise_error("GeoArrowKernelInit('{self.cname_str}'>)", result)

def __dealloc__(self):
if self.c_kernel.release != NULL:
self.c_kernel.release(&self.c_kernel)

def start(self, SchemaHolder schema, const char* options):
cdef GeoArrowError error
cdef Error error = Error()
out = SchemaHolder()
cdef int result = self.c_kernel.start(&self.c_kernel, &schema.c_schema,
options, &out.c_schema, &error)
options, &out.c_schema, &error.c_error)
if result != GEOARROW_OK:
raise ValueError(error.message)
error.raise_message(f"GeoArrowKernel<{self.cname_str}>::start()", result)

Check warning on line 443 in python/src/geoarrow/_lib.pyx

View check run for this annotation

Codecov / codecov/patch

python/src/geoarrow/_lib.pyx#L443

Added line #L443 was not covered by tests

return out

def push_batch(self, ArrayHolder array):
cdef GeoArrowError error
cdef Error error = Error()
out = ArrayHolder()
cdef int result
with nogil:
result = self.c_kernel.push_batch(&self.c_kernel, &array.c_array,
&out.c_array, &error)
&out.c_array, &error.c_error)
if result != GEOARROW_OK:
raise ValueError(error.message)
error.raise_message(f"GeoArrowKernel<{self.cname_str}>::push_batch()", result)

return out

def finish(self):
cdef GeoArrowError error
cdef Error error = Error()

Check warning on line 460 in python/src/geoarrow/_lib.pyx

View check run for this annotation

Codecov / codecov/patch

python/src/geoarrow/_lib.pyx#L460

Added line #L460 was not covered by tests
out = ArrayHolder()
cdef int result
with nogil:
result = self.c_kernel.finish(&self.c_kernel, &out.c_array, &error)
result = self.c_kernel.finish(&self.c_kernel, &out.c_array, &error.c_error)

Check warning on line 464 in python/src/geoarrow/_lib.pyx

View check run for this annotation

Codecov / codecov/patch

python/src/geoarrow/_lib.pyx#L464

Added line #L464 was not covered by tests
if result != GEOARROW_OK:
raise ValueError(error.message)
error.raise_message(f"GeoArrowKernel<{self.cname_str}>::finish()", result)

Check warning on line 466 in python/src/geoarrow/_lib.pyx

View check run for this annotation

Codecov / codecov/patch

python/src/geoarrow/_lib.pyx#L466

Added line #L466 was not covered by tests

def push_batch_agg(self, ArrayHolder array):
cdef GeoArrowError error
cdef Error error = Error()
cdef int result = self.c_kernel.push_batch(&self.c_kernel, &array.c_array,
NULL, &error)
NULL, &error.c_error)
if result != GEOARROW_OK:
raise ValueError(error.message)
error.raise_message(f"GeoArrowKernel<{self.cname_str}>::push_batch()", result)

def finish_agg(self):
cdef GeoArrowError error
cdef Error error = Error()
out = ArrayHolder()
cdef int result = self.c_kernel.finish(&self.c_kernel, &out.c_array, &error)
cdef int result = self.c_kernel.finish(&self.c_kernel, &out.c_array, &error.c_error)
if result != GEOARROW_OK:
raise ValueError(error.message)
error.raise_message(f"GeoArrowKernel<{self.cname_str}>::finish()", result)

Check warning on line 480 in python/src/geoarrow/_lib.pyx

View check run for this annotation

Codecov / codecov/patch

python/src/geoarrow/_lib.pyx#L480

Added line #L480 was not covered by tests

return out


Expand All @@ -459,12 +489,12 @@
def __init__(self, ArrayHolder array, SchemaHolder schema):
self._base = array

cdef GeoArrowError error
cdef int result = GeoArrowArrayViewInitFromSchema(&self.c_array_view, &schema.c_schema, &error)
cdef Error error = Error()
cdef int result = GeoArrowArrayViewInitFromSchema(&self.c_array_view, &schema.c_schema, &error.c_error)
if result != GEOARROW_OK:
raise ValueError(error.message.decode('UTF-8'))
error.raise_message("GeoArrowArrayViewInitFromSchema()", result)

Check warning on line 495 in python/src/geoarrow/_lib.pyx

View check run for this annotation

Codecov / codecov/patch

python/src/geoarrow/_lib.pyx#L495

Added line #L495 was not covered by tests

result = GeoArrowArrayViewSetArray(&self.c_array_view, &array.c_array, &error)
result = GeoArrowArrayViewSetArray(&self.c_array_view, &array.c_array, &error.c_error)
if result != GEOARROW_OK:
raise ValueError(error.message.decode('UTF-8'))

Expand Down Expand Up @@ -568,40 +598,40 @@

def __init__(self, SchemaHolder schema):
self._schema = schema
cdef GeoArrowError error
cdef int result = GeoArrowBuilderInitFromSchema(&self.c_builder, &schema.c_schema, &error)
cdef Error error = Error()
cdef int result = GeoArrowBuilderInitFromSchema(&self.c_builder, &schema.c_schema, &error.c_error)
if result != GEOARROW_OK:
raise ValueError(error.message.decode('UTF-8'))
error.raise_message("GeoArrowBuilderInitFromSchema()", result)

Check warning on line 604 in python/src/geoarrow/_lib.pyx

View check run for this annotation

Codecov / codecov/patch

python/src/geoarrow/_lib.pyx#L604

Added line #L604 was not covered by tests

def __dealloc__(self):
GeoArrowBuilderReset(&self.c_builder)

def set_buffer_uint8(self, int64_t i, object obj):
cdef const unsigned char[:] view = memoryview(obj)
cdef int result = GeoArrowBuilderSetPyBuffer(&self.c_builder, i, <PyObject*>obj, &(view[0]), view.shape[0])
if result != 0:
raise ValueError("GeoArrowBuilderSetPyBuffer() failed")
if result != GEOARROW_OK:
Error.raise_error("GeoArrowBuilderSetPyBuffer()", result)

Check warning on line 613 in python/src/geoarrow/_lib.pyx

View check run for this annotation

Codecov / codecov/patch

python/src/geoarrow/_lib.pyx#L613

Added line #L613 was not covered by tests

def set_buffer_int32(self, int64_t i, object obj):
cdef const int32_t[:] view = memoryview(obj)
cdef int result = GeoArrowBuilderSetPyBuffer(&self.c_builder, i, <PyObject*>obj, &(view[0]), view.shape[0] * 4)
if result != 0:
raise ValueError("GeoArrowBuilderSetPyBuffer() failed")
if result != GEOARROW_OK:
Error.raise_error("GeoArrowBuilderSetPyBuffer()", result)

Check warning on line 619 in python/src/geoarrow/_lib.pyx

View check run for this annotation

Codecov / codecov/patch

python/src/geoarrow/_lib.pyx#L619

Added line #L619 was not covered by tests

def set_buffer_double(self, int64_t i, object obj):
cdef const double[:] view = memoryview(obj)
cdef int result = GeoArrowBuilderSetPyBuffer(&self.c_builder, i, <PyObject*>obj, &(view[0]), view.shape[0] * 8)
if result != 0:
raise ValueError("GeoArrowBuilderSetPyBuffer() failed")
if result != GEOARROW_OK:
Error.raise_error("GeoArrowBuilderSetPyBuffer()", result)

Check warning on line 625 in python/src/geoarrow/_lib.pyx

View check run for this annotation

Codecov / codecov/patch

python/src/geoarrow/_lib.pyx#L625

Added line #L625 was not covered by tests

@property
def schema(self):
return self._schema

def finish(self):
out = ArrayHolder()
cdef GeoArrowError error
cdef int result = GeoArrowBuilderFinish(&self.c_builder, &out.c_array, &error)
cdef Error error = Error()
cdef int result = GeoArrowBuilderFinish(&self.c_builder, &out.c_array, &error.c_error)
if result != GEOARROW_OK:
raise ValueError(error.decode('UTF-8'))
error.raise_message("GeoArrowBuilderFinish()", result)

Check warning on line 636 in python/src/geoarrow/_lib.pyx

View check run for this annotation

Codecov / codecov/patch

python/src/geoarrow/_lib.pyx#L636

Added line #L636 was not covered by tests
return out
10 changes: 9 additions & 1 deletion python/src/geoarrow/lib.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
from . import _lib
from ._lib import CKernel, SchemaHolder, ArrayHolder, CVectorType, CArrayView, CBuilder
from ._lib import (
CKernel,
SchemaHolder,
ArrayHolder,
CVectorType,
CArrayView,
CBuilder,
GeoArrowCException,
)


class GeometryType:
Expand Down
4 changes: 2 additions & 2 deletions python/src/geoarrow/pyarrow/_compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def parse_all(obj):
>>> ga.parse_all(["POINT (0 1"])
Traceback (most recent call last):
...
ValueError: b"Expected ')' at byte 10"
geoarrow._lib.GeoArrowCException: GeoArrowKernel<visit_void_agg>::push_batch() failed (22): Expected ')' at byte 10
"""
obj = obj_as_array_or_chunked(obj)

Expand Down Expand Up @@ -546,7 +546,7 @@ def with_geometry_type(obj, geometry_type):
>>> ga.with_geometry_type(["MULTIPOINT (0 1, 2 3)"], ga.GeometryType.POINT)
Traceback (most recent call last):
...
ValueError: b"Can't convert feature with >1 coordinate to POINT"
geoarrow._lib.GeoArrowCException: GeoArrowKernel<as_geoarrow>::push_batch() failed (22): Can't convert feature with >1 coordinate to POINT
"""
obj = as_geoarrow(obj)
if geometry_type == obj.type.geometry_type:
Expand Down
2 changes: 1 addition & 1 deletion python/src/geoarrow/pyarrow/_kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def format_wkt(type_in, significant_digits=None, max_element_size_bytes=None):

@staticmethod
def as_geoarrow(type_in, type_id):
return Kernel("as_geoarrow", type_in, type=type_id)
return Kernel("as_geoarrow", type_in, type=int(type_id))

@staticmethod
def unique_geometry_types_agg(type_in):
Expand Down
8 changes: 4 additions & 4 deletions python/src/geoarrow/pyarrow/_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def id(self):

>>> import geoarrow.pyarrow as ga
>>> ga.wkb().id
100001
<GeoArrowType.65536|32768|1024|512|128|32|1: 100001>
"""
return self._type.id

Expand Down Expand Up @@ -156,7 +156,7 @@ def coord_type(self):
>>> ga.linestring().coord_type == ga.CoordType.SEPARATE
True
>>> ga.linestring().with_coord_type(ga.CoordType.INTERLEAVED).coord_type
2
<GeoArrowCoordType.GEOARROW_COORD_TYPE_INTERLEAVED: 2>
"""
return self._type.coord_type

Expand All @@ -168,7 +168,7 @@ def edge_type(self):
>>> ga.linestring().edge_type == ga.EdgeType.PLANAR
True
>>> ga.linestring().with_edge_type(ga.EdgeType.SPHERICAL).edge_type
1
<GeoArrowEdgeType.GEOARROW_EDGE_TYPE_SPHERICAL: 1>
"""
return self._type.edge_type

Expand All @@ -180,7 +180,7 @@ def crs_type(self):
>>> ga.point().crs_type == ga.CrsType.NONE
True
>>> ga.point().with_crs("EPSG:1234").crs_type
1
<GeoArrowCrsType.GEOARROW_CRS_TYPE_UNKNOWN: 1>
"""
return self._type.crs_type

Expand Down
2 changes: 1 addition & 1 deletion python/tests/test_geoarrow_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def test_kernel_void_agg():


def test_kernel_init_error():
with pytest.raises(ValueError):
with pytest.raises(lib.GeoArrowCException):
lib.CKernel(b"not_a_kernel")


Expand Down
3 changes: 2 additions & 1 deletion python/tests/test_geoarrow_pandas.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pyarrow as pa
import geoarrow.pandas as gapd
import geoarrow.pyarrow as ga
import geoarrow.lib as lib
import numpy as np


Expand Down Expand Up @@ -156,7 +157,7 @@ def test_pyarrow_integration():
def test_accessor_parse_all():
series = pd.Series(["POINT (0 1)"])
assert series.geoarrow.parse_all() is series
with pytest.raises(ValueError):
with pytest.raises(lib.GeoArrowCException):
pd.Series(["NOT WKT"]).geoarrow.parse_all()


Expand Down
4 changes: 2 additions & 2 deletions python/tests/test_geoarrow_pyarrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,8 @@ def test_kernel_visit_void():
["POINT (30 10)", "NOT VALID WKT AT ALL"], ga.wkt(), validate=False
)
kernel = ga.Kernel.visit_void_agg(array.type)
with pytest.raises(ValueError):
kernel.push(array) is None
with pytest.raises(lib.GeoArrowCException):
kernel.push(array)
out = kernel.finish()
assert out.type == pa.null()
assert len(out) == 1
Expand Down
Loading
Loading