diff --git a/tests/test_geodataframe.py b/tests/test_geodataframe.py index cd423e5..423a1c5 100644 --- a/tests/test_geodataframe.py +++ b/tests/test_geodataframe.py @@ -8,8 +8,8 @@ import numpy as np from shapely.geometry import Point, Polygon -from geopandas import GeoDataFrame, read_file -import tests.util +from geopandas import GeoDataFrame, read_file, GeoSeries +import tests.util as tu class TestDataFrame(unittest.TestCase): @@ -17,7 +17,7 @@ class TestDataFrame(unittest.TestCase): def setUp(self): N = 10 - nybb_filename = tests.util.download_nybb() + nybb_filename = tu.download_nybb() self.df = read_file('/nybb_13a/nybb.shp', vfs='zip://' + nybb_filename) self.tempdir = tempfile.mkdtemp() @@ -36,15 +36,17 @@ class TestDataFrame(unittest.TestCase): self.assertTrue(self.df2.crs == self.crs) def test_geometry_property(self): - tests.util.assert_seq_equal(self.df.geometry, self.df['geometry']) + tu.assert_geoseries_equal(self.df.geometry, self.df['geometry'], + check_dtype=True, check_index_type=True) + df = self.df.copy() new_geom = [Point(x,y) for x, y in zip(range(len(self.df)), range(len(self.df)))] - df.geometry = new_geom - tests.util.assert_seq_equal(df.geometry, new_geom) - # should this be tested here? - tests.util.assert_seq_equal(df['geometry'], new_geom) + + new_geom = GeoSeries(new_geom, index=df.index) + tu.assert_geoseries_equal(df.geometry, new_geom) + tu.assert_geoseries_equal(df['geometry'], new_geom) def _should_raise_att_error(): df = self.df.copy() @@ -61,14 +63,14 @@ class TestDataFrame(unittest.TestCase): self.assertRaises(KeyError, _should_raise_key_error) def test_set_geometry(self): - geom = [Point(x,y) for x,y in zip(range(5), range(5))] + geom = GeoSeries([Point(x,y) for x,y in zip(range(5), range(5))]) original_geom = self.df.geometry df2 = self.df.set_geometry(geom) self.assert_(self.df is not df2) - tests.util.assert_seq_equal(df2.geometry, geom) - tests.util.assert_seq_equal(self.df.geometry, original_geom) - tests.util.assert_seq_equal(self.df['geometry'], self.df.geometry) + tu.assert_geoseries_equal(df2.geometry, geom) + tu.assert_geoseries_equal(self.df.geometry, original_geom) + tu.assert_geoseries_equal(self.df['geometry'], self.df.geometry) def test_set_geometry_col(self): g = self.df.geometry @@ -79,23 +81,22 @@ class TestDataFrame(unittest.TestCase): # Drop is true by default self.assert_('simplified_geometry' not in df2) - tests.util.assert_seq_equal(df2.geometry, g_simplified) + tu.assert_geoseries_equal(df2.geometry, g_simplified) def test_set_geometry_col_no_drop(self): g = self.df.geometry g_simplified = g.simplify(100) self.df['simplified_geometry'] = g_simplified df2 = self.df.set_geometry('simplified_geometry', drop=False) - self.assert_('simplified_geometry' in df2) - tests.util.assert_seq_equal(df2.geometry, g_simplified) + tu.assert_geoseries_equal(df2.geometry, g_simplified) def test_set_geometry_inplace(self): geom = [Point(x,y) for x,y in zip(range(5), range(5))] ret = self.df.set_geometry(geom, inplace=True) self.assert_(ret is None) - tests.util.assert_seq_equal(self.df['geometry'], geom) - tests.util.assert_seq_equal(self.df.geometry, geom) + geom = GeoSeries(geom, index=self.df.index) + tu.assert_geoseries_equal(self.df.geometry, geom) def test_to_json(self): text = self.df.to_json() @@ -197,8 +198,8 @@ class TestDataFrame(unittest.TestCase): self.assertTrue(all(df2['geometry'].almost_equals(utm['geometry'], decimal=2))) def test_from_postgis_default(self): - con = tests.util.connect('test_geopandas') - if con is None or not tests.util.create_db(self.df): + con = tu.connect('test_geopandas') + if con is None or not tu.create_db(self.df): raise unittest.case.SkipTest() try: @@ -207,11 +208,11 @@ class TestDataFrame(unittest.TestCase): finally: con.close() - tests.util.validate_boro_df(self, df) + tu.validate_boro_df(self, df) def test_from_postgis_custom_geom_col(self): - con = tests.util.connect('test_geopandas') - if con is None or not tests.util.create_db(self.df): + con = tu.connect('test_geopandas') + if con is None or not tu.create_db(self.df): raise unittest.case.SkipTest() try: @@ -223,4 +224,4 @@ class TestDataFrame(unittest.TestCase): finally: con.close() - tests.util.validate_boro_df(self, df) + tu.validate_boro_df(self, df) diff --git a/tests/util.py b/tests/util.py index 5223965..1c353d6 100644 --- a/tests/util.py +++ b/tests/util.py @@ -2,7 +2,6 @@ import os.path import urllib2 from geopandas import GeoDataFrame, GeoSeries -import numpy as np try: @@ -97,24 +96,91 @@ def assert_seq_equal(left, right): """Poor man's version of assert_almost_equal which isn't working with Shapely objects right now""" assert len(left) == len(right), "Mismatched lengths: %d != %d" % (len(left), len(right)) + for elem_left, elem_right in zip(left, right): assert elem_left == elem_right, "%r != %r" % (left, right) - return True def geom_equals(this, that): + """Test for geometric equality. Empty geometries are considered equal. + + Parameters + ---------- + this, that : arrays of Geo objects (or anything that has an `is_empty` + attribute) """ - Test for geometric equality, allowing all empty geometries to be considered equal - """ - empty = np.logical_and(this.is_empty, that.is_empty) - eq = this.equals(that) - return np.all(np.logical_or(eq, empty)) + + return (this.equals(that) | (this.is_empty & that.is_empty)).all() def geom_almost_equals(this, that): + """Test for 'almost' geometric equality. Empty geometries considered equal. + + Parameters + ---------- + this, that : arrays of Geo objects (or anything that has an `is_empty` + property) """ - Test for geometric equality, allowing all empty geometries to be considered almost equal + + return (this.almost_equals(that) | (this.is_empty & that.is_empty)).all() + +# TODO: Remove me when standardizing on pandas 0.13, which already includes +# this test util. +def assert_isinstance(obj, klass_or_tuple): + assert isinstance(obj, klass_or_tuple), "type: %r != %r" % ( + type(obj).__name__, + getattr(klass_or_tuple, '__name__', + klass_or_tuple)) + +def assert_geoseries_equal(left, right, check_dtype=False, + check_index_type=False, + check_series_type=True, + check_less_precise=False, + check_geom_type=False): + """Test util for checking that two GeoSeries are equal. + + Parameters + ---------- + left, right : two GeoSeries + check_dtype : bool, default False + if True, check geo dtype [only included so it's a drop-in replacement + for assert_series_equal] + check_index_type : bool, default False + check that index types are equal + check_series_type : bool, default True + check that both are same type (*and* are GeoSeries). If False, + will attempt to convert both into GeoSeries. + check_less_precise : bool, default False + if True, use geom_almost_equals. if False, use geom_equals. + check_geom_type : bool, default False + if True, check that all the geom types are equal. """ - empty = np.logical_and(this.is_empty, that.is_empty) - eq = this.almost_equals(that) - return np.all(np.logical_or(eq, empty)) + assert len(left) == len(right), "%d != %d" % (len(left), len(right)) + + if check_index_type: + assert_isinstance(left.index, type(right.index)) + + if check_dtype: + assert left.dtype == right.dtype, "dtype: %s != %s" % (left.dtype, + right.dtype) + + if check_series_type: + assert isinstance(left, GeoSeries) + assert_isinstance(left, type(right)) + else: + if not isinstance(left, GeoSeries): + left = GeoSeries(left) + if not isinstance(right, GeoSeries): + right = GeoSeries(right, index=left.index) + + assert left.index.equals(right.index), "index: %s != %s" % (left.index, + right.index) + + if check_geom_type: + assert (left.type == right.type).all(), "type: %s != %s" % (left.type, + right.type) + + if check_less_precise: + assert geom_almost_equals(left, right) + else: + assert geom_equals(left, right)