[Git][debian-gis-team/python-shapely][experimental] 4 commits: New upstream version 2.0~b2

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Sat Oct 29 13:03:34 BST 2022



Bas Couwenberg pushed to branch experimental at Debian GIS Project / python-shapely


Commits:
5be11660 by Bas Couwenberg at 2022-10-29T13:50:58+02:00
New upstream version 2.0~b2
- - - - -
a9f7c592 by Bas Couwenberg at 2022-10-29T13:51:00+02:00
Update upstream source from tag 'upstream/2.0_b2'

Update to upstream version '2.0~b2'
with Debian dir 95a8a0719212c39dab8644fa3c8a2777cd64072b
- - - - -
27795f05 by Bas Couwenberg at 2022-10-29T13:52:35+02:00
New upstream beta release.

- - - - -
5d8be325 by Bas Couwenberg at 2022-10-29T13:53:42+02:00
Set distribution to experimental.

- - - - -


20 changed files:

- .github/workflows/tests.yml
- .travis.yml
- CHANGES.txt
- debian/changelog
- docs/geometry.rst
- docs/migration_pygeos.rst
- shapely/constructive.py
- shapely/geometry/base.py
- shapely/geometry/linestring.py
- shapely/geometry/point.py
- + shapely/tests/geometry/test_format.py
- shapely/tests/geometry/test_geometry_base.py
- shapely/tests/geometry/test_hash.py
- shapely/tests/geometry/test_point.py
- src/pygeom.c
- src/pygeom.h
- − tests/test_binascii_hex.txt
- tests/test_buffer.py
- − tests/test_doctests.py
- tests/test_parallel_offset.py


Changes:

=====================================
.github/workflows/tests.yml
=====================================
@@ -58,6 +58,11 @@ jobs:
             python: 3.9
             geos: 3.10.3
             numpy: 1.19.5
+          # pypy
+          - os: ubuntu-latest
+            python: "pypy3.8"
+            geos: 3.11.0
+            numpy: 1.23.3
 
     env:
       GEOS_VERSION: ${{ matrix.geos }}


=====================================
.travis.yml
=====================================
@@ -61,5 +61,7 @@ deploy:
     secure: "hU7JzC2F1GomDVpSOw9L3WHV/qwVWkc3NI6YCkkqUArMyYnJPSMBJck9ugeZIJ6OrIKORs50vIAdGrYQnjbhcntQzwc384mfnNO3FNPMnkBaxi4y0ofERy/ygqysM+tEOXINzJpFcYyylpknQdSnuzLSgYhdm+OXfob5Sqy/ABX+dXEuz1pb7UWvK0oYcLC1PYkfneFK4IcUIHYuMhia48y0jfxlez9gFZMAos3PKtn6m9CRN4xU370RgNjvy7Ey/hXwiTlm4rrX4KbEFj1q/SoaXvgK+mQqofM7n/4MakA8VFzKtz5a/L64f4iiJy0V2WgO/DiO2fLFwfEFmr+23WY8TTkMV/p7IAjZzeMY9ZmODymzXRKaJxIVt0MerLiwdul7nVCmXbJ/HkQwW2p32IUxzL37XaEk6ZN4lTb+5BhPA9e6jCZdgRY8sfJrrOzFxNNVm0wuf9nbve662PYhmgq9sETk4sdvqK8ODem/TSqMZzsq6FPRf2JCeFGZn+2TAKp+nwAFTByoJ/mMNsTc3TjtAzFhhtd2DUQriGadD+aNPZexA+yKCVSY/EGDYxpbnyS1h1fJv17kgyLxQfUi5FDBwrcGX0Ld01IyqcQbaw57DLDTQYYK4yvrfsYaQJDIQlySe8BkwgtJ5Dz9WP13MUZJ7VrISYMdTRU805eTvRE="
   skip_cleanup: true
   skip_existing: true
+  distributions: ""
   on:
     tags: true
+    condition: $CIBUILDWHEEL = 1


=====================================
CHANGES.txt
=====================================
@@ -1,6 +1,17 @@
 Changes
 =======
 
+2.0b2 (2022-10-29)
+------------------
+
+Relevant changes in behaviour compared to 2.0b1:
+
+- Fix for compatibility with PyPy (#1577).
+- Fix to the ``Point()`` constructor to accept arrays of length 1 for the x and y
+  coordinates (fix compatibility with Shapely 1.8).
+- Raise ValueError for non-finite distance in the ``buffer()`` and ``offset_curve()``
+  methods on the Geometry classes (consistent with Shapely 1.8).
+
 2.0b1 (2022-10-17)
 ------------------
 


=====================================
debian/changelog
=====================================
@@ -1,3 +1,9 @@
+python-shapely (2.0~b2-1~exp1) experimental; urgency=medium
+
+  * New upstream beta release.
+
+ -- Bas Couwenberg <sebastic at debian.org>  Sat, 29 Oct 2022 13:53:30 +0200
+
 python-shapely (2.0~b1-1~exp1) experimental; urgency=medium
 
   * New upstream beta release.


=====================================
docs/geometry.rst
=====================================
@@ -68,7 +68,7 @@ Geometries can be serialized using pickle:
   <POINT (1 1)>
 
 .. warning:: Pickling will convert linearrings to linestrings.
-             See :func:`shapely.io.to_wkb` for a complete list of limitations.
+             See :func:`shapely.to_wkb` for a complete list of limitations.
 
 Hashing
 ~~~~~~~
@@ -88,7 +88,7 @@ Therefore, geometries are equal if and only if their WKB representations are equ
   {<POINT (1 1)>, <POINT (5.2 52.1)>}
 
 .. warning:: Due to limitations of WKB, linearrings will equal linestrings if they contain the exact same points.
-             See :func:`shapely.io.to_wkb`.
+             See :func:`shapely.to_wkb`.
 
 Comparing two geometries directly is also supported.
 This is the same as using :func:`shapely.predicates.equals_exact` with a ``tolerance`` value of zero.
@@ -99,3 +99,77 @@ This is the same as using :func:`shapely.predicates.equals_exact` with a ``toler
   True
   >>> point_1 != point_2
   True
+
+Formatting
+~~~~~~~~~~
+
+Geometries can be formatted to strings using properties, functions,
+or a Python format specification.
+
+The most convenient is to use ``.wkb_hex`` and ``.wkt`` properties.
+
+.. code:: python
+
+  >>> from shapely import Point, to_wkb, to_wkt, to_geojson
+  >>> pt = Point(-169.910918, -18.997564)
+  >>> pt.wkb_hex
+  0101000000CF6A813D263D65C0BDAAB35A60FF32C0
+  >>> pt.wkt
+  POINT (-169.910918 -18.997564)
+
+More output options can be found using using :func:`~shapely.to_wkb`,
+:func:`~shapely.to_wkt`, and :func:`~shapely.to_geojson` functions.
+
+.. code:: python
+
+  >>> to_wkb(pt, hex=True, byte_order=0)
+  0000000001C0653D263D816ACFC032FF605AB3AABD
+  >>> to_wkt(pt, rounding_precision=3)
+  POINT (-169.911 -18.998)
+  >>> print(to_geojson(pt, indent=2))
+  {
+    "type": "Point",
+    "coordinates": [
+      -169.910918,
+      -18.997564
+    ]
+  }
+
+A format specification may also be used to control the format and precision.
+
+.. code:: python
+
+    >>> print(f"Cave near {pt:.3f}")
+    Cave near POINT (-169.911 -18.998)
+    >>> print(f"or hex-encoded as {pt:x}")
+    or hex-encoded as 0101000000cf6a813d263d65c0bdaab35a60ff32c0
+
+Shapely has a format specification inspired from Python's
+`Format Specification Mini-Language
+<https://docs.python.org/3/library/string.html#formatspec>`_ described next.
+
+Semantic for format specification
+---------------------------------
+
+.. productionlist:: format-spec
+  format_spec: [0][.`precision`][`type`]
+  precision: `digit`+
+  type: "f" | "F" | "g" | "G" | "x" | "X"
+
+Format types ``'f'`` and ``'F'`` are to use a fixed-point notation, which is
+activated by setting GEOS' trim option off.
+The upper case variant converts ``nan`` to ``NAN`` and ``inf`` to ``INF``.
+
+Format types ``'g'`` and ``'G'`` are to use a "general format",
+where unnecessary digits are trimmed. This notation is activated by setting
+GEOS' trim option on. The upper case variant is similar to
+``'F'``, and may also display an upper-case ``"E"`` if scientific notation
+is required. Note that this representation may be different for GEOS 3.10.0
+and later, which does not use scientific notation.
+
+For numeric outputs ``'f'`` and ``'g'``, the precision is optional, and if not
+specified, rounding precision will be disabled showing full precision.
+
+Format types ``'x'`` and ``'X'`` show a hex-encoded string representation of
+WKB or Well-Known Binary, with the case of the output matched the
+case of the format type character.


=====================================
docs/migration_pygeos.rst
=====================================
@@ -87,3 +87,4 @@ Other differences
 - The behaviour of ``union_all()`` / ``intersection_all()`` / ``symmetric_difference_all``
   was changed to return an empty GeometryCollection for an empty or all-None
   sequence as input (instead of returning None).
+- The ``radius`` keyword of the ``buffer()`` funtion was renamed to ``distance``.


=====================================
shapely/constructive.py
=====================================
@@ -83,7 +83,7 @@ MultiLineString, MultiPoint, Point, Polygon
 @multithreading_enabled
 def buffer(
     geometry,
-    radius,
+    distance,
     quad_segs=8,
     cap_style="round",
     join_style="round",
@@ -92,11 +92,11 @@ def buffer(
     **kwargs
 ):
     """
-    Computes the buffer of a geometry for positive and negative buffer radius.
+    Computes the buffer of a geometry for positive and negative buffer distance.
 
     The buffer of a geometry is defined as the Minkowski sum (or difference,
-    for negative width) of the geometry with a circle with radius equal to the
-    absolute value of the buffer radius.
+    for negative distance) of the geometry with a circle with radius equal
+    to the absolute value of the buffer distance.
 
     The buffer operation always returns a polygonal result. The negative
     or zero-distance buffer of lines and points is always empty.
@@ -104,7 +104,7 @@ def buffer(
     Parameters
     ----------
     geometry : Geometry or array_like
-    width : float or array_like
+    distance : float or array_like
         Specifies the circle radius in the Minkowski sum (or difference)..
     quad_segs : int, default 8
         Specifies the number of linear segments in a quarter circle in the
@@ -178,7 +178,7 @@ def buffer(
         raise TypeError("single_sided only accepts scalar values")
     return lib.buffer(
         geometry,
-        radius,
+        distance,
         np.intc(quad_segs),
         np.intc(cap_style),
         np.intc(join_style),


=====================================
shapely/geometry/base.py
=====================================
@@ -5,6 +5,7 @@ geometry objects, but has no effect on geometric analysis. All
 operations are performed in the x-y plane. Thus, geometries with
 different z values may intersect or be equal.
 """
+import re
 from warnings import warn
 
 import numpy as np
@@ -81,7 +82,7 @@ class BaseGeometry(shapely.Geometry):
 
     """
 
-    __slots__ = ["__weakref__"]
+    __slots__ = []
 
     def __new__(self):
         warn(
@@ -103,6 +104,51 @@ class BaseGeometry(shapely.Geometry):
     def __nonzero__(self):
         return self.__bool__()
 
+    def __format__(self, format_spec):
+        """Format a geometry using a format specification."""
+        # bypass reqgexp for simple cases
+        if format_spec == "":
+            return shapely.to_wkt(self, rounding_precision=-1)
+        elif format_spec == "x":
+            return shapely.to_wkb(self, hex=True).lower()
+        elif format_spec == "X":
+            return shapely.to_wkb(self, hex=True)
+
+        # fmt: off
+        format_spec_regexp = (
+            "(?:0?\\.(?P<prec>[0-9]+))?"
+            "(?P<fmt_code>[fFgGxX]?)"
+        )
+        # fmt: on
+        match = re.fullmatch(format_spec_regexp, format_spec)
+        if match is None:
+            raise ValueError(f"invalid format specifier: {format_spec}")
+
+        prec, fmt_code = match.groups()
+
+        if prec:
+            prec = int(prec)
+        else:
+            # GEOS has a default rounding_precision -1
+            prec = -1
+
+        if not fmt_code:
+            fmt_code = "g"
+
+        if fmt_code in ("g", "G"):
+            res = shapely.to_wkt(self, rounding_precision=prec, trim=True)
+        elif fmt_code in ("f", "F"):
+            res = shapely.to_wkt(self, rounding_precision=prec, trim=False)
+        elif fmt_code in ("x", "X"):
+            raise ValueError("hex representation does not specify precision")
+        else:
+            raise NotImplementedError(f"unhandled fmt_code: {fmt_code}")
+
+        if fmt_code.isupper():
+            return res.upper()
+        else:
+            return res
+
     def __repr__(self):
         try:
             wkt = super().__str__()
@@ -464,6 +510,8 @@ class BaseGeometry(shapely.Geometry):
 
         if mitre_limit == 0.0:
             raise ValueError("Cannot compute offset from zero-length line segment")
+        elif not np.isfinite(distance):
+            raise ValueError("buffer distance must be finite")
 
         return shapely.buffer(
             self,


=====================================
shapely/geometry/linestring.py
=====================================
@@ -1,5 +1,6 @@
 """Line strings and related utilities
 """
+import numpy as np
 
 import shapely
 from shapely.geometry.base import BaseGeometry, JOIN_STYLE
@@ -146,6 +147,8 @@ class LineString(BaseGeometry):
         """
         if mitre_limit == 0.0:
             raise ValueError("Cannot compute offset from zero-length line segment")
+        elif not np.isfinite(distance):
+            raise ValueError("offset_curve distance must be finite")
         return shapely.offset_curve(self, distance, quad_segs, join_style, mitre_limit)
 
     def parallel_offset(


=====================================
shapely/geometry/point.py
=====================================
@@ -65,14 +65,12 @@ class Point(BaseGeometry):
             if not hasattr(coords, "__getitem__"):  # generators
                 coords = list(coords)
 
-            if isinstance(coords[0], tuple):
-                coords = coords[0]
-
-            geom = shapely.points(coords)
+            coords = np.asarray(coords).squeeze()
         else:
             # 2 or 3 args
-            geom = shapely.points(np.array(args))
+            coords = np.array(args).squeeze()
 
+        geom = shapely.points(coords)
         if not isinstance(geom, Point):
             raise ValueError("Invalid values passed to Point constructor")
         return geom


=====================================
shapely/tests/geometry/test_format.py
=====================================
@@ -0,0 +1,111 @@
+import pytest
+
+from shapely import Point, Polygon
+from shapely.geos import geos_version
+
+
+def test_format_invalid():
+    # check invalid spec formats
+    pt = Point(1, 2)
+    test_list = [
+        ("5G", ValueError, "invalid format specifier"),
+        (".f", ValueError, "invalid format specifier"),
+        ("0.2e", ValueError, "invalid format specifier"),
+        (".1x", ValueError, "hex representation does not specify precision"),
+    ]
+    for format_spec, err, match in test_list:
+        with pytest.raises(err, match=match):
+            format(pt, format_spec)
+
+
+def test_format_point():
+    # example coordinate data
+    xy1 = (0.12345678901234567, 1.2345678901234567e10)
+    xy2 = (-169.910918, -18.997564)
+    xyz3 = (630084, 4833438, 76)
+
+    # list of tuples to test; see structure at top of the for-loop
+    test_list = [
+        (".0f", xy1, "POINT (0 12345678901)", True),
+        (".1f", xy1, "POINT (0.1 12345678901.2)", True),
+        ("0.2f", xy2, "POINT (-169.91 -19.00)", True),
+        (".3F", (float("inf"), -float("inf")), "POINT (INF -INF)", True),
+    ]
+    if geos_version < (3, 10, 0):
+        # 'g' format varies depending on GEOS version
+        test_list += [
+            (".1g", xy1, "POINT (0.1 1e+10)", True),
+            (".6G", xy1, "POINT (0.123457 1.23457E+10)", True),
+            ("0.12g", xy1, "POINT (0.123456789012 12345678901.2)", True),
+            ("0.4g", xy2, "POINT (-169.9 -19)", True),
+        ]
+    else:
+        test_list += [
+            (".1g", xy1, "POINT (0.1 12345678901.2)", False),
+            (".6G", xy1, "POINT (0.123457 12345678901.234568)", False),
+            ("0.12g", xy1, "POINT (0.123456789012 12345678901.234568)", False),
+            ("g", xy2, "POINT (-169.910918 -18.997564)", False),
+            ("0.2g", xy2, "POINT (-169.91 -19)", False),
+        ]
+    # without precsions test GEOS rounding_precision=-1; different than Python
+    test_list += [
+        ("f", (1, 2), f"POINT ({1:.16f} {2:.16f})", False),
+        ("F", xyz3, "POINT Z ({:.16f} {:.16f} {:.16f})".format(*xyz3), False),
+        ("g", xyz3, "POINT Z (630084 4833438 76)", False),
+    ]
+    for format_spec, coords, expt_wkt, same_python_float in test_list:
+        pt = Point(*coords)
+        # basic checks
+        assert f"{pt}" == pt.wkt
+        assert format(pt, "") == pt.wkt
+        assert format(pt, "x") == pt.wkb_hex.lower()
+        assert format(pt, "X") == pt.wkb_hex
+        # check formatted WKT to expected
+        assert format(pt, format_spec) == expt_wkt, format_spec
+        # check Python's format consistency
+        text_coords = expt_wkt[expt_wkt.index("(") + 1 : expt_wkt.index(")")]
+        is_same = []
+        for coord, expt_coord in zip(coords, text_coords.split()):
+            py_fmt_float = format(float(coord), format_spec)
+            if same_python_float:
+                assert py_fmt_float == expt_coord, format_spec
+            else:
+                is_same.append(py_fmt_float == expt_coord)
+        if not same_python_float:
+            assert not all(is_same), f"{format_spec!r} with {expt_wkt}"
+
+
+def test_format_polygon():
+    # check basic cases
+    poly = Point(0, 0).buffer(10, 2)
+    assert f"{poly}" == poly.wkt
+    assert format(poly, "") == poly.wkt
+    assert format(poly, "x") == poly.wkb_hex.lower()
+    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))>"
+    )
+
+    # 'g' format varies depending on GEOS version
+    if geos_version < (3, 10, 0):
+        expected_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 = (
+            "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()
+    assert f"{empty}" == "POLYGON EMPTY"
+    assert format(empty, "") == empty.wkt
+    assert format(empty, ".2G") == empty.wkt
+    assert format(empty, "x") == empty.wkb_hex.lower()
+    assert format(empty, "X") == empty.wkb_hex


=====================================
shapely/tests/geometry/test_geometry_base.py
=====================================
@@ -1,3 +1,4 @@
+import platform
 import weakref
 
 import numpy as np
@@ -45,6 +46,10 @@ geometries_all_types = [
 ]
 
 
+ at pytest.mark.skipif(
+    platform.python_implementation() == "PyPy",
+    reason="Setting custom attributes doesn't fail on PyPy",
+)
 @pytest.mark.parametrize("geom", geometries_all_types)
 def test_setattr_disallowed(geom):
     with pytest.raises(AttributeError):


=====================================
shapely/tests/geometry/test_hash.py
=====================================
@@ -1,35 +1,28 @@
-from shapely import GeometryCollection, LineString, MultiPoint, Point
-
-
-def test_point():
-    g = Point(1, 2)
-    assert hash(g) == hash(Point(1, 2))
-    assert hash(g) != hash(Point(1, 3))
-
-
-def test_multipoint():
-    g = MultiPoint([(1, 2), (3, 4)])
-    assert hash(g) == hash(MultiPoint([(1, 2), (3, 4)]))
-    assert hash(g) != hash(MultiPoint([(1, 2), (3, 3)]))
-
-
-def test_linestring():
-    g = LineString([(1, 2), (3, 4)])
-    assert hash(g) == hash(LineString([(1, 2), (3, 4)]))
-    assert hash(g) != hash(LineString([(1, 2), (3, 3)]))
-
-
-def test_polygon():
-    g = Point(0, 0).buffer(1.0)
-    assert hash(g) == hash(Point(0, 0).buffer(1.0))
-    assert hash(g) != hash(Point(0, 0).buffer(1.1))
-
-
-def test_collection():
-    g = GeometryCollection([Point(1, 2), LineString([(1, 2), (3, 4)])])
-    assert hash(g) == hash(
-        GeometryCollection([Point(1, 2), LineString([(1, 2), (3, 4)])])
-    )
-    assert hash(g) != hash(
-        GeometryCollection([Point(1, 2), LineString([(1, 2), (3, 3)])])
-    )
+import pytest
+
+import shapely
+from shapely.affinity import translate
+from shapely.geometry import GeometryCollection, LineString, MultiPoint, Point
+
+
+ at pytest.mark.parametrize(
+    "geom",
+    [
+        Point(1, 2),
+        MultiPoint([(1, 2), (3, 4)]),
+        LineString([(1, 2), (3, 4)]),
+        Point(0, 0).buffer(1.0),
+        GeometryCollection([Point(1, 2), LineString([(1, 2), (3, 4)])]),
+    ],
+    ids=[
+        "Point",
+        "MultiPoint",
+        "LineString",
+        "Polygon",
+        "GeometryCollection",
+    ],
+)
+def test_hash(geom):
+    h1 = hash(geom)
+    assert h1 == hash(shapely.from_wkb(geom.wkb))
+    assert h1 != hash(translate(geom, 1.0, 2.0))


=====================================
shapely/tests/geometry/test_point.py
=====================================
@@ -34,6 +34,8 @@ def test_from_sequence():
     # From coordinate sequence
     p = Point([(3.0, 4.0)])
     assert p.coords[:] == [(3.0, 4.0)]
+    p = Point([[3.0, 4.0]])
+    assert p.coords[:] == [(3.0, 4.0)]
 
     # 3D
     p = Point((3.0, 4.0, 5.0))
@@ -53,6 +55,17 @@ def test_from_numpy():
     assert p.coords[:] == [(1.0, 2.0, 3.0)]
 
 
+def test_from_numpy_xy():
+    # Construct from separate x, y numpy arrays - if those are length 1,
+    # this is allowed for compat with shapely 1.8
+    # (https://github.com/shapely/shapely/issues/1587)
+    p = Point(np.array([1.0]), np.array([2.0]))
+    assert p.coords[:] == [(1.0, 2.0)]
+
+    p = Point(np.array([1.0]), np.array([2.0]), np.array([3.0]))
+    assert p.coords[:] == [(1.0, 2.0, 3.0)]
+
+
 def test_from_point():
     # From another point
     p = Point(3.0, 4.0)


=====================================
src/pygeom.c
=====================================
@@ -38,11 +38,15 @@ PyObject* GeometryObject_FromGEOS(GEOSGeometry* ptr, GEOSContextHandle_t ctx) {
   } else {
     self->ptr = ptr;
     self->ptr_prepared = NULL;
+    self->weakreflist = (PyObject *)NULL;
     return (PyObject*)self;
   }
 }
 
 static void GeometryObject_dealloc(GeometryObject* self) {
+  if (self->weakreflist != NULL) {
+    PyObject_ClearWeakRefs((PyObject *)self);
+  }
   if (self->ptr != NULL) {
     // not using GEOS_INIT, but using global context instead
     GEOSContextHandle_t ctx = geos_context[0];
@@ -396,6 +400,7 @@ PyTypeObject GeometryType = {
     .tp_repr = (reprfunc)GeometryObject_repr,
     .tp_hash = (hashfunc)GeometryObject_hash,
     .tp_richcompare = (richcmpfunc)GeometryObject_richcompare,
+    .tp_weaklistoffset = offsetof(GeometryObject, weakreflist),
     .tp_str = (reprfunc)GeometryObject_str,
 };
 


=====================================
src/pygeom.h
=====================================
@@ -6,8 +6,11 @@
 #include "geos.h"
 
 typedef struct {
-  PyObject_HEAD void* ptr;
+  PyObject_HEAD
+  void* ptr;
   void* ptr_prepared;
+  /* For weak references */
+  PyObject *weakreflist;
 } GeometryObject;
 
 extern PyTypeObject GeometryType;


=====================================
tests/test_binascii_hex.txt deleted
=====================================
@@ -1,47 +0,0 @@
-Round-tripping geometries through hex-encoded binary
-====================================================
-
-Hex-encoded binary is the PostGIS geometry representation, and so this is a
-test of the ability to store Shapely geometries in PostGIS.
-
-Point
------
-
-  >>> from shapely.geometry import Point
-  >>> point = Point(0.0, 0.0)
-  >>> from binascii import a2b_hex, b2a_hex
-  >>> x = b2a_hex(point.wkb)
-  >>> from shapely import wkb
-  >>> shape = wkb.loads(a2b_hex(x))
-  >>> shape # doctest: +ELLIPSIS
-  <POINT (0 0)>
-
-LineString
-----------
-
-  >>> from shapely.geometry import LineString
-  >>> line = LineString([(0.0, 0.0), (1.0, 1.0)])
-  >>> x = b2a_hex(line.wkb)
-  >>> shape = wkb.loads(a2b_hex(x))
-  >>> shape # doctest: +ELLIPSIS
-  <LINESTRING (0 0, 1 1)>
-
-Polygon
-----------
-
-  >>> from shapely.geometry import Polygon
-  >>> polygon = Polygon([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)])
-  >>> x = b2a_hex(polygon.wkb)
-  >>> shape = wkb.loads(a2b_hex(x))
-  >>> shape # doctest: +ELLIPSIS
-  <POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))>
-
-Polygon with hole
------------------
-
-  >>> polygon = Polygon([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)], [[(0.1,0.1), (0.1,0.2), (0.2,0.2), (0.2,0.1)]])
-  >>> x = b2a_hex(polygon.wkb)
-  >>> shape = wkb.loads(a2b_hex(x))
-  >>> shape.wkt # doctest: +ELLIPSIS
-  'POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0), (0.1 0.1, 0.1 0.2, 0.2 0.2, 0.2 0.1, 0.1 0.1))'
-


=====================================
tests/test_buffer.py
=====================================
@@ -6,6 +6,13 @@ from shapely.geometry.base import CAP_STYLE, JOIN_STYLE
 from shapely.constructive import BufferCapStyle, BufferJoinStyle
 
 
+ at pytest.mark.parametrize("distance", [float("nan"), float("inf")])
+def test_non_finite_distance(distance):
+    g = geometry.Point(0, 0)
+    with pytest.raises(ValueError, match="distance must be finite"):
+        g.buffer(distance)
+
+
 class BufferTests(unittest.TestCase):
     """Test Buffer Point/Line/Polygon with and without single_sided params"""
 


=====================================
tests/test_doctests.py deleted
=====================================
@@ -1,36 +0,0 @@
-import os
-import doctest
-from . import unittest
-from glob import glob
-
-optionflags = (doctest.REPORT_ONLY_FIRST_FAILURE |
-               doctest.NORMALIZE_WHITESPACE |
-               doctest.ELLIPSIS)
-
-
-def list_doctests():
-    print(__file__)
-    source_files = glob(os.path.join(os.path.dirname(__file__), '*.txt'))
-    return [filename for filename in source_files]
-
-
-def open_file(filename, mode='r'):
-    """Helper function to open files from within the tests package."""
-    return open(os.path.join(os.path.dirname(__file__), filename), mode)
-
-
-def setUp(test):
-    test.globs.update(dict(open_file=open_file,))
-
-
-def test_suite():
-    return unittest.TestSuite(
-        [doctest.DocFileSuite(os.path.basename(filename),
-                              optionflags=optionflags,
-                              setUp=setUp)
-         for filename
-         in list_doctests()])
-
-if __name__ == "__main__":
-    runner = unittest.TextTestRunner(verbosity=1)
-    runner.run(test_suite())


=====================================
tests/test_parallel_offset.py
=====================================
@@ -1,8 +1,17 @@
+import pytest
+
 from . import unittest
 from shapely.geometry import LineString, LinearRing
 from shapely.testing import assert_geometries_equal
 
 
+ at pytest.mark.parametrize("distance", [float("nan"), float("inf")])
+def test_non_finite_distance(distance):
+    g = LineString([(0, 0), (10, 0)])
+    with pytest.raises(ValueError, match="distance must be finite"):
+        g.parallel_offset(distance)
+
+
 class OperationsTestCase(unittest.TestCase):
 
     def test_parallel_offset_linestring(self):



View it on GitLab: https://salsa.debian.org/debian-gis-team/python-shapely/-/compare/aa946a47498792eac2f8c971efc9c9a82bb5febd...5d8be325bfb0baa14cf9e19dc110d8837f3af5a4

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-shapely/-/compare/aa946a47498792eac2f8c971efc9c9a82bb5febd...5d8be325bfb0baa14cf9e19dc110d8837f3af5a4
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20221029/9a5bb66a/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list