Skip to content

Commit d1fc79d

Browse files
authored
REF: Avoid kwargs in rename_axis (#51072)
* Explicitly list rename_axis arguments * Explicitly list rename_axis arguments * Fix default value * Fix tests * Fix copy default and docstring * Remove unneeded * make keyword only
1 parent e63831e commit d1fc79d

File tree

3 files changed

+40
-87
lines changed

3 files changed

+40
-87
lines changed

pandas/core/generic.py

+22-56
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,7 @@
9090
SettingWithCopyError,
9191
SettingWithCopyWarning,
9292
)
93-
from pandas.util._decorators import (
94-
doc,
95-
rewrite_axis_style_signature,
96-
)
93+
from pandas.util._decorators import doc
9794
from pandas.util._exceptions import find_stack_level
9895
from pandas.util._validators import (
9996
validate_ascending,
@@ -509,38 +506,6 @@ def _construct_axes_dict(self, axes: Sequence[Axis] | None = None, **kwargs):
509506
d.update(kwargs) # type: ignore[arg-type]
510507
return d
511508

512-
@final
513-
@classmethod
514-
def _construct_axes_from_arguments(
515-
cls, args, kwargs, require_all: bool_t = False, sentinel=None
516-
):
517-
"""
518-
Construct and returns axes if supplied in args/kwargs.
519-
520-
If require_all, raise if all axis arguments are not supplied
521-
return a tuple of (axes, kwargs).
522-
523-
sentinel specifies the default parameter when an axis is not
524-
supplied; useful to distinguish when a user explicitly passes None
525-
in scenarios where None has special meaning.
526-
"""
527-
# construct the args
528-
args = list(args)
529-
for a in cls._AXIS_ORDERS:
530-
531-
# look for a argument by position
532-
if a not in kwargs:
533-
try:
534-
kwargs[a] = args.pop(0)
535-
except IndexError as err:
536-
if require_all:
537-
raise TypeError(
538-
"not enough/duplicate arguments specified!"
539-
) from err
540-
541-
axes = {a: kwargs.pop(a, sentinel) for a in cls._AXIS_ORDERS}
542-
return axes, kwargs
543-
544509
@final
545510
@classmethod
546511
def _get_axis_number(cls, axis: Axis) -> AxisInt:
@@ -1077,8 +1042,11 @@ def rename_axis(
10771042
self: NDFrameT,
10781043
mapper: IndexLabel | lib.NoDefault = ...,
10791044
*,
1045+
index=...,
1046+
columns=...,
1047+
axis: Axis = ...,
1048+
copy: bool_t | None = ...,
10801049
inplace: Literal[False] = ...,
1081-
**kwargs,
10821050
) -> NDFrameT:
10831051
...
10841052

@@ -1087,8 +1055,11 @@ def rename_axis(
10871055
self,
10881056
mapper: IndexLabel | lib.NoDefault = ...,
10891057
*,
1058+
index=...,
1059+
columns=...,
1060+
axis: Axis = ...,
1061+
copy: bool_t | None = ...,
10901062
inplace: Literal[True],
1091-
**kwargs,
10921063
) -> None:
10931064
...
10941065

@@ -1097,18 +1068,23 @@ def rename_axis(
10971068
self: NDFrameT,
10981069
mapper: IndexLabel | lib.NoDefault = ...,
10991070
*,
1071+
index=...,
1072+
columns=...,
1073+
axis: Axis = ...,
1074+
copy: bool_t | None = ...,
11001075
inplace: bool_t = ...,
1101-
**kwargs,
11021076
) -> NDFrameT | None:
11031077
...
11041078

1105-
@rewrite_axis_style_signature("mapper", [("copy", True)])
11061079
def rename_axis(
11071080
self: NDFrameT,
11081081
mapper: IndexLabel | lib.NoDefault = lib.no_default,
11091082
*,
1083+
index=lib.no_default,
1084+
columns=lib.no_default,
1085+
axis: Axis = 0,
1086+
copy: bool_t | None = None,
11101087
inplace: bool_t = False,
1111-
**kwargs,
11121088
) -> NDFrameT | None:
11131089
"""
11141090
Set the name of the axis for the index or columns.
@@ -1129,7 +1105,7 @@ def rename_axis(
11291105
and/or ``columns``.
11301106
axis : {0 or 'index', 1 or 'columns'}, default 0
11311107
The axis to rename. For `Series` this parameter is unused and defaults to 0.
1132-
copy : bool, default True
1108+
copy : bool, default None
11331109
Also copy underlying data.
11341110
inplace : bool, default False
11351111
Modifies the object directly, instead of creating a new Series
@@ -1233,23 +1209,11 @@ class name
12331209
cat 4 0
12341210
monkey 2 2
12351211
"""
1236-
kwargs["inplace"] = inplace
1237-
axes, kwargs = self._construct_axes_from_arguments(
1238-
(), kwargs, sentinel=lib.no_default
1239-
)
1240-
copy: bool_t | None = kwargs.pop("copy", None)
1212+
axes = {"index": index, "columns": columns}
12411213

1242-
inplace = kwargs.pop("inplace", False)
1243-
axis = kwargs.pop("axis", 0)
12441214
if axis is not None:
12451215
axis = self._get_axis_number(axis)
12461216

1247-
if kwargs:
1248-
raise TypeError(
1249-
"rename_axis() got an unexpected keyword "
1250-
f'argument "{list(kwargs.keys())[0]}"'
1251-
)
1252-
12531217
inplace = validate_bool_kwarg(inplace, "inplace")
12541218

12551219
if mapper is not lib.no_default:
@@ -4530,7 +4494,9 @@ def drop(
45304494
axis_name = self._get_axis_name(axis)
45314495
axes = {axis_name: labels}
45324496
elif index is not None or columns is not None:
4533-
axes, _ = self._construct_axes_from_arguments((index, columns), {})
4497+
axes = {"index": index}
4498+
if self.ndim == 2:
4499+
axes["columns"] = columns
45344500
else:
45354501
raise ValueError(
45364502
"Need to specify at least one of 'labels', 'index' or 'columns'"

pandas/core/series.py

+18
Original file line numberDiff line numberDiff line change
@@ -4903,6 +4903,24 @@ def reindex( # type: ignore[override]
49034903
tolerance=tolerance,
49044904
)
49054905

4906+
@doc(NDFrame.rename_axis)
4907+
def rename_axis( # type: ignore[override]
4908+
self: Series,
4909+
mapper: IndexLabel | lib.NoDefault = lib.no_default,
4910+
*,
4911+
index=lib.no_default,
4912+
axis: Axis = 0,
4913+
copy: bool = True,
4914+
inplace: bool = False,
4915+
) -> Series | None:
4916+
return super().rename_axis(
4917+
mapper=mapper,
4918+
index=index,
4919+
axis=axis,
4920+
copy=copy,
4921+
inplace=inplace,
4922+
)
4923+
49064924
@overload
49074925
def drop(
49084926
self,

pandas/util/_decorators.py

-31
Original file line numberDiff line numberDiff line change
@@ -337,36 +337,6 @@ def wrapper(*args, **kwargs):
337337
return decorate
338338

339339

340-
def rewrite_axis_style_signature(
341-
name: str, extra_params: list[tuple[str, Any]]
342-
) -> Callable[[F], F]:
343-
def decorate(func: F) -> F:
344-
@wraps(func)
345-
def wrapper(*args, **kwargs) -> Callable[..., Any]:
346-
return func(*args, **kwargs)
347-
348-
kind = inspect.Parameter.POSITIONAL_OR_KEYWORD
349-
params = [
350-
inspect.Parameter("self", kind),
351-
inspect.Parameter(name, kind, default=None),
352-
inspect.Parameter("index", kind, default=None),
353-
inspect.Parameter("columns", kind, default=None),
354-
inspect.Parameter("axis", kind, default=None),
355-
]
356-
357-
for pname, default in extra_params:
358-
params.append(inspect.Parameter(pname, kind, default=default))
359-
360-
sig = inspect.Signature(params)
361-
362-
# https://github.com/python/typing/issues/598
363-
# error: "F" has no attribute "__signature__"
364-
func.__signature__ = sig # type: ignore[attr-defined]
365-
return cast(F, wrapper)
366-
367-
return decorate
368-
369-
370340
def doc(*docstrings: None | str | Callable, **params) -> Callable[[F], F]:
371341
"""
372342
A decorator take docstring templates, concatenate them and perform string
@@ -531,6 +501,5 @@ def indent(text: str | None, indents: int = 1) -> str:
531501
"deprecate_nonkeyword_arguments",
532502
"doc",
533503
"future_version_msg",
534-
"rewrite_axis_style_signature",
535504
"Substitution",
536505
]

0 commit comments

Comments
 (0)