shapely 2.1.0__tar.gz → 2.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {shapely-2.1.0 → shapely-2.1.1}/CHANGES.txt +11 -0
- {shapely-2.1.0 → shapely-2.1.1}/CITATION.cff +2 -2
- {shapely-2.1.0 → shapely-2.1.1}/PKG-INFO +1 -1
- {shapely-2.1.0 → shapely-2.1.1}/docs/geometry.rst +28 -14
- {shapely-2.1.0 → shapely-2.1.1}/docs/manual.rst +1 -28
- {shapely-2.1.0 → shapely-2.1.1}/docs/migration.rst +27 -26
- {shapely-2.1.0 → shapely-2.1.1}/shapely/_geometry_helpers.pyx +46 -11
- {shapely-2.1.0 → shapely-2.1.1}/shapely/_version.py +3 -3
- {shapely-2.1.0 → shapely-2.1.1}/shapely/decorators.py +84 -34
- {shapely-2.1.0 → shapely-2.1.1}/shapely/io.py +2 -1
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_polylabel.py +4 -1
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_constructive.py +6 -4
- shapely-2.1.1/shapely/tests/test_decorators.py +138 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_ragged_array.py +77 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely.egg-info/PKG-INFO +1 -1
- {shapely-2.1.0 → shapely-2.1.1}/shapely.egg-info/SOURCES.txt +1 -0
- {shapely-2.1.0 → shapely-2.1.1}/CREDITS.txt +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/LICENSE.txt +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/README.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/constructive.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/coordinates.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/coverage.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/creation.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/design.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/index.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/installation.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/io.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/linear.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/measurement.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/migration_pygeos.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/plotting.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/predicates.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/properties.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/release.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/set_operations.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/strtree.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/docs/testing.rst +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/pyproject.toml +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/setup.cfg +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/setup.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/__init__.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/_coverage.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/_enum.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/_geometry.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/_geos.pxd +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/_geos.pyx +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/_pygeos_api.pxd +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/_ragged_array.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/affinity.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/algorithms/__init__.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/algorithms/_oriented_envelope.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/algorithms/cga.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/algorithms/polylabel.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/conftest.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/constructive.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/coordinates.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/coords.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/creation.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/errors.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/geometry/__init__.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/geometry/base.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/geometry/collection.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/geometry/geo.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/geometry/linestring.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/geometry/multilinestring.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/geometry/multipoint.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/geometry/multipolygon.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/geometry/point.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/geometry/polygon.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/geos.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/linear.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/measurement.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/ops.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/plotting.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/predicates.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/prepared.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/set_operations.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/speedups.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/strtree.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/testing.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/__init__.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/common.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/__init__.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/test_collection.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/test_coords.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/test_decimal.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/test_emptiness.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/test_equality.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/test_format.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/test_geometry_base.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/test_hash.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/test_linestring.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/test_multi.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/test_multilinestring.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/test_multipoint.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/test_multipolygon.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/test_point.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/geometry/test_polygon.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/__init__.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/conftest.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_affinity.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_box.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_buffer.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_cga.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_clip_by_rect.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_create_inconsistent_dimensionality.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_delaunay.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_empty_polygons.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_equality.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_geointerface.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_invalid_geometries.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_linear_referencing.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_linemerge.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_locale.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_make_valid.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_mapping.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_minimum_clearance.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_ndarrays.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_nearest.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_operations.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_operators.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_orient.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_parallel_offset.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_persist.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_pickle.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_polygonize.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_predicates.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_prepared.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_products_z.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_shape.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_shared_paths.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_singularity.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_snap.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_split.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_substring.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_svg.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_transform.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_union.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_validation.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_vectorized.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_voronoi_diagram.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_wkb.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/test_wkt.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/legacy/threading_test.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_coordinates.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_coverage.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_creation.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_creation_indices.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_geometry.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_io.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_linear.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_measurement.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_misc.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_plotting.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_predicates.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_set_operations.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_strtree.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/tests/test_testing.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/validation.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/vectorized/__init__.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/wkb.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely/wkt.py +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely.egg-info/dependency_links.txt +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely.egg-info/requires.txt +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/shapely.egg-info/top_level.txt +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/c_api.c +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/c_api.h +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/coords.c +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/coords.h +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/fast_loop_macros.h +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/geos.c +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/geos.h +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/kvec.h +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/lib.c +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/pygeom.c +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/pygeom.h +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/pygeos.c +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/pygeos.h +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/strtree.c +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/strtree.h +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/ufuncs.c +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/ufuncs.h +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/vector.c +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/src/vector.h +0 -0
- {shapely-2.1.0 → shapely-2.1.1}/versioneer.py +0 -0
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
Changes
|
|
2
2
|
=======
|
|
3
3
|
|
|
4
|
+
2.1.1 (2025-05-19)
|
|
5
|
+
------------------
|
|
6
|
+
|
|
7
|
+
Bug fixes:
|
|
8
|
+
|
|
9
|
+
- Fix performance degradation calling shapely functions (caused by deprecation
|
|
10
|
+
of certain positional arguments) (#2283).
|
|
11
|
+
- Fix crash caused by `from_ragged_array()` (#2291).
|
|
12
|
+
- Fix compilation error building with recent LLVM toolchain (#2293).
|
|
13
|
+
|
|
14
|
+
|
|
4
15
|
2.1.0 (2025-04-03)
|
|
5
16
|
------------------
|
|
6
17
|
|
|
@@ -2,8 +2,8 @@ cff-version: 1.2.0
|
|
|
2
2
|
message: "Please cite this software using these metadata."
|
|
3
3
|
type: software
|
|
4
4
|
title: Shapely
|
|
5
|
-
version: "2.1.
|
|
6
|
-
date-released: "2025-
|
|
5
|
+
version: "2.1.1"
|
|
6
|
+
date-released: "2025-05-19"
|
|
7
7
|
doi: 10.5281/zenodo.5597138
|
|
8
8
|
abstract: "Manipulation and analysis of geometric objects in the Cartesian plane."
|
|
9
9
|
repository-artifact: https://pypi.org/project/Shapely
|
|
@@ -84,7 +84,7 @@ Therefore, geometries are equal if and only if their WKB representations are equ
|
|
|
84
84
|
>>> point_1 = Point(5.2, 52.1)
|
|
85
85
|
>>> point_2 = Point(1, 1)
|
|
86
86
|
>>> point_3 = Point(5.2, 52.1)
|
|
87
|
-
>>> {point_1, point_2, point_3}
|
|
87
|
+
>>> {point_1, point_2, point_3} # doctest: +SKIP
|
|
88
88
|
{<POINT (1 1)>, <POINT (5.2 52.1)>}
|
|
89
89
|
|
|
90
90
|
.. warning:: Due to limitations of WKB, linearrings will equal linestrings if they contain the exact same points.
|
|
@@ -113,9 +113,9 @@ The most convenient is to use ``.wkb_hex`` and ``.wkt`` properties.
|
|
|
113
113
|
>>> from shapely import Point, to_wkb, to_wkt, to_geojson
|
|
114
114
|
>>> pt = Point(-169.910918, -18.997564)
|
|
115
115
|
>>> pt.wkb_hex
|
|
116
|
-
0101000000CF6A813D263D65C0BDAAB35A60FF32C0
|
|
116
|
+
'0101000000CF6A813D263D65C0BDAAB35A60FF32C0'
|
|
117
117
|
>>> pt.wkt
|
|
118
|
-
POINT (-169.910918 -18.997564)
|
|
118
|
+
'POINT (-169.910918 -18.997564)'
|
|
119
119
|
|
|
120
120
|
More output options can be found using using :func:`~shapely.to_wkb`,
|
|
121
121
|
:func:`~shapely.to_wkt`, and :func:`~shapely.to_geojson` functions.
|
|
@@ -123,9 +123,9 @@ More output options can be found using using :func:`~shapely.to_wkb`,
|
|
|
123
123
|
.. code:: python
|
|
124
124
|
|
|
125
125
|
>>> to_wkb(pt, hex=True, byte_order=0)
|
|
126
|
-
0000000001C0653D263D816ACFC032FF605AB3AABD
|
|
126
|
+
'0000000001C0653D263D816ACFC032FF605AB3AABD'
|
|
127
127
|
>>> to_wkt(pt, rounding_precision=3)
|
|
128
|
-
POINT (-169.911 -18.998)
|
|
128
|
+
'POINT (-169.911 -18.998)'
|
|
129
129
|
>>> print(to_geojson(pt, indent=2))
|
|
130
130
|
{
|
|
131
131
|
"type": "Point",
|
|
@@ -158,21 +158,35 @@ Semantic for format specification
|
|
|
158
158
|
|
|
159
159
|
Format types ``'f'`` and ``'F'`` are to use a fixed-point notation, which is
|
|
160
160
|
activated by setting GEOS' trim option off.
|
|
161
|
-
The upper case variant converts ``nan`` to ``NAN`` and ``inf`` to ``INF``.
|
|
162
161
|
|
|
163
|
-
Format types ``'g'`` and ``'G'`` are to use a "general format",
|
|
162
|
+
Format types ``'g'`` (default) and ``'G'`` are to use a "general format",
|
|
164
163
|
where unnecessary digits are trimmed. This notation is activated by setting
|
|
165
|
-
GEOS' trim option on.
|
|
166
|
-
|
|
167
|
-
is required. Note that this representation may be different for GEOS 3.10.0
|
|
168
|
-
and later, which does not use scientific notation.
|
|
164
|
+
GEOS' trim option on. This option sometimes enables
|
|
165
|
+
:ref:`scientific-formatting`.
|
|
169
166
|
|
|
170
|
-
For numeric outputs ``
|
|
167
|
+
For numeric outputs ``[fFgG]``, the precision is optional, and if not
|
|
171
168
|
specified, rounding precision will be disabled showing full precision.
|
|
172
169
|
|
|
173
170
|
Format types ``'x'`` and ``'X'`` show a hex-encoded string representation of
|
|
174
|
-
WKB or Well-Known Binary
|
|
175
|
-
|
|
171
|
+
WKB or Well-Known Binary.
|
|
172
|
+
|
|
173
|
+
The upper case letter variant converts all non-numeric values to uppercase,
|
|
174
|
+
e.g. ``nan`` to ``NAN``, or ``e`` to ``E``.
|
|
175
|
+
|
|
176
|
+
.. _scientific-formatting:
|
|
177
|
+
|
|
178
|
+
Scientific formatting
|
|
179
|
+
---------------------
|
|
180
|
+
|
|
181
|
+
WKT outputs may sometimes use scientific formatting, depending on the GEOS
|
|
182
|
+
version, coordinate value and WKT writer options. GEOS versions 3.10 to 3.12
|
|
183
|
+
never use scientific formatting (only showing positional), while older and
|
|
184
|
+
newer versions may use scientific formatting for large and small coordinate
|
|
185
|
+
values (e.g. ``POINT (1.234e+18 1.234e-11)``).
|
|
186
|
+
|
|
187
|
+
Scientific formatting can always be disabled by setting ``trim=False`` for
|
|
188
|
+
:func:`~shapely.to_wkt` or other WKT writer methods,
|
|
189
|
+
which sets the WKT writer to use fixed-precision number formatting.
|
|
176
190
|
|
|
177
191
|
.. _canonical-form:
|
|
178
192
|
|
|
@@ -1285,34 +1285,7 @@ and that copies of these are collected into a list
|
|
|
1285
1285
|
>>> features = [c, a, d, b, c]
|
|
1286
1286
|
|
|
1287
1287
|
that we'd prefer to have ordered as ``[d, c, c, b, a]`` in reverse containment
|
|
1288
|
-
order.
|
|
1289
|
-
function that operates on each list element and returns a value for comparison.
|
|
1290
|
-
Our key function will be a wrapper class that implements ``__lt__()`` using
|
|
1291
|
-
Shapely's binary :meth:`~object.within` predicate.
|
|
1292
|
-
|
|
1293
|
-
.. code-block:: python
|
|
1294
|
-
|
|
1295
|
-
>>> class Within:
|
|
1296
|
-
... def __init__(self, o):
|
|
1297
|
-
... self.o = o
|
|
1298
|
-
... def __lt__(self, other):
|
|
1299
|
-
... return self.o.within(other.o)
|
|
1300
|
-
|
|
1301
|
-
As the howto says, the `less than` comparison is guaranteed to be used in
|
|
1302
|
-
sorting. That's what we'll rely on to spatially sort. Trying it out on features
|
|
1303
|
-
`d` and `c`, we see that it works.
|
|
1304
|
-
|
|
1305
|
-
.. code-block:: pycon
|
|
1306
|
-
|
|
1307
|
-
>>> Within(d) < Within(c)
|
|
1308
|
-
False
|
|
1309
|
-
|
|
1310
|
-
It also works on the list of features, producing the order we want.
|
|
1311
|
-
|
|
1312
|
-
.. code-block:: pycon
|
|
1313
|
-
|
|
1314
|
-
>>> [d, c, c, b, a] == sorted(features, key=Within, reverse=True)
|
|
1315
|
-
True
|
|
1288
|
+
order.
|
|
1316
1289
|
|
|
1317
1290
|
DE-9IM Relationships
|
|
1318
1291
|
--------------------
|
|
@@ -5,9 +5,9 @@ Migrating to Shapely 1.8 / 2.0
|
|
|
5
5
|
==============================
|
|
6
6
|
|
|
7
7
|
Shapely 1.8.0 is a transitional version introducing several warnings in
|
|
8
|
-
|
|
8
|
+
transition to 2.0.0.
|
|
9
9
|
|
|
10
|
-
Shapely 2.0.0
|
|
10
|
+
Shapely 2.0.0 was a major release with a refactor of the internals with
|
|
11
11
|
considerable performance improvements (based on the developments in the
|
|
12
12
|
`PyGEOS <https://github.com/pygeos/pygeos>`__ package), along with several
|
|
13
13
|
breaking changes.
|
|
@@ -33,13 +33,13 @@ can change their coordinates in-place. Illustrative code::
|
|
|
33
33
|
>>> print(line)
|
|
34
34
|
LINESTRING (0 0, 2 2)
|
|
35
35
|
|
|
36
|
-
>>> line.coords = [(0, 0), (10, 0), (10, 10)]
|
|
37
|
-
>>> print(line)
|
|
36
|
+
>>> line.coords = [(0, 0), (10, 0), (10, 10)] # doctest: +SKIP
|
|
37
|
+
>>> print(line) # doctest: +SKIP
|
|
38
38
|
LINESTRING (0 0, 10 0, 10 10)
|
|
39
39
|
|
|
40
40
|
In Shapely 1.8, this will start raising a warning::
|
|
41
41
|
|
|
42
|
-
>>> line.coords = [(0, 0), (10, 0), (10, 10)]
|
|
42
|
+
>>> line.coords = [(0, 0), (10, 0), (10, 10)] # doctest: +SKIP
|
|
43
43
|
ShapelyDeprecationWarning: Setting the 'coords' to mutate a Geometry
|
|
44
44
|
in place is deprecated, and will not be possible any more in Shapely 2.0
|
|
45
45
|
|
|
@@ -56,15 +56,16 @@ Setting custom attributes
|
|
|
56
56
|
-------------------------
|
|
57
57
|
|
|
58
58
|
Another consequence of the geometry objects becoming immutable is that
|
|
59
|
-
assigning custom attributes, which
|
|
59
|
+
assigning custom attributes, which previously worked, will no longer be
|
|
60
|
+
possible.
|
|
60
61
|
|
|
61
|
-
|
|
62
|
+
Previously, custom attributes could have ben added::
|
|
62
63
|
|
|
63
|
-
>>> line.name = "my_geometry"
|
|
64
|
-
>>> line.name
|
|
64
|
+
>>> line.name = "my_geometry" # doctest: +SKIP
|
|
65
|
+
>>> line.name # doctest: +SKIP
|
|
65
66
|
'my_geometry'
|
|
66
67
|
|
|
67
|
-
In Shapely 1.8, this will
|
|
68
|
+
In Shapely 1.8, this will raise a warning, and will raise an
|
|
68
69
|
AttributeError in Shapely 2.0.
|
|
69
70
|
|
|
70
71
|
**How do I update my code?** There is no direct alternative for adding custom
|
|
@@ -85,18 +86,18 @@ Some examples of this with Shapely 1.x:
|
|
|
85
86
|
|
|
86
87
|
>>> from shapely.geometry import Point, MultiPoint
|
|
87
88
|
>>> mp = MultiPoint([(1, 1), (2, 2), (3, 3)])
|
|
88
|
-
>>> print(mp)
|
|
89
|
+
>>> print(mp) # doctest: +SKIP
|
|
89
90
|
MULTIPOINT (1 1, 2 2, 3 3)
|
|
90
|
-
>>> for part in mp:
|
|
91
|
-
... print(part)
|
|
91
|
+
>>> for part in mp: # doctest: +SKIP
|
|
92
|
+
... print(part) # doctest: +SKIP
|
|
92
93
|
POINT (1 1)
|
|
93
94
|
POINT (2 2)
|
|
94
95
|
POINT (3 3)
|
|
95
|
-
>>> print(mp[1])
|
|
96
|
+
>>> print(mp[1]) # doctest: +SKIP
|
|
96
97
|
POINT (2 2)
|
|
97
|
-
>>> len(mp)
|
|
98
|
+
>>> len(mp) # doctest: +SKIP
|
|
98
99
|
3
|
|
99
|
-
>>> list(mp)
|
|
100
|
+
>>> list(mp) # doctest: +SKIP
|
|
100
101
|
[<shapely.geometry.point.Point at 0x7f2e0912bf10>,
|
|
101
102
|
<shapely.geometry.point.Point at 0x7f2e09fed820>,
|
|
102
103
|
<shapely.geometry.point.Point at 0x7f2e09fed4c0>]
|
|
@@ -104,8 +105,8 @@ Some examples of this with Shapely 1.x:
|
|
|
104
105
|
Starting with Shapely 1.8, all the examples above will start raising a
|
|
105
106
|
deprecation warning. For example:
|
|
106
107
|
|
|
107
|
-
>>> for part in mp:
|
|
108
|
-
... print(part)
|
|
108
|
+
>>> for part in mp: # doctest: +SKIP
|
|
109
|
+
... print(part) # doctest: +SKIP
|
|
109
110
|
ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated
|
|
110
111
|
and will be removed in Shapely 2.0. Use the `geoms` property to access the
|
|
111
112
|
constituent parts of a multi-part geometry.
|
|
@@ -129,7 +130,7 @@ The examples above can be updated to::
|
|
|
129
130
|
POINT (2 2)
|
|
130
131
|
>>> len(mp.geoms)
|
|
131
132
|
3
|
|
132
|
-
>>> list(mp.geoms)
|
|
133
|
+
>>> list(mp.geoms) # doctest: +SKIP
|
|
133
134
|
[<shapely.geometry.point.Point at 0x7f2e0912bf10>,
|
|
134
135
|
<shapely.geometry.point.Point at 0x7f2e09fed820>,
|
|
135
136
|
<shapely.geometry.point.Point at 0x7f2e09fed4c0>]
|
|
@@ -152,7 +153,7 @@ A small example::
|
|
|
152
153
|
|
|
153
154
|
>>> line = LineString([(0, 0), (1, 1), (2, 2)])
|
|
154
155
|
>>> import numpy as np
|
|
155
|
-
>>> np.asarray(line)
|
|
156
|
+
>>> np.asarray(line) # doctest: +SKIP
|
|
156
157
|
array([[0., 0.],
|
|
157
158
|
[1., 1.],
|
|
158
159
|
[2., 2.]])
|
|
@@ -160,9 +161,9 @@ A small example::
|
|
|
160
161
|
In addition, there are also the explicit ``array_interface()`` method and
|
|
161
162
|
``ctypes`` attribute to get access to the coordinates as array data:
|
|
162
163
|
|
|
163
|
-
>>> line.ctypes
|
|
164
|
+
>>> line.ctypes # doctest: +SKIP
|
|
164
165
|
<shapely.geometry.linestring.c_double_Array_6 at 0x7f75261eb740>
|
|
165
|
-
>>> line.array_interface()
|
|
166
|
+
>>> line.array_interface() # doctest: +SKIP
|
|
166
167
|
{'version': 3,
|
|
167
168
|
'typestr': '<f8',
|
|
168
169
|
'data': <shapely.geometry.linestring.c_double_Array_6 at 0x7f752664ae40>,
|
|
@@ -177,7 +178,7 @@ removed from those geometry classes, and limited to the ``coords``.
|
|
|
177
178
|
Starting with Shapely 1.8, converting a geometry object to a NumPy array
|
|
178
179
|
directly will start raising a warning::
|
|
179
180
|
|
|
180
|
-
>>> np.asarray(line)
|
|
181
|
+
>>> np.asarray(line) # doctest: +SKIP
|
|
181
182
|
ShapelyDeprecationWarning: The array interface is deprecated and will no longer
|
|
182
183
|
work in Shapely 2.0. Convert the '.coords' to a NumPy array instead.
|
|
183
184
|
array([[0., 0.],
|
|
@@ -209,7 +210,7 @@ as follows::
|
|
|
209
210
|
|
|
210
211
|
>>> from shapely.geometry import Point
|
|
211
212
|
>>> arr = np.array([Point(0, 0), Point(1, 1), Point(2, 2)])
|
|
212
|
-
>>> arr
|
|
213
|
+
>>> arr # doctest: +SKIP
|
|
213
214
|
array([<shapely.geometry.point.Point object at 0x7fb798407cd0>,
|
|
214
215
|
<shapely.geometry.point.Point object at 0x7fb7982831c0>,
|
|
215
216
|
<shapely.geometry.point.Point object at 0x7fb798283b80>],
|
|
@@ -300,7 +301,7 @@ creation methods. A small example for an empty Polygon geometry:
|
|
|
300
301
|
>>> g1 = Polygon()
|
|
301
302
|
>>> type(g1)
|
|
302
303
|
<class 'shapely.geometry.polygon.Polygon'>
|
|
303
|
-
>>> g1.wkt
|
|
304
|
+
>>> g1.wkt # doctest: +SKIP
|
|
304
305
|
GEOMETRYCOLLECTION EMPTY
|
|
305
306
|
|
|
306
307
|
# Converting from WKT gives a correct empty polygon
|
|
@@ -309,7 +310,7 @@ creation methods. A small example for an empty Polygon geometry:
|
|
|
309
310
|
>>> type(g2)
|
|
310
311
|
<class 'shapely.geometry.polygon.Polygon'>
|
|
311
312
|
>>> g2.wkt
|
|
312
|
-
POLYGON EMPTY
|
|
313
|
+
'POLYGON EMPTY'
|
|
313
314
|
|
|
314
315
|
Shapely 1.8 does not yet change this inconsistent behaviour, but starting
|
|
315
316
|
with Shapely 2.0, the different methods will always consistently give an
|
|
@@ -284,7 +284,7 @@ def get_parts(object[:] array, bint extract_rings=0):
|
|
|
284
284
|
|
|
285
285
|
@cython.boundscheck(False)
|
|
286
286
|
@cython.wraparound(False)
|
|
287
|
-
cdef void _deallocate_arr(
|
|
287
|
+
cdef void _deallocate_arr(GEOSContextHandle_t handle, np.intp_t[:] arr, Py_ssize_t last_geom_i) noexcept nogil:
|
|
288
288
|
"""Deallocate a temporary geometry array to prevent memory leaks"""
|
|
289
289
|
cdef Py_ssize_t i = 0
|
|
290
290
|
cdef GEOSGeometry *g
|
|
@@ -421,7 +421,7 @@ def collections_1d(object geometries, object indices, int geometry_type = 7, obj
|
|
|
421
421
|
coll = GEOSGeom_createPolygon_r(
|
|
422
422
|
geos_handle,
|
|
423
423
|
<GEOSGeometry*> temp_geoms_view[0],
|
|
424
|
-
NULL if coll_size <= 1 else <GEOSGeometry**> &temp_geoms_view[1],
|
|
424
|
+
<GEOSGeometry**> NULL if coll_size <= 1 else <GEOSGeometry**> &temp_geoms_view[1],
|
|
425
425
|
coll_size - 1
|
|
426
426
|
)
|
|
427
427
|
else: # Polygon, empty
|
|
@@ -454,7 +454,7 @@ def _from_ragged_array_multi_linear(
|
|
|
454
454
|
MultiLineString (geometry_type 5): linear_type is a LineString (1)
|
|
455
455
|
"""
|
|
456
456
|
cdef:
|
|
457
|
-
Py_ssize_t n_geoms
|
|
457
|
+
Py_ssize_t n_total_coords, n_rings, n_geoms
|
|
458
458
|
Py_ssize_t i, k
|
|
459
459
|
Py_ssize_t i1, i2, k1, k2
|
|
460
460
|
Py_ssize_t n_coords, linear_idx
|
|
@@ -463,12 +463,26 @@ def _from_ragged_array_multi_linear(
|
|
|
463
463
|
GEOSGeometry *linear = NULL
|
|
464
464
|
GEOSGeometry *geom = NULL
|
|
465
465
|
|
|
466
|
+
n_total_coords = coordinates.shape[0]
|
|
467
|
+
n_rings = offsets1.shape[0] - 1
|
|
466
468
|
n_geoms = offsets2.shape[0] - 1
|
|
467
469
|
|
|
470
|
+
if offsets2[n_geoms] > n_rings:
|
|
471
|
+
raise ValueError(
|
|
472
|
+
f"Number of rings indicated by the geometry offsets ({offsets2[n_geoms]}) "
|
|
473
|
+
f"larger than indicated by the shape of the linear offsets array ({n_rings})"
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
if offsets1[n_rings] > n_total_coords:
|
|
477
|
+
raise ValueError(
|
|
478
|
+
f"Number of coordinates indicated by the linear offsets ({offsets1[n_rings]}) "
|
|
479
|
+
f"larger than the shape of the coordinates array ({n_total_coords})"
|
|
480
|
+
)
|
|
481
|
+
|
|
468
482
|
# A temporary array for the geometries that will be given to CreatePolygon/Collection.
|
|
469
|
-
# For simplicity, we use
|
|
470
|
-
#
|
|
471
|
-
temp_linear = np.empty(shape=(
|
|
483
|
+
# For simplicity, we use n_rings instead of calculating the max needed size
|
|
484
|
+
# as max(diff(offsets2)) (trading performance for a bit more memory usage)
|
|
485
|
+
temp_linear = np.empty(shape=(n_rings, ), dtype=np.intp)
|
|
472
486
|
cdef np.intp_t[:] temp_linear_view = temp_linear
|
|
473
487
|
# A temporary array for resulting geometries
|
|
474
488
|
temp_geoms = np.empty(shape=(n_geoms, ), dtype=np.intp)
|
|
@@ -570,7 +584,7 @@ def _from_ragged_array_multipolygon(
|
|
|
570
584
|
Create MultiPolygons from coordinate and offset arrays.
|
|
571
585
|
"""
|
|
572
586
|
cdef:
|
|
573
|
-
Py_ssize_t n_geoms
|
|
587
|
+
Py_ssize_t n_total_coords, n_rings, n_parts, n_geoms
|
|
574
588
|
Py_ssize_t i, j, k
|
|
575
589
|
Py_ssize_t i1, i2, j1, j2, k1, k2
|
|
576
590
|
Py_ssize_t n_coords, rings_idx, parts_idx
|
|
@@ -580,14 +594,35 @@ def _from_ragged_array_multipolygon(
|
|
|
580
594
|
GEOSGeometry *part = NULL
|
|
581
595
|
GEOSGeometry *geom = NULL
|
|
582
596
|
|
|
597
|
+
n_total_coords = coordinates.shape[0]
|
|
598
|
+
n_rings = offsets1.shape[0] - 1
|
|
599
|
+
n_parts = offsets2.shape[0] - 1
|
|
583
600
|
n_geoms = offsets3.shape[0] - 1
|
|
584
601
|
|
|
602
|
+
if offsets3[n_geoms] > n_parts:
|
|
603
|
+
raise ValueError(
|
|
604
|
+
f"Number of geometry parts indicated by the geometry offsets ({offsets3[n_geoms]}) "
|
|
605
|
+
f"larger than indicated by the shape of the part offsets array ({n_parts})"
|
|
606
|
+
)
|
|
607
|
+
|
|
608
|
+
if offsets2[n_parts] > n_rings:
|
|
609
|
+
raise ValueError(
|
|
610
|
+
f"Number of rings indicated by the part offsets ({offsets2[n_parts]}) "
|
|
611
|
+
f"larger than indicated by the shape of the linear offsets array ({n_rings})"
|
|
612
|
+
)
|
|
613
|
+
|
|
614
|
+
if offsets1[n_rings] > n_total_coords:
|
|
615
|
+
raise ValueError(
|
|
616
|
+
f"Number of coordinates indicated by the linear offsets ({offsets1[n_rings]}) "
|
|
617
|
+
f"larger than the shape of the coordinates array ({n_total_coords})"
|
|
618
|
+
)
|
|
619
|
+
|
|
585
620
|
# A temporary array for the geometries that will be given to CreatePolygon
|
|
586
|
-
# and CreateCollection. For simplicity, we use
|
|
587
|
-
# the max needed size (trading performance for a bit more memory usage)
|
|
588
|
-
temp_rings = np.empty(shape=(
|
|
621
|
+
# and CreateCollection. For simplicity, we use n_rings/n_parts instead of
|
|
622
|
+
# calculating the max needed size (trading performance for a bit more memory usage)
|
|
623
|
+
temp_rings = np.empty(shape=(n_rings, ), dtype=np.intp)
|
|
589
624
|
cdef np.intp_t[:] temp_rings_view = temp_rings
|
|
590
|
-
temp_parts = np.empty(shape=(
|
|
625
|
+
temp_parts = np.empty(shape=(n_parts, ), dtype=np.intp)
|
|
591
626
|
cdef np.intp_t[:] temp_parts_view = temp_parts
|
|
592
627
|
# A temporary array for resulting geometries
|
|
593
628
|
temp_geoms = np.empty(shape=(n_geoms, ), dtype=np.intp)
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2025-
|
|
11
|
+
"date": "2025-05-19T12:40:46+0200",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "2.1.
|
|
14
|
+
"full-revisionid": "b49155ea7eaec698a0357fb9bc1147533b566916",
|
|
15
|
+
"version": "2.1.1"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""Decorators for Shapely functions."""
|
|
2
2
|
|
|
3
|
-
import inspect
|
|
4
3
|
import os
|
|
5
4
|
import warnings
|
|
6
|
-
from
|
|
5
|
+
from collections.abc import Callable, Iterable
|
|
6
|
+
from functools import lru_cache, wraps
|
|
7
|
+
from inspect import unwrap
|
|
7
8
|
|
|
8
9
|
import numpy as np
|
|
9
10
|
|
|
@@ -92,41 +93,90 @@ def multithreading_enabled(func):
|
|
|
92
93
|
return wrapped
|
|
93
94
|
|
|
94
95
|
|
|
95
|
-
def deprecate_positional(
|
|
96
|
-
|
|
96
|
+
def deprecate_positional(
|
|
97
|
+
should_be_kwargs: Iterable[str],
|
|
98
|
+
category: type[Warning] = DeprecationWarning,
|
|
99
|
+
):
|
|
100
|
+
"""Show warning if positional arguments are used that should be keyword.
|
|
101
|
+
|
|
102
|
+
Parameters
|
|
103
|
+
----------
|
|
104
|
+
should_be_kwargs : Iterable[str]
|
|
105
|
+
Names of parameters that should be passed as keyword arguments.
|
|
106
|
+
category : type[Warning], optional (default: DeprecationWarning)
|
|
107
|
+
Warning category to use for deprecation warnings.
|
|
108
|
+
|
|
109
|
+
Returns
|
|
110
|
+
-------
|
|
111
|
+
callable
|
|
112
|
+
Decorator function that adds positional argument deprecation warnings.
|
|
113
|
+
|
|
114
|
+
Examples
|
|
115
|
+
--------
|
|
116
|
+
>>> from shapely.decorators import deprecate_positional
|
|
117
|
+
>>> @deprecate_positional(['b', 'c'])
|
|
118
|
+
... def example(a, b, c=None):
|
|
119
|
+
... return a, b, c
|
|
120
|
+
...
|
|
121
|
+
>>> example(1, 2) # doctest: +SKIP
|
|
122
|
+
DeprecationWarning: positional argument `b` for `example` is deprecated. ...
|
|
123
|
+
(1, 2, None)
|
|
124
|
+
>>> example(1, b=2) # No warnings
|
|
125
|
+
(1, 2, None)
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
def decorator(func: Callable):
|
|
129
|
+
code = unwrap(func).__code__
|
|
130
|
+
|
|
131
|
+
# positional parameters are the first co_argcount names
|
|
132
|
+
pos_names = code.co_varnames[: code.co_argcount]
|
|
133
|
+
# build a name -> index map
|
|
134
|
+
name_to_idx = {name: idx for idx, name in enumerate(pos_names)}
|
|
135
|
+
# pick out only those names we care about
|
|
136
|
+
deprecate_positions = [
|
|
137
|
+
(name_to_idx[name], name)
|
|
138
|
+
for name in should_be_kwargs
|
|
139
|
+
if name in name_to_idx
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
# early exit if there are no deprecated positional args
|
|
143
|
+
if not deprecate_positions:
|
|
144
|
+
return func
|
|
145
|
+
|
|
146
|
+
# earliest position where a warning could occur
|
|
147
|
+
warn_from = min(deprecate_positions)[0]
|
|
148
|
+
|
|
149
|
+
@lru_cache(10)
|
|
150
|
+
def make_msg(n_args: int):
|
|
151
|
+
used = [name for idx, name in deprecate_positions if idx < n_args]
|
|
152
|
+
|
|
153
|
+
if len(used) == 1:
|
|
154
|
+
args_txt = f"`{used[0]}`"
|
|
155
|
+
plr = ""
|
|
156
|
+
isare = "is"
|
|
157
|
+
else:
|
|
158
|
+
plr = "s"
|
|
159
|
+
isare = "are"
|
|
160
|
+
if len(used) == 2:
|
|
161
|
+
args_txt = " and ".join(f"`{u}`" for u in used)
|
|
162
|
+
else:
|
|
163
|
+
args_txt = ", ".join(f"`{u}`" for u in used[:-1])
|
|
164
|
+
args_txt += f", and `{used[-1]}`"
|
|
165
|
+
|
|
166
|
+
return (
|
|
167
|
+
f"positional argument{plr} {args_txt} for `{func.__name__}` "
|
|
168
|
+
f"{isare} deprecated. Please use keyword argument{plr} instead."
|
|
169
|
+
)
|
|
97
170
|
|
|
98
|
-
def decorator(func):
|
|
99
171
|
@wraps(func)
|
|
100
172
|
def wrapper(*args, **kwargs):
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
f"`{arg}`"
|
|
109
|
-
for arg in args_bind.arguments.keys()
|
|
110
|
-
if arg in should_be_kwargs
|
|
111
|
-
]
|
|
112
|
-
if warn_args:
|
|
113
|
-
if len(warn_args) == 1:
|
|
114
|
-
plr = ""
|
|
115
|
-
isare = "is"
|
|
116
|
-
args = warn_args[0]
|
|
117
|
-
else:
|
|
118
|
-
plr = "s"
|
|
119
|
-
isare = "are"
|
|
120
|
-
if len(warn_args) < 3:
|
|
121
|
-
args = " and ".join(warn_args)
|
|
122
|
-
else:
|
|
123
|
-
args = ", ".join(warn_args[:-1]) + ", and " + warn_args[-1]
|
|
124
|
-
msg = (
|
|
125
|
-
f"positional argument{plr} {args} for `{func.__name__}` "
|
|
126
|
-
f"{isare} deprecated. Please use keyword argument{plr} instead."
|
|
127
|
-
)
|
|
128
|
-
warnings.warn(msg, category=category, stacklevel=2)
|
|
129
|
-
return ret_value
|
|
173
|
+
result = func(*args, **kwargs)
|
|
174
|
+
|
|
175
|
+
n = len(args)
|
|
176
|
+
if n > warn_from:
|
|
177
|
+
warnings.warn(make_msg(n), category=category, stacklevel=2)
|
|
178
|
+
|
|
179
|
+
return result
|
|
130
180
|
|
|
131
181
|
return wrapper
|
|
132
182
|
|
|
@@ -56,7 +56,8 @@ def to_wkt(
|
|
|
56
56
|
The rounding precision when writing the WKT string. Set to a value of
|
|
57
57
|
-1 to indicate the full precision.
|
|
58
58
|
trim : bool, default True
|
|
59
|
-
If True, trim unnecessary decimals (trailing zeros).
|
|
59
|
+
If True, trim unnecessary decimals (trailing zeros). If False,
|
|
60
|
+
use fixed-precision number formatting.
|
|
60
61
|
output_dimension : int, default None
|
|
61
62
|
The output dimension for the WKT string. Supported values are 2, 3 and
|
|
62
63
|
4 for GEOS 3.12+. Default None will automatically choose 3 or 4,
|
|
@@ -48,7 +48,10 @@ class PolylabelTestCase(unittest.TestCase):
|
|
|
48
48
|
]
|
|
49
49
|
)
|
|
50
50
|
label = polylabel(polygon)
|
|
51
|
-
if shapely.geos_version >= (3,
|
|
51
|
+
if shapely.geos_version >= (3, 14, 0):
|
|
52
|
+
# https://github.com/libgeos/geos/issues/1265
|
|
53
|
+
assert label.coords[:] == [(32.722025, -117.195155)]
|
|
54
|
+
elif shapely.geos_version >= (3, 12, 0):
|
|
52
55
|
# recent GEOS corrects for this
|
|
53
56
|
assert label.coords[:] == [(32.722025, -117.201875)]
|
|
54
57
|
else:
|
|
@@ -1184,7 +1184,7 @@ def test_maximum_inscribed_circle_all_types(geometry):
|
|
|
1184
1184
|
GEOSException,
|
|
1185
1185
|
match=(
|
|
1186
1186
|
"Argument must be Polygonal or LinearRing|" # GEOS < 3.10.4
|
|
1187
|
-
"
|
|
1187
|
+
"must be a Polygon or MultiPolygon|"
|
|
1188
1188
|
"Operation not supported by GeometryCollection"
|
|
1189
1189
|
),
|
|
1190
1190
|
):
|
|
@@ -1193,7 +1193,7 @@ def test_maximum_inscribed_circle_all_types(geometry):
|
|
|
1193
1193
|
|
|
1194
1194
|
if geometry.is_empty:
|
|
1195
1195
|
with pytest.raises(
|
|
1196
|
-
GEOSException, match="Empty input geometry is not supported"
|
|
1196
|
+
GEOSException, match="Empty input(?: geometry)? is not supported"
|
|
1197
1197
|
):
|
|
1198
1198
|
shapely.maximum_inscribed_circle(geometry)
|
|
1199
1199
|
return
|
|
@@ -1227,13 +1227,15 @@ def test_maximum_inscribed_circle_empty():
|
|
|
1227
1227
|
GEOSException,
|
|
1228
1228
|
match=(
|
|
1229
1229
|
"Argument must be Polygonal or LinearRing|" # GEOS < 3.10.4
|
|
1230
|
-
"
|
|
1230
|
+
"must be a Polygon or MultiPolygon"
|
|
1231
1231
|
),
|
|
1232
1232
|
):
|
|
1233
1233
|
shapely.maximum_inscribed_circle(geometry)
|
|
1234
1234
|
|
|
1235
1235
|
geometry = shapely.from_wkt("POLYGON EMPTY")
|
|
1236
|
-
with pytest.raises(
|
|
1236
|
+
with pytest.raises(
|
|
1237
|
+
GEOSException, match="Empty input(?: geometry)? is not supported"
|
|
1238
|
+
):
|
|
1237
1239
|
shapely.maximum_inscribed_circle(geometry)
|
|
1238
1240
|
|
|
1239
1241
|
|