Repository: shapely/shapely
Pull request #1502 (2022-08-25 10:48:19)

DOC: update migration guide to use 'packaging' instead of 'distutils'
Distutils is deprecated, so the documentation should suggest an alternative method to compare versions (one of [many](https://stackoverflow.com/q/11887762)).

Also, this approach needed `version.parse("2.0a1")` to be compared to work with the existing pre-release.

coveralls: ## Pull Request Test Coverage Report for [Build 2925931821](https://coveralls.io/builds/51940255)

* **0** of **0**   changed or added relevant lines in **0** files are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage remained the same at **85.844%**

---



|  Totals | [![Coverage Status](https://coveralls.io/builds/51940255/badge)](https://coveralls.io/builds/51940255) |
| :-- | --: |
| Change from base [Build 2878254665](https://coveralls.io/builds/51745917): |  0.0% |
| Covered Lines: | 3014 |
| Relevant Lines: | 3511 |

---
##### 💛  - [Coveralls](https://coveralls.io)


Patch:
diff --git a/docs/migration.rst b/docs/migration.rst
index 217170c..afb9136 100644
--- a/docs/migration.rst
+++ b/docs/migration.rst
@@ -261,9 +261,9 @@ manager that can be copied into your project::
     import contextlib
     import shapely
     import warnings
-    from distutils.version import LooseVersion
+    from packaging import version  # https://packaging.pypa.io/
 
-    SHAPELY_GE_20 = str(shapely.__version__) >= LooseVersion("2.0")
+    SHAPELY_GE_20 = version.parse(shapely.__version__) >= version.parse("2.0a1")
 
     try:
         from shapely.errors import ShapelyDeprecationWarning as shapely_warning
diff --git a/shapely/geometry/base.py b/shapely/geometry/base.py
index 0a5b053..74a2da4 100644
--- a/shapely/geometry/base.py
+++ b/shapely/geometry/base.py
@@ -622,6 +622,8 @@ class BaseGeometry:
         if mitre_limit == 0.0:
             raise ValueError(
                 'Cannot compute offset from zero-length line segment')
+        elif not math.isfinite(distance):
+            raise ValueError("buffer distance must be finite")
 
         if 'buffer_with_params' in self.impl:
             params = self._lgeos.GEOSBufferParams_create()
diff --git a/shapely/geometry/linestring.py b/shapely/geometry/linestring.py
index 9a4ede8..13484f4 100644
--- a/shapely/geometry/linestring.py
+++ b/shapely/geometry/linestring.py
@@ -2,6 +2,7 @@
 """
 
 from ctypes import c_double
+import math
 import warnings
 
 from shapely.coords import CoordinateSequence
@@ -171,6 +172,8 @@ class LineString(BaseGeometry):
         if mitre_limit == 0.0:
             raise ValueError(
                 'Cannot compute offset from zero-length line segment')
+        elif not math.isfinite(distance):
+            raise ValueError("parallel_offset distance must be finite")
         try:
             return geom_factory(self.impl['parallel_offset'](
                 self, distance, resolution, join_style, mitre_limit, side))


Test patch:
diff --git a/tests/test_buffer.py b/tests/test_buffer.py
index 0e83530..6fd8478 100644
--- a/tests/test_buffer.py
+++ b/tests/test_buffer.py
@@ -1,7 +1,16 @@
+import pytest
+
 from . import unittest
 from shapely import geometry
 
 
+@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 BufferSingleSidedCase(unittest.TestCase):
     """ Test Buffer Point/Line/Polygon with and without single_sided params """
 
diff --git a/tests/test_parallel_offset.py b/tests/test_parallel_offset.py
index 661291a..09f3834 100644
--- a/tests/test_parallel_offset.py
+++ b/tests/test_parallel_offset.py
@@ -1,6 +1,15 @@
+import pytest
+
 from . import unittest
 from shapely.geometry import LineString, LinearRing
-from shapely.wkt import loads
+
+
+@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):