code: def deprecate_kwarg(
      old_arg_name: str,
      new_arg_name: str | None,
      mapping: Mapping[Any, Any] | Callable[[Any], Any] | None = None,
      stacklevel: int = 2,
  ) -> Callable[[F], F]:
      """
      Decorator to deprecate a keyword argument of a function.
  
      Parameters
      ----------
      old_arg_name : str
          Name of argument in function to deprecate
      new_arg_name : str or None
          Name of preferred argument in function. Use None to raise warning that
          ``old_arg_name`` keyword is deprecated.
      mapping : dict or callable
          If mapping is present, use it to translate old arguments to
          new arguments. A callable must do its own value checking;
          values not found in a dict will be forwarded unchanged.
  
      Examples
      --------
      The following deprecates 'cols', using 'columns' instead
  
      >>> @deprecate_kwarg(old_arg_name='cols', new_arg_name='columns')
      ... def f(columns=''):
      ...     print(columns)
      ...
      >>> f(columns='should work ok')
      should work ok
  
      >>> f(cols='should raise warning')  # doctest: +SKIP
      FutureWarning: cols is deprecated, use columns instead
        warnings.warn(msg, FutureWarning)
      should raise warning
  
      >>> f(cols='should error', columns="can\'t pass do both")  # doctest: +SKIP
      TypeError: Can only specify 'cols' or 'columns', not both
  
      >>> @deprecate_kwarg('old', 'new', {'yes': True, 'no': False})
      ... def f(new=False):
      ...     print('yes!' if new else 'no!')
      ...
      >>> f(old='yes')  # doctest: +SKIP
      FutureWarning: old='yes' is deprecated, use new=True instead
        warnings.warn(msg, FutureWarning)
      yes!
  
      To raise a warning that a keyword will be removed entirely in the future
  
      >>> @deprecate_kwarg(old_arg_name='cols', new_arg_name=None)
      ... def f(cols='', another_param=''):
      ...     print(cols)
      ...
      >>> f(cols='should raise warning')  # doctest: +SKIP
      FutureWarning: the 'cols' keyword is deprecated and will be removed in a
      future version please takes steps to stop use of 'cols'
      should raise warning
      >>> f(another_param='should not raise warning')  # doctest: +SKIP
      should not raise warning
  
      >>> f(cols='should raise warning', another_param='')  # doctest: +SKIP
      FutureWarning: the 'cols' keyword is deprecated and will be removed in a
      future version please takes steps to stop use of 'cols'
      should raise warning
      """
      if (
          mapping is not None
          and not hasattr(mapping, "get")
          and not callable(mapping)
      ):
          raise TypeError(
              "mapping from old to new argument values must be dict or callable!"
          )
  
      def _deprecate_kwarg(func: F) -> F:
          @wraps(func)
          def wrapper(*args, **kwargs) -> Callable[..., Any]:
              old_arg_value = kwargs.pop(old_arg_name, None)
  
              if old_arg_value is not None:
                  if new_arg_name is None:
                      msg = (
                          f"the {repr(old_arg_name)} keyword is deprecated and "
                          "will be removed in a future version. Please take "
                          f"steps to stop the use of {repr(old_arg_name)}"
                      )
                      warnings.warn(
                          msg, FutureWarning, stacklevel=stacklevel
                      )
                      kwargs[old_arg_name] = old_arg_value
                      return func(*args, **kwargs)
  
                  elif mapping is not None:
                      if callable(mapping):
                          new_arg_value = mapping(old_arg_value)
                      else:
                          new_arg_value = mapping.get(
                              old_arg_value, old_arg_value
                          )
                      msg = (
                          f"the {old_arg_name}={repr(old_arg_value)} keyword is "
                          "deprecated, use "
                          f"{new_arg_name}={repr(new_arg_value)} instead."
                      )
                  else:
                      new_arg_value = old_arg_value
                      msg = (
                          f"the {repr(old_arg_name)} keyword is deprecated, "
                          f"use {repr(new_arg_name)} instead."
                      )
  
                  warnings.warn(
                      msg, FutureWarning, stacklevel=stacklevel
                  )
                  if kwargs.get(new_arg_name) is not None:
                      msg = (
                          f"Can only specify {repr(old_arg_name)} "
                          f"or {repr(new_arg_name)}, not both."
                      )
                      raise TypeError(msg)
                  kwargs[new_arg_name] = new_arg_value
              return func(*args, **kwargs)
  
          return cast(F, wrapper)
  
      return _deprecate_kwarg
  
imports: from __future__ import annotations
  from functools import wraps
  import inspect
  from textwrap import dedent
  from typing import Any, Callable, Mapping, cast
  import warnings
  from pandas._libs.properties import cache_readonly
  from pandas._typing import F, T
  from pandas.util._exceptions import find_stack_level
label_desc: Use image node_id 2 for calling a global function with example usage: deprecate_kwarg(old_arg_name, new_arg_name, mapping, stacklevel) and returns: _deprecate_kwarg, cast, func, func