Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-Shapely for openSUSE:Factory checked in at 2024-05-06 17:53:15 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-Shapely (Old) and /work/SRC/openSUSE:Factory/.python-Shapely.new.1880 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-Shapely" Mon May 6 17:53:15 2024 rev:26 rq:1171977 version:2.0.4 Changes: -------- --- /work/SRC/openSUSE:Factory/python-Shapely/python-Shapely.changes 2023-12-17 21:36:15.910174424 +0100 +++ /work/SRC/openSUSE:Factory/.python-Shapely.new.1880/python-Shapely.changes 2024-05-06 17:53:33.127739374 +0200 @@ -1,0 +2,17 @@ +Sun May 5 11:01:36 UTC 2024 - Ben Greiner <c...@bnavigator.de> + +- Update to 2.0.4 + * Fix bug in ``to_wkt`` with multiple empty Z geometries (#2012). + * Fix bug in ``to_ragged_array`` for an array of Points with + missing values (#2034). + * Compatibility with numpy 2 +- Release 2.0.3 + * Fix regression in the ``oriented_envelope`` ufunc to accept + array-like input in case of GEOS<3.12 (#1929). + * The binary wheels are not yet compatible with a future NumPy + 2.0 release, therefore a ``numpy<2`` upper pin was added to the + requirements (#1972). + * Upgraded the GEOS version in the binary wheel distributions to + 3.11.3. + +------------------------------------------------------------------- Old: ---- shapely-2.0.2.tar.gz New: ---- shapely-2.0.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-Shapely.spec ++++++ --- /var/tmp/diff_new_pack.lsE63s/_old 2024-05-06 17:53:33.727761257 +0200 +++ /var/tmp/diff_new_pack.lsE63s/_new 2024-05-06 17:53:33.731761403 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-Shapely # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-Shapely -Version: 2.0.2 +Version: 2.0.4 Release: 0 Summary: Geospatial geometries, predicates, and operations License: BSD-3-Clause @@ -26,7 +26,7 @@ Source: https://files.pythonhosted.org/packages/source/s/shapely/shapely-%{version}.tar.gz BuildRequires: %{python_module Cython >= 0.29 with %python-Cython < 3} BuildRequires: %{python_module devel >= 3.8} -BuildRequires: %{python_module numpy-devel >= 1.16} +BuildRequires: %{python_module numpy-devel >= 1.25} BuildRequires: %{python_module pip} BuildRequires: %{python_module setuptools} BuildRequires: %{python_module wheel} @@ -45,7 +45,7 @@ # (libgeos_c1 is detected due to some Cython optimized lib, but libgeos3 is not) # use requires_eq in order to be detectable by the python_subpackages rewriter %requires_eq %(rpm -q --requires geos-devel | grep libgeos) -Requires: python-numpy >= 1.16 +Requires: (python-numpy >= 1.14 with python-numpy < 3) Provides: python-shapely = %{version}-%{release} Obsoletes: python-shapely < %{version}-%{release} %python_subpackages ++++++ shapely-2.0.2.tar.gz -> shapely-2.0.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/CHANGES.txt new/shapely-2.0.4/CHANGES.txt --- old/shapely-2.0.2/CHANGES.txt 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/CHANGES.txt 2024-04-17 00:00:57.000000000 +0200 @@ -1,6 +1,26 @@ Changes ======= +2.0.4 (2024-04-16) +------------------ + +Wheels for Python versions >= 3.9 will be compatible with the upcoming NumPy 2.0 +release (as well as with supported NumPy 1.x versions). + +Bug fixes: + +- Fix bug in ``to_wkt`` with multiple empty Z geometries (#2012). +- Fix bug in ``to_ragged_array`` for an array of Points with missing values (#2034). + +2.0.3 (2024-02-16) +------------------ + +- Fix regression in the ``oriented_envelope`` ufunc to accept array-like input + in case of GEOS<3.12 (#1929). +- The binary wheels are not yet compatible with a future NumPy 2.0 release, + therefore a ``numpy<2`` upper pin was added to the requirements (#1972). +- Upgraded the GEOS version in the binary wheel distributions to 3.11.3. + 2.0.2 (2023-10-12) ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/CITATION.cff new/shapely-2.0.4/CITATION.cff --- old/shapely-2.0.2/CITATION.cff 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/CITATION.cff 2024-04-17 00:00:57.000000000 +0200 @@ -2,8 +2,8 @@ message: "Please cite this software using these metadata." type: software title: Shapely -version: "2.0.2" -date-released: "2023-10-12" +version: "2.0.4" +date-released: "2024-04-16" doi: 10.5281/zenodo.5597138 abstract: "Manipulation and analysis of geometric objects in the Cartesian plane." repository-artifact: https://pypi.org/project/Shapely diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/PKG-INFO new/shapely-2.0.4/PKG-INFO --- old/shapely-2.0.2/PKG-INFO 2023-10-12 22:06:51.502693000 +0200 +++ new/shapely-2.0.4/PKG-INFO 2024-04-17 00:01:12.009678400 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: shapely -Version: 2.0.2 +Version: 2.0.4 Summary: Manipulation and analysis of geometric objects Author: Sean Gillies Maintainer: Shapely contributors @@ -26,7 +26,7 @@ Requires-Python: >=3.7 Description-Content-Type: text/x-rst License-File: LICENSE.txt -Requires-Dist: numpy>=1.14 +Requires-Dist: numpy<3,>=1.14 Provides-Extra: test Requires-Dist: pytest; extra == "test" Requires-Dist: pytest-cov; extra == "test" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/pyproject.toml new/shapely-2.0.4/pyproject.toml --- old/shapely-2.0.2/pyproject.toml 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/pyproject.toml 2024-04-17 00:00:57.000000000 +0200 @@ -1,7 +1,12 @@ [build-system] requires = [ "Cython", - "oldest-supported-numpy", + # Starting with NumPy 1.25, NumPy is (by default) as far back compatible + # as oldest-support-numpy was (customizable with a NPY_TARGET_VERSION + # define). For older Python versions (where NumPy 1.25 is not yet avaiable) + # continue using oldest-support-numpy. + "oldest-supported-numpy; python_version<'3.9'", + "numpy>=1.25; python_version>='3.9'", "setuptools>=61.0.0", ] build-backend = "setuptools.build_meta" @@ -38,7 +43,7 @@ ] requires-python = ">=3.7" dependencies = [ - "numpy>=1.14", + "numpy>=1.14,<3", ] [project.optional-dependencies] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely/_ragged_array.py new/shapely-2.0.4/shapely/_ragged_array.py --- old/shapely-2.0.2/shapely/_ragged_array.py 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/shapely/_ragged_array.py 2024-04-17 00:00:57.000000000 +0200 @@ -37,7 +37,7 @@ get_type_id, ) from shapely.coordinates import get_coordinates -from shapely.predicates import is_empty +from shapely.predicates import is_empty, is_missing __all__ = ["to_ragged_array", "from_ragged_array"] @@ -50,7 +50,8 @@ coords = get_coordinates(arr, include_z=include_z) # empty points are represented by NaNs - empties = is_empty(arr) + # + missing geometries should also be present with some value + empties = is_empty(arr) | is_missing(arr) if empties.any(): indices = np.nonzero(empties)[0] indices = indices - np.arange(len(indices)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely/_version.py new/shapely-2.0.4/shapely/_version.py --- old/shapely-2.0.2/shapely/_version.py 2023-10-12 22:06:51.502693000 +0200 +++ new/shapely-2.0.4/shapely/_version.py 2024-04-17 00:01:12.009678400 +0200 @@ -8,11 +8,11 @@ version_json = ''' { - "date": "2023-10-12T21:49:31+0200", + "date": "2024-04-16T23:57:44+0200", "dirty": false, "error": null, - "full-revisionid": "8d45d434037267ba9b1f1de409d1b5396d6c9219", - "version": "2.0.2" + "full-revisionid": "3853e1170173125b7e86cbb5cc8dab1c274c3999", + "version": "2.0.4" } ''' # END VERSION_JSON diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely/algorithms/_oriented_envelope.py new/shapely-2.0.4/shapely/algorithms/_oriented_envelope.py --- old/shapely-2.0.2/shapely/algorithms/_oriented_envelope.py 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/shapely/algorithms/_oriented_envelope.py 2024-04-17 00:00:57.000000000 +0200 @@ -17,8 +17,6 @@ """ if geometry is None: return None - if not hasattr(geometry, "geom_type"): - return np.array([_oriented_envelope_min_area(g) for g in geometry]) if geometry.is_empty: return shapely.from_wkt("POLYGON EMPTY") @@ -53,3 +51,8 @@ # check for the minimum area rectangle and return it transf_rect, inv_matrix = min(_transformed_rects(), key=lambda r: r[0].area) return affine_transform(transf_rect, inv_matrix) + + +_oriented_envelope_min_area_vectorized = np.frompyfunc( + _oriented_envelope_min_area, 1, 1 +) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely/constructive.py new/shapely-2.0.4/shapely/constructive.py --- old/shapely-2.0.2/shapely/constructive.py 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/shapely/constructive.py 2024-04-17 00:00:57.000000000 +0200 @@ -2,7 +2,7 @@ from shapely import lib from shapely._enum import ParamEnum -from shapely.algorithms._oriented_envelope import _oriented_envelope_min_area +from shapely.algorithms._oriented_envelope import _oriented_envelope_min_area_vectorized from shapely.decorators import multithreading_enabled, requires_geos __all__ = [ @@ -1028,7 +1028,7 @@ <POLYGON EMPTY> """ if lib.geos_version < (3, 12, 0): - f = _oriented_envelope_min_area + f = _oriented_envelope_min_area_vectorized else: f = _oriented_envelope_geos return f(geometry, **kwargs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely/decorators.py new/shapely-2.0.4/shapely/decorators.py --- old/shapely-2.0.2/shapely/decorators.py 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/shapely/decorators.py 2024-04-17 00:00:57.000000000 +0200 @@ -39,7 +39,7 @@ # Insert the message at the first double newline position = doc.find("\n\n") + 2 # Figure out the indentation level - indent = 2 + indent = 0 while True: if doc[position + indent] == " ": indent += 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely/geometry/polygon.py new/shapely-2.0.4/shapely/geometry/polygon.py --- old/shapely-2.0.2/shapely/geometry/polygon.py 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/shapely/geometry/polygon.py 2024-04-17 00:00:57.000000000 +0200 @@ -10,7 +10,7 @@ from shapely.geometry.linestring import LineString from shapely.geometry.point import Point -__all__ = ["Polygon", "LinearRing"] +__all__ = ["orient", "Polygon", "LinearRing"] def _unpickle_linearring(wkb): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely/testing.py new/shapely-2.0.4/shapely/testing.py --- old/shapely-2.0.2/shapely/testing.py 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/shapely/testing.py 2024-04-17 00:00:57.000000000 +0200 @@ -106,8 +106,8 @@ if normalize: x = shapely.normalize(x) y = shapely.normalize(y) - x = np.array(x, copy=False) - y = np.array(y, copy=False) + x = np.asarray(x) + y = np.asarray(y) is_scalar = x.ndim == 0 or y.ndim == 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely/tests/common.py new/shapely-2.0.4/shapely/tests/common.py --- old/shapely-2.0.2/shapely/tests/common.py 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/shapely/tests/common.py 2024-04-17 00:00:57.000000000 +0200 @@ -92,3 +92,34 @@ with ignore_invalid(): line_string_nan = shapely.LineString([(np.nan, np.nan), (np.nan, np.nan)]) + + +class ArrayLike: + """ + Simple numpy Array like class that implements the + ufunc protocol. + """ + + def __init__(self, array): + self._array = np.asarray(array) + + def __len__(self): + return len(self._array) + + def __getitem(self, key): + return self._array[key] + + def __iter__(self): + return self._array.__iter__() + + def __array__(self): + return np.asarray(self._array) + + def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): + if method == "__call__": + inputs = [ + arg._array if isinstance(arg, self.__class__) else arg for arg in inputs + ] + return self.__class__(ufunc(*inputs, **kwargs)) + else: + return NotImplemented diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely/tests/geometry/test_format.py new/shapely-2.0.4/shapely/tests/geometry/test_format.py --- old/shapely-2.0.2/shapely/tests/geometry/test_format.py 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/shapely/tests/geometry/test_format.py 2024-04-17 00:00:57.000000000 +0200 @@ -84,23 +84,28 @@ assert format(poly, "X") == poly.wkb_hex # Use f-strings with extra characters and rounding precision - assert f"<{poly:.2f}>" == ( - "<POLYGON ((10.00 0.00, 7.07 -7.07, 0.00 -10.00, -7.07 -7.07, " - "-10.00 -0.00, -7.07 7.07, -0.00 10.00, 7.07 7.07, 10.00 0.00))>" - ) + if geos_version < (3, 13, 0): + assert f"<{poly:.2f}>" == ( + "<POLYGON ((10.00 0.00, 7.07 -7.07, 0.00 -10.00, -7.07 -7.07, " + "-10.00 -0.00, -7.07 7.07, -0.00 10.00, 7.07 7.07, 10.00 0.00))>" + ) + else: + assert f"<{poly:.2f}>" == ( + "<POLYGON ((10.00 0.00, 7.07 -7.07, 0.00 -10.00, -7.07 -7.07, " + "-10.00 0.00, -7.07 7.07, 0.00 10.00, 7.07 7.07, 10.00 0.00))>" + ) # 'g' format varies depending on GEOS version if geos_version < (3, 10, 0): - expected_2G = ( + assert f"{poly:.2G}" == ( "POLYGON ((10 0, 7.1 -7.1, 1.6E-14 -10, -7.1 -7.1, " "-10 -3.2E-14, -7.1 7.1, -4.6E-14 10, 7.1 7.1, 10 0))" ) else: - expected_2G = ( + assert f"{poly:.2G}" == ( "POLYGON ((10 0, 7.07 -7.07, 0 -10, -7.07 -7.07, " "-10 0, -7.07 7.07, 0 10, 7.07 7.07, 10 0))" ) - assert f"{poly:.2G}" == expected_2G # check empty empty = Polygon() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely/tests/test_constructive.py new/shapely-2.0.4/shapely/tests/test_constructive.py --- old/shapely-2.0.2/shapely/tests/test_constructive.py 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/shapely/tests/test_constructive.py 2024-04-17 00:00:57.000000000 +0200 @@ -17,6 +17,7 @@ from shapely.testing import assert_geometries_equal from shapely.tests.common import ( all_types, + ArrayLike, empty, empty_line_string, empty_point, @@ -981,6 +982,17 @@ assert_geometries_equal(actual, expected, normalize=True, tolerance=1e-3) +def test_oriented_evelope_array_like(): + # https://github.com/shapely/shapely/issues/1929 + # because we have a custom python implementation, need to ensure this has + # the same capabilities as numpy ufuncs to work with array-likes + geometries = [Point(1, 1).buffer(1), Point(2, 2).buffer(1)] + actual = shapely.oriented_envelope(ArrayLike(geometries)) + assert isinstance(actual, ArrayLike) + expected = shapely.oriented_envelope(geometries) + assert_geometries_equal(np.asarray(actual), expected) + + @pytest.mark.skipif(shapely.geos_version < (3, 11, 0), reason="GEOS < 3.11") def test_concave_hull_kwargs(): p = Point(10, 10) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely/tests/test_io.py new/shapely-2.0.4/shapely/tests/test_io.py --- old/shapely-2.0.2/shapely/tests/test_io.py 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/shapely/tests/test_io.py 2024-04-17 00:00:57.000000000 +0200 @@ -287,6 +287,15 @@ assert shapely.to_wkt(None) is None +def test_to_wkt_array_with_empty_z(): + # See GH-2004 + empty_wkt = ["POINT Z EMPTY", None, "POLYGON Z EMPTY"] + empty_geoms = shapely.from_wkt(empty_wkt) + if shapely.geos_version < (3, 9, 0): + empty_wkt = ["POINT EMPTY", None, "POLYGON EMPTY"] + assert list(shapely.to_wkt(empty_geoms)) == empty_wkt + + def test_to_wkt_exceptions(): with pytest.raises(TypeError): shapely.to_wkt(1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely/tests/test_misc.py new/shapely-2.0.4/shapely/tests/test_misc.py --- old/shapely-2.0.2/shapely/tests/test_misc.py 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/shapely/tests/test_misc.py 2024-04-17 00:00:57.000000000 +0200 @@ -1,5 +1,6 @@ import os import sys +from inspect import cleandoc from itertools import chain from string import ascii_letters, digits from unittest import mock @@ -83,13 +84,22 @@ """ -expected_docstring = """Docstring that will be mocked. +def expected_docstring(**kwds): + doc = """Docstring that will be mocked. {indent}A multiline. {indent}.. note:: 'func' requires at least GEOS {version}. {indent}Some description. -{indent}""" +{indent}""".format( + **kwds + ) + if sys.version_info[:2] >= (3, 13): + # There are subtle differences between inspect.cleandoc() and + # _PyCompile_CleanDoc(). Most significantly, the latter does not remove + # leading or trailing blank lines. + return cleandoc(doc) + "\n" + return doc @pytest.mark.parametrize("version", ["3.7.0", "3.7.1", "3.6.2"]) @@ -104,7 +114,7 @@ with pytest.raises(shapely.errors.UnsupportedGEOSVersionError): wrapped() - assert wrapped.__doc__ == expected_docstring.format(version=version, indent=" " * 4) + assert wrapped.__doc__ == expected_docstring(version=version, indent=" " * 4) @pytest.mark.parametrize("version", ["3.6.0", "3.8.0"]) @@ -112,7 +122,7 @@ """The requires_geos decorator always adapts the docstring.""" wrapped = requires_geos(version)(func) - assert wrapped.__doc__ == expected_docstring.format(version=version, indent=" " * 4) + assert wrapped.__doc__ == expected_docstring(version=version, indent=" " * 4) @pytest.mark.parametrize("version", ["3.6.0", "3.8.0"]) @@ -120,7 +130,7 @@ """The requires_geos decorator adjusts methods docstrings correctly""" wrapped = requires_geos(version)(SomeClass.func) - assert wrapped.__doc__ == expected_docstring.format(version=version, indent=" " * 8) + assert wrapped.__doc__ == expected_docstring(version=version, indent=" " * 8) @multithreading_enabled diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely/tests/test_ragged_array.py new/shapely-2.0.4/shapely/tests/test_ragged_array.py --- old/shapely-2.0.2/shapely/tests/test_ragged_array.py 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/shapely/tests/test_ragged_array.py 2024-04-17 00:00:57.000000000 +0200 @@ -110,18 +110,30 @@ "POINT EMPTY", "POINT EMPTY", "POINT (4 4)", + None, "POINT EMPTY", ] ) typ, result, offsets = shapely.to_ragged_array(arr) expected = np.array( - [[0, 0], [1, 1], [np.nan, np.nan], [np.nan, np.nan], [4, 4], [np.nan, np.nan]] + [ + [0, 0], + [1, 1], + [np.nan, np.nan], + [np.nan, np.nan], + [4, 4], + [np.nan, np.nan], + [np.nan, np.nan], + ] ) assert typ == shapely.GeometryType.POINT + assert len(result) == len(arr) assert_allclose(result, expected) assert len(offsets) == 0 geoms = shapely.from_ragged_array(typ, result) + # in a roundtrip, missing geometries come back as empty + arr[-2] = shapely.from_wkt("POINT EMPTY") assert_geometries_equal(geoms, arr) @@ -133,6 +145,7 @@ "LINESTRING EMPTY", "LINESTRING EMPTY", "LINESTRING (10 10, 20 20, 10 40)", + None, "LINESTRING EMPTY", ] ) @@ -151,13 +164,15 @@ [10.0, 40.0], ] ) - expected_offsets = np.array([0, 3, 7, 7, 7, 10, 10]) + expected_offsets = np.array([0, 3, 7, 7, 7, 10, 10, 10]) assert typ == shapely.GeometryType.LINESTRING assert_allclose(coords, expected) assert len(offsets) == 1 assert_allclose(offsets[0], expected_offsets) result = shapely.from_ragged_array(typ, coords, offsets) + # in a roundtrip, missing geometries come back as empty + arr[-2] = shapely.from_wkt("LINESTRING EMPTY") assert_geometries_equal(result, arr) @@ -169,6 +184,7 @@ "POLYGON EMPTY", "POLYGON EMPTY", "POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))", + None, "POLYGON EMPTY", ] ) @@ -197,7 +213,7 @@ ] ) expected_offsets1 = np.array([0, 5, 10, 14, 19]) - expected_offsets2 = np.array([0, 1, 3, 3, 3, 4, 4]) + expected_offsets2 = np.array([0, 1, 3, 3, 3, 4, 4, 4]) assert typ == shapely.GeometryType.POLYGON assert_allclose(coords, expected) @@ -206,6 +222,8 @@ assert_allclose(offsets[1], expected_offsets2) result = shapely.from_ragged_array(typ, coords, offsets) + # in a roundtrip, missing geometries come back as empty + arr[-2] = shapely.from_wkt("POLYGON EMPTY") assert_geometries_equal(result, arr) @@ -217,6 +235,7 @@ "MULTIPOINT EMPTY", "MULTIPOINT EMPTY", "MULTIPOINT (30 10, 10 30, 40 40)", + None, "MULTIPOINT EMPTY", ] ) @@ -233,7 +252,7 @@ [40.0, 40.0], ] ) - expected_offsets = np.array([0, 4, 5, 5, 5, 8, 8]) + expected_offsets = np.array([0, 4, 5, 5, 5, 8, 8, 8]) assert typ == shapely.GeometryType.MULTIPOINT assert_allclose(coords, expected) @@ -241,6 +260,8 @@ assert_allclose(offsets[0], expected_offsets) result = shapely.from_ragged_array(typ, coords, offsets) + # in a roundtrip, missing geometries come back as empty + arr[-2] = shapely.from_wkt("MULTIPOINT EMPTY") assert_geometries_equal(result, arr) @@ -252,6 +273,7 @@ "MULTILINESTRING EMPTY", "MULTILINESTRING EMPTY", "MULTILINESTRING ((35 10, 45 45), (15 40, 10 20), (30 10, 10 30, 40 40))", + None, "MULTILINESTRING EMPTY", ] ) @@ -278,7 +300,7 @@ ] ) expected_offsets1 = np.array([0, 3, 6, 10, 12, 14, 17]) - expected_offsets2 = np.array([0, 1, 3, 3, 3, 6, 6]) + expected_offsets2 = np.array([0, 1, 3, 3, 3, 6, 6, 6]) assert typ == shapely.GeometryType.MULTILINESTRING assert_allclose(coords, expected) @@ -287,6 +309,8 @@ assert_allclose(offsets[1], expected_offsets2) result = shapely.from_ragged_array(typ, coords, offsets) + # in a roundtrip, missing geometries come back as empty + arr[-2] = shapely.from_wkt("MULTILINESTRING EMPTY") assert_geometries_equal(result, arr) @@ -298,6 +322,7 @@ "MULTIPOLYGON EMPTY", "MULTIPOLYGON EMPTY", "MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)))", + None, "MULTIPOLYGON EMPTY", ] ) @@ -335,7 +360,7 @@ ) expected_offsets1 = np.array([0, 5, 9, 13, 19, 23, 27]) expected_offsets2 = np.array([0, 2, 3, 5, 6]) - expected_offsets3 = np.array([0, 1, 3, 3, 3, 4, 4]) + expected_offsets3 = np.array([0, 1, 3, 3, 3, 4, 4, 4]) assert typ == shapely.GeometryType.MULTIPOLYGON assert_allclose(coords, expected) @@ -345,6 +370,8 @@ assert_allclose(offsets[2], expected_offsets3) result = shapely.from_ragged_array(typ, coords, offsets) + # in a roundtrip, missing geometries come back as empty + arr[-2] = shapely.from_wkt("MULTIPOLYGON EMPTY") assert_geometries_equal(result, arr) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely/tests/test_set_operations.py new/shapely-2.0.4/shapely/tests/test_set_operations.py --- old/shapely-2.0.2/shapely/tests/test_set_operations.py 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/shapely/tests/test_set_operations.py 2024-04-17 00:00:57.000000000 +0200 @@ -53,6 +53,13 @@ @pytest.mark.parametrize("a", all_types) @pytest.mark.parametrize("func", SET_OPERATIONS) def test_set_operation_array(a, func): + if ( + func is shapely.difference + and a.geom_type == "GeometryCollection" + and shapely.get_num_geometries(a) == 2 + and shapely.geos_version == (3, 9, 5) + ): + pytest.xfail("GEOS 3.9.5 crashes with mixed collection") actual = func(a, point) assert isinstance(actual, Geometry) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely/tests/test_strtree.py new/shapely-2.0.4/shapely/tests/test_strtree.py --- old/shapely-2.0.2/shapely/tests/test_strtree.py 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/shapely/tests/test_strtree.py 2024-04-17 00:00:57.000000000 +0200 @@ -10,7 +10,7 @@ from numpy.testing import assert_array_equal import shapely -from shapely import box, geos_version, MultiPoint, Point, STRtree +from shapely import box, geos_version, LineString, MultiPoint, Point, STRtree from shapely.errors import UnsupportedGEOSVersionError from shapely.testing import assert_geometries_equal from shapely.tests.common import ( @@ -928,12 +928,12 @@ # box contains points but touches only those at edges (box(3, 3, 6, 6), [3, 6]), ([box(3, 3, 6, 6)], [[0, 0], [3, 6]]), - # buffer completely contains point in tree + # polygon completely contains point in tree (shapely.buffer(Point(3, 3), 1), []), ([shapely.buffer(Point(3, 3), 1)], [[], []]), - # buffer intersects 2 points but touches only one - (shapely.buffer(Point(0, 1), 1), [1]), - ([shapely.buffer(Point(0, 1), 1)], [[0], [1]]), + # linestring intersects 2 points but touches only one + (LineString([(-1, -1), (1, 1)]), [1]), + ([LineString([(-1, -1), (1, 1)])], [[0], [1]]), # multipoints intersect but not valid relation (MultiPoint([[5, 5], [7, 7]]), []), ([MultiPoint([[5, 5], [7, 7]])], [[], []]), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely.egg-info/PKG-INFO new/shapely-2.0.4/shapely.egg-info/PKG-INFO --- old/shapely-2.0.2/shapely.egg-info/PKG-INFO 2023-10-12 22:06:51.000000000 +0200 +++ new/shapely-2.0.4/shapely.egg-info/PKG-INFO 2024-04-17 00:01:11.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: shapely -Version: 2.0.2 +Version: 2.0.4 Summary: Manipulation and analysis of geometric objects Author: Sean Gillies Maintainer: Shapely contributors @@ -26,7 +26,7 @@ Requires-Python: >=3.7 Description-Content-Type: text/x-rst License-File: LICENSE.txt -Requires-Dist: numpy>=1.14 +Requires-Dist: numpy<3,>=1.14 Provides-Extra: test Requires-Dist: pytest; extra == "test" Requires-Dist: pytest-cov; extra == "test" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/shapely.egg-info/requires.txt new/shapely-2.0.4/shapely.egg-info/requires.txt --- old/shapely-2.0.2/shapely.egg-info/requires.txt 2023-10-12 22:06:51.000000000 +0200 +++ new/shapely-2.0.4/shapely.egg-info/requires.txt 2024-04-17 00:01:11.000000000 +0200 @@ -1,4 +1,4 @@ -numpy>=1.14 +numpy<3,>=1.14 [docs] numpydoc==1.1.* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/shapely-2.0.2/src/ufuncs.c new/shapely-2.0.4/src/ufuncs.c --- old/shapely-2.0.2/src/ufuncs.c 2023-10-12 22:06:28.000000000 +0200 +++ new/shapely-2.0.4/src/ufuncs.c 2024-04-17 00:00:57.000000000 +0200 @@ -3351,8 +3351,9 @@ goto finish; } if (wkt != NULL) { + Py_XDECREF(*out); *out = PyUnicode_FromString(wkt); - goto finish; + continue; } #else