holoviz / spatialpandas

Pandas extension arrays for spatial/geometric operations
BSD 2-Clause "Simplified" License
308 stars 25 forks source link

Move to Pixi, Hatchling, Pre-commit, and Ruff #142

Closed hoxbro closed 1 month ago

hoxbro commented 1 month ago

I have temporarily added upper pins to pandas, pyarrow, and geopandas. This is so the tests can pass in this PR, and we can, in follow-up PRs, tackle the individual packages upgrade.

For now, I have only added a smaller set of pre-commit and ruff settings; this, again, can be expanded in other PRs.

I also added support for Python 3.12 and Moto 5.

Supersedes #135 Fixes #93

hoxbro commented 1 month ago

Difference in build:

                                   Spatialpandas - wheel
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Files only in run 1                       ┃ Files only in run 2                         ┃
┃ spatialpandas 0.4.10 py2.py3 none any.whl ┃ spatialpandas 0.4.11a2.post1.dev19+g1f46a13 ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ $VERSION.dist-info/LICENSE                │ $VERSION.dist-info/licenses/LICENSE         │
│ $VERSION.dist-info/top_level.txt          │ $VERSION.dist-info/licenses/NOTICE          │
│ spatialpandas/.version                    │ spatialpandas/__version.py                  │
│ -                                         │ spatialpandas/_version.py                   │
└───────────────────────────────────────────┴─────────────────────────────────────────────┘
                                                   Spatialpandas - sdist
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Files only in run 1                                  ┃ Files only in run 2                                              ┃
┃ spatialpandas 0.4.10                                 ┃ spatialpandas 0.4.11a2.post1.dev19+g1f46a13                      ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ $VERSION/CHANGELOG.md                                │ $VERSION/.gitignore                                              │
│ $VERSION/MANIFEST.in                                 │ $VERSION/examples/Overview.ipynb                                 │
│ $VERSION/setup.cfg                                   │ $VERSION/examples/Polygon-Array-Construction-From-Exterior.ipynb │
│ $VERSION/setup.py                                    │ $VERSION/scripts/conda/build.sh                                  │
│ $VERSION/spatialpandas.egg-info/PKG-INFO             │ $VERSION/scripts/conda/recipe/meta.yaml                          │
│ $VERSION/spatialpandas.egg-info/SOURCES.txt          │ $VERSION/spatialpandas/__version.py                              │
│ $VERSION/spatialpandas.egg-info/dependency_links.txt │ $VERSION/spatialpandas/_version.py                               │
│ $VERSION/spatialpandas.egg-info/requires.txt         │ -                                                                │
│ $VERSION/spatialpandas.egg-info/top_level.txt        │ -                                                                │
│ $VERSION/spatialpandas/.version                      │ -                                                                │
└──────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────┘

                                             Spatialpandas - conda #1
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Files only in run 1                                         ┃ Files only in run 2                               ┃
┃ spatialpandas 0.4.10                                        ┃ spatialpandas 0.4.11a2.post1.dev19+g1f46a13       ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ site-packages/$VERSION-py3.12.egg-info/PKG-INFO             │ info/test/run_test.bat                            │
│ site-packages/$VERSION-py3.12.egg-info/SOURCES.txt          │ info/test/run_test.sh                             │
│ site-packages/$VERSION-py3.12.egg-info/dependency_links.txt │ info/test/test_time_dependencies.json             │
│ site-packages/$VERSION-py3.12.egg-info/requires.txt         │ site-packages/$VERSION.dist-info/INSTALLER        │
│ site-packages/$VERSION-py3.12.egg-info/top_level.txt        │ site-packages/$VERSION.dist-info/METADATA         │
│ site-packages/spatialpandas/.version                        │ site-packages/$VERSION.dist-info/RECORD           │
│ -                                                           │ site-packages/$VERSION.dist-info/REQUESTED        │
│ -                                                           │ site-packages/$VERSION.dist-info/WHEEL            │
│ -                                                           │ site-packages/$VERSION.dist-info/direct_url.json  │
│ -                                                           │ site-packages/$VERSION.dist-info/licenses/LICENSE │
│ -                                                           │ site-packages/$VERSION.dist-info/licenses/NOTICE  │
│ -                                                           │ site-packages/spatialpandas/__version.py          │
│ -                                                           │ site-packages/spatialpandas/_version.py           │
└─────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────┘
hoxbro commented 1 month ago

This PR is in a good state.

There are still some edge cases, as shown by the hypothesis tests, but I will say that is out of scope for this PR.

hoxbro commented 1 month ago

Two cases failing with Hypothesis, will open an issue after this PR has been merged. Both seems to be related to strict comparison.

For test_segment_intersection, we could add a skip if it is not a line but a point. I have done that in https://github.com/holoviz/spatialpandas/pull/142/commits/c3b2b5659abb4435e3a24494506769e9e489add9.

# Failing: test_multipolygon_cx_selection
import geopandas as gpd
from shapely.geometry import shape
from spatialpandas.geometry import MultiPolygonArray

geometry = {
    "type": "MultiPolygon",
    "coordinates": [
        [
            [
                [-40.584103603229096, -3.6817177099899876],
                [-25.93909571878391, 27.960034115881996],
                [-29.06279226754736, 50.0],
                [-2.0859372955624726, 50.0],
                [2.491304910804627, 32.34563365363812],
                [15.039797653702573, 31.198711405699328],
                [22.789773854429544, 19.718458404794436],
                [50.0, 20.800773018225026],
                [50.0, 10.074395460794436],
                [16.96014963061812, -28.981388627755035],
                [8.698742846075964, -47.44958665067525],
                [-15.177316735436102, -19.715134610036017],
                [-40.584103603229096, -3.6817177099899876],
            ]
        ]
    ],
}
gp_multipolygon = gpd.GeoSeries([shape(geometry)])
xslice, yslice = (slice(None, 0.0, None), slice(50.0, None, None))  # Works if slice is 50.0000001
expected = MultiPolygonArray.from_geopandas(gp_multipolygon.cx[xslice, yslice])
result = MultiPolygonArray.from_geopandas(gp_multipolygon).cx[xslice, yslice]
assert all(expected == result)
# Failing: test_segment_intersection
from shapely import geometry as sg
from spatialpandas.geometry._algorithms.intersection import segments_intersect

ax0, ay0, ax1, ay1, bx0, by0, bx1, by1 = 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, -1.0, -1.0

result = segments_intersect(ax0, ay0, ax1, ay1, bx0, by0, bx1, by1)

line1 = sg.LineString([(ax0, ay0), (ax1, ay1)])
line2 = sg.LineString([(bx0, by0), (bx1, by1)])
expected = line1.intersects(line2)
assert result == expected