From f7ae4442819153674bf57531bde70aeeb6251860 Mon Sep 17 00:00:00 2001
From: Brock Mendel <jbrockmendel@gmail.com>
Date: Tue, 23 Oct 2018 15:10:23 -0700
Subject: [PATCH 01/12] remove unused errors kwarg

---
 pandas/core/frame.py        | 2 +-
 pandas/core/ops.py          | 3 +--
 pandas/core/sparse/frame.py | 2 +-
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/pandas/core/frame.py b/pandas/core/frame.py
index 6dd9174028f18..d3dcae48dc6a0 100644
--- a/pandas/core/frame.py
+++ b/pandas/core/frame.py
@@ -4978,7 +4978,7 @@ def _combine_match_columns(self, other, func, level=None):
         assert left.columns.equals(right.index)
         return ops.dispatch_to_series(left, right, func, axis="columns")
 
-    def _combine_const(self, other, func, errors='raise'):
+    def _combine_const(self, other, func):
         assert lib.is_scalar(other) or np.ndim(other) == 0
         return ops.dispatch_to_series(self, other, func)
 
diff --git a/pandas/core/ops.py b/pandas/core/ops.py
index f29b4410fbf54..fc862c90402e1 100644
--- a/pandas/core/ops.py
+++ b/pandas/core/ops.py
@@ -1940,8 +1940,7 @@ def f(self, other):
 
             # straight boolean comparisons we want to allow all columns
             # (regardless of dtype to pass thru) See #4537 for discussion.
-            res = self._combine_const(other, func,
-                                      errors='ignore')
+            res = self._combine_const(other, func)
             return res.fillna(True).astype(bool)
 
     f.__name__ = op_name
diff --git a/pandas/core/sparse/frame.py b/pandas/core/sparse/frame.py
index e46df2b2bde70..56a5f4f49243f 100644
--- a/pandas/core/sparse/frame.py
+++ b/pandas/core/sparse/frame.py
@@ -642,7 +642,7 @@ def _combine_match_columns(self, other, func, level=None):
             new_data, index=self.index, columns=union,
             default_fill_value=self.default_fill_value).__finalize__(self)
 
-    def _combine_const(self, other, func, errors='raise'):
+    def _combine_const(self, other, func):
         return self._apply_columns(lambda x: func(x, other))
 
     def _reindex_index(self, index, method, copy, level, fill_value=np.nan,

From cdb7c5f030ce19d4a0d3568d5d230bd514a7fe00 Mon Sep 17 00:00:00 2001
From: Brock Mendel <jbrockmendel@gmail.com>
Date: Tue, 23 Oct 2018 16:31:09 -0700
Subject: [PATCH 02/12] Make strict copies for xfailed tests

---
 pandas/tests/arithmetic/conftest.py         |  3 +-
 pandas/tests/arithmetic/test_numeric.py     | 31 +++++++-
 pandas/tests/arithmetic/test_timedelta64.py | 79 +++++++++++++++++++++
 3 files changed, 111 insertions(+), 2 deletions(-)

diff --git a/pandas/tests/arithmetic/conftest.py b/pandas/tests/arithmetic/conftest.py
index b800b66e8edea..dfb50583af948 100644
--- a/pandas/tests/arithmetic/conftest.py
+++ b/pandas/tests/arithmetic/conftest.py
@@ -84,7 +84,8 @@ def three_days(request):
                         pd.Timedelta(hours=2).to_pytimedelta(),
                         pd.Timedelta(seconds=2 * 3600),
                         np.timedelta64(2, 'h'),
-                        np.timedelta64(120, 'm')])
+                        np.timedelta64(120, 'm')],
+                ids=lambda x: str(x))
 def two_hours(request):
     """
     Several timedelta-like and DateOffset objects that each represent
diff --git a/pandas/tests/arithmetic/test_numeric.py b/pandas/tests/arithmetic/test_numeric.py
index 25845dd8b3151..7ca999cd4bf4f 100644
--- a/pandas/tests/arithmetic/test_numeric.py
+++ b/pandas/tests/arithmetic/test_numeric.py
@@ -151,7 +151,7 @@ def test_numeric_arr_rdiv_tdscalar(self, three_days, numeric_idx, box):
         index = numeric_idx[1:3]
 
         broken = (isinstance(three_days, np.timedelta64) and
-                  three_days.dtype != 'm8[ns]')
+                  three_days.dtype == 'm8[D]')
         broken = broken or isinstance(three_days, pd.offsets.Tick)
         if box is not pd.Index and broken:
             # np.timedelta64(3, 'D') / 2 == np.timedelta64(1, 'D')
@@ -169,6 +169,35 @@ def test_numeric_arr_rdiv_tdscalar(self, three_days, numeric_idx, box):
         with pytest.raises(TypeError):
             index / three_days
 
+    @pytest.mark.xfail(reason="timedelta64 not converted to nanos; "
+                              "Tick division is not implemented",
+                       strict=True)
+    @pytest.mark.parametrize('box', [pd.Series, pd.DataFrame])
+    def test_numeric_arr_rdiv_tdscalar_failing(self, three_days,
+                                               numeric_idx, box):
+        # This is a duplicate of test_numeric_arr_rdiv_tdscalar specific to
+        # failing cases.  This allows us to make the "xfail" strict and be
+        # notified if/when these cases are fixed.
+        index = numeric_idx[1:3]
+
+        # np.timedelta64(3, 'D') / 2 == np.timedelta64(1, 'D')
+        broken = (isinstance(three_days, np.timedelta64) and
+                  three_days.dtype == 'm8[D]')
+        broken =  broken or isinstance(three_days, pd.offsets.Tick)
+        if not broken:
+            # raise a fake exception for the working cases
+            assert False
+
+        expected = TimedeltaIndex(['3 Days', '36 Hours'])
+
+        index = tm.box_expected(index, box)
+        expected = tm.box_expected(expected, box)
+
+        result = three_days / index
+        tm.assert_equal(result, expected)
+
+        with pytest.raises(TypeError):
+            index / three_days
 
 # ------------------------------------------------------------------
 # Arithmetic
diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py
index 14a55785c243b..239de7572a904 100644
--- a/pandas/tests/arithmetic/test_timedelta64.py
+++ b/pandas/tests/arithmetic/test_timedelta64.py
@@ -359,6 +359,24 @@ def test_td64arr_add_str_invalid(self, box):
         with pytest.raises(TypeError):
             'a' + tdi
 
+    @pytest.mark.xfail(reason="Tries to broadcast",
+                       strict=True, raises=ValueError)
+    @pytest.mark.parametrize('op', [operator.add, ops.radd,
+                                    operator.sub, ops.rsub],
+                             ids=lambda x: x.__name__)
+    def test_td64arr_add_sub_float_fail(self, op):
+        # This is a duplicate of test_td64arr_add_sub_float specific to
+        # the failing cases.  This allows us to make the "xfail" strict and
+        # get alerted if/when the broken cases are fixed.
+        box = pd.DataFrame
+        other = np.array([2.0, 3.0])
+
+        tdi = TimedeltaIndex(['-1 days', '-1 days'])
+        tdi = tm.box_expected(tdi, box)
+
+        with pytest.raises(TypeError):
+            op(tdi, other)
+
     @pytest.mark.parametrize('other', [3.14, np.array([2.0, 3.0])])
     @pytest.mark.parametrize('op', [operator.add, ops.radd,
                                     operator.sub, ops.rsub],
@@ -567,6 +585,38 @@ def test_td64arr_add_sub_numeric_scalar_invalid(self, box, scalar, tdser):
         with pytest.raises(err):
             scalar - tdser
 
+    @pytest.mark.xfail(reason="Tries to broadcast incorrectly",
+                       strict=True, raises=ValueError)
+    @pytest.mark.parametrize('dtype', ['int64', 'int32', 'int16',
+                                       'uint64', 'uint32', 'uint16', 'uint8',
+                                       'float64', 'float32', 'float16'])
+    @pytest.mark.parametrize('vec', [
+        np.array([1, 2, 3]),
+        pd.Index([1, 2, 3]),
+    ], ids=lambda x: type(x).__name__)
+    def test_td64arr_add_sub_numeric_arr_invalid_failing(self, vec,
+                                                         dtype, tdser):
+        # This is a duplicate of test_td64arr_add_sub_numeric_arr_invalid
+        # specific to the failing cases.  This lets us have a "strict" xfail
+        # and get alerted if/when the cases are fixed.
+        box = pd.DataFrame
+
+        tdser = tm.box_expected(tdser, box)
+        err = TypeError
+        if box is pd.Index and not dtype.startswith('float'):
+            err = NullFrequencyError
+
+        vector = vec.astype(dtype)
+        # TODO: parametrize over these four ops?
+        with pytest.raises(err):
+            tdser + vector
+        with pytest.raises(err):
+            vector + tdser
+        with pytest.raises(err):
+            tdser - vector
+        with pytest.raises(err):
+            vector - tdser
+
     @pytest.mark.parametrize('dtype', ['int64', 'int32', 'int16',
                                        'uint64', 'uint32', 'uint16', 'uint8',
                                        'float64', 'float32', 'float16'])
@@ -919,6 +969,35 @@ def test_td64arr_with_offset_series(self, names, box_df_fail):
             res3 = tdi - other
         tm.assert_equal(res3, expected_sub)
 
+    @pytest.mark.xfail(reason="Attempts to broadcast incorrectly",
+                       strict=True, raises=ValueError)
+    @pytest.mark.parametrize('obox', [np.array, pd.Index])
+    def test_td64arr_addsub_anchored_offset_arraylike_fail(self, obox):
+        # This is a duplicate of test_td64arr_addsub_anchored_offset_arraylike
+        # specific to the failing cases, so that we can have a "strict" xfail,
+        # and be alerted if/when the case is fixed.
+        box = pd.DataFrame
+
+        tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00'])
+        tdi = tm.box_expected(tdi, box)
+
+        anchored = obox([pd.offsets.MonthEnd(), pd.offsets.Day(n=2)])
+
+        # addition/subtraction ops with anchored offsets should issue
+        # a PerformanceWarning and _then_ raise a TypeError.
+        with pytest.raises(TypeError):
+            with tm.assert_produces_warning(PerformanceWarning):
+                tdi + anchored
+        with pytest.raises(TypeError):
+            with tm.assert_produces_warning(PerformanceWarning):
+                anchored + tdi
+        with pytest.raises(TypeError):
+            with tm.assert_produces_warning(PerformanceWarning):
+                tdi - anchored
+        with pytest.raises(TypeError):
+            with tm.assert_produces_warning(PerformanceWarning):
+                anchored - tdi
+
     @pytest.mark.parametrize('obox', [np.array, pd.Index, pd.Series])
     def test_td64arr_addsub_anchored_offset_arraylike(self, obox, box):
         # GH#18824

From 3117c8ee963a93e737577da657734703ffbdda3c Mon Sep 17 00:00:00 2001
From: Brock Mendel <jbrockmendel@gmail.com>
Date: Tue, 23 Oct 2018 16:31:32 -0700
Subject: [PATCH 03/12] Fix RangeIndex with DataFrame op to return
 NotImplemented

---
 pandas/core/indexes/range.py | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/pandas/core/indexes/range.py b/pandas/core/indexes/range.py
index 2b2f9ca51ce12..73bcbf1ceef7e 100644
--- a/pandas/core/indexes/range.py
+++ b/pandas/core/indexes/range.py
@@ -16,7 +16,8 @@
 from pandas.core.dtypes.common import (
     is_int64_dtype, is_integer, is_scalar, is_timedelta64_dtype
 )
-from pandas.core.dtypes.generic import ABCSeries, ABCTimedeltaIndex
+from pandas.core.dtypes.generic import (
+    ABCSeries, ABCTimedeltaIndex, ABCDataFrame)
 from pandas.core.indexes.base import Index, _index_shared_docs
 from pandas.core.indexes.numeric import Int64Index
 from pandas.util._decorators import Appender, cache_readonly
@@ -557,6 +558,9 @@ def __getitem__(self, key):
         return super_getitem(key)
 
     def __floordiv__(self, other):
+        if isinstance(other, ABCDataFrame):
+            return NotImplemented
+
         if is_integer(other) and other != 0:
             if (len(self) == 0 or
                     self._start % other == 0 and
@@ -588,7 +592,7 @@ def _make_evaluate_binop(op, step=False):
             """
 
             def _evaluate_numeric_binop(self, other):
-                if isinstance(other, ABCSeries):
+                if isinstance(other, (ABCSeries, ABCDataFrame)):
                     return NotImplemented
                 elif isinstance(other, ABCTimedeltaIndex):
                     # Defer to TimedeltaIndex implementation

From 1354fcecc9743757edeaf9fba72b2840bc82a5bb Mon Sep 17 00:00:00 2001
From: Brock Mendel <jbrockmendel@gmail.com>
Date: Tue, 23 Oct 2018 16:58:02 -0700
Subject: [PATCH 04/12] Fix reversed ops with np.timedelta64 and Tick

---
 pandas/core/ops.py                      |  9 +++++-
 pandas/tests/arithmetic/test_numeric.py | 37 -------------------------
 2 files changed, 8 insertions(+), 38 deletions(-)

diff --git a/pandas/core/ops.py b/pandas/core/ops.py
index fc862c90402e1..3c14446882315 100644
--- a/pandas/core/ops.py
+++ b/pandas/core/ops.py
@@ -45,6 +45,8 @@
     ABCIndex, ABCIndexClass,
     ABCSparseSeries, ABCSparseArray)
 
+from pandas.tseries.offsets import Tick
+
 
 # -----------------------------------------------------------------------------
 # Ops Wrapping Utilities
@@ -125,11 +127,16 @@ def maybe_upcast_for_op(obj):
     Be careful to call this *after* determining the `name` attribute to be
     attached to the result of the arithmetic operation.
     """
-    if type(obj) is datetime.timedelta:
+    if type(obj) is datetime.timedelta or isinstance(obj, Tick):
         # GH#22390  cast up to Timedelta to rely on Timedelta
         # implementation; otherwise operation against numeric-dtype
         # raises TypeError
         return pd.Timedelta(obj)
+    elif isinstance(obj, np.timedelta64):
+        # In particular non-nanosecond timedelta64 needs to be cast to
+        # nanoseconds, or else we get undesired behavior like
+        # np.timedelta64(3, 'D') / 2 == np.timedelta64(1, 'D')
+        return pd.Timedelta(obj)
     elif isinstance(obj, np.ndarray) and is_timedelta64_dtype(obj):
         # GH#22390 Unfortunately we need to special-case right-hand
         # timedelta64 dtypes because numpy casts integer dtypes to
diff --git a/pandas/tests/arithmetic/test_numeric.py b/pandas/tests/arithmetic/test_numeric.py
index 7ca999cd4bf4f..b8b88630a4344 100644
--- a/pandas/tests/arithmetic/test_numeric.py
+++ b/pandas/tests/arithmetic/test_numeric.py
@@ -150,14 +150,6 @@ def test_numeric_arr_mul_tdscalar(self, scalar_td, numeric_idx, box):
     def test_numeric_arr_rdiv_tdscalar(self, three_days, numeric_idx, box):
         index = numeric_idx[1:3]
 
-        broken = (isinstance(three_days, np.timedelta64) and
-                  three_days.dtype == 'm8[D]')
-        broken = broken or isinstance(three_days, pd.offsets.Tick)
-        if box is not pd.Index and broken:
-            # np.timedelta64(3, 'D') / 2 == np.timedelta64(1, 'D')
-            raise pytest.xfail("timedelta64 not converted to nanos; "
-                               "Tick division not implemented")
-
         expected = TimedeltaIndex(['3 Days', '36 Hours'])
 
         index = tm.box_expected(index, box)
@@ -169,35 +161,6 @@ def test_numeric_arr_rdiv_tdscalar(self, three_days, numeric_idx, box):
         with pytest.raises(TypeError):
             index / three_days
 
-    @pytest.mark.xfail(reason="timedelta64 not converted to nanos; "
-                              "Tick division is not implemented",
-                       strict=True)
-    @pytest.mark.parametrize('box', [pd.Series, pd.DataFrame])
-    def test_numeric_arr_rdiv_tdscalar_failing(self, three_days,
-                                               numeric_idx, box):
-        # This is a duplicate of test_numeric_arr_rdiv_tdscalar specific to
-        # failing cases.  This allows us to make the "xfail" strict and be
-        # notified if/when these cases are fixed.
-        index = numeric_idx[1:3]
-
-        # np.timedelta64(3, 'D') / 2 == np.timedelta64(1, 'D')
-        broken = (isinstance(three_days, np.timedelta64) and
-                  three_days.dtype == 'm8[D]')
-        broken =  broken or isinstance(three_days, pd.offsets.Tick)
-        if not broken:
-            # raise a fake exception for the working cases
-            assert False
-
-        expected = TimedeltaIndex(['3 Days', '36 Hours'])
-
-        index = tm.box_expected(index, box)
-        expected = tm.box_expected(expected, box)
-
-        result = three_days / index
-        tm.assert_equal(result, expected)
-
-        with pytest.raises(TypeError):
-            index / three_days
 
 # ------------------------------------------------------------------
 # Arithmetic

From f0c280df44e8dbadb49b49f8ae5c0ff894fc553f Mon Sep 17 00:00:00 2001
From: Brock Mendel <jbrockmendel@gmail.com>
Date: Tue, 23 Oct 2018 17:04:01 -0700
Subject: [PATCH 05/12] update xfails

---
 pandas/tests/arithmetic/test_timedelta64.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py
index 239de7572a904..0e803acca8bdc 100644
--- a/pandas/tests/arithmetic/test_timedelta64.py
+++ b/pandas/tests/arithmetic/test_timedelta64.py
@@ -1128,7 +1128,6 @@ def test_tdi_mul_float_series(self, box_df_fail):
         pd.RangeIndex(1, 11)
     ], ids=lambda x: type(x).__name__)
     def test_tdi_rmul_arraylike(self, other, box_df_fail):
-        # RangeIndex fails to return NotImplemented, for others
         # DataFrame tries to broadcast incorrectly
         box = box_df_fail
 
@@ -1415,9 +1414,10 @@ def test_td64arr_mul_int_series(self, box_df_fail, names):
         result = ser * tdi
         tm.assert_equal(result, expected)
 
-        # The direct operation tdi * ser still needs to be fixed.
         result = ser.__rmul__(tdi)
         tm.assert_equal(result, expected)
+        result = tdi * ser
+        tm.assert_equal(result, expected)
 
     # TODO: Should we be parametrizing over types for `ser` too?
     @pytest.mark.parametrize('names', [(None, None, None),

From 28e588b5a243bd705cfad62c196350d7592105a0 Mon Sep 17 00:00:00 2001
From: Brock Mendel <jbrockmendel@gmail.com>
Date: Tue, 23 Oct 2018 17:19:23 -0700
Subject: [PATCH 06/12] update to more specific xfail

---
 pandas/tests/arithmetic/test_timedelta64.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py
index 0e803acca8bdc..30adee1d1f19a 100644
--- a/pandas/tests/arithmetic/test_timedelta64.py
+++ b/pandas/tests/arithmetic/test_timedelta64.py
@@ -1127,9 +1127,9 @@ def test_tdi_mul_float_series(self, box_df_fail):
         pd.Float64Index(range(1, 11)),
         pd.RangeIndex(1, 11)
     ], ids=lambda x: type(x).__name__)
-    def test_tdi_rmul_arraylike(self, other, box_df_fail):
+    def test_tdi_rmul_arraylike(self, other, box_df_broadcast_failure):
         # DataFrame tries to broadcast incorrectly
-        box = box_df_fail
+        box = box_df_broadcast_failure
 
         tdi = TimedeltaIndex(['1 Day'] * 10)
         expected = timedelta_range('1 days', '10 days')

From 50c4c960222bdc0bcd673a0b428a7086b9332d4c Mon Sep 17 00:00:00 2001
From: Brock Mendel <jbrockmendel@gmail.com>
Date: Tue, 23 Oct 2018 17:22:06 -0700
Subject: [PATCH 07/12] Implement transpose option for box_expected

---
 pandas/tests/arithmetic/test_timedelta64.py | 10 ++++------
 pandas/util/testing.py                      |  9 ++++++++-
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py
index 30adee1d1f19a..ccbfe8acf8a87 100644
--- a/pandas/tests/arithmetic/test_timedelta64.py
+++ b/pandas/tests/arithmetic/test_timedelta64.py
@@ -1342,20 +1342,18 @@ def test_td64arr_div_numeric_scalar(self, box, two, tdser):
                                         Series([20, 30, 40])],
                              ids=lambda x: type(x).__name__)
     @pytest.mark.parametrize('op', [operator.mul, ops.rmul])
-    def test_td64arr_rmul_numeric_array(self, op, box_df_fail,
-                                        vector, dtype, tdser):
+    def test_td64arr_rmul_numeric_array(self, op, box, vector, dtype, tdser):
         # GH#4521
         # divide/multiply by integers
-        box = box_df_fail  # broadcasts incorrectly but doesn't raise
         vector = vector.astype(dtype)
 
         expected = Series(['1180 Days', '1770 Days', 'NaT'],
                           dtype='timedelta64[ns]')
 
-        tdser = tm.box_expected(tdser, box)
+        tdser = tm.box_expected(tdser, box, transpose=True)
         # TODO: Make this up-casting more systematic?
-        box = Series if (box is pd.Index and type(vector) is Series) else box
-        expected = tm.box_expected(expected, box)
+        box2 = Series if (box is pd.Index and type(vector) is Series) else box
+        expected = tm.box_expected(expected, box2, transpose=True)
 
         result = op(vector, tdser)
         tm.assert_equal(result, expected)
diff --git a/pandas/util/testing.py b/pandas/util/testing.py
index b5ec0912c5c26..055a8418137d2 100644
--- a/pandas/util/testing.py
+++ b/pandas/util/testing.py
@@ -1544,7 +1544,7 @@ def assert_equal(left, right, **kwargs):
         raise NotImplementedError(type(left))
 
 
-def box_expected(expected, box_cls):
+def box_expected(expected, box_cls, transpose=False):
     """
     Helper function to wrap the expected output of a test in a given box_class.
 
@@ -1552,6 +1552,8 @@ def box_expected(expected, box_cls):
     ----------
     expected : np.ndarray, Index, Series
     box_cls : {Index, Series, DataFrame}
+    transpose : bool
+        whether to transpose the result; only relevant for DataFrame
 
     Returns
     -------
@@ -1563,6 +1565,11 @@ def box_expected(expected, box_cls):
         expected = pd.Series(expected)
     elif box_cls is pd.DataFrame:
         expected = pd.Series(expected).to_frame()
+        if transpose:
+            # For tests in which a DataFrame operates with a 1-dimensional
+            # array-like other, broadcasting conventions require us to transpose
+            # both the DataFrame operand and the expected result.
+            expected = expected.T
     else:
         raise NotImplementedError(box_cls)
     return expected

From c4285a7d9dad9a9a1c5069df5ce8cd5bd26f5d3f Mon Sep 17 00:00:00 2001
From: Brock Mendel <jbrockmendel@gmail.com>
Date: Tue, 23 Oct 2018 17:45:17 -0700
Subject: [PATCH 08/12] use transpose=True to fix many xfails

---
 pandas/tests/arithmetic/test_datetime64.py  |   6 +-
 pandas/tests/arithmetic/test_period.py      |  12 +-
 pandas/tests/arithmetic/test_timedelta64.py | 201 +++++---------------
 3 files changed, 50 insertions(+), 169 deletions(-)

diff --git a/pandas/tests/arithmetic/test_datetime64.py b/pandas/tests/arithmetic/test_datetime64.py
index 36bb0aca066fb..8be63479443fd 100644
--- a/pandas/tests/arithmetic/test_datetime64.py
+++ b/pandas/tests/arithmetic/test_datetime64.py
@@ -1365,14 +1365,12 @@ def test_sub_period(self, freq, box):
                                     operator.sub, ops.rsub])
     @pytest.mark.parametrize('pi_freq', ['D', 'W', 'Q', 'H'])
     @pytest.mark.parametrize('dti_freq', [None, 'D'])
-    def test_dti_sub_pi(self, dti_freq, pi_freq, op, box_df_broadcast_failure):
+    def test_dti_sub_pi(self, dti_freq, pi_freq, op, box):
         # GH#20049 subtracting PeriodIndex should raise TypeError
-        box = box_df_broadcast_failure
-
         dti = pd.DatetimeIndex(['2011-01-01', '2011-01-02'], freq=dti_freq)
         pi = dti.to_period(pi_freq)
 
-        dti = tm.box_expected(dti, box)
+        dti = tm.box_expected(dti, box, transpose=True)
         # TODO: Also box pi?
         with pytest.raises(TypeError):
             op(dti, pi)
diff --git a/pandas/tests/arithmetic/test_period.py b/pandas/tests/arithmetic/test_period.py
index fe98b74499983..5fbb69ba52c28 100644
--- a/pandas/tests/arithmetic/test_period.py
+++ b/pandas/tests/arithmetic/test_period.py
@@ -344,14 +344,12 @@ class TestPeriodIndexArithmetic(object):
     # PeriodIndex - other is defined for integers, timedelta-like others,
     #   and PeriodIndex (with matching freq)
 
-    def test_parr_add_iadd_parr_raises(self, box_df_broadcast_failure):
-        box = box_df_broadcast_failure
-
+    def test_parr_add_iadd_parr_raises(self, box):
         rng = pd.period_range('1/1/2000', freq='D', periods=5)
         other = pd.period_range('1/6/2000', freq='D', periods=5)
         # TODO: parametrize over boxes for other?
 
-        rng = tm.box_expected(rng, box)
+        rng = tm.box_expected(rng, box, transpose=True)
         # An earlier implementation of PeriodIndex addition performed
         # a set operation (union).  This has since been changed to
         # raise a TypeError. See GH#14164 and GH#13077 for historical
@@ -388,14 +386,12 @@ def test_pi_sub_pi_with_nat(self):
         expected = pd.Index([pd.NaT, 0 * off, 0 * off, 0 * off, 0 * off])
         tm.assert_index_equal(result, expected)
 
-    def test_parr_sub_pi_mismatched_freq(self, box_df_broadcast_failure):
-        box = box_df_broadcast_failure
-
+    def test_parr_sub_pi_mismatched_freq(self, box):
         rng = pd.period_range('1/1/2000', freq='D', periods=5)
         other = pd.period_range('1/6/2000', freq='H', periods=5)
         # TODO: parametrize over boxes for other?
 
-        rng = tm.box_expected(rng, box)
+        rng = tm.box_expected(rng, box, transpose=True)
         with pytest.raises(period.IncompatibleFrequency):
             rng - other
 
diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py
index ccbfe8acf8a87..001e4755c7b13 100644
--- a/pandas/tests/arithmetic/test_timedelta64.py
+++ b/pandas/tests/arithmetic/test_timedelta64.py
@@ -359,35 +359,13 @@ def test_td64arr_add_str_invalid(self, box):
         with pytest.raises(TypeError):
             'a' + tdi
 
-    @pytest.mark.xfail(reason="Tries to broadcast",
-                       strict=True, raises=ValueError)
-    @pytest.mark.parametrize('op', [operator.add, ops.radd,
-                                    operator.sub, ops.rsub],
-                             ids=lambda x: x.__name__)
-    def test_td64arr_add_sub_float_fail(self, op):
-        # This is a duplicate of test_td64arr_add_sub_float specific to
-        # the failing cases.  This allows us to make the "xfail" strict and
-        # get alerted if/when the broken cases are fixed.
-        box = pd.DataFrame
-        other = np.array([2.0, 3.0])
-
-        tdi = TimedeltaIndex(['-1 days', '-1 days'])
-        tdi = tm.box_expected(tdi, box)
-
-        with pytest.raises(TypeError):
-            op(tdi, other)
-
     @pytest.mark.parametrize('other', [3.14, np.array([2.0, 3.0])])
     @pytest.mark.parametrize('op', [operator.add, ops.radd,
                                     operator.sub, ops.rsub],
                              ids=lambda x: x.__name__)
     def test_td64arr_add_sub_float(self, box, op, other):
-        if box is pd.DataFrame and isinstance(other, np.ndarray):
-            pytest.xfail("Tries to broadcast, raising "
-                         "ValueError instead of TypeError")
-
         tdi = TimedeltaIndex(['-1 days', '-1 days'])
-        tdi = tm.box_expected(tdi, box)
+        tdi = tm.box_expected(tdi, box, transpose=True)
 
         with pytest.raises(TypeError):
             op(tdi, other)
@@ -408,15 +386,14 @@ def test_td64arr_sub_period(self, box, freq):
 
     @pytest.mark.parametrize('pi_freq', ['D', 'W', 'Q', 'H'])
     @pytest.mark.parametrize('tdi_freq', [None, 'H'])
-    def test_td64arr_sub_pi(self, box_df_broadcast_failure, tdi_freq, pi_freq):
+    def test_td64arr_sub_pi(self, box, tdi_freq, pi_freq):
         # GH#20049 subtracting PeriodIndex should raise TypeError
-        box = box_df_broadcast_failure
         tdi = TimedeltaIndex(['1 hours', '2 hours'], freq=tdi_freq)
         dti = Timestamp('2018-03-07 17:16:40') + tdi
         pi = dti.to_period(pi_freq)
 
         # TODO: parametrize over box for pi?
-        tdi = tm.box_expected(tdi, box)
+        tdi = tm.box_expected(tdi, box, transpose=True)
         with pytest.raises(TypeError):
             tdi - pi
 
@@ -478,16 +455,14 @@ def test_td64arr_add_sub_timestamp(self, box):
         with pytest.raises(TypeError):
             tdser - ts
 
-    def test_tdi_sub_dt64_array(self, box_df_broadcast_failure):
-        box = box_df_broadcast_failure
-
+    def test_tdi_sub_dt64_array(self, box):
         dti = pd.date_range('2016-01-01', periods=3)
         tdi = dti - dti.shift(1)
         dtarr = dti.values
         expected = pd.DatetimeIndex(dtarr) - tdi
 
-        tdi = tm.box_expected(tdi, box)
-        expected = tm.box_expected(expected, box)
+        tdi = tm.box_expected(tdi, box, transpose=True)
+        expected = tm.box_expected(expected, box, transpose=True)
 
         with pytest.raises(TypeError):
             tdi - dtarr
@@ -496,16 +471,14 @@ def test_tdi_sub_dt64_array(self, box_df_broadcast_failure):
         result = dtarr - tdi
         tm.assert_equal(result, expected)
 
-    def test_tdi_add_dt64_array(self, box_df_broadcast_failure):
-        box = box_df_broadcast_failure
-
+    def test_tdi_add_dt64_array(self, box):
         dti = pd.date_range('2016-01-01', periods=3)
         tdi = dti - dti.shift(1)
         dtarr = dti.values
         expected = pd.DatetimeIndex(dtarr) + tdi
 
-        tdi = tm.box_expected(tdi, box)
-        expected = tm.box_expected(expected, box)
+        tdi = tm.box_expected(tdi, box, transpose=True)
+        expected = tm.box_expected(expected, box, transpose=True)
 
         result = tdi + dtarr
         tm.assert_equal(result, expected)
@@ -539,11 +512,10 @@ def test_td64arr_rsub_int_series_invalid(self, box, tdser):
         with pytest.raises(err):
             Series([2, 3, 4]) - tdser
 
-    def test_td64arr_add_intlike(self, box_df_broadcast_failure):
+    def test_td64arr_add_intlike(self, box):
         # GH#19123
-        box = box_df_broadcast_failure
         tdi = TimedeltaIndex(['59 days', '59 days', 'NaT'])
-        ser = tm.box_expected(tdi, box)
+        ser = tm.box_expected(tdi, box, transpose=True)
         err = TypeError if box is not pd.Index else NullFrequencyError
 
         other = Series([20, 30, 40], dtype='uint8')
@@ -585,38 +557,6 @@ def test_td64arr_add_sub_numeric_scalar_invalid(self, box, scalar, tdser):
         with pytest.raises(err):
             scalar - tdser
 
-    @pytest.mark.xfail(reason="Tries to broadcast incorrectly",
-                       strict=True, raises=ValueError)
-    @pytest.mark.parametrize('dtype', ['int64', 'int32', 'int16',
-                                       'uint64', 'uint32', 'uint16', 'uint8',
-                                       'float64', 'float32', 'float16'])
-    @pytest.mark.parametrize('vec', [
-        np.array([1, 2, 3]),
-        pd.Index([1, 2, 3]),
-    ], ids=lambda x: type(x).__name__)
-    def test_td64arr_add_sub_numeric_arr_invalid_failing(self, vec,
-                                                         dtype, tdser):
-        # This is a duplicate of test_td64arr_add_sub_numeric_arr_invalid
-        # specific to the failing cases.  This lets us have a "strict" xfail
-        # and get alerted if/when the cases are fixed.
-        box = pd.DataFrame
-
-        tdser = tm.box_expected(tdser, box)
-        err = TypeError
-        if box is pd.Index and not dtype.startswith('float'):
-            err = NullFrequencyError
-
-        vector = vec.astype(dtype)
-        # TODO: parametrize over these four ops?
-        with pytest.raises(err):
-            tdser + vector
-        with pytest.raises(err):
-            vector + tdser
-        with pytest.raises(err):
-            tdser - vector
-        with pytest.raises(err):
-            vector - tdser
-
     @pytest.mark.parametrize('dtype', ['int64', 'int32', 'int16',
                                        'uint64', 'uint32', 'uint16', 'uint8',
                                        'float64', 'float32', 'float16'])
@@ -627,10 +567,7 @@ def test_td64arr_add_sub_numeric_arr_invalid_failing(self, vec,
         # TODO: Add DataFrame in here?
     ], ids=lambda x: type(x).__name__)
     def test_td64arr_add_sub_numeric_arr_invalid(self, box, vec, dtype, tdser):
-        if box is pd.DataFrame and not isinstance(vec, Series):
-            raise pytest.xfail(reason="Tries to broadcast incorrectly")
-
-        tdser = tm.box_expected(tdser, box)
+        tdser = tm.box_expected(tdser, box, transpose=True)
         err = TypeError
         if box is pd.Index and not dtype.startswith('float'):
             err = NullFrequencyError
@@ -702,32 +639,28 @@ def test_timedelta64_operations_with_timedeltas(self):
         # roundtrip
         tm.assert_series_equal(result + td2, td1)
 
-    def test_td64arr_add_td64_array(self, box_df_broadcast_failure):
-        box = box_df_broadcast_failure
-
+    def test_td64arr_add_td64_array(self, box):
         dti = pd.date_range('2016-01-01', periods=3)
         tdi = dti - dti.shift(1)
         tdarr = tdi.values
 
         expected = 2 * tdi
-        tdi = tm.box_expected(tdi, box)
-        expected = tm.box_expected(expected, box)
+        tdi = tm.box_expected(tdi, box, transpose=True)
+        expected = tm.box_expected(expected, box, transpose=True)
 
         result = tdi + tdarr
         tm.assert_equal(result, expected)
         result = tdarr + tdi
         tm.assert_equal(result, expected)
 
-    def test_td64arr_sub_td64_array(self, box_df_broadcast_failure):
-        box = box_df_broadcast_failure
-
+    def test_td64arr_sub_td64_array(self, box):
         dti = pd.date_range('2016-01-01', periods=3)
         tdi = dti - dti.shift(1)
         tdarr = tdi.values
 
         expected = 0 * tdi
-        tdi = tm.box_expected(tdi, box)
-        expected = tm.box_expected(expected, box)
+        tdi = tm.box_expected(tdi, box, transpose=True)
+        expected = tm.box_expected(expected, box, transpose=True)
 
         result = tdi - tdarr
         tm.assert_equal(result, expected)
@@ -877,23 +810,23 @@ def test_td64arr_add_offset_index(self, names, box_df_broadcast_failure):
 
     # TODO: combine with test_td64arr_add_offset_index by parametrizing
     # over second box?
-    def test_td64arr_add_offset_array(self, box_df_broadcast_failure):
+    def test_td64arr_add_offset_array(self, box):
         # GH#18849
-        box = box_df_broadcast_failure
         tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00'])
         other = np.array([pd.offsets.Hour(n=1), pd.offsets.Minute(n=-2)])
 
         expected = TimedeltaIndex([tdi[n] + other[n] for n in range(len(tdi))],
                                   freq='infer')
 
-        tdi = tm.box_expected(tdi, box)
-        expected = tm.box_expected(expected, box)
+        tdi = tm.box_expected(tdi, box, transpose=True)
+        expected = tm.box_expected(expected, box, transpose=True)
 
-        with tm.assert_produces_warning(PerformanceWarning):
+        exwarning = PerformanceWarning if box is not pd.DataFrame else None
+        with tm.assert_produces_warning(exwarning):
             res = tdi + other
         tm.assert_equal(res, expected)
 
-        with tm.assert_produces_warning(PerformanceWarning):
+        with tm.assert_produces_warning(exwarning):
             res2 = other + tdi
         tm.assert_equal(res2, expected)
 
@@ -918,19 +851,19 @@ def test_td64arr_sub_offset_index(self, names, box_df_broadcast_failure):
             res = tdi - other
         tm.assert_equal(res, expected)
 
-    def test_td64arr_sub_offset_array(self, box_df_broadcast_failure):
+    def test_td64arr_sub_offset_array(self, box):
         # GH#18824
-        box = box_df_broadcast_failure
         tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00'])
         other = np.array([pd.offsets.Hour(n=1), pd.offsets.Minute(n=-2)])
 
         expected = TimedeltaIndex([tdi[n] - other[n] for n in range(len(tdi))],
                                   freq='infer')
 
-        tdi = tm.box_expected(tdi, box)
-        expected = tm.box_expected(expected, box)
+        tdi = tm.box_expected(tdi, box, transpose=True)
+        expected = tm.box_expected(expected, box, transpose=True)
 
-        with tm.assert_produces_warning(PerformanceWarning):
+        exwarning = PerformanceWarning if box is not pd.DataFrame else None
+        with tm.assert_produces_warning(exwarning):
             res = tdi - other
         tm.assert_equal(res, expected)
 
@@ -969,43 +902,11 @@ def test_td64arr_with_offset_series(self, names, box_df_fail):
             res3 = tdi - other
         tm.assert_equal(res3, expected_sub)
 
-    @pytest.mark.xfail(reason="Attempts to broadcast incorrectly",
-                       strict=True, raises=ValueError)
-    @pytest.mark.parametrize('obox', [np.array, pd.Index])
-    def test_td64arr_addsub_anchored_offset_arraylike_fail(self, obox):
-        # This is a duplicate of test_td64arr_addsub_anchored_offset_arraylike
-        # specific to the failing cases, so that we can have a "strict" xfail,
-        # and be alerted if/when the case is fixed.
-        box = pd.DataFrame
-
-        tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00'])
-        tdi = tm.box_expected(tdi, box)
-
-        anchored = obox([pd.offsets.MonthEnd(), pd.offsets.Day(n=2)])
-
-        # addition/subtraction ops with anchored offsets should issue
-        # a PerformanceWarning and _then_ raise a TypeError.
-        with pytest.raises(TypeError):
-            with tm.assert_produces_warning(PerformanceWarning):
-                tdi + anchored
-        with pytest.raises(TypeError):
-            with tm.assert_produces_warning(PerformanceWarning):
-                anchored + tdi
-        with pytest.raises(TypeError):
-            with tm.assert_produces_warning(PerformanceWarning):
-                tdi - anchored
-        with pytest.raises(TypeError):
-            with tm.assert_produces_warning(PerformanceWarning):
-                anchored - tdi
-
     @pytest.mark.parametrize('obox', [np.array, pd.Index, pd.Series])
     def test_td64arr_addsub_anchored_offset_arraylike(self, obox, box):
         # GH#18824
-        if box is pd.DataFrame and obox is not pd.Series:
-            raise pytest.xfail(reason="Attempts to broadcast incorrectly")
-
         tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00'])
-        tdi = tm.box_expected(tdi, box)
+        tdi = tm.box_expected(tdi, box, transpose=True)
 
         anchored = obox([pd.offsets.MonthEnd(), pd.offsets.Day(n=2)])
 
@@ -1081,40 +982,37 @@ def test_tdi_mul_int_array_zerodim(self, box):
         result = idx * np.array(5, dtype='int64')
         tm.assert_equal(result, expected)
 
-    def test_tdi_mul_int_array(self, box_df_broadcast_failure):
-        box = box_df_broadcast_failure
+    def test_tdi_mul_int_array(self, box):
         rng5 = np.arange(5, dtype='int64')
         idx = TimedeltaIndex(rng5)
         expected = TimedeltaIndex(rng5 ** 2)
 
-        idx = tm.box_expected(idx, box)
-        expected = tm.box_expected(expected, box)
+        idx = tm.box_expected(idx, box, transpose=True)
+        expected = tm.box_expected(expected, box, transpose=True)
 
         result = idx * rng5
         tm.assert_equal(result, expected)
 
-    def test_tdi_mul_int_series(self, box_df_fail):
-        box = box_df_fail
+    def test_tdi_mul_int_series(self, box):
         idx = TimedeltaIndex(np.arange(5, dtype='int64'))
         expected = TimedeltaIndex(np.arange(5, dtype='int64') ** 2)
 
-        idx = tm.box_expected(idx, box)
+        idx = tm.box_expected(idx, box, transpose=True)
 
         box2 = pd.Series if box is pd.Index else box
-        expected = tm.box_expected(expected, box2)
+        expected = tm.box_expected(expected, box2, transpose=True)
 
         result = idx * pd.Series(np.arange(5, dtype='int64'))
         tm.assert_equal(result, expected)
 
-    def test_tdi_mul_float_series(self, box_df_fail):
-        box = box_df_fail
+    def test_tdi_mul_float_series(self, box):
         idx = TimedeltaIndex(np.arange(5, dtype='int64'))
-        idx = tm.box_expected(idx, box)
+        idx = tm.box_expected(idx, box, transpose=True)
 
         rng5f = np.arange(5, dtype='float64')
         expected = TimedeltaIndex(rng5f * (rng5f + 0.1))
         box2 = pd.Series if box is pd.Index else box
-        expected = tm.box_expected(expected, box2)
+        expected = tm.box_expected(expected, box2, transpose=True)
 
         result = idx * Series(rng5f + 0.1)
         tm.assert_equal(result, expected)
@@ -1127,15 +1025,12 @@ def test_tdi_mul_float_series(self, box_df_fail):
         pd.Float64Index(range(1, 11)),
         pd.RangeIndex(1, 11)
     ], ids=lambda x: type(x).__name__)
-    def test_tdi_rmul_arraylike(self, other, box_df_broadcast_failure):
-        # DataFrame tries to broadcast incorrectly
-        box = box_df_broadcast_failure
-
+    def test_tdi_rmul_arraylike(self, other, box):
         tdi = TimedeltaIndex(['1 Day'] * 10)
         expected = timedelta_range('1 days', '10 days')
 
-        tdi = tm.box_expected(tdi, box)
-        expected = tm.box_expected(expected, box)
+        tdi = tm.box_expected(tdi, box, transpose=True)
+        expected = tm.box_expected(expected, box, transpose=True)
 
         result = other * tdi
         tm.assert_equal(result, expected)
@@ -1358,14 +1253,6 @@ def test_td64arr_rmul_numeric_array(self, op, box, vector, dtype, tdser):
         result = op(vector, tdser)
         tm.assert_equal(result, expected)
 
-    @pytest.mark.parametrize('box', [
-        pd.Index,
-        Series,
-        pytest.param(pd.DataFrame,
-                     marks=pytest.mark.xfail(reason="broadcasts along "
-                                                    "wrong axis",
-                                             strict=True))
-    ], ids=lambda x: x.__name__)
     @pytest.mark.parametrize('dtype', ['int64', 'int32', 'int16',
                                        'uint64', 'uint32', 'uint16', 'uint8',
                                        'float64', 'float32', 'float16'])
@@ -1380,9 +1267,9 @@ def test_td64arr_div_numeric_array(self, box, vector, dtype, tdser):
         expected = Series(['2.95D', '1D 23H 12m', 'NaT'],
                           dtype='timedelta64[ns]')
 
-        tdser = tm.box_expected(tdser, box)
+        tdser = tm.box_expected(tdser, box, transpose=True)
         box = Series if (box is pd.Index and type(vector) is Series) else box
-        expected = tm.box_expected(expected, box)
+        expected = tm.box_expected(expected, box, transpose=True)
 
         result = tdser / vector
         tm.assert_equal(result, expected)

From a79486548b885c8571a3177032331a6977762666 Mon Sep 17 00:00:00 2001
From: Brock Mendel <jbrockmendel@gmail.com>
Date: Tue, 23 Oct 2018 18:21:53 -0700
Subject: [PATCH 09/12] use transpose in box_expected to fix most remaining
 xfails

---
 pandas/tests/arithmetic/conftest.py         | 28 --------
 pandas/tests/arithmetic/test_timedelta64.py | 77 ++++++++++++---------
 2 files changed, 44 insertions(+), 61 deletions(-)

diff --git a/pandas/tests/arithmetic/conftest.py b/pandas/tests/arithmetic/conftest.py
index dfb50583af948..76b4022ce6f0a 100644
--- a/pandas/tests/arithmetic/conftest.py
+++ b/pandas/tests/arithmetic/conftest.py
@@ -142,31 +142,3 @@ def box(request):
     behavior with respect to arithmetic operations.
     """
     return request.param
-
-
-@pytest.fixture(params=[pd.Index,
-                        pd.Series,
-                        pytest.param(pd.DataFrame,
-                                     marks=pytest.mark.xfail(strict=True))],
-                ids=lambda x: x.__name__)
-def box_df_fail(request):
-    """
-    Fixture equivalent to `box` fixture but xfailing the DataFrame case.
-    """
-    return request.param
-
-
-@pytest.fixture(params=[
-    pd.Index,
-    pd.Series,
-    pytest.param(pd.DataFrame,
-                 marks=pytest.mark.xfail(reason="Tries to broadcast "
-                                                "incorrectly",
-                                         strict=True, raises=ValueError))
-], ids=lambda x: x.__name__)
-def box_df_broadcast_failure(request):
-    """
-    Fixture equivalent to `box` but with the common failing case where
-    the DataFrame operation tries to broadcast incorrectly.
-    """
-    return request.param
diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py
index 001e4755c7b13..97b37795e8c6a 100644
--- a/pandas/tests/arithmetic/test_timedelta64.py
+++ b/pandas/tests/arithmetic/test_timedelta64.py
@@ -671,17 +671,19 @@ def test_td64arr_sub_td64_array(self, box):
     @pytest.mark.parametrize('names', [(None, None, None),
                                        ('Egon', 'Venkman', None),
                                        ('NCC1701D', 'NCC1701D', 'NCC1701D')])
-    def test_td64arr_add_sub_tdi(self, box_df_broadcast_failure, names):
+    def test_td64arr_add_sub_tdi(self, box, names):
         # GH#17250 make sure result dtype is correct
         # GH#19043 make sure names are propagated correctly
-        box = box_df_broadcast_failure
+        if box is pd.DataFrame and names[0] != names[1]:
+            return
+
         tdi = TimedeltaIndex(['0 days', '1 day'], name=names[0])
         ser = Series([Timedelta(hours=3), Timedelta(hours=4)], name=names[1])
         expected = Series([Timedelta(hours=3), Timedelta(days=1, hours=4)],
                           name=names[2])
 
-        ser = tm.box_expected(ser, box)
-        expected = tm.box_expected(expected, box)
+        ser = tm.box_expected(ser, box, transpose=True)
+        expected = tm.box_expected(expected, box, transpose=True)
 
         result = tdi + ser
         tm.assert_equal(result, expected)
@@ -699,7 +701,7 @@ def test_td64arr_add_sub_tdi(self, box_df_broadcast_failure, names):
 
         expected = Series([Timedelta(hours=-3), Timedelta(days=1, hours=-4)],
                           name=names[2])
-        expected = tm.box_expected(expected, box)
+        expected = tm.box_expected(expected, box, transpose=True)
 
         result = tdi - ser
         tm.assert_equal(result, expected)
@@ -787,9 +789,11 @@ def test_timedelta64_operations_with_DateOffset(self):
     @pytest.mark.parametrize('names', [(None, None, None),
                                        ('foo', 'bar', None),
                                        ('foo', 'foo', 'foo')])
-    def test_td64arr_add_offset_index(self, names, box_df_broadcast_failure):
+    def test_td64arr_add_offset_index(self, names, box):
         # GH#18849, GH#19744
-        box = box_df_broadcast_failure
+        if box is pd.DataFrame and names[0] != names[1]:
+            return
+
         tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00'],
                              name=names[0])
         other = pd.Index([pd.offsets.Hour(n=1), pd.offsets.Minute(n=-2)],
@@ -797,14 +801,15 @@ def test_td64arr_add_offset_index(self, names, box_df_broadcast_failure):
 
         expected = TimedeltaIndex([tdi[n] + other[n] for n in range(len(tdi))],
                                   freq='infer', name=names[2])
-        tdi = tm.box_expected(tdi, box)
-        expected = tm.box_expected(expected, box)
+        tdi = tm.box_expected(tdi, box, transpose=True)
+        expected = tm.box_expected(expected, box, transpose=True)
 
-        with tm.assert_produces_warning(PerformanceWarning):
+        exwarning = PerformanceWarning if box is not pd.DataFrame else None
+        with tm.assert_produces_warning(exwarning):
             res = tdi + other
         tm.assert_equal(res, expected)
 
-        with tm.assert_produces_warning(PerformanceWarning):
+        with tm.assert_produces_warning(exwarning):
             res2 = other + tdi
         tm.assert_equal(res2, expected)
 
@@ -833,9 +838,11 @@ def test_td64arr_add_offset_array(self, box):
     @pytest.mark.parametrize('names', [(None, None, None),
                                        ('foo', 'bar', None),
                                        ('foo', 'foo', 'foo')])
-    def test_td64arr_sub_offset_index(self, names, box_df_broadcast_failure):
+    def test_td64arr_sub_offset_index(self, names, box):
         # GH#18824, GH#19744
-        box = box_df_broadcast_failure
+        if box is pd.DataFrame and names[0] != names[1]:
+            return
+
         tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00'],
                              name=names[0])
         other = pd.Index([pd.offsets.Hour(n=1), pd.offsets.Minute(n=-2)],
@@ -844,10 +851,11 @@ def test_td64arr_sub_offset_index(self, names, box_df_broadcast_failure):
         expected = TimedeltaIndex([tdi[n] - other[n] for n in range(len(tdi))],
                                   freq='infer', name=names[2])
 
-        tdi = tm.box_expected(tdi, box)
-        expected = tm.box_expected(expected, box)
+        tdi = tm.box_expected(tdi, box, transpose=True)
+        expected = tm.box_expected(expected, box, transpose=True)
 
-        with tm.assert_produces_warning(PerformanceWarning):
+        exwarning = PerformanceWarning if box is not pd.DataFrame else None
+        with tm.assert_produces_warning(exwarning):
             res = tdi - other
         tm.assert_equal(res, expected)
 
@@ -870,10 +878,13 @@ def test_td64arr_sub_offset_array(self, box):
     @pytest.mark.parametrize('names', [(None, None, None),
                                        ('foo', 'bar', None),
                                        ('foo', 'foo', 'foo')])
-    def test_td64arr_with_offset_series(self, names, box_df_fail):
+    def test_td64arr_with_offset_series(self, names, box):
         # GH#18849
-        box = box_df_fail
+        if box is pd.DataFrame and names[0] != names[1]:
+            return
+
         box2 = Series if box is pd.Index else box
+        exwarning = PerformanceWarning if box is not pd.DataFrame else None
 
         tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00'],
                              name=names[0])
@@ -882,23 +893,23 @@ def test_td64arr_with_offset_series(self, names, box_df_fail):
 
         expected_add = Series([tdi[n] + other[n] for n in range(len(tdi))],
                               name=names[2])
-        tdi = tm.box_expected(tdi, box)
-        expected_add = tm.box_expected(expected_add, box2)
+        expected_sub = Series([tdi[n] - other[n] for n in range(len(tdi))],
+                              name=names[2])
 
-        with tm.assert_produces_warning(PerformanceWarning):
+        tdi = tm.box_expected(tdi, box, transpose=True)
+        expected_add = tm.box_expected(expected_add, box2, transpose=True)
+
+        with tm.assert_produces_warning(exwarning):
             res = tdi + other
         tm.assert_equal(res, expected_add)
 
-        with tm.assert_produces_warning(PerformanceWarning):
+        with tm.assert_produces_warning(exwarning):
             res2 = other + tdi
         tm.assert_equal(res2, expected_add)
 
-        # TODO: separate/parametrize add/sub test?
-        expected_sub = Series([tdi[n] - other[n] for n in range(len(tdi))],
-                              name=names[2])
-        expected_sub = tm.box_expected(expected_sub, box2)
+        expected_sub = tm.box_expected(expected_sub, box2, transpose=True)
 
-        with tm.assert_produces_warning(PerformanceWarning):
+        with tm.assert_produces_warning(exwarning):
             res3 = tdi - other
         tm.assert_equal(res3, expected_sub)
 
@@ -1280,9 +1291,11 @@ def test_td64arr_div_numeric_array(self, box, vector, dtype, tdser):
     @pytest.mark.parametrize('names', [(None, None, None),
                                        ('Egon', 'Venkman', None),
                                        ('NCC1701D', 'NCC1701D', 'NCC1701D')])
-    def test_td64arr_mul_int_series(self, box_df_fail, names):
+    def test_td64arr_mul_int_series(self, box, names):
         # GH#19042 test for correct name attachment
-        box = box_df_fail  # broadcasts along wrong axis, but doesn't raise
+        if box is pd.DataFrame and names[0] != names[1]:
+            return
+
         tdi = TimedeltaIndex(['0days', '1day', '2days', '3days', '4days'],
                              name=names[0])
         # TODO: Should we be parametrizing over types for `ser` too?
@@ -1292,15 +1305,13 @@ def test_td64arr_mul_int_series(self, box_df_fail, names):
                           dtype='timedelta64[ns]',
                           name=names[2])
 
-        tdi = tm.box_expected(tdi, box)
+        tdi = tm.box_expected(tdi, box, transpose=True)
         box = Series if (box is pd.Index and type(ser) is Series) else box
-        expected = tm.box_expected(expected, box)
+        expected = tm.box_expected(expected, box, transpose=True)
 
         result = ser * tdi
         tm.assert_equal(result, expected)
 
-        result = ser.__rmul__(tdi)
-        tm.assert_equal(result, expected)
         result = tdi * ser
         tm.assert_equal(result, expected)
 

From 370c8778e5f1b3bc06a41e3953116da07ea37db4 Mon Sep 17 00:00:00 2001
From: Brock Mendel <jbrockmendel@gmail.com>
Date: Tue, 23 Oct 2018 18:34:09 -0700
Subject: [PATCH 10/12] flake8 fixup

---
 pandas/util/testing.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pandas/util/testing.py b/pandas/util/testing.py
index 055a8418137d2..46d313f438e3c 100644
--- a/pandas/util/testing.py
+++ b/pandas/util/testing.py
@@ -1567,8 +1567,8 @@ def box_expected(expected, box_cls, transpose=False):
         expected = pd.Series(expected).to_frame()
         if transpose:
             # For tests in which a DataFrame operates with a 1-dimensional
-            # array-like other, broadcasting conventions require us to transpose
-            # both the DataFrame operand and the expected result.
+            # array-like other, broadcasting conventions require us to
+            # transpose both the DataFrame operand and the expected result.
             expected = expected.T
     else:
         raise NotImplementedError(box_cls)

From 870862cc42095596e27d557b39096e7b318af9e6 Mon Sep 17 00:00:00 2001
From: Brock Mendel <jbrockmendel@gmail.com>
Date: Tue, 23 Oct 2018 20:00:33 -0700
Subject: [PATCH 11/12] fix incorrectly-xfailed test

---
 pandas/tests/internals/test_internals.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/pandas/tests/internals/test_internals.py b/pandas/tests/internals/test_internals.py
index b6a83b786bab2..e2c9ebef72bc1 100644
--- a/pandas/tests/internals/test_internals.py
+++ b/pandas/tests/internals/test_internals.py
@@ -1243,7 +1243,6 @@ def test_binop_other(self, op, value, dtype):
                    (operator.mul, '<M8[ns]'),
                    (operator.add, '<M8[ns]'),
                    (operator.pow, '<m8[ns]'),
-                   (operator.mod, '<m8[ns]'),
                    (operator.mul, '<m8[ns]')}
 
         if (op, dtype) in invalid:

From cb3109f938dadddbb4a1ee514e97a224d0cb55f1 Mon Sep 17 00:00:00 2001
From: Brock Mendel <jbrockmendel@gmail.com>
Date: Tue, 23 Oct 2018 20:11:17 -0700
Subject: [PATCH 12/12] tests for RangeIndex returning NotImplemented

---
 pandas/core/indexes/range.py       |  2 +-
 pandas/tests/indexes/test_range.py | 19 +++++++++++++++++++
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/pandas/core/indexes/range.py b/pandas/core/indexes/range.py
index 73bcbf1ceef7e..5ee4d3407eb00 100644
--- a/pandas/core/indexes/range.py
+++ b/pandas/core/indexes/range.py
@@ -558,7 +558,7 @@ def __getitem__(self, key):
         return super_getitem(key)
 
     def __floordiv__(self, other):
-        if isinstance(other, ABCDataFrame):
+        if isinstance(other, (ABCSeries, ABCDataFrame)):
             return NotImplemented
 
         if is_integer(other) and other != 0:
diff --git a/pandas/tests/indexes/test_range.py b/pandas/tests/indexes/test_range.py
index 0e47fcd52f625..fd2df39b1e7e7 100644
--- a/pandas/tests/indexes/test_range.py
+++ b/pandas/tests/indexes/test_range.py
@@ -189,6 +189,25 @@ def test_constructor_name(self):
         assert copy.name == 'copy'
         assert new.name == 'new'
 
+    # TODO: mod, divmod?
+    @pytest.mark.parametrize('op', [operator.add, operator.sub,
+                                    operator.mul, operator.floordiv,
+                                    operator.truediv, operator.pow])
+    def test_arithmetic_with_frame_or_series(self, op):
+        # check that we return NotImplemented when operating with Series
+        # or DataFrame
+        index = pd.RangeIndex(5)
+        other = pd.Series(np.random.randn(5))
+
+        expected = op(pd.Series(index), other)
+        result = op(index, other)
+        tm.assert_series_equal(result, expected)
+
+        other = pd.DataFrame(np.random.randn(2, 5))
+        expected = op(pd.DataFrame([index, index]), other)
+        result = op(index, other)
+        tm.assert_frame_equal(result, expected)
+
     def test_numeric_compat2(self):
         # validate that we are handling the RangeIndex overrides to numeric ops
         # and returning RangeIndex where possible