8000 BUG: Check for wrong arguments in index subclasses constructors · pandas-dev/pandas@d6052d5 · GitHub
[go: up one dir, main page]

Skip to content
  • Commit d6052d5

    Browse files
    committed
    BUG: Check for wrong arguments in index subclasses constructors
    Tidy up constructor signatures for different types of index
    1 parent 52cffa3 commit d6052d5

    File tree

    10 files changed

    +67
    -34
    lines changed

    10 files changed

    +67
    -34
    lines changed

    doc/source/whatsnew/v0.23.0.txt

    Lines changed: 1 addition & 0 deletions 8000
    Original file line numberDiff line numberDiff line change
    @@ -935,6 +935,7 @@ Indexing
    935935
    - Bug in :func:`IntervalIndex.symmetric_difference` where the symmetric difference with a non-``IntervalIndex`` did not raise (:issue:`18475`)
    936936
    - Bug in :class:`IntervalIndex` where set operations that returned an empty ``IntervalIndex`` had the wrong dtype (:issue:`19101`)
    937937
    - Bug in :meth:`DataFrame.drop_duplicates` where no ``KeyError`` is raised when passing in columns that don't exist on the ``DataFrame`` (issue:`19726`)
    938+
    - Bug in ``Index`` subclasses constructors that ignore unexpected keyword arguments (:issue:`19348`)
    938939

    939940

    940941
    MultiIndex

    pandas/core/indexes/category.py

    Lines changed: 1 addition & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -76,7 +76,7 @@ class CategoricalIndex(Index, accessor.PandasDelegate):
    7676
    _attributes = ['name']
    7777

    7878
    def __new__(cls, data=None, categories=None, ordered=None, dtype=None,
    79-
    copy=False, name=None, fastpath=False, **kwargs):
    79+
    copy=False, name=None, fastpath=False):
    8080

    8181
    if fastpath:
    8282
    return cls._simple_new(data, name=name, dtype=dtype)

    pandas/core/indexes/datetimes.py

    Lines changed: 9 additions & 7 deletions
    Original file line numberDiff line numberDiff line change
    @@ -213,6 +213,10 @@ class DatetimeIndex(DatelikeOps, TimelikeOps, DatetimeIndexOpsMixin,
    213213
    Attempt to infer fall dst-transition hours based on order
    214214
    name : object
    215215
    Name to be stored in the index
    216+
    dayfirst : bool, default False
    217+
    If True, parse dates in `data` with the day first order
    218+
    yearfirst : bool, default False
    219+
    If True parse dates in `data` with the year first order
    216220
    217221
    Attributes
    218222
    ----------
    @@ -272,6 +276,7 @@ class DatetimeIndex(DatelikeOps, TimelikeOps, DatetimeIndexOpsMixin,
    272276
    Index : The base pandas Index type
    273277
    TimedeltaIndex : Index of timedelta64 data
    274278
    PeriodIndex : Index of Period data
    279+
    pandas.to_datetime : Convert argument to datetime
    275280
    """
    276281

    277282
    _typ = 'datetimeindex'
    @@ -327,10 +332,10 @@ def _add_comparison_methods(cls):
    327332
    @deprecate_kwarg(old_arg_name='infer_dst', new_arg_name='ambiguous',
    328333
    mapping={True: 'infer', False: 'raise'})
    329334
    def __new__(cls, data=None,
    330-
    freq=None, start=None, end=None, periods=None,
    331-
    copy=False, name=None, tz=None,
    332-
    verify_integrity=True, normalize=False,
    333-
    closed=None, ambiguous='raise', dtype=None, **kwargs):
    335+
    freq=None, start=None, end=None, periods=None, tz=None,
    336+
    normalize=False, closed=None, ambiguous='raise',
    337+
    dayfirst=False, yearfirst=False, dtype=None,
    338+
    copy=False, name=None, verify_integrity=True):
    334339

    335340
    # This allows to later ensure that the 'copy' parameter is honored:
    336341
    if isinstance(data, Index):
    @@ -341,9 +346,6 @@ def __new__(cls, data=None,
    341346
    if name is None and hasattr(data, 'name'):
    342347
    name = data.name
    343348

    344-
    dayfirst = kwargs.pop('dayfirst', None)
    345-
    yearfirst = kwargs.pop('yearfirst', None)
    346-
    347349
    freq_infer = False
    348350
    if not isinstance(freq, DateOffset):
    349351

    pandas/core/indexes/interval.py

    Lines changed: 2 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -213,8 +213,8 @@ class IntervalIndex(IntervalMixin, Index):
    213213

    214214
    _mask = None
    215215

    216-
    def __new__(cls, data, closed=None, name=None, copy=False, dtype=None,
    217-
    fastpath=False, verify_integrity=True):
    216+
    def __new__(cls, data, closed=None, dtype=None, copy=False,
    217+
    name=None, fastpath=False, verify_integrity=True):
    218218

    219219
    if fastpath:
    220220
    return cls._simple_new(data.left, data.right, closed, name,

    pandas/core/indexes/multi.py

    Lines changed: 2 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -208,8 +208,8 @@ class MultiIndex(Index):
    208208
    rename = Index.set_names
    209209

    210210
    def __new__(cls, levels=None, labels=None, sortorder=None, names=None,
    211-
    copy=False, verify_integrity=True, _set_identity=True,
    212-
    name=None, **kwargs):
    211+
    dtype=None, copy=False, name=None,
    212+
    verify_integrity=True, _set_identity=True):
    213213

    214214
    # compat with Index
    215215
    if name is not None:

    pandas/core/indexes/period.py

    Lines changed: 10 additions & 3 deletions
    Original file line numberDiff line numberDiff line change
    @@ -234,8 +234,15 @@ def _add_comparison_methods(cls):
    234234
    cls.__ge__ = _period_index_cmp('__ge__', cls)
    235235

    236236
    def __new__(cls, data=None, ordinal=None, freq=None, start=None, end=None,
    237-
    periods=None, copy=False, name=None, tz=None, dtype=None,
    238-
    **kwargs):
    237+
    periods=None, tz=None, dtype=None, copy=False, name=None,
    238+
    **fields):
    239+
    240+
    valid_field_set = {'year', 'month', 'day', 'quarter',
    241+
    'hour', 'minute', 'second'}
    242+
    243+
    if not set(fields).issubset(valid_field_set):
    244+
    raise TypeError('__new__() got an unexpected keyword argument {}'.
    245+
    format(list(set(fields) - valid_field_set)[0]))
    239246

    240247
    if periods is not None:
    241248
    if is_float(periods):
    @@ -267,7 +274,7 @@ def __new__(cls, data=None, ordinal=None, freq=None, start=None, end=None,
    267274
    data = np.asarray(ordinal, dtype=np.int64)
    268275
    else:
    269276
    data, freq = cls._generate_range(start, end, periods,
    270-
    freq, kwargs)
    277+
    freq, fields)
    271278
    return cls._from_ordinals(data, name=name, freq=freq)
    272279

    273280
    if isinstance(data, PeriodIndex):

    pandas/core/indexes/range.py

    Lines changed: 3 additions & 3 deletions
    Original file line numberDiff line numberDiff line change
    @@ -65,8 +65,8 @@ class RangeIndex(Int64Index):
    6565
    _typ = 'rangeindex'
    6666
    _engine_type = libindex.Int64Engine
    6767

    68-
    def __new__(cls, start=None, stop=None, step=None, name=None, dtype=None,
    69-
    fastpath=False, copy=False, **kwargs):
    68+
    def __new__(cls, start=None, stop=None, step=None,
    69+
    dtype=None, copy=False, name=None, fastpath=False):
    7070

    7171
    if fastpath:
    7272
    return cls._simple_new(start, stop, step, name=name)
    @@ -550,7 +550,7 @@ def __getitem__(self, key):
    550550
    stop = self._start + self._step * stop
    551551
    step = self._step * step
    552552

    553-
    return RangeIndex(start, stop, step, self.name, fastpath=True)
    553+
    return RangeIndex(start, stop, step, name=self.name, fastpath=True)
    554554

    555555
    # fall back to Int64Index
    556556
    return super_getitem(key)

    pandas/core/indexes/timedeltas.py

    Lines changed: 3 additions & 4 deletions
    Original file line numberDiff line numberDiff line change
    @@ -197,10 +197,9 @@ def _add_comparison_methods(cls):
    197197

    198198
    freq = None
    199199

    200-
    def __new__(cls, data=None, unit=None,
    201-
    freq=None, start=None, end=None, periods=None,
    202-
    copy=False, name=None,
    203-
    closed=None, verify_integrity=True, **kwargs):
    200+
    def __new__(cls, data=None, unit=None, freq=None, start=None, end=None,
    201+
    periods=None, closed=None, dtype=None, copy=False,
    202+
    name=None, verify_integrity=True):
    204203

    205204
    if isinstance(data, TimedeltaIndex) and freq is None and name is None:
    206205
    if copy:

    pandas/tests/indexes/test_base.py

    Lines changed: 7 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -2326,3 +2326,10 @@ def test_generated_op_names(opname, indices):
    23262326
    opname = '__{name}__'.format(name=opname)
    23272327
    method = getattr(index, opname)
    23282328
    assert method.__name__ == opname
    2329+
    2330+
    2331+
    @pytest.mark.parametrize('idx_maker', tm.index_subclass_makers_generator())
    2332+
    def test_index_subclass_constructor_wrong_kwargs(idx_maker):
    2333+
    # GH #19348
    2334+
    with tm.assert_raises_regex(TypeError, 'unexpected keyword argument'):
    2335+
    idx_maker(foo='bar')

    pandas/util/testing.py

    Lines changed: 29 additions & 12 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1539,16 +1539,16 @@ def makeUnicodeIndex(k=10, name=None):
    15391539
    return Index(randu_array(nchars=10, size=k), name=name)
    15401540

    15411541

    1542-
    def makeCategoricalIndex(k=10, n=3, name=None):
    1542+
    def makeCategoricalIndex(k=10, n=3, name=None, **kwargs):
    15431543
    """ make a length k index or n categories """
    15441544
    x = rands_array(nchars=4, size=n)
    1545-
    return CategoricalIndex(np.random.choice(x, k), name=name)
    1545+
    return CategoricalIndex(np.random.choice(x, k), name=name, **kwargs)
    15461546

    15471547

    1548-
    def makeIntervalIndex(k=10, name=None):
    1548+
    def makeIntervalIndex(k=10, name=None, **kwargs):
    15491549
    """ make a length k IntervalIndex """
    15501550
    x = np.linspace(0, 100, num=(k + 1))
    1551-
    return IntervalIndex.from_breaks(x, name=name)
    1551+
    return IntervalIndex.from_breaks(x, name=name, **kwargs)
    15521552

    15531553

    15541554
    def makeBoolIndex(k=10, name=None):
    @@ -1567,31 +1567,37 @@ def makeUIntIndex(k=10, name=None):
    15671567
    return Index([2**63 + i for i in lrange(k)], name=name)
    15681568

    15691569

    1570-
    def makeRangeIndex(k=10, name=None):
    1571-
    return RangeIndex(0, k, 1, name=name)
    1570+
    def makeRangeIndex(k=10, name=None, **kwargs):
    1571+
    return RangeIndex(0, k, 1, name=name, **kwargs)
    15721572

    15731573

    15741574
    def makeFloatIndex(k=10, name=None):
    15751575
    values = sorted(np.random.random_sample(k)) - np.random.random_sample(1)
    15761576
    return Index(values * (10 ** np.random.randint(0, 9)), name=name)
    15771577

    15781578

    1579-
    def makeDateIndex(k=10, freq='B', name=None):
    1579+
    def makeDateIndex(k=10, freq='B', name=None, **kwargs):
    15801580
    dt = datetime(2000, 1, 1)
    15811581
    dr = bdate_range(dt, periods=k, freq=freq, name=name)
    1582-
    return DatetimeIndex(dr, name=name)
    1582+
    return DatetimeIndex(dr, name=name, **kwargs)
    15831583

    15841584

    1585-
    def makeTimedeltaIndex(k=10, freq='D', name=None):
    1586-
    return TimedeltaIndex(start='1 day', periods=k, freq=freq, name=name)
    1585+
    def makeTimedeltaIndex(k=10, freq='D', name=None, **kwargs):
    1586+
    return TimedeltaIndex(start='1 day', periods=k, freq=freq,
    1587+
    name=name, **kwargs)
    15871588

    15881589

    1589-
    def makePeriodIndex(k=10, name=None):
    1590+
    def makePeriodIndex(k=10, name=None, **kwargs):
    15901591
    dt = datetime(2000, 1, 1)
    1591-
    dr = PeriodIndex(start=dt, periods=k, freq='B', name=name)
    1592+
    dr = PeriodIndex(start=dt, periods=k, freq='B', name=name, **kwargs)
    15921593
    return dr
    15931594

    15941595

    1596+
    def makeMultiIndex(k=10, names=None, **kwargs):
    1597+
    return MultiIndex.from_product(
    1598+
    (('foo', 'bar'), (1, 2)), names=names, **kwargs)
    1599+
    1600+
    15951601
    def all_index_generator(k=10):
    15961602
    """Generator which can be iterated over to get instances of all the various
    15971603
    index classes.
    @@ -1609,6 +1615,17 @@ def all_index_generator(k=10):
    16091615
    yield make_index_func(k=k)
    16101616

    16111617

    1618+
    def index_subclass_makers_generator():
    1619+
    make_index_funcs = [
    1620+
    makeDateIndex, makePeriodIndex,
    1621+
    makeTimedeltaIndex, makeRangeIndex,
    1622+
    makeIntervalIndex, makeCategoricalIndex,
    1623+
    makeMultiIndex
    1624+
    ]
    1625+
    for make_index_func in make_index_funcs:
    1626+
    yield make_index_func
    1627+
    1628+
    16121629
    def all_timeseries_index_generator(k=10):
    16131630
    """Generator which can be iterated over to get instances of all the classes
    16141631
    which represent time-seires.

    0 commit comments

    Comments
     (0)
    0