- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 19.2k
Description
This is something I discovered while responding to feedback for #21902
There's a lot going on tests/indexes/common.py, and to skip tests that cannot work, several tests have an if condition to exclude certain cases. In particular, test_has_duplicates (currently still named ambiguously as test_duplicates) has a check
if type(indices) is not self._holder:
    pytest.skip(...)
which I wanted to copy to test_duplicated.
@jreback asked my why this isn't if not isinstance(indices, self._holder), but adding this caused errors. Upon some investigating, it turns out that the isinstance-check with Int64Index yields the wrong result within pytest. In a normal interpreter, the answers are as expected:
import pandas as pd
pd.__version__
# 0.24.0.dev0+422.gcfa618249.dirty
isinstance(pd.DatetimeIndex, pd.Int64Index)
# False
isinstance(pd.PeriodIndex, pd.Int64Index)
# False
isinstance(pd.TimedeltaIndex, pd.Int64Index)
# False
But changing test_has_duplicates as follows shows that this is not the same in pytest:
    def test_has_duplicates(self, indices):
        if not isinstance(indices, self._holder):  # <- changed as requested
            pytest.skip('Can only check if we have the correct type')
        if not len(indices) or isinstance(indices, MultiIndex):
            # MultiIndex tested separately in:
            # tests/indexes/multi/test_unique_and_duplicates
            pytest.skip('Skip check for empty Index and MultiIndex')
        # the following check shows that inheritance is sometimes broken
        if (isinstance(indices, self._holder)
            and type(indices) is not self._holder
            and self._holder is not Index):
            # for legitimate inheritance the results of isinstance(A, B) and
            # type(A) is B will be different (this is why we exclude B=Index).
            # But this also catches cases where isinstance yields the wrong answer
            raise ValueError(f'type(A): {type(indices).__name__}, '
                             f'B: {self._holder.__name__}, isinstance(A, B): '
                             f'{isinstance(indices, self._holder)}, '
                             f'type(A) is B: {type(indices) is self._holder}')
        idx = self._holder([indices[0]] * 5)
        assert not idx.is_unique
        assert idx.has_duplicates
This yields the following output in a run of pytest pandas/tests/indexes:
================================== FAILURES ===================================
______________ TestInt64Index.test_has_duplicates[DatetimeIndex] ______________
[...]
E           ValueError: type(A): DatetimeIndex, B: Int64Index, isinstance(A, B): True, type(A) is B: False
_______________ TestInt64Index.test_has_duplicates[PeriodIndex] _______________
[...]
E           ValueError: type(A): PeriodIndex, B: Int64Index, isinstance(A, B): True, type(A) is B: False
_____________ TestInt64Index.test_has_duplicates[TimedeltaIndex] ______________
[...]
E           ValueError: type(A): TimedeltaIndex, B: Int64Index, isinstance(A, B): True, type(A) is B: False
====== 3 failed, 7686 passed, 1033 skipped, 10 xfailed in 122.11 seconds ======