Skip to content

CLN: simplify+annotate _shallow_copy #32244

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from pandas._libs import algos as libalgos, index as libindex, lib
import pandas._libs.join as libjoin
from pandas._libs.lib import is_datetime_array
from pandas._libs.lib import is_datetime_array, no_default
from pandas._libs.tslibs import OutOfBoundsDatetime, Timestamp
from pandas._libs.tslibs.period import IncompatibleFrequency
from pandas._libs.tslibs.timezones import tz_compare
Expand Down Expand Up @@ -485,7 +485,7 @@ def _get_attributes_dict(self):
"""
return {k: getattr(self, k, None) for k in self._attributes}

def _shallow_copy(self, values=None, **kwargs):
def _shallow_copy(self, values=None, name: Label = no_default):
"""
Create a new Index with the same class as the caller, don't copy the
data, use the same object attributes with passed in attributes taking
Expand All @@ -496,16 +496,14 @@ def _shallow_copy(self, values=None, **kwargs):
Parameters
----------
values : the values to create the new Index, optional
kwargs : updates the default attributes for this Index
name : Label, defaults to self.name
"""
name = self.name if name is no_default else name

if values is None:
values = self.values

attributes = self._get_attributes_dict()

attributes.update(kwargs)

return self._simple_new(values, **attributes)
return self._simple_new(values, name=name)

def _shallow_copy_with_infer(self, values, **kwargs):
"""
Expand Down
7 changes: 5 additions & 2 deletions pandas/core/indexes/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

from pandas._libs import index as libindex
from pandas._libs.hashtable import duplicated_int64
from pandas._libs.lib import no_default
from pandas._typing import Label
from pandas.util._decorators import Appender, cache_readonly

from pandas.core.dtypes.common import (
Expand Down Expand Up @@ -264,13 +266,14 @@ def _simple_new(cls, values, name=None, dtype=None):
# --------------------------------------------------------------------

@Appender(Index._shallow_copy.__doc__)
def _shallow_copy(self, values=None, **kwargs):
def _shallow_copy(self, values=None, name: Label = no_default):
name = self.name if name is no_default else name

if values is None:
values = self.values

cat = Categorical(values, dtype=self.dtype)

name = kwargs.get("name", self.name)
return type(self)._simple_new(cat, name=name)

def _is_dtype_compat(self, other) -> bool:
Expand Down
15 changes: 7 additions & 8 deletions pandas/core/indexes/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from pandas._libs import NaT, iNaT, join as libjoin, lib
from pandas._libs.tslibs import timezones
from pandas._typing import Label
from pandas.compat.numpy import function as nv
from pandas.errors import AbstractMethodError
from pandas.util._decorators import Appender, cache_readonly
Expand Down Expand Up @@ -649,26 +650,26 @@ def _set_freq(self, freq):

self._data._freq = freq

def _shallow_copy(self, values=None, **kwargs):
def _shallow_copy(self, values=None, name: Label = lib.no_default):
name = self.name if name is lib.no_default else name

if values is None:
values = self._data

if isinstance(values, type(self)):
values = values._data
if isinstance(values, np.ndarray):
# TODO: We would rather not get here
if kwargs.get("freq") is not None:
raise ValueError(kwargs)
values = type(self._data)(values, dtype=self.dtype)

attributes = self._get_attributes_dict()

if "freq" not in kwargs and self.freq is not None:
if self.freq is not None:
if isinstance(values, (DatetimeArray, TimedeltaArray)):
if values.freq is None:
del attributes["freq"]

attributes.update(kwargs)
attributes["name"] = name
return type(self)._simple_new(values, **attributes)

# --------------------------------------------------------------------
Expand Down Expand Up @@ -738,9 +739,7 @@ def intersection(self, other, sort=False):
# this point, depending on the values.

result._set_freq(None)
result = self._shallow_copy(
result._data, name=result.name, dtype=result.dtype, freq=None
)
result = self._shallow_copy(result._data, name=result.name)
if result.freq is None:
result._set_freq("infer")
return result
Expand Down
4 changes: 2 additions & 2 deletions pandas/core/indexes/numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import numpy as np

from pandas._libs import index as libindex, lib
from pandas._typing import Dtype
from pandas._typing import Dtype, Label
from pandas.util._decorators import Appender, cache_readonly

from pandas.core.dtypes.cast import astype_nansafe
Expand Down Expand Up @@ -103,7 +103,7 @@ def _maybe_cast_slice_bound(self, label, side, kind):
return self._maybe_cast_indexer(label)

@Appender(Index._shallow_copy.__doc__)
def _shallow_copy(self, values=None, name=lib.no_default):
def _shallow_copy(self, values=None, name: Label = lib.no_default):
name = name if name is not lib.no_default else self.name

if values is not None and not self._can_hold_na and values.dtype.kind == "f":
Expand Down
19 changes: 6 additions & 13 deletions pandas/core/indexes/period.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import numpy as np

from pandas._libs import index as libindex
from pandas._libs.lib import no_default
from pandas._libs.tslibs import frequencies as libfrequencies, resolution
from pandas._libs.tslibs.parsing import parse_time_string
from pandas._libs.tslibs.period import Period
from pandas._typing import Label
from pandas.util._decorators import Appender, cache_readonly

from pandas.core.dtypes.common import (
Expand Down Expand Up @@ -248,8 +250,10 @@ def _has_complex_internals(self):
# used to avoid libreduction code paths, which raise or require conversion
return True

def _shallow_copy(self, values=None, **kwargs):
def _shallow_copy(self, values=None, name: Label = no_default):
# TODO: simplify, figure out type of values
name = name if name is not no_default else self.name

if values is None:
values = self._data

Expand All @@ -263,18 +267,7 @@ def _shallow_copy(self, values=None, **kwargs):
# GH#30713 this should never be reached
raise TypeError(type(values), getattr(values, "dtype", None))

# We don't allow changing `freq` in _shallow_copy.
validate_dtype_freq(self.dtype, kwargs.get("freq"))
attributes = self._get_attributes_dict()

attributes.update(kwargs)
if not len(values) and "dtype" not in kwargs:
attributes["dtype"] = self.dtype
return self._simple_new(values, **attributes)

def _shallow_copy_with_infer(self, values=None, **kwargs):
""" we always want to return a PeriodIndex """
return self._shallow_copy(values=values, **kwargs)
return self._simple_new(values, name=name)

def _maybe_convert_timedelta(self, other):
"""
Expand Down
10 changes: 6 additions & 4 deletions pandas/core/indexes/range.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import numpy as np

from pandas._libs import index as libindex
from pandas._libs.lib import no_default
from pandas._typing import Label
import pandas.compat as compat
from pandas.compat.numpy import function as nv
from pandas.util._decorators import Appender, cache_readonly
Expand Down Expand Up @@ -385,13 +387,13 @@ def tolist(self):
return list(self._range)

@Appender(Int64Index._shallow_copy.__doc__)
def _shallow_copy(self, values=None, **kwargs):
def _shallow_copy(self, values=None, name: Label = no_default):
name = self.name if name is no_default else name

if values is None:
name = kwargs.get("name", self.name)
return self._simple_new(self._range, name=name)
else:
kwargs.setdefault("name", self.name)
return self._int64index._shallow_copy(values, **kwargs)
return Int64Index._simple_new(values, name=name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is self._int64index replaced with Int64Index? does this affect subclassing?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Int64Index is more direct, avoids constructing self._int64index

Shouldn't affect subclasses, which isn't really supported anyway.


@Appender(Int64Index.copy.__doc__)
def copy(self, name=None, deep=False, dtype=None, **kwargs):
Expand Down
8 changes: 1 addition & 7 deletions pandas/tests/indexes/period/test_period.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,9 @@ def test_shallow_copy_empty(self):
def test_shallow_copy_i8(self):
# GH-24391
pi = period_range("2018-01-01", periods=3, freq="2D")
result = pi._shallow_copy(pi.asi8, freq=pi.freq)
result = pi._shallow_copy(pi.asi8)
tm.assert_index_equal(result, pi)

def test_shallow_copy_changing_freq_raises(self):
pi = period_range("2018-01-01", periods=3, freq="2D")
msg = "specified freq and dtype are different"
with pytest.raises(IncompatibleFrequency, match=msg):
pi._shallow_copy(pi, freq="H")

def test_view_asi8(self):
idx = PeriodIndex([], freq="M")

Expand Down