diff --git a/pandas/tests/indexes/interval/test_interval.py b/pandas/tests/indexes/interval/test_interval.py index e4f25ff143273..ba451da10573a 100644 --- a/pandas/tests/indexes/interval/test_interval.py +++ b/pandas/tests/indexes/interval/test_interval.py @@ -403,13 +403,16 @@ def test_get_item(self, closed): # To be removed, replaced by test_interval_new.py (see #16316, #16386) def test_get_loc_value(self): - pytest.raises(KeyError, self.index.get_loc, 0) + with pytest.raises(KeyError, match="^0$"): + self.index.get_loc(0) assert self.index.get_loc(0.5) == 0 assert self.index.get_loc(1) == 0 assert self.index.get_loc(1.5) == 1 assert self.index.get_loc(2) == 1 - pytest.raises(KeyError, self.index.get_loc, -1) - pytest.raises(KeyError, self.index.get_loc, 3) + with pytest.raises(KeyError, match="^-1$"): + self.index.get_loc(-1) + with pytest.raises(KeyError, match="^3$"): + self.index.get_loc(3) idx = IntervalIndex.from_tuples([(0, 2), (1, 3)]) assert idx.get_loc(0.5) == 0 @@ -419,10 +422,12 @@ def test_get_loc_value(self): tm.assert_numpy_array_equal(np.sort(idx.get_loc(2)), np.array([0, 1], dtype='intp')) assert idx.get_loc(3) == 1 - pytest.raises(KeyError, idx.get_loc, 3.5) + with pytest.raises(KeyError, match=r"^3\.5$"): + idx.get_loc(3.5) idx = IntervalIndex.from_arrays([0, 2], [1, 3]) - pytest.raises(KeyError, idx.get_loc, 1.5) + with pytest.raises(KeyError, match=r"^1\.5$"): + idx.get_loc(1.5) # To be removed, replaced by test_interval_new.py (see #16316, #16386) def slice_locs_cases(self, breaks): @@ -486,7 +491,9 @@ def test_slice_locs_decreasing_float64(self): # To be removed, replaced by test_interval_new.py (see #16316, #16386) def test_slice_locs_fails(self): index = IntervalIndex.from_tuples([(1, 2), (0, 1), (2, 3)]) - with pytest.raises(KeyError): + msg = ("'can only get slices from an IntervalIndex if bounds are" + " non-overlapping and all monotonic increasing or decreasing'") + with pytest.raises(KeyError, match=msg): index.slice_locs(1, 2) # To be removed, replaced by test_interval_new.py (see #16316, #16386) @@ -494,9 +501,12 @@ def test_get_loc_interval(self): assert self.index.get_loc(Interval(0, 1)) == 0 assert self.index.get_loc(Interval(0, 0.5)) == 0 assert self.index.get_loc(Interval(0, 1, 'left')) == 0 - pytest.raises(KeyError, self.index.get_loc, Interval(2, 3)) - pytest.raises(KeyError, self.index.get_loc, - Interval(-1, 0, 'left')) + msg = r"Interval\(2, 3, closed='right'\)" + with pytest.raises(KeyError, match=msg): + self.index.get_loc(Interval(2, 3)) + msg = r"Interval\(-1, 0, closed='left'\)" + with pytest.raises(KeyError, match=msg): + self.index.get_loc(Interval(-1, 0, 'left')) # Make consistent with test_interval_new.py (see #16316, #16386) @pytest.mark.parametrize('item', [3, Interval(1, 4)]) @@ -981,9 +991,11 @@ def test_comparison(self): self.index > 0 with pytest.raises(TypeError, match='unorderable types'): self.index <= 0 - with pytest.raises(TypeError): + msg = r"unorderable types: Interval\(\) > int\(\)" + with pytest.raises(TypeError, match=msg): self.index > np.arange(2) - with pytest.raises(ValueError): + msg = "Lengths must match to compare" + with pytest.raises(ValueError, match=msg): self.index > np.arange(3) def test_missing_values(self, closed): @@ -993,7 +1005,9 @@ def test_missing_values(self, closed): [np.nan, 0, 1], [np.nan, 1, 2], closed=closed) assert idx.equals(idx2) - with pytest.raises(ValueError): + msg = ("missing values must be missing in the same location both left" + " and right sides") + with pytest.raises(ValueError, match=msg): IntervalIndex.from_arrays( [np.nan, 0, 1], np.array([0, 1, 2]), closed=closed) diff --git a/pandas/tests/indexes/test_base.py b/pandas/tests/indexes/test_base.py index 8415bab802239..26dcf7d6bc234 100644 --- a/pandas/tests/indexes/test_base.py +++ b/pandas/tests/indexes/test_base.py @@ -4,6 +4,7 @@ from datetime import datetime, timedelta import math import operator +import re import sys import numpy as np @@ -107,7 +108,10 @@ def test_constructor_copy(self): def test_constructor_corner(self): # corner case - pytest.raises(TypeError, Index, 0) + msg = (r"Index\(\.\.\.\) must be called with a collection of some" + " kind, 0 was passed") + with pytest.raises(TypeError, match=msg): + Index(0) @pytest.mark.parametrize("index_vals", [ [('A', 1), 'B'], ['B', ('A', 1)]]) @@ -488,21 +492,22 @@ def test_constructor_cast(self): Index(["a", "b", "c"], dtype=float) def test_view_with_args(self): - restricted = ['unicodeIndex', 'strIndex', 'catIndex', 'boolIndex', 'empty'] - - for i in restricted: - ind = self.indices[i] - - # with arguments - pytest.raises(TypeError, lambda: ind.view('i8')) - - # these are ok for i in list(set(self.indices.keys()) - set(restricted)): ind = self.indices[i] + ind.view('i8') - # with arguments + @pytest.mark.parametrize('index_type', [ + 'unicodeIndex', + 'strIndex', + pytest.param('catIndex', marks=pytest.mark.xfail(reason="gh-25464")), + 'boolIndex', + 'empty']) + def test_view_with_args_object_array_raises(self, index_type): + ind = self.indices[index_type] + msg = "Cannot change data-type for object array" + with pytest.raises(TypeError, match=msg): ind.view('i8') def test_astype(self): @@ -565,8 +570,8 @@ def test_delete(self, pos, expected): def test_delete_raises(self): index = Index(['a', 'b', 'c', 'd'], name='index') - with pytest.raises((IndexError, ValueError)): - # either depending on numpy version + msg = "index 5 is out of bounds for axis 0 with size 4" + with pytest.raises(IndexError, match=msg): index.delete(5) def test_identical(self): @@ -683,7 +688,9 @@ def test_empty_fancy_raises(self, attr): assert index[[]].identical(empty_index) # np.ndarray only accepts ndarray of int & bool dtypes, so should Index - pytest.raises(IndexError, index.__getitem__, empty_farr) + msg = r"arrays used as indices must be of integer \(or boolean\) type" + with pytest.raises(IndexError, match=msg): + index[empty_farr] @pytest.mark.parametrize("sort", [None, False]) def test_intersection(self, sort): @@ -1426,13 +1433,14 @@ def test_get_indexer_strings(self, method, expected): def test_get_indexer_strings_raises(self): index = pd.Index(['b', 'c']) - with pytest.raises(TypeError): + msg = r"unsupported operand type\(s\) for -: 'str' and 'str'" + with pytest.raises(TypeError, match=msg): index.get_indexer(['a', 'b', 'c', 'd'], method='nearest') - with pytest.raises(TypeError): + with pytest.raises(TypeError, match=msg): index.get_indexer(['a', 'b', 'c', 'd'], method='pad', tolerance=2) - with pytest.raises(TypeError): + with pytest.raises(TypeError, match=msg): index.get_indexer(['a', 'b', 'c', 'd'], method='pad', tolerance=[2, 2, 2, 2]) @@ -1685,8 +1693,11 @@ def test_drop_tuple(self, values, to_drop): tm.assert_index_equal(result, expected) removed = index.drop(to_drop[1]) + msg = r"\"\[{}\] not found in axis\"".format( + re.escape(to_drop[1].__repr__())) for drop_me in to_drop[1], [to_drop[1]]: - pytest.raises(KeyError, removed.drop, drop_me) + with pytest.raises(KeyError, match=msg): + removed.drop(drop_me) @pytest.mark.parametrize("method,expected,sort", [ ('intersection', np.array([(1, 'A'), (2, 'A'), (1, 'B'), (2, 'B')], diff --git a/pandas/tests/indexes/test_category.py b/pandas/tests/indexes/test_category.py index d889135160ae2..95fac2f6ae05b 100644 --- a/pandas/tests/indexes/test_category.py +++ b/pandas/tests/indexes/test_category.py @@ -181,18 +181,21 @@ def test_create_categorical(self): expected = Categorical(['a', 'b', 'c']) tm.assert_categorical_equal(result, expected) - def test_disallow_set_ops(self): - + @pytest.mark.parametrize('func,op_name', [ + (lambda idx: idx - idx, '__sub__'), + (lambda idx: idx + idx, '__add__'), + (lambda idx: idx - ['a', 'b'], '__sub__'), + (lambda idx: idx + ['a', 'b'], '__add__'), + (lambda idx: ['a', 'b'] - idx, '__rsub__'), + (lambda idx: ['a', 'b'] + idx, '__radd__'), + ]) + def test_disallow_set_ops(self, func, op_name): # GH 10039 # set ops (+/-) raise TypeError idx = pd.Index(pd.Categorical(['a', 'b'])) - - pytest.raises(TypeError, lambda: idx - idx) - pytest.raises(TypeError, lambda: idx + idx) - pytest.raises(TypeError, lambda: idx - ['a', 'b']) - pytest.raises(TypeError, lambda: idx + ['a', 'b']) - pytest.raises(TypeError, lambda: ['a', 'b'] - idx) - pytest.raises(TypeError, lambda: ['a', 'b'] + idx) + msg = "cannot perform {} with this index type: CategoricalIndex" + with pytest.raises(TypeError, match=msg.format(op_name)): + func(idx) def test_method_delegation(self): @@ -231,8 +234,9 @@ def test_method_delegation(self): list('aabbca'), categories=list('cabdef'), ordered=True)) # invalid - pytest.raises(ValueError, lambda: ci.set_categories( - list('cab'), inplace=True)) + msg = "cannot use inplace with CategoricalIndex" + with pytest.raises(ValueError, match=msg): + ci.set_categories(list('cab'), inplace=True) def test_contains(self): @@ -357,12 +361,11 @@ def test_append(self): tm.assert_index_equal(result, ci, exact=True) # appending with different categories or reordered is not ok - pytest.raises( - TypeError, - lambda: ci.append(ci.values.set_categories(list('abcd')))) - pytest.raises( - TypeError, - lambda: ci.append(ci.values.reorder_categories(list('abc')))) + msg = "all inputs must be Index" + with pytest.raises(TypeError, match=msg): + ci.append(ci.values.set_categories(list('abcd'))) + with pytest.raises(TypeError, match=msg): + ci.append(ci.values.reorder_categories(list('abc'))) # with objects result = ci.append(Index(['c', 'a'])) @@ -370,7 +373,9 @@ def test_append(self): tm.assert_index_equal(result, expected, exact=True) # invalid objects - pytest.raises(TypeError, lambda: ci.append(Index(['a', 'd']))) + msg = "cannot append a non-category item to a CategoricalIndex" + with pytest.raises(TypeError, match=msg): + ci.append(Index(['a', 'd'])) # GH14298 - if base object is not categorical -> coerce to object result = Index(['c', 'a']).append(ci) @@ -406,7 +411,10 @@ def test_insert(self): tm.assert_index_equal(result, expected, exact=True) # invalid - pytest.raises(TypeError, lambda: ci.insert(0, 'd')) + msg = ("cannot insert an item into a CategoricalIndex that is not" + " already an existing category") + with pytest.raises(TypeError, match=msg): + ci.insert(0, 'd') # GH 18295 (test missing) expected = CategoricalIndex(['a', np.nan, 'a', 'b', 'c', 'b']) @@ -633,12 +641,16 @@ def test_get_indexer(self): r1 = idx1.get_indexer(idx2) assert_almost_equal(r1, np.array([0, 1, 2, -1], dtype=np.intp)) - pytest.raises(NotImplementedError, - lambda: idx2.get_indexer(idx1, method='pad')) - pytest.raises(NotImplementedError, - lambda: idx2.get_indexer(idx1, method='backfill')) - pytest.raises(NotImplementedError, - lambda: idx2.get_indexer(idx1, method='nearest')) + msg = ("method='pad' and method='backfill' not implemented yet for" + " CategoricalIndex") + with pytest.raises(NotImplementedError, match=msg): + idx2.get_indexer(idx1, method='pad') + with pytest.raises(NotImplementedError, match=msg): + idx2.get_indexer(idx1, method='backfill') + + msg = "method='nearest' not implemented yet for CategoricalIndex" + with pytest.raises(NotImplementedError, match=msg): + idx2.get_indexer(idx1, method='nearest') def test_get_loc(self): # GH 12531 @@ -776,12 +788,15 @@ def test_equals_categorical(self): # invalid comparisons with pytest.raises(ValueError, match="Lengths must match"): ci1 == Index(['a', 'b', 'c']) - pytest.raises(TypeError, lambda: ci1 == ci2) - pytest.raises( - TypeError, lambda: ci1 == Categorical(ci1.values, ordered=False)) - pytest.raises( - TypeError, - lambda: ci1 == Categorical(ci1.values, categories=list('abc'))) + + msg = ("categorical index comparisons must have the same categories" + " and ordered attributes") + with pytest.raises(TypeError, match=msg): + ci1 == ci2 + with pytest.raises(TypeError, match=msg): + ci1 == Categorical(ci1.values, ordered=False) + with pytest.raises(TypeError, match=msg): + ci1 == Categorical(ci1.values, categories=list('abc')) # tests # make sure that we are testing for category inclusion properly diff --git a/pandas/tests/indexes/test_common.py b/pandas/tests/indexes/test_common.py index fd356202a8ce5..03448129a48fc 100644 --- a/pandas/tests/indexes/test_common.py +++ b/pandas/tests/indexes/test_common.py @@ -3,6 +3,8 @@ any index subclass. Makes use of the `indices` fixture defined in pandas/tests/indexes/conftest.py. """ +import re + import numpy as np import pytest @@ -189,8 +191,14 @@ def test_unique(self, indices): result = indices.unique(level=level) tm.assert_index_equal(result, expected) - for level in 3, 'wrong': - pytest.raises((IndexError, KeyError), indices.unique, level=level) + msg = "Too many levels: Index has only 1 level, not 4" + with pytest.raises(IndexError, match=msg): + indices.unique(level=3) + + msg = r"Level wrong must be same as name \({}\)".format( + re.escape(indices.name.__repr__())) + with pytest.raises(KeyError, match=msg): + indices.unique(level='wrong') def test_get_unique_index(self, indices): # MultiIndex tested separately @@ -239,12 +247,16 @@ def test_get_unique_index(self, indices): tm.assert_index_equal(result, expected) def test_sort(self, indices): - pytest.raises(TypeError, indices.sort) + msg = "cannot sort an Index object in-place, use sort_values instead" + with pytest.raises(TypeError, match=msg): + indices.sort() def test_mutability(self, indices): if not len(indices): pytest.skip('Skip check for empty Index') - pytest.raises(TypeError, indices.__setitem__, 0, indices[0]) + msg = "Index does not support mutable operations" + with pytest.raises(TypeError, match=msg): + indices[0] = indices[0] def test_view(self, indices): assert indices.view().name == indices.name diff --git a/pandas/tests/indexes/test_numeric.py b/pandas/tests/indexes/test_numeric.py index a64340c02cd22..26413f4519eff 100644 --- a/pandas/tests/indexes/test_numeric.py +++ b/pandas/tests/indexes/test_numeric.py @@ -1,15 +1,17 @@ # -*- coding: utf-8 -*- from datetime import datetime +import re import numpy as np import pytest from pandas._libs.tslibs import Timestamp -from pandas.compat import range +from pandas.compat import PY2, range import pandas as pd from pandas import Float64Index, Index, Int64Index, Series, UInt64Index +from pandas.api.types import pandas_dtype from pandas.tests.indexes.common import Base import pandas.util.testing as tm @@ -153,12 +155,22 @@ def test_constructor(self): result = Index(np.array([np.nan])) assert pd.isna(result.values).all() + @pytest.mark.skipif(PY2, reason="pytest.raises match regex fails") def test_constructor_invalid(self): # invalid - pytest.raises(TypeError, Float64Index, 0.) - pytest.raises(TypeError, Float64Index, ['a', 'b', 0.]) - pytest.raises(TypeError, Float64Index, [Timestamp('20130101')]) + msg = (r"Float64Index\(\.\.\.\) must be called with a collection of" + r" some kind, 0\.0 was passed") + with pytest.raises(TypeError, match=msg): + Float64Index(0.) + msg = ("String dtype not supported, you may need to explicitly cast to" + " a numeric type") + with pytest.raises(TypeError, match=msg): + Float64Index(['a', 'b', 0.]) + msg = (r"float\(\) argument must be a string or a number, not" + " 'Timestamp'") + with pytest.raises(TypeError, match=msg): + Float64Index([Timestamp('20130101')]) def test_constructor_coerce(self): @@ -216,12 +228,17 @@ def test_astype(self): # invalid for dtype in ['M8[ns]', 'm8[ns]']: - pytest.raises(TypeError, lambda: i.astype(dtype)) + msg = ("Cannot convert Float64Index to dtype {}; integer values" + " are required for conversion").format(pandas_dtype(dtype)) + with pytest.raises(TypeError, match=re.escape(msg)): + i.astype(dtype) # GH 13149 for dtype in ['int16', 'int32', 'int64']: i = Float64Index([0, 1.1, np.NAN]) - pytest.raises(ValueError, lambda: i.astype(dtype)) + msg = "Cannot convert NA to integer" + with pytest.raises(ValueError, match=msg): + i.astype(dtype) def test_type_coercion_fail(self, any_int_dtype): # see gh-15832 @@ -275,12 +292,16 @@ def test_get_loc(self): assert idx.get_loc(1.1, method) == loc assert idx.get_loc(1.1, method, tolerance=0.9) == loc - pytest.raises(KeyError, idx.get_loc, 'foo') - pytest.raises(KeyError, idx.get_loc, 1.5) - pytest.raises(KeyError, idx.get_loc, 1.5, method='pad', - tolerance=0.1) - pytest.raises(KeyError, idx.get_loc, True) - pytest.raises(KeyError, idx.get_loc, False) + with pytest.raises(KeyError, match="^'foo'$"): + idx.get_loc('foo') + with pytest.raises(KeyError, match=r"^1\.5$"): + idx.get_loc(1.5) + with pytest.raises(KeyError, match=r"^1\.5$"): + idx.get_loc(1.5, method='pad', tolerance=0.1) + with pytest.raises(KeyError, match="^True$"): + idx.get_loc(True) + with pytest.raises(KeyError, match="^False$"): + idx.get_loc(False) with pytest.raises(ValueError, match='must be numeric'): idx.get_loc(1.4, method='nearest', tolerance='foo') @@ -310,15 +331,20 @@ def test_get_loc_na(self): # not representable by slice idx = Float64Index([np.nan, 1, np.nan, np.nan]) assert idx.get_loc(1) == 1 - pytest.raises(KeyError, idx.slice_locs, np.nan) + msg = "'Cannot get left slice bound for non-unique label: nan" + with pytest.raises(KeyError, match=msg): + idx.slice_locs(np.nan) def test_get_loc_missing_nan(self): # GH 8569 idx = Float64Index([1, 2]) assert idx.get_loc(1) == 0 - pytest.raises(KeyError, idx.get_loc, 3) - pytest.raises(KeyError, idx.get_loc, np.nan) - pytest.raises(KeyError, idx.get_loc, [np.nan]) + with pytest.raises(KeyError, match=r"^3\.0$"): + idx.get_loc(3) + with pytest.raises(KeyError, match="^nan$"): + idx.get_loc(np.nan) + with pytest.raises(KeyError, match=r"^\[nan\]$"): + idx.get_loc([np.nan]) def test_contains_nans(self): i = Float64Index([1.0, 2.0, np.nan]) @@ -499,13 +525,17 @@ def test_union_noncomparable(self): tm.assert_index_equal(result, expected) def test_cant_or_shouldnt_cast(self): + msg = ("String dtype not supported, you may need to explicitly cast to" + " a numeric type") # can't data = ['foo', 'bar', 'baz'] - pytest.raises(TypeError, self._holder, data) + with pytest.raises(TypeError, match=msg): + self._holder(data) # shouldn't data = ['0', '1', '2'] - pytest.raises(TypeError, self._holder, data) + with pytest.raises(TypeError, match=msg): + self._holder(data) def test_view_index(self): self.index.view(Index) @@ -576,7 +606,10 @@ def test_constructor(self): tm.assert_index_equal(index, expected) # scalar raise Exception - pytest.raises(TypeError, Int64Index, 5) + msg = (r"Int64Index\(\.\.\.\) must be called with a collection of some" + " kind, 5 was passed") + with pytest.raises(TypeError, match=msg): + Int64Index(5) # copy arr = self.index.values diff --git a/pandas/tests/indexes/timedeltas/test_arithmetic.py b/pandas/tests/indexes/timedeltas/test_arithmetic.py index 04977023d7c62..3173252e174ab 100644 --- a/pandas/tests/indexes/timedeltas/test_arithmetic.py +++ b/pandas/tests/indexes/timedeltas/test_arithmetic.py @@ -198,20 +198,34 @@ def test_ops_ndarray(self): expected = pd.to_timedelta(['2 days']).values tm.assert_numpy_array_equal(td + other, expected) tm.assert_numpy_array_equal(other + td, expected) - pytest.raises(TypeError, lambda: td + np.array([1])) - pytest.raises(TypeError, lambda: np.array([1]) + td) + msg = r"unsupported operand type\(s\) for \+: 'Timedelta' and 'int'" + with pytest.raises(TypeError, match=msg): + td + np.array([1]) + msg = (r"unsupported operand type\(s\) for \+: 'numpy.ndarray' and" + " 'Timedelta'") + with pytest.raises(TypeError, match=msg): + np.array([1]) + td expected = pd.to_timedelta(['0 days']).values tm.assert_numpy_array_equal(td - other, expected) tm.assert_numpy_array_equal(-other + td, expected) - pytest.raises(TypeError, lambda: td - np.array([1])) - pytest.raises(TypeError, lambda: np.array([1]) - td) + msg = r"unsupported operand type\(s\) for -: 'Timedelta' and 'int'" + with pytest.raises(TypeError, match=msg): + td - np.array([1]) + msg = (r"unsupported operand type\(s\) for -: 'numpy.ndarray' and" + " 'Timedelta'") + with pytest.raises(TypeError, match=msg): + np.array([1]) - td expected = pd.to_timedelta(['2 days']).values tm.assert_numpy_array_equal(td * np.array([2]), expected) tm.assert_numpy_array_equal(np.array([2]) * td, expected) - pytest.raises(TypeError, lambda: td * other) - pytest.raises(TypeError, lambda: other * td) + msg = ("ufunc multiply cannot use operands with types" + r" dtype\('