Skip to content

Commit d72a933

Browse files
authored
fix!: Generate child fields as non-nullable (#95)
This aligns geoarrow-c with geoarrow-rs and the geoarrow implementation in the forthcoming geopandas! This is a huge breaking change in the sense that it causes a lot of tests to fail in geoarrow-pyarrow; however, it is not much of a breaking change in the sense that the implementations here never check the nullability flag on import (and geoarrow-pyarrow defers to them almost everywhere).
1 parent 7787766 commit d72a933

File tree

4 files changed

+100
-89
lines changed

4 files changed

+100
-89
lines changed

.github/workflows/python.yaml

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,10 @@ jobs:
1919
strategy:
2020
matrix:
2121
os: [ubuntu-latest]
22-
python-version: ['3.8', '3.9', '3.10', '3.11']
22+
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
2323

2424
steps:
2525
- uses: actions/checkout@v4
26-
- uses: actions/checkout@v4
27-
with:
28-
repository: geoarrow/geoarrow-python
29-
path: geoarrow-python
30-
3126

3227
- name: Set up Python ${{ matrix.python-version }}
3328
uses: actions/setup-python@v4
@@ -40,28 +35,10 @@ jobs:
4035
pushd python/geoarrow-c
4136
pip install ".[test]"
4237
43-
- name: Install (geoarrow-pyarrow)
44-
run: |
45-
pushd geoarrow-python/geoarrow-pyarrow
46-
pip install ".[test]"
47-
48-
- name: Install (geoarrow-pandas)
49-
run: |
50-
pushd geoarrow-python/geoarrow-pandas
51-
pip install ".[test]"
52-
5338
- name: Run tests (geoarrow-c)
5439
run: |
5540
pytest python/geoarrow-c/tests -v -s
5641
57-
- name: Run tests (geoarrow-pyarrow)
58-
run: |
59-
pytest geoarrow-python/geoarrow-pyarrow/tests -v -s
60-
61-
- name: Run tests (geoarrow-pandas)
62-
run: |
63-
pytest geoarrow-python/geoarrow-pandas/tests -v -s
64-
6542
- name: Install coverage dependencies
6643
run: |
6744
sudo apt-get install -y lcov
@@ -72,8 +49,10 @@ jobs:
7249
pip install -e python/geoarrow-c/
7350
7451
- name: Coverage (geoarrow-c)
75-
if: success() && matrix.python-version == '3.11'
52+
if: success() && matrix.python-version == '3.12'
7653
run: |
54+
pip install setuptools Cython
55+
7756
pushd python/geoarrow-c
7857
7958
# Build with Cython + gcc coverage options
@@ -99,13 +78,13 @@ jobs:
9978
popd
10079
10180
- name: Upload coverage to codecov
102-
if: success() && matrix.python-version == '3.11'
81+
if: success() && matrix.python-version == '3.12'
10382
uses: codecov/codecov-action@v2
10483
with:
10584
files: 'python/geoarrow-c/coverage.info,python/geoarrow-c/coverage.xml'
10685

10786
- name: Run doctests
108-
if: success() && matrix.python-version == '3.11'
87+
if: success() && matrix.python-version == '3.12'
10988
run: |
11089
pushd python/geoarrow-c
11190
pytest --pyargs geoarrow.c --doctest-modules

python/geoarrow-c/tests/test_geoarrow_lib.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,10 @@ def test_c_vector_type():
9898

9999
pa_type = pa.DataType._import_from_c(schema._addr())
100100
pa_type_expected = pa.struct(
101-
[pa.field("x", pa.float64()), pa.field("y", pa.float64())]
101+
[
102+
pa.field("x", pa.float64(), nullable=False),
103+
pa.field("y", pa.float64(), nullable=False),
104+
]
102105
)
103106

104107
# Depending on how the tests are run, the extension type might be

src/geoarrow/schema.c

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ static GeoArrowErrorCode GeoArrowSchemaInitCoordFixedSizeList(struct ArrowSchema
1515
NANOARROW_RETURN_NOT_OK(ArrowSchemaSetName(schema->children[0], dims));
1616
NANOARROW_RETURN_NOT_OK(ArrowSchemaSetType(schema->children[0], NANOARROW_TYPE_DOUBLE));
1717

18+
// Set child field non-nullable
19+
schema->children[0]->flags = 0;
20+
1821
return GEOARROW_OK;
1922
}
2023

@@ -29,15 +32,17 @@ static GeoArrowErrorCode GeoArrowSchemaInitCoordStruct(struct ArrowSchema* schem
2932
NANOARROW_RETURN_NOT_OK(
3033
ArrowSchemaInitFromType(schema->children[i], NANOARROW_TYPE_DOUBLE));
3134
NANOARROW_RETURN_NOT_OK(ArrowSchemaSetName(schema->children[i], dim_name));
35+
// Set child non-nullable
36+
schema->children[i]->flags = 0;
3237
}
3338

3439
return GEOARROW_OK;
3540
}
3641

37-
static GeoArrowErrorCode GeoArrowSchemaInitListStruct(struct ArrowSchema* schema,
38-
enum GeoArrowCoordType coord_type,
39-
const char* dims, int n,
40-
const char** child_names) {
42+
static GeoArrowErrorCode GeoArrowSchemaInitListOf(struct ArrowSchema* schema,
43+
enum GeoArrowCoordType coord_type,
44+
const char* dims, int n,
45+
const char** child_names) {
4146
if (n == 0) {
4247
switch (coord_type) {
4348
case GEOARROW_COORD_TYPE_SEPARATE:
@@ -51,9 +56,14 @@ static GeoArrowErrorCode GeoArrowSchemaInitListStruct(struct ArrowSchema* schema
5156
ArrowSchemaInit(schema);
5257
NANOARROW_RETURN_NOT_OK(ArrowSchemaSetFormat(schema, "+l"));
5358
NANOARROW_RETURN_NOT_OK(ArrowSchemaAllocateChildren(schema, 1));
54-
NANOARROW_RETURN_NOT_OK(GeoArrowSchemaInitListStruct(schema->children[0], coord_type,
55-
dims, n - 1, child_names + 1));
56-
return ArrowSchemaSetName(schema->children[0], child_names[0]);
59+
NANOARROW_RETURN_NOT_OK(GeoArrowSchemaInitListOf(schema->children[0], coord_type,
60+
dims, n - 1, child_names + 1));
61+
NANOARROW_RETURN_NOT_OK(ArrowSchemaSetName(schema->children[0], child_names[0]));
62+
63+
// Set child field non-nullable
64+
schema->children[0]->flags = 0;
65+
66+
return NANOARROW_OK;
5767
}
5868
}
5969

@@ -112,32 +122,42 @@ GeoArrowErrorCode GeoArrowSchemaInit(struct ArrowSchema* schema, enum GeoArrowTy
112122
case GEOARROW_GEOMETRY_TYPE_POINT:
113123
switch (coord_type) {
114124
case GEOARROW_COORD_TYPE_SEPARATE:
115-
return GeoArrowSchemaInitCoordStruct(schema, dims);
125+
NANOARROW_RETURN_NOT_OK(GeoArrowSchemaInitCoordStruct(schema, dims));
126+
break;
116127
case GEOARROW_COORD_TYPE_INTERLEAVED:
117-
return GeoArrowSchemaInitCoordFixedSizeList(schema, dims);
128+
NANOARROW_RETURN_NOT_OK(GeoArrowSchemaInitCoordFixedSizeList(schema, dims));
129+
break;
118130
default:
119131
return EINVAL;
120132
}
133+
break;
121134

122135
case GEOARROW_GEOMETRY_TYPE_LINESTRING:
123-
return GeoArrowSchemaInitListStruct(schema, coord_type, dims, 1,
124-
CHILD_NAMES_LINESTRING);
136+
NANOARROW_RETURN_NOT_OK(
137+
GeoArrowSchemaInitListOf(schema, coord_type, dims, 1, CHILD_NAMES_LINESTRING));
138+
break;
125139
case GEOARROW_GEOMETRY_TYPE_MULTIPOINT:
126-
return GeoArrowSchemaInitListStruct(schema, coord_type, dims, 1,
127-
CHILD_NAMES_MULTIPOINT);
140+
NANOARROW_RETURN_NOT_OK(
141+
GeoArrowSchemaInitListOf(schema, coord_type, dims, 1, CHILD_NAMES_MULTIPOINT));
142+
break;
128143
case GEOARROW_GEOMETRY_TYPE_POLYGON:
129-
return GeoArrowSchemaInitListStruct(schema, coord_type, dims, 2,
130-
CHILD_NAMES_POLYGON);
144+
NANOARROW_RETURN_NOT_OK(
145+
GeoArrowSchemaInitListOf(schema, coord_type, dims, 2, CHILD_NAMES_POLYGON));
146+
break;
131147
case GEOARROW_GEOMETRY_TYPE_MULTILINESTRING:
132-
return GeoArrowSchemaInitListStruct(schema, coord_type, dims, 2,
133-
CHILD_NAMES_MULTILINESTRING);
148+
NANOARROW_RETURN_NOT_OK(GeoArrowSchemaInitListOf(schema, coord_type, dims, 2,
149+
CHILD_NAMES_MULTILINESTRING));
150+
break;
134151
case GEOARROW_GEOMETRY_TYPE_MULTIPOLYGON:
135-
return GeoArrowSchemaInitListStruct(schema, coord_type, dims, 3,
136-
CHILD_NAMES_MULTIPOLYGON);
152+
NANOARROW_RETURN_NOT_OK(GeoArrowSchemaInitListOf(schema, coord_type, dims, 3,
153+
CHILD_NAMES_MULTIPOLYGON));
154+
break;
137155

138156
default:
139157
return ENOTSUP;
140158
}
159+
160+
return NANOARROW_OK;
141161
}
142162

143163
GeoArrowErrorCode GeoArrowSchemaInitExtension(struct ArrowSchema* schema,

0 commit comments

Comments
 (0)