-
Notifications
You must be signed in to change notification settings - Fork 43
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
[Done] Fix WKB/WKT of empty (multi)points on GEOS 3.9 #392
Changes from 6 commits
060738b
87f2f24
6aeac42
8edb2f6
0fdbc1e
f1f7f19
b6dd4b0
df262c1
e24743e
55d2503
88d49ba
2c792b5
6fd61e4
e316c6f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ | |
|
||
import pygeos | ||
|
||
from .common import all_types, empty_point, point, point_z | ||
from .common import all_types, empty_point, empty_point_z, point, point_z | ||
|
||
# fmt: off | ||
POINT11_WKB = b"\x01\x01\x00\x00\x00" + struct.pack("<2d", 1.0, 1.0) | ||
|
@@ -375,17 +375,24 @@ def test_to_wkb_srid(): | |
|
||
|
||
@pytest.mark.skipif( | ||
pygeos.geos_version >= (3, 8, 0), reason="Pre GEOS 3.8.0 has 3D empty points" | ||
pygeos.geos_version < (3, 9, 0), | ||
reason="Pre GEOS 3.9 empty point serialization is buggy", | ||
) | ||
@pytest.mark.parametrize( | ||
"geom,dims,expected", | ||
[ | ||
(empty_point, 2, POINT_NAN_WKB), | ||
(empty_point, 3, POINTZ_NAN_WKB), | ||
(empty_point, 3, POINT_NAN_WKB), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This behaviour changed? (which seems a correct change though) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On GEOS < 3.8, to_wkb(empty_point, output_dimension=3) indeed gave the (faulty) 3D WKB string I split the test into 3 to make this more clear and updated the docs. |
||
(empty_point_z, 2, POINT_NAN_WKB), | ||
(empty_point_z, 3, POINTZ_NAN_WKB), | ||
(pygeos.multipoints([empty_point]), 2, MULTIPOINT_NAN_WKB), | ||
(pygeos.multipoints([empty_point]), 3, MULTIPOINTZ_NAN_WKB), | ||
(pygeos.multipoints([empty_point]), 3, MULTIPOINT_NAN_WKB), | ||
(pygeos.multipoints([empty_point_z]), 2, MULTIPOINT_NAN_WKB), | ||
(pygeos.multipoints([empty_point_z]), 3, MULTIPOINTZ_NAN_WKB), | ||
(pygeos.geometrycollections([empty_point]), 2, GEOMETRYCOLLECTION_NAN_WKB), | ||
(pygeos.geometrycollections([empty_point]), 3, GEOMETRYCOLLECTIONZ_NAN_WKB), | ||
(pygeos.geometrycollections([empty_point]), 3, GEOMETRYCOLLECTION_NAN_WKB), | ||
(pygeos.geometrycollections([empty_point_z]), 2, GEOMETRYCOLLECTION_NAN_WKB), | ||
(pygeos.geometrycollections([empty_point_z]), 3, GEOMETRYCOLLECTIONZ_NAN_WKB), | ||
( | ||
pygeos.geometrycollections([pygeos.multipoints([empty_point])]), | ||
2, | ||
|
@@ -394,42 +401,21 @@ def test_to_wkb_srid(): | |
( | ||
pygeos.geometrycollections([pygeos.multipoints([empty_point])]), | ||
3, | ||
NESTED_COLLECTIONZ_NAN_WKB, | ||
NESTED_COLLECTION_NAN_WKB, | ||
), | ||
], | ||
) | ||
def test_to_wkb_point_empty_pre_geos38(geom, dims, expected): | ||
actual = pygeos.to_wkb(geom, output_dimension=dims, byte_order=1) | ||
# Use numpy.isnan; there are many byte representations for NaN | ||
assert actual[: -dims * 8] == expected[: -dims * 8] | ||
assert np.isnan(struct.unpack("<{}d".format(dims), actual[-dims * 8 :])).all() | ||
|
||
|
||
@pytest.mark.skipif( | ||
pygeos.geos_version < (3, 8, 0), reason="Post GEOS 3.8.0 has 2D empty points" | ||
) | ||
@pytest.mark.parametrize( | ||
"geom,dims,expected", | ||
[ | ||
(empty_point, 2, POINT_NAN_WKB), | ||
(empty_point, 3, POINT_NAN_WKB), | ||
(pygeos.multipoints([empty_point]), 2, MULTIPOINT_NAN_WKB), | ||
(pygeos.multipoints([empty_point]), 3, MULTIPOINT_NAN_WKB), | ||
(pygeos.geometrycollections([empty_point]), 2, GEOMETRYCOLLECTION_NAN_WKB), | ||
(pygeos.geometrycollections([empty_point]), 3, GEOMETRYCOLLECTION_NAN_WKB), | ||
( | ||
pygeos.geometrycollections([pygeos.multipoints([empty_point])]), | ||
pygeos.geometrycollections([pygeos.multipoints([empty_point_z])]), | ||
2, | ||
NESTED_COLLECTION_NAN_WKB, | ||
), | ||
( | ||
pygeos.geometrycollections([pygeos.multipoints([empty_point])]), | ||
pygeos.geometrycollections([pygeos.multipoints([empty_point_z])]), | ||
3, | ||
NESTED_COLLECTION_NAN_WKB, | ||
NESTED_COLLECTIONZ_NAN_WKB, | ||
), | ||
], | ||
) | ||
def test_to_wkb_point_empty_post_geos38(geom, dims, expected): | ||
def test_to_wkb_point_empty(geom, dims, expected): | ||
# Post GEOS 3.8: empty point is 2D | ||
caspervdw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
actual = pygeos.to_wkb(geom, output_dimension=dims, byte_order=1) | ||
# Use numpy.isnan; there are many byte representations for NaN | ||
caspervdw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
@@ -438,24 +424,26 @@ def test_to_wkb_point_empty_post_geos38(geom, dims, expected): | |
|
||
|
||
@pytest.mark.parametrize( | ||
"wkb,expected_type", | ||
"wkb,expected_type,expected_dim", | ||
[ | ||
(POINT_NAN_WKB, 0), | ||
(POINTZ_NAN_WKB, 0), | ||
(MULTIPOINT_NAN_WKB, 4), | ||
(MULTIPOINTZ_NAN_WKB, 4), | ||
(GEOMETRYCOLLECTION_NAN_WKB, 7), | ||
(GEOMETRYCOLLECTIONZ_NAN_WKB, 7), | ||
(NESTED_COLLECTION_NAN_WKB, 7), | ||
(NESTED_COLLECTIONZ_NAN_WKB, 7), | ||
(POINT_NAN_WKB, 0, 2), | ||
(POINTZ_NAN_WKB, 0, 3), | ||
(MULTIPOINT_NAN_WKB, 4, 2), | ||
(MULTIPOINTZ_NAN_WKB, 4, 3), | ||
(GEOMETRYCOLLECTION_NAN_WKB, 7, 2), | ||
(GEOMETRYCOLLECTIONZ_NAN_WKB, 7, 3), | ||
(NESTED_COLLECTION_NAN_WKB, 7, 2), | ||
(NESTED_COLLECTIONZ_NAN_WKB, 7, 3), | ||
], | ||
) | ||
def test_from_wkb_point_empty(wkb, expected_type): | ||
def test_from_wkb_point_empty(wkb, expected_type, expected_dim): | ||
geom = pygeos.from_wkb(wkb) | ||
# POINT (nan nan) transforms to an empty point | ||
# Note that the dimensionality (2D/3D) is GEOS-version dependent | ||
assert pygeos.is_empty(geom) | ||
assert pygeos.get_type_id(geom) == expected_type | ||
# Note that the dimensionality (2D/3D) is GEOS-version dependent | ||
if pygeos.geos_version >= (3, 9, 0): | ||
assert pygeos.get_coordinate_dimension(geom) == expected_dim | ||
|
||
|
||
def test_to_wkb_point_empty_srid(): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to ensure I am correctly reading this: you removed testing for this for GEOS <= 3.8? (which I am fine with, given the version dependent behaviour, as long as we can guarantee correct and stable behaviour starting with GEOS 3.9)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(although there is now a whole block of code in geos.c between
#if !GEOS_SINCE_3_9_0
/#endif
that isn't really tested at all? Or is it still tested through other tests?)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You’re right, there should be some testing in GEOS<3.9, now the code isn’t touched anymore in the unittests.
Not sure what exactly to test. I don’t like “confirming faulty behaviour” which the previous tests did. Maybe just run the function and make sure it doesn’t segfault. I’ll remove the skip to see what exactly we have to do on earlier versions.