From 56982aff9d1a3ddde97e73f9ff93a020cbc3d225 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 6 Feb 2020 19:23:21 -0800 Subject: [PATCH 1/4] parametrize --- pandas/tests/indexing/test_floats.py | 231 ++++++++++++++------------- pandas/tests/indexing/test_scalar.py | 67 ++++---- 2 files changed, 153 insertions(+), 145 deletions(-) diff --git a/pandas/tests/indexing/test_floats.py b/pandas/tests/indexing/test_floats.py index 199d9e1013e23..1361818a2932e 100644 --- a/pandas/tests/indexing/test_floats.py +++ b/pandas/tests/indexing/test_floats.py @@ -59,115 +59,117 @@ def test_scalar_error(self, index_func): with pytest.raises(TypeError, match=msg): s.iloc[3.0] = 0 - def test_scalar_non_numeric(self): - - # GH 4892 - # float_indexers should raise exceptions - # on appropriate Index types & accessors - - for index in [ + @pytest.mark.parametrize( + "index_func", + [ tm.makeStringIndex, tm.makeUnicodeIndex, tm.makeCategoricalIndex, tm.makeDateIndex, tm.makeTimedeltaIndex, tm.makePeriodIndex, - ]: + ], + ) + def test_scalar_non_numeric(self, index_func): - i = index(5) + # GH 4892 + # float_indexers should raise exceptions + # on appropriate Index types & accessors - for s in [ - Series(np.arange(len(i)), index=i), - DataFrame(np.random.randn(len(i), len(i)), index=i, columns=i), - ]: + i = index_func(5) - # getting - for idxr, getitem in [(lambda x: x.iloc, False), (lambda x: x, True)]: + for s in [ + Series(np.arange(len(i)), index=i), + DataFrame(np.random.randn(len(i), len(i)), index=i, columns=i), + ]: - # gettitem on a DataFrame is a KeyError as it is indexing - # via labels on the columns - if getitem and isinstance(s, DataFrame): - error = KeyError - msg = r"^3(\.0)?$" - else: - error = TypeError - msg = ( - r"cannot do (label|index|positional) indexing " - r"on {klass} with these indexers \[3\.0\] of " - r"{kind}|" - "Cannot index by location index with a " - "non-integer key".format(klass=type(i), kind=str(float)) - ) - with pytest.raises(error, match=msg): - idxr(s)[3.0] - - # label based can be a TypeError or KeyError - if s.index.inferred_type in { - "categorical", - "string", - "unicode", - "mixed", - }: + # getting + for idxr, getitem in [(lambda x: x.iloc, False), (lambda x: x, True)]: + + # gettitem on a DataFrame is a KeyError as it is indexing + # via labels on the columns + if getitem and isinstance(s, DataFrame): error = KeyError - msg = r"^3\.0$" + msg = r"^3(\.0)?$" else: error = TypeError msg = ( - r"cannot do (label|index) indexing " + r"cannot do (label|index|positional) indexing " r"on {klass} with these indexers \[3\.0\] of " - r"{kind}".format(klass=type(i), kind=str(float)) + r"{kind}|" + "Cannot index by location index with a " + "non-integer key".format(klass=type(i), kind=str(float)) ) with pytest.raises(error, match=msg): - s.loc[3.0] - - # contains - assert 3.0 not in s - - # setting with a float fails with iloc + idxr(s)[3.0] + + # label based can be a TypeError or KeyError + if s.index.inferred_type in { + "categorical", + "string", + "unicode", + "mixed", + }: + error = KeyError + msg = r"^3\.0$" + else: + error = TypeError msg = ( - r"cannot do (label|index|positional) indexing " + r"cannot do (label|index) indexing " r"on {klass} with these indexers \[3\.0\] of " r"{kind}".format(klass=type(i), kind=str(float)) ) - with pytest.raises(TypeError, match=msg): - s.iloc[3.0] = 0 - - # setting with an indexer - if s.index.inferred_type in ["categorical"]: - # Value or Type Error - pass - elif s.index.inferred_type in ["datetime64", "timedelta64", "period"]: - - # these should prob work - # and are inconsistent between series/dataframe ATM - # for idxr in [lambda x: x]: - # s2 = s.copy() - # - # with pytest.raises(TypeError): - # idxr(s2)[3.0] = 0 - pass - - else: - - s2 = s.copy() - s2.loc[3.0] = 10 - assert s2.index.is_object() + with pytest.raises(error, match=msg): + s.loc[3.0] - for idxr in [lambda x: x]: - s2 = s.copy() - idxr(s2)[3.0] = 0 - assert s2.index.is_object() + # contains + assert 3.0 not in s - # fallsback to position selection, series only - s = Series(np.arange(len(i)), index=i) - s[3] + # setting with a float fails with iloc msg = ( - r"cannot do (label|index) indexing " + r"cannot do (label|index|positional) indexing " r"on {klass} with these indexers \[3\.0\] of " r"{kind}".format(klass=type(i), kind=str(float)) ) with pytest.raises(TypeError, match=msg): - s[3.0] + s.iloc[3.0] = 0 + + # setting with an indexer + if s.index.inferred_type in ["categorical"]: + # Value or Type Error + pass + elif s.index.inferred_type in ["datetime64", "timedelta64", "period"]: + + # these should prob work + # and are inconsistent between series/dataframe ATM + # for idxr in [lambda x: x]: + # s2 = s.copy() + # + # with pytest.raises(TypeError): + # idxr(s2)[3.0] = 0 + pass + + else: + + s2 = s.copy() + s2.loc[3.0] = 10 + assert s2.index.is_object() + + for idxr in [lambda x: x]: + s2 = s.copy() + idxr(s2)[3.0] = 0 + assert s2.index.is_object() + + # fallsback to position selection, series only + s = Series(np.arange(len(i)), index=i) + s[3] + msg = ( + r"cannot do (label|index) indexing " + r"on {klass} with these indexers \[3\.0\] of " + r"{kind}".format(klass=type(i), kind=str(float)) + ) + with pytest.raises(TypeError, match=msg): + s[3.0] def test_scalar_with_mixed(self): @@ -222,52 +224,59 @@ def test_scalar_with_mixed(self): expected = 3 assert result == expected - def test_scalar_integer(self): + @pytest.mark.parametrize( + "index_func", + [ + tm.makeIntIndex, + tm.makeRangeIndex, + ], + ) + def test_scalar_integer(self, index_func): # test how scalar float indexers work on int indexes # integer index - for i in [Int64Index(range(5)), RangeIndex(5)]: + i = index_func(5) - for s in [ - Series(np.arange(len(i))), - DataFrame(np.random.randn(len(i), len(i)), index=i, columns=i), - ]: + for s in [ + Series(np.arange(len(i))), + DataFrame(np.random.randn(len(i), len(i)), index=i, columns=i), + ]: - # coerce to equal int - for idxr, getitem in [(lambda x: x.loc, False), (lambda x: x, True)]: + # coerce to equal int + for idxr, getitem in [(lambda x: x.loc, False), (lambda x: x, True)]: - result = idxr(s)[3.0] - self.check(result, s, 3, getitem) + result = idxr(s)[3.0] + self.check(result, s, 3, getitem) - # coerce to equal int - for idxr, getitem in [(lambda x: x.loc, False), (lambda x: x, True)]: + # coerce to equal int + for idxr, getitem in [(lambda x: x.loc, False), (lambda x: x, True)]: - if isinstance(s, Series): + if isinstance(s, Series): - def compare(x, y): - assert x == y + def compare(x, y): + assert x == y - expected = 100 + expected = 100 + else: + compare = tm.assert_series_equal + if getitem: + expected = Series(100, index=range(len(s)), name=3) else: - compare = tm.assert_series_equal - if getitem: - expected = Series(100, index=range(len(s)), name=3) - else: - expected = Series(100.0, index=range(len(s)), name=3) + expected = Series(100.0, index=range(len(s)), name=3) - s2 = s.copy() - idxr(s2)[3.0] = 100 + s2 = s.copy() + idxr(s2)[3.0] = 100 - result = idxr(s2)[3.0] - compare(result, expected) + result = idxr(s2)[3.0] + compare(result, expected) - result = idxr(s2)[3] - compare(result, expected) + result = idxr(s2)[3] + compare(result, expected) - # contains - # coerce to equal int - assert 3.0 in s + # contains + # coerce to equal int + assert 3.0 in s def test_scalar_float(self): diff --git a/pandas/tests/indexing/test_scalar.py b/pandas/tests/indexing/test_scalar.py index 312a0c6531cfb..55cbe66cf2ec3 100644 --- a/pandas/tests/indexing/test_scalar.py +++ b/pandas/tests/indexing/test_scalar.py @@ -9,61 +9,60 @@ class TestScalar(Base): - def test_at_and_iat_get(self): + + @pytest.mark.parametrize("kind", ["series", "frame"]) + def test_at_and_iat_get(self, kind): def _check(f, func, values=False): if f is not None: - indicies = self.generate_indices(f, values) - for i in indicies: + indices = self.generate_indices(f, values) + for i in indices: result = getattr(f, func)[i] expected = self.get_value(func, f, i, values) tm.assert_almost_equal(result, expected) - for kind in self._kinds: - - d = getattr(self, kind) + d = getattr(self, kind) - # iat - for f in [d["ints"], d["uints"]]: - _check(f, "iat", values=True) + # iat + for f in [d["ints"], d["uints"]]: + _check(f, "iat", values=True) - for f in [d["labels"], d["ts"], d["floats"]]: - if f is not None: - msg = "iAt based indexing can only have integer indexers" - with pytest.raises(ValueError, match=msg): - self.check_values(f, "iat") + for f in [d["labels"], d["ts"], d["floats"]]: + if f is not None: + msg = "iAt based indexing can only have integer indexers" + with pytest.raises(ValueError, match=msg): + self.check_values(f, "iat") - # at - for f in [d["ints"], d["uints"], d["labels"], d["ts"], d["floats"]]: - _check(f, "at") + # at + for f in [d["ints"], d["uints"], d["labels"], d["ts"], d["floats"]]: + _check(f, "at") - def test_at_and_iat_set(self): + @pytest.mark.parametrize("kind", ["series", "frame"]) + def test_at_and_iat_set(self, kind): def _check(f, func, values=False): if f is not None: - indicies = self.generate_indices(f, values) - for i in indicies: + indices = self.generate_indices(f, values) + for i in indices: getattr(f, func)[i] = 1 expected = self.get_value(func, f, i, values) tm.assert_almost_equal(expected, 1) - for kind in self._kinds: + d = getattr(self, kind) - d = getattr(self, kind) + # iat + for f in [d["ints"], d["uints"]]: + _check(f, "iat", values=True) - # iat - for f in [d["ints"], d["uints"]]: - _check(f, "iat", values=True) - - for f in [d["labels"], d["ts"], d["floats"]]: - if f is not None: - msg = "iAt based indexing can only have integer indexers" - with pytest.raises(ValueError, match=msg): - _check(f, "iat") + for f in [d["labels"], d["ts"], d["floats"]]: + if f is not None: + msg = "iAt based indexing can only have integer indexers" + with pytest.raises(ValueError, match=msg): + _check(f, "iat") - # at - for f in [d["ints"], d["uints"], d["labels"], d["ts"], d["floats"]]: - _check(f, "at") + # at + for f in [d["ints"], d["uints"], d["labels"], d["ts"], d["floats"]]: + _check(f, "at") class TestScalar2: From 31affac95d7d13156c0e4c6dddb58949094c98d3 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 6 Feb 2020 19:25:06 -0800 Subject: [PATCH 2/4] parametrize --- pandas/tests/indexing/test_floats.py | 65 +++++++++++++--------------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/pandas/tests/indexing/test_floats.py b/pandas/tests/indexing/test_floats.py index 1361818a2932e..e891670001709 100644 --- a/pandas/tests/indexing/test_floats.py +++ b/pandas/tests/indexing/test_floats.py @@ -225,58 +225,55 @@ def test_scalar_with_mixed(self): assert result == expected @pytest.mark.parametrize( - "index_func", - [ - tm.makeIntIndex, - tm.makeRangeIndex, - ], + "index_func", [tm.makeIntIndex, tm.makeRangeIndex], ) - def test_scalar_integer(self, index_func): + @pytest.mark.parametrize("klass", [Series, DataFrame]) + def test_scalar_integer(self, index_func, klass): # test how scalar float indexers work on int indexes # integer index i = index_func(5) - for s in [ - Series(np.arange(len(i))), - DataFrame(np.random.randn(len(i), len(i)), index=i, columns=i), - ]: + if klass is Series: + obj = Series(np.arange(len(i))) + else: + obj = DataFrame(np.random.randn(len(i), len(i)), index=i, columns=i) - # coerce to equal int - for idxr, getitem in [(lambda x: x.loc, False), (lambda x: x, True)]: + # coerce to equal int + for idxr, getitem in [(lambda x: x.loc, False), (lambda x: x, True)]: - result = idxr(s)[3.0] - self.check(result, s, 3, getitem) + result = idxr(obj)[3.0] + self.check(result, obj, 3, getitem) - # coerce to equal int - for idxr, getitem in [(lambda x: x.loc, False), (lambda x: x, True)]: + # coerce to equal int + for idxr, getitem in [(lambda x: x.loc, False), (lambda x: x, True)]: - if isinstance(s, Series): + if isinstance(obj, Series): - def compare(x, y): - assert x == y + def compare(x, y): + assert x == y - expected = 100 + expected = 100 + else: + compare = tm.assert_series_equal + if getitem: + expected = Series(100, index=range(len(obj)), name=3) else: - compare = tm.assert_series_equal - if getitem: - expected = Series(100, index=range(len(s)), name=3) - else: - expected = Series(100.0, index=range(len(s)), name=3) + expected = Series(100.0, index=range(len(obj)), name=3) - s2 = s.copy() - idxr(s2)[3.0] = 100 + s2 = obj.copy() + idxr(s2)[3.0] = 100 - result = idxr(s2)[3.0] - compare(result, expected) + result = idxr(s2)[3.0] + compare(result, expected) - result = idxr(s2)[3] - compare(result, expected) + result = idxr(s2)[3] + compare(result, expected) - # contains - # coerce to equal int - assert 3.0 in s + # contains + # coerce to equal int + assert 3.0 in obj def test_scalar_float(self): From f8521ffcd781fa0c83c1fedef81be5d78572985f Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 6 Feb 2020 19:27:59 -0800 Subject: [PATCH 3/4] parametrize --- pandas/tests/indexing/test_floats.py | 217 ++++++++++++++------------- 1 file changed, 109 insertions(+), 108 deletions(-) diff --git a/pandas/tests/indexing/test_floats.py b/pandas/tests/indexing/test_floats.py index e891670001709..9aba5a20af717 100644 --- a/pandas/tests/indexing/test_floats.py +++ b/pandas/tests/indexing/test_floats.py @@ -328,76 +328,74 @@ def test_scalar_float(self): with pytest.raises(TypeError, match=msg): s2.iloc[3.0] = 0 - def test_slice_non_numeric(self): - - # GH 4892 - # float_indexers should raise exceptions - # on appropriate Index types & accessors - - for index in [ + @pytest.mark.parametrize( + "index_func", + [ tm.makeStringIndex, tm.makeUnicodeIndex, tm.makeDateIndex, tm.makeTimedeltaIndex, tm.makePeriodIndex, + ], + ) + def test_slice_non_numeric(self, index_func): + + # GH 4892 + # float_indexers should raise exceptions + # on appropriate Index types & accessors + + index = index_func(5) + for s in [ + Series(range(5), index=index), + DataFrame(np.random.randn(5, 2), index=index), ]: - index = index(5) - for s in [ - Series(range(5), index=index), - DataFrame(np.random.randn(5, 2), index=index), - ]: + # getitem + for l in [slice(3.0, 4), slice(3, 4.0), slice(3.0, 4.0)]: + + msg = ( + "cannot do slice indexing " + r"on {klass} with these indexers \[(3|4)\.0\] of " + "{kind}".format(klass=type(index), kind=str(float)) + ) + with pytest.raises(TypeError, match=msg): + s.iloc[l] - # getitem - for l in [slice(3.0, 4), slice(3, 4.0), slice(3.0, 4.0)]: + for idxr in [lambda x: x.loc, lambda x: x.iloc, lambda x: x]: msg = ( "cannot do slice indexing " - r"on {klass} with these indexers \[(3|4)\.0\] of " - "{kind}".format(klass=type(index), kind=str(float)) + r"on {klass} with these indexers " + r"\[(3|4)(\.0)?\] " + r"of ({kind_float}|{kind_int})".format( + klass=type(index), kind_float=str(float), kind_int=str(int), + ) ) with pytest.raises(TypeError, match=msg): - s.iloc[l] - - for idxr in [lambda x: x.loc, lambda x: x.iloc, lambda x: x]: - - msg = ( - "cannot do slice indexing " - r"on {klass} with these indexers " - r"\[(3|4)(\.0)?\] " - r"of ({kind_float}|{kind_int})".format( - klass=type(index), - kind_float=str(float), - kind_int=str(int), - ) - ) - with pytest.raises(TypeError, match=msg): - idxr(s)[l] + idxr(s)[l] - # setitem - for l in [slice(3.0, 4), slice(3, 4.0), slice(3.0, 4.0)]: + # setitem + for l in [slice(3.0, 4), slice(3, 4.0), slice(3.0, 4.0)]: + msg = ( + "cannot do slice indexing " + r"on {klass} with these indexers \[(3|4)\.0\] of " + "{kind}".format(klass=type(index), kind=str(float)) + ) + with pytest.raises(TypeError, match=msg): + s.iloc[l] = 0 + + for idxr in [lambda x: x.loc, lambda x: x.iloc, lambda x: x]: msg = ( "cannot do slice indexing " - r"on {klass} with these indexers \[(3|4)\.0\] of " - "{kind}".format(klass=type(index), kind=str(float)) + r"on {klass} with these indexers " + r"\[(3|4)(\.0)?\] " + r"of ({kind_float}|{kind_int})".format( + klass=type(index), kind_float=str(float), kind_int=str(int), + ) ) with pytest.raises(TypeError, match=msg): - s.iloc[l] = 0 - - for idxr in [lambda x: x.loc, lambda x: x.iloc, lambda x: x]: - msg = ( - "cannot do slice indexing " - r"on {klass} with these indexers " - r"\[(3|4)(\.0)?\] " - r"of ({kind_float}|{kind_int})".format( - klass=type(index), - kind_float=str(float), - kind_int=str(int), - ) - ) - with pytest.raises(TypeError, match=msg): - idxr(s)[l] = 0 + idxr(s)[l] = 0 def test_slice_integer(self): @@ -530,83 +528,86 @@ def test_integer_positional_indexing(self): with pytest.raises(TypeError, match=msg): idxr(s)[l] - def test_slice_integer_frame_getitem(self): + @pytest.mark.parametrize( + "index_func", [tm.makeIntIndex, tm.makeRangeIndex], + ) + def test_slice_integer_frame_getitem(self, index_func): # similar to above, but on the getitem dim (of a DataFrame) - for index in [Int64Index(range(5)), RangeIndex(5)]: + index = index_func(5) - s = DataFrame(np.random.randn(5, 2), index=index) + s = DataFrame(np.random.randn(5, 2), index=index) - def f(idxr): + def f(idxr): - # getitem - for l in [slice(0.0, 1), slice(0, 1.0), slice(0.0, 1.0)]: - - result = idxr(s)[l] - indexer = slice(0, 2) - self.check(result, s, indexer, False) - - # positional indexing - msg = ( - "cannot do slice indexing " - r"on {klass} with these indexers \[(0|1)\.0\] of " - "{kind}".format(klass=type(index), kind=str(float)) - ) - with pytest.raises(TypeError, match=msg): - s[l] + # getitem + for l in [slice(0.0, 1), slice(0, 1.0), slice(0.0, 1.0)]: - # getitem out-of-bounds - for l in [slice(-10, 10), slice(-10.0, 10.0)]: - - result = idxr(s)[l] - self.check(result, s, slice(-10, 10), True) + result = idxr(s)[l] + indexer = slice(0, 2) + self.check(result, s, indexer, False) # positional indexing msg = ( "cannot do slice indexing " - r"on {klass} with these indexers \[-10\.0\] of " + r"on {klass} with these indexers \[(0|1)\.0\] of " "{kind}".format(klass=type(index), kind=str(float)) ) with pytest.raises(TypeError, match=msg): - s[slice(-10.0, 10.0)] + s[l] - # getitem odd floats - for l, res in [ - (slice(0.5, 1), slice(1, 2)), - (slice(0, 0.5), slice(0, 1)), - (slice(0.5, 1.5), slice(1, 2)), - ]: + # getitem out-of-bounds + for l in [slice(-10, 10), slice(-10.0, 10.0)]: - result = idxr(s)[l] - self.check(result, s, res, False) + result = idxr(s)[l] + self.check(result, s, slice(-10, 10), True) - # positional indexing - msg = ( - "cannot do slice indexing " - r"on {klass} with these indexers \[0\.5\] of " - "{kind}".format(klass=type(index), kind=str(float)) - ) - with pytest.raises(TypeError, match=msg): - s[l] + # positional indexing + msg = ( + "cannot do slice indexing " + r"on {klass} with these indexers \[-10\.0\] of " + "{kind}".format(klass=type(index), kind=str(float)) + ) + with pytest.raises(TypeError, match=msg): + s[slice(-10.0, 10.0)] - # setitem - for l in [slice(3.0, 4), slice(3, 4.0), slice(3.0, 4.0)]: + # getitem odd floats + for l, res in [ + (slice(0.5, 1), slice(1, 2)), + (slice(0, 0.5), slice(0, 1)), + (slice(0.5, 1.5), slice(1, 2)), + ]: - sc = s.copy() - idxr(sc)[l] = 0 - result = idxr(sc)[l].values.ravel() - assert (result == 0).all() + result = idxr(s)[l] + self.check(result, s, res, False) - # positional indexing - msg = ( - "cannot do slice indexing " - r"on {klass} with these indexers \[(3|4)\.0\] of " - "{kind}".format(klass=type(index), kind=str(float)) - ) - with pytest.raises(TypeError, match=msg): - s[l] = 0 + # positional indexing + msg = ( + "cannot do slice indexing " + r"on {klass} with these indexers \[0\.5\] of " + "{kind}".format(klass=type(index), kind=str(float)) + ) + with pytest.raises(TypeError, match=msg): + s[l] + + # setitem + for l in [slice(3.0, 4), slice(3, 4.0), slice(3.0, 4.0)]: + + sc = s.copy() + idxr(sc)[l] = 0 + result = idxr(sc)[l].values.ravel() + assert (result == 0).all() + + # positional indexing + msg = ( + "cannot do slice indexing " + r"on {klass} with these indexers \[(3|4)\.0\] of " + "{kind}".format(klass=type(index), kind=str(float)) + ) + with pytest.raises(TypeError, match=msg): + s[l] = 0 - f(lambda x: x.loc) + f(lambda x: x.loc) def test_slice_float(self): From 118ac4d3d34f16ba067f940ca1ec850662200174 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 7 Feb 2020 08:08:14 -0800 Subject: [PATCH 4/4] blackify --- pandas/tests/indexing/test_scalar.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pandas/tests/indexing/test_scalar.py b/pandas/tests/indexing/test_scalar.py index 55cbe66cf2ec3..789e6022746d6 100644 --- a/pandas/tests/indexing/test_scalar.py +++ b/pandas/tests/indexing/test_scalar.py @@ -9,7 +9,6 @@ class TestScalar(Base): - @pytest.mark.parametrize("kind", ["series", "frame"]) def test_at_and_iat_get(self, kind): def _check(f, func, values=False):