From 9f5413f8e992472d89d312cc4853d74c76fbbdf1 Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Thu, 26 Aug 2021 00:14:12 +0200 Subject: [PATCH] TST/BUG: deal with various warnings from the tests (#2075) * TST: deal with various warnings from the tests * Update geopandas/tests/test_plotting.py Co-authored-by: Martin Fleischmann * Update geopandas/tests/test_plotting.py Co-authored-by: Martin Fleischmann * add check_less_precise=True back Co-authored-by: Martin Fleischmann --- geopandas/geoseries.py | 6 +++ geopandas/testing.py | 20 +++++++--- geopandas/tests/test_array.py | 15 +++++++- geopandas/tests/test_extension_array.py | 17 ++++++++- geopandas/tests/test_geocode.py | 2 +- geopandas/tests/test_geodataframe.py | 18 ++++++--- geopandas/tests/test_geom_methods.py | 50 +++++++++++++++++-------- geopandas/tests/test_plotting.py | 4 +- geopandas/tools/geocoding.py | 8 +++- 9 files changed, 105 insertions(+), 35 deletions(-) diff --git a/geopandas/geoseries.py b/geopandas/geoseries.py index 928f08c..3f540df 100644 --- a/geopandas/geoseries.py +++ b/geopandas/geoseries.py @@ -187,6 +187,12 @@ class GeoSeries(GeoPandasBase, Series): kwargs.pop("dtype", None) # Use Series constructor to handle input data with compat.ignore_shapely2_warnings(): + # suppress additional warning from pandas for empty data + # (will always give object dtype instead of float dtype in the future, + # making the `if s.empty: s = s.astype(object)` below unnecessary) + warnings.filterwarnings( + "ignore", "The default dtype for empty Series", FutureWarning + ) s = pd.Series(data, index=index, name=name, **kwargs) # prevent trying to convert non-geometry objects if s.dtype != object: diff --git a/geopandas/testing.py b/geopandas/testing.py index 66c2c28..0c89730 100644 --- a/geopandas/testing.py +++ b/geopandas/testing.py @@ -12,12 +12,20 @@ from geopandas import _vectorized def _isna(this): """isna version that works for both scalars and (Geo)Series""" - if hasattr(this, "isna"): - return this.isna() - elif hasattr(this, "isnull"): - return this.isnull() - else: - return pd.isnull(this) + with warnings.catch_warnings(): + # GeoSeries.isna will raise a warning about no longer returning True + # for empty geometries. This helper is used below always in combination + # with an is_empty check to preserve behaviour, and thus we ignore the + # warning here to avoid it bubbling up to the user + warnings.filterwarnings( + "ignore", r"GeoSeries.isna\(\) previously returned", UserWarning + ) + if hasattr(this, "isna"): + return this.isna() + elif hasattr(this, "isnull"): + return this.isnull() + else: + return pd.isnull(this) def _geom_equals_mask(this, that): diff --git a/geopandas/tests/test_array.py b/geopandas/tests/test_array.py index 3770ca2..e7633c0 100644 --- a/geopandas/tests/test_array.py +++ b/geopandas/tests/test_array.py @@ -447,7 +447,18 @@ def test_binary_geo_scalar(attr): @pytest.mark.parametrize( - "attr", ["is_closed", "is_valid", "is_empty", "is_simple", "has_z", "is_ring"] + "attr", + [ + "is_closed", + "is_valid", + "is_empty", + "is_simple", + "has_z", + # for is_ring we raise a warning about the value for Polygon changing + pytest.param( + "is_ring", marks=pytest.mark.filterwarnings("ignore:is_ring:FutureWarning") + ), + ], ) def test_unary_predicates(attr): na_value = False @@ -484,6 +495,8 @@ def test_unary_predicates(attr): assert result.tolist() == expected +# for is_ring we raise a warning about the value for Polygon changing +@pytest.mark.filterwarnings("ignore:is_ring:FutureWarning") def test_is_ring(): g = [ shapely.geometry.LinearRing([(0, 0), (1, 1), (1, -1)]), diff --git a/geopandas/tests/test_extension_array.py b/geopandas/tests/test_extension_array.py index b7db16a..1c37bdc 100644 --- a/geopandas/tests/test_extension_array.py +++ b/geopandas/tests/test_extension_array.py @@ -23,6 +23,7 @@ from pandas.tests.extension import base as extension_tests import shapely.geometry from geopandas.array import GeometryArray, GeometryDtype, from_shapely +from geopandas._compat import ignore_shapely2_warnings import pytest @@ -48,7 +49,8 @@ def dtype(): def make_data(): a = np.empty(100, dtype=object) - a[:] = [shapely.geometry.Point(i, i) for i in range(100)] + with ignore_shapely2_warnings(): + a[:] = [shapely.geometry.Point(i, i) for i in range(100)] ga = from_shapely(a) return ga @@ -299,7 +301,8 @@ class TestInterface(extension_tests.BaseInterfaceTests): result = np.array(data, dtype=object) # expected = np.array(list(data), dtype=object) expected = np.empty(len(data), dtype=object) - expected[:] = list(data) + with ignore_shapely2_warnings(): + expected[:] = list(data) assert_array_equal(result, expected) def test_contains(self, data, data_missing): @@ -404,6 +407,11 @@ def all_arithmetic_operators(request): return request.param +# an inherited test from pandas creates a Series from a list of geometries, which +# triggers the warning from Shapely, out of control of GeoPandas, so ignoring here +@pytest.mark.filterwarnings( + "ignore:The array interface is deprecated and will no longer work in Shapely 2.0" +) class TestArithmeticOps(extension_tests.BaseArithmeticOpsTests): @pytest.mark.skip(reason="not applicable") def test_divmod_series_array(self, data, data_for_twos): @@ -414,6 +422,11 @@ class TestArithmeticOps(extension_tests.BaseArithmeticOpsTests): pass +# an inherited test from pandas creates a Series from a list of geometries, which +# triggers the warning from Shapely, out of control of GeoPandas, so ignoring here +@pytest.mark.filterwarnings( + "ignore:The array interface is deprecated and will no longer work in Shapely 2.0" +) class TestComparisonOps(extension_tests.BaseComparisonOpsTests): def _compare_other(self, s, data, op_name, other): op = getattr(operator, op_name.strip("_")) diff --git a/geopandas/tests/test_geocode.py b/geopandas/tests/test_geocode.py index f2daf9d..4b1c8cc 100644 --- a/geopandas/tests/test_geocode.py +++ b/geopandas/tests/test_geocode.py @@ -134,7 +134,7 @@ def test_bad_provider_reverse(): from geopy.exc import GeocoderNotFound with pytest.raises(GeocoderNotFound): - reverse_geocode(["cambridge, ma"], "badprovider") + reverse_geocode([Point(0, 0)], "badprovider") def test_forward(locations, points): diff --git a/geopandas/tests/test_geodataframe.py b/geopandas/tests/test_geodataframe.py index 0b9e247..cbfebbd 100644 --- a/geopandas/tests/test_geodataframe.py +++ b/geopandas/tests/test_geodataframe.py @@ -15,6 +15,7 @@ from shapely.geometry import Point import geopandas from geopandas import GeoDataFrame, GeoSeries, read_file from geopandas.array import GeometryArray, GeometryDtype, from_shapely +from geopandas._compat import ignore_shapely2_warnings from geopandas.testing import assert_geodataframe_equal, assert_geoseries_equal from geopandas.tests.util import PACKAGE_DIR, validate_boro_df @@ -367,6 +368,9 @@ class TestDataFrame: assert len(data["features"]) == 5 assert "id" in data["features"][0].keys() + @pytest.mark.filterwarnings( + "ignore:Geometry column does not contain geometry:UserWarning" + ) def test_to_json_geom_col(self): df = self.df.copy() df["geom"] = df["geometry"] @@ -872,7 +876,8 @@ class TestConstructor: "B": np.arange(3.0), "geometry": [Point(x, x) for x in range(3)], } - a = np.array([data["A"], data["B"], data["geometry"]], dtype=object).T + with ignore_shapely2_warnings(): + a = np.array([data["A"], data["B"], data["geometry"]], dtype=object).T df = GeoDataFrame(a, columns=["A", "B", "geometry"]) check_geodataframe(df) @@ -887,7 +892,8 @@ class TestConstructor: "geometry": [Point(x, x) for x in range(3)], } gpdf = GeoDataFrame(data) - pddf = pd.DataFrame(data) + with ignore_shapely2_warnings(): + pddf = pd.DataFrame(data) check_geodataframe(gpdf) assert type(pddf) == pd.DataFrame @@ -917,7 +923,8 @@ class TestConstructor: gpdf = GeoDataFrame(data, geometry="other_geom") check_geodataframe(gpdf, "other_geom") - pddf = pd.DataFrame(data) + with ignore_shapely2_warnings(): + pddf = pd.DataFrame(data) for df in [gpdf, pddf]: res = GeoDataFrame(df, geometry="other_geom") @@ -1003,7 +1010,8 @@ class TestConstructor: def test_overwrite_geometry(self): # GH602 data = pd.DataFrame({"geometry": [1, 2, 3], "col1": [4, 5, 6]}) - geoms = pd.Series([Point(i, i) for i in range(3)]) + with ignore_shapely2_warnings(): + geoms = pd.Series([Point(i, i) for i in range(3)]) # passed geometry kwarg should overwrite geometry column in data res = GeoDataFrame(data, geometry=geoms) assert_geoseries_equal(res.geometry, GeoSeries(geoms)) @@ -1028,6 +1036,6 @@ class TestConstructor: def test_geodataframe_crs(): - gdf = GeoDataFrame() + gdf = GeoDataFrame(columns=["geometry"]) gdf.crs = "IGNF:ETRS89UTM28" assert gdf.crs.to_authority() == ("IGNF", "ETRS89UTM28") diff --git a/geopandas/tests/test_geom_methods.py b/geopandas/tests/test_geom_methods.py index a617dc3..895693b 100644 --- a/geopandas/tests/test_geom_methods.py +++ b/geopandas/tests/test_geom_methods.py @@ -245,13 +245,15 @@ class TestGeomMethods: "intersection", self.all_none, self.g1, self.empty ) - assert len(self.g0.intersection(self.g9, align=True) == 8) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert len(self.g0.intersection(self.g9, align=True) == 8) assert len(self.g0.intersection(self.g9, align=False) == 7) def test_union_series(self): self._test_binary_topological("union", self.sq, self.g1, self.g2) - assert len(self.g0.union(self.g9, align=True) == 8) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert len(self.g0.union(self.g9, align=True) == 8) assert len(self.g0.union(self.g9, align=False) == 7) def test_union_polygon(self): @@ -260,7 +262,8 @@ class TestGeomMethods: def test_symmetric_difference_series(self): self._test_binary_topological("symmetric_difference", self.sq, self.g3, self.g4) - assert len(self.g0.symmetric_difference(self.g9, align=True) == 8) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert len(self.g0.symmetric_difference(self.g9, align=True) == 8) assert len(self.g0.symmetric_difference(self.g9, align=False) == 7) def test_symmetric_difference_poly(self): @@ -273,7 +276,8 @@ class TestGeomMethods: expected = GeoSeries([GeometryCollection(), self.t2]) self._test_binary_topological("difference", expected, self.g1, self.g2) - assert len(self.g0.difference(self.g9, align=True) == 8) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert len(self.g0.difference(self.g9, align=True) == 8) assert len(self.g0.difference(self.g9, align=False) == 7) def test_difference_poly(self): @@ -365,7 +369,8 @@ class TestGeomMethods: assert_array_dtype_equal(expected, self.g0.contains(self.t1)) expected = [False, True, True, True, True, True, False, False] - assert_array_dtype_equal(expected, self.g0.contains(self.g9, align=True)) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert_array_dtype_equal(expected, self.g0.contains(self.g9, align=True)) expected = [False, False, True, False, False, False, False] assert_array_dtype_equal(expected, self.g0.contains(self.g9, align=False)) @@ -389,7 +394,8 @@ class TestGeomMethods: assert_array_dtype_equal(expected, self.crossed_lines.crosses(self.l3)) expected = [False] * 8 - assert_array_dtype_equal(expected, self.g0.crosses(self.g9, align=True)) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert_array_dtype_equal(expected, self.g0.crosses(self.g9, align=True)) expected = [False] * 7 assert_array_dtype_equal(expected, self.g0.crosses(self.g9, align=False)) @@ -399,7 +405,8 @@ class TestGeomMethods: assert_array_dtype_equal(expected, self.g0.disjoint(self.t1)) expected = [False] * 8 - assert_array_dtype_equal(expected, self.g0.disjoint(self.g9, align=True)) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert_array_dtype_equal(expected, self.g0.disjoint(self.g9, align=True)) expected = [False, False, False, False, True, False, False] assert_array_dtype_equal(expected, self.g0.disjoint(self.g9, align=False)) @@ -436,7 +443,8 @@ class TestGeomMethods: index=range(8), ) - assert_array_dtype_equal(expected, self.g0.relate(self.g9, align=True)) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert_array_dtype_equal(expected, self.g0.relate(self.g9, align=True)) expected = Series( [ @@ -462,7 +470,8 @@ class TestGeomMethods: assert_array_dtype_equal(expected, self.g6.distance(self.na_none)) expected = Series(np.array([np.nan, 0, 0, 0, 0, 0, np.nan, np.nan]), range(8)) - assert_array_dtype_equal(expected, self.g0.distance(self.g9, align=True)) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert_array_dtype_equal(expected, self.g0.distance(self.g9, align=True)) val = self.g0.iloc[4].distance(self.g9.iloc[4]) expected = Series(np.array([0, 0, 0, 0, val, np.nan, np.nan]), self.g0.index) @@ -489,7 +498,8 @@ class TestGeomMethods: assert_array_dtype_equal(expected, self.g0.intersects(self.empty_poly)) expected = [False, True, True, True, True, True, False, False] - assert_array_dtype_equal(expected, self.g0.intersects(self.g9, align=True)) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert_array_dtype_equal(expected, self.g0.intersects(self.g9, align=True)) expected = [True, True, True, True, False, False, False] assert_array_dtype_equal(expected, self.g0.intersects(self.g9, align=False)) @@ -502,7 +512,8 @@ class TestGeomMethods: assert_array_dtype_equal(expected, self.g4.overlaps(self.t1)) expected = [False] * 8 - assert_array_dtype_equal(expected, self.g0.overlaps(self.g9, align=True)) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert_array_dtype_equal(expected, self.g0.overlaps(self.g9, align=True)) expected = [False] * 7 assert_array_dtype_equal(expected, self.g0.overlaps(self.g9, align=False)) @@ -512,7 +523,8 @@ class TestGeomMethods: assert_array_dtype_equal(expected, self.g0.touches(self.t1)) expected = [False] * 8 - assert_array_dtype_equal(expected, self.g0.touches(self.g9, align=True)) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert_array_dtype_equal(expected, self.g0.touches(self.g9, align=True)) expected = [True, False, False, True, False, False, False] assert_array_dtype_equal(expected, self.g0.touches(self.g9, align=False)) @@ -525,7 +537,8 @@ class TestGeomMethods: assert_array_dtype_equal(expected, self.g0.within(self.sq)) expected = [False, True, True, True, True, True, False, False] - assert_array_dtype_equal(expected, self.g0.within(self.g9, align=True)) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert_array_dtype_equal(expected, self.g0.within(self.g9, align=True)) expected = [False, True, False, False, False, False, False] assert_array_dtype_equal(expected, self.g0.within(self.g9, align=False)) @@ -542,7 +555,8 @@ class TestGeomMethods: assert_series_equal(res, exp) expected = [False, True, True, True, True, True, False, False] - assert_array_dtype_equal(expected, self.g0.covers(self.g9, align=True)) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert_array_dtype_equal(expected, self.g0.covers(self.g9, align=True)) expected = [False, False, True, False, False, False, False] assert_array_dtype_equal(expected, self.g0.covers(self.g9, align=False)) @@ -562,7 +576,8 @@ class TestGeomMethods: assert_series_equal(res, exp) expected = [False, True, True, True, True, True, False, False] - assert_array_dtype_equal(expected, self.g0.covered_by(self.g9, align=True)) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert_array_dtype_equal(expected, self.g0.covered_by(self.g9, align=True)) expected = [False, True, False, False, False, False, False] assert_array_dtype_equal(expected, self.g0.covered_by(self.g9, align=False)) @@ -575,6 +590,8 @@ class TestGeomMethods: expected = Series(np.array([False] * len(self.g1)), self.g1.index) self._test_unary_real("is_empty", expected, self.g1) + # for is_ring we raise a warning about the value for Polygon changing + @pytest.mark.filterwarnings("ignore:is_ring:FutureWarning") def test_is_ring(self): expected = Series(np.array([True] * len(self.g1)), self.g1.index) self._test_unary_real("is_ring", expected, self.g1) @@ -688,7 +705,8 @@ class TestGeomMethods: s = GeoSeries([Point(2, 2), Point(0.5, 0.5)], index=[1, 2]) expected = Series([np.nan, 2.0, np.nan]) - assert_series_equal(self.g5.project(s), expected) + with pytest.warns(UserWarning, match="The indices .+ different"): + assert_series_equal(self.g5.project(s), expected) expected = Series([2.0, 0.5], index=self.g5.index) assert_series_equal(self.g5.project(s, align=False), expected) diff --git a/geopandas/tests/test_plotting.py b/geopandas/tests/test_plotting.py index d7a2d6a..ff1879d 100644 --- a/geopandas/tests/test_plotting.py +++ b/geopandas/tests/test_plotting.py @@ -516,7 +516,7 @@ class TestLineStringPlotting: self.df.plot(linestyle=ls, linewidth=1), self.df.plot(column="values", linestyle=ls, linewidth=1), ]: - np.testing.assert_array_equal(exp_ls, ax.collections[0].get_linestyle()) + assert exp_ls == ax.collections[0].get_linestyle() def test_style_kwargs_linewidth(self): # single @@ -947,7 +947,7 @@ class TestNonuniformGeometryPlotting: self.series.plot(linestyles=ls, linewidth=1), self.df.plot(linestyles=ls, linewidth=1), ]: - np.testing.assert_array_equal(exp_ls, ax.collections[0].get_linestyle()) + assert exp_ls == ax.collections[0].get_linestyle() def test_style_kwargs_linewidth(self): # single diff --git a/geopandas/tools/geocoding.py b/geopandas/tools/geocoding.py index 7743d1a..bba8bb6 100644 --- a/geopandas/tools/geocoding.py +++ b/geopandas/tools/geocoding.py @@ -123,8 +123,12 @@ def _query(data, forward, provider, throttle_time, **kwargs): from geopy.geocoders.base import GeocoderQueryError from geopy.geocoders import get_geocoder_for_service - if not isinstance(data, pd.Series): - data = pd.Series(data) + if forward: + if not isinstance(data, pd.Series): + data = pd.Series(data) + else: + if not isinstance(data, geopandas.GeoSeries): + data = geopandas.GeoSeries(data) if isinstance(provider, str): provider = get_geocoder_for_service(provider)