
    ^j#                        U d Z ddlZddlZddlZddlmZmZmZ ddlmZ ddl	m
Z
mZmZmZmZmZ ddlmZ ddlmZmZmZmZmZmZmZ ddlmZmZ dd	lmZmZ d
ZdZ e!e"d<   dZ#dZ$dZ%dZ&ejN                  Z'ejP                  Z( eee)      Z*e+e,ee,   f   Z-ddddddddZ.e+e,e,f   e"d<   dee,   ddfdZ/de0ej                     de0ej                     fdZ1dededdfd Z2ded!eeef   ddfd"Z3dedee4deef   deeef   fd#Z5deded$e+e,e
f   defd%Z6d&ed'e7e
d(f   d)e+e,e
f   de+e,e
f   fd*Z8d&ed)e+e,e
f   de+e,e
f   fd+Z9e fd,edede,d-e!d.e,ddfd/Z:dede,fd0Z;de fd,ededede4eef   d1e,d2e,dee,   d-e!ddfd3Z<de fd,eded4e-d1e,d2e,dee,   d-e!ddfd5Z=d6ed(e
f   ded(e
f   dee4ded(e
f   ef   d7eed(e
f   ef   d8e7e
d(f   d$e+e,e
f   d9ed,eed:      d;e!d<e4d=e4defd>Z>ej~                  d?d?e*d@ddddAdAdBfdee4deef   d1e,d2e,d,ee   d;e!dee,   dCee-   dDee+e,e
f      dEee4ef   dFe4dGedH   deed(e
f   ged(e
f   f   fdIZ@y)Ja  Deprecation wrapper and utilities for marking deprecated code.

This module provides the main ``@deprecated`` decorator for marking functions and
methods as deprecated while optionally forwarding calls to their replacements.
Class-level deprecation is handled by :func:`~deprecate.proxy.deprecated_class`.

Key Components:
    - :func:`~deprecate.deprecation.deprecated`: Main decorator for deprecation with automatic call forwarding
    - Warning templates for different deprecation scenarios
    - Internal helpers for argument mapping and warning management

Copyright (C) 2020-2026 Jiri Borovec <6035284+Borda@users.noreply.github.com>

    N)cached_propertypartialwraps)	Parameter)AnyCallableLiteralOptionalUnioncast)warn)DeprecationConfig
TargetMode	_CallPlan_DeprecatedCallable_has_deprecation_meta_HasDeprecationMeta_WrapperState)"_update_docstring_with_deprecationnormalize_docstring_style)_get_signature!get_func_arguments_types_defaultszv1.0   _DEFAULT_STACKLEVEL_TO_CALLERzThe `%(source_name)s` was deprecated since v%(deprecated_in)s in favor of `%(target_path)s`. It will be removed in v%(remove_in)s.zThe `%(source_name)s` uses deprecated arguments: %(argument_map)s. They were deprecated since v%(deprecated_in)s and will be removed in v%(remove_in)s.z`%(old_arg)s` -> `%(new_arg)s`zdThe `%(source_name)s` was deprecated since v%(deprecated_in)s. It will be removed in v%(remove_in)s.)categoryxzx.yz0.0z1.0zx -> y)source_namesource_pathdeprecated_in	remove_intarget_nametarget_pathargument_map_TEMPLATE_MGS_PROBE_ARGStemplate_mgsreturnc           	          | sy	 | t         z   y# t        t        t        f$ r$}t        d|dt	        t                      |d}~ww xY w)a
  Probe ``template_mgs`` with every documented placeholder, raising at decoration time on failure.

    Args:
        template_mgs: User-supplied warning message template, or ``None``.  ``None`` and empty strings are
            no-ops because the call sites already fall back to the built-in templates.

    Raises:
        ValueError: When ``template_mgs`` references an unknown ``%(...)s`` key, uses a malformed conversion
            specifier, or otherwise fails ``%``-formatting against the full placeholder set.

    NzInvalid template_mgs: z. Available placeholders: )r$   KeyError	TypeError
ValueErrorlist)r%   excs     `/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/deprecate/deprecation.py_validate_template_mgsr.   L   sW     //i, $SG+EdKcFdEef
	s   	 AAAparamsc                 ^    | D cg c]  }|j                   t        t        fv s| c}S c c}w )z<Filter positional-only and positional-or-keyword parameters.)kindPOSITIONAL_ONLYPOSITIONAL_OR_KEYWORD)r/   params     r-   _get_positional_paramsr5   b   s'    %`eI^7_)_E```s   **sourcetargetc                    | j                   dk(  rt        |dd      dk(  ryt        | dd      }t        |dd      }|j                  dd      }|j                  dd      }t        |      dk7  st        |      dk7  ry|d	   |d	   }}|j	                  d
      s|j	                  d
      ry	 t        j                  d      j                  j                  dd      }|r&|j                  dd      d   j                  d      s|}|j                  dd      d	   }	t
        j                  j                  t        |dd      d      }
|
t        |
|	      sy|j                  dd      d   }|j                  dd      d   }t        | dd       d| }t        |dd       d| }||k(  ryt        d| j                    d|j                    d| d| d	      # t        t        f$ r Y w xY w)u  Raise ``TypeError`` when target is a method on a different class than source.

    Forwarding a class method to a method on a *different* class silently passes ``self`` of the wrong type, causing
    runtime attribute errors.  This guard detects the misconfiguration at decoration time by comparing the immediate
    class name extracted from each callable's ``__qualname__``.

    Qualname patterns and how they are handled:

    - ``"MyClass.method"``                   → class ``MyClass``
    - ``"outer.<locals>.MyClass.method"``    → class ``MyClass`` (class inside a function)
    - ``"outer.<locals>.<lambda>"``          → skipped; prefix ends with ``<locals>``
    - ``"base_sum_kwargs"``                  → skipped; no dot means module-level function

    False positive resolution — ``__qualname__`` is a display string, not an ownership API, so two scenarios used to
    yield spurious warnings.  Both are now handled:

    - **Decorators that rewrite ``__qualname__``** (e.g. a decorator applied before
      :func:`~deprecate.deprecated` that sets ``fn.__qualname__ = "OtherClass.method"``): resolved by reading
      ``__qualname__`` from the enclosing class
      body frame via :func:`sys._getframe`.  Python itself sets ``__qualname__`` in the class-body locals at
      class-definition time, so this value reflects the true enclosing class regardless of any decorator that
      mutated the source callable's ``__qualname__`` attribute.
    - **Metaclass-generated classes** (``type("Name", bases, ns)``, ``__init_subclass__``, or manual assignment
      producing qualnames like ``"FakeOwner.method"`` for unrelated types): resolved by verifying that the
      top-level class name in the qualname prefix actually exists in the callable's module globals.  When the
      referenced class does not exist, the qualname is unreliable and the guard returns without raising.

    Args:
        source: The callable being decorated with ``@deprecated``.
        target: The replacement callable supplied as the ``target`` argument.

    __init____name__ N__qualname__.      r   <locals><
__module__zCannot use @deprecated on 'z' with target 'z': cross-class method forwarding is not supported because `self` would carry the wrong type. The target must be a method on the same class ('z') or a full class (use target=z for class migration).)r:   getattrrsplitlenendswithsys	_getframef_localsget
startswithr*   AttributeErrorsplitmoduleshasattrr)   r<   )r6   r7   src_qualnametgt_qualname	src_parts	tgt_parts
src_prefix
tgt_prefixframe_qntgt_top_class
tgt_modulesrc_class_nametgt_class_name	src_owner	tgt_owners                  r-    _check_cross_class_method_targetr^   g   s   H *$R)HJ)V6>26L6>26L##C+I##C+I
9~c)n1&q\9Q<
J:&**=*=j*I==#,,00DHOOC3B7BB3G!J $$S!,Q/Mr!BDIJgj-&H&&sA.r2N&&sA.r2N6<45QzlCI6<45QzlCII

%f&9&9%: ;  !;;I:J K''5&66L		N ) ' s   *AG G"!G"outer_targetc                    | j                   j                  }| j                  }t        |      r3t        |      r(t	        j
                  d| dt         dt        d       yt        |      r:|t        j                  u r(t	        j
                  d| dt         dt        d       yt        |      r:|t        j                  u r(t	        j
                  d| dt         dt        d       y|t        j                  u r3t        |      r(t	        j
                  d| dt         dt        d       y|t        j                  u r:|t        j                  u r(t	        j
                  d| d	t         dt        d       y|t        j                  u r:|t        j                  u r(t	        j
                  d| d
t         dt        d       y|t        j                  u r|t        j                  u sA|t        j                  u r|t        j                  u s|t        j                  u rt        |      ryt	        j
                  d| dt         dt        d       y)u  Emit ``UserWarning`` at decoration time for unsupported stacking combinations.

    Only called when ``source`` already carries ``__deprecated__`` metadata (i.e. is itself a
    ``@deprecated`` wrapper).  Supported combinations are silently accepted:

    - ``ARGS_REMAP`` (outer) + ``ARGS_REMAP`` (inner): multi-step arg renames across versions.
    - ``ARGS_REMAP`` (outer) + ``NOTIFY`` (inner): lifecycle pattern — rename args first, deprecate
      the whole function later.
    - ``NOTIFY`` (outer) + ``callable`` (inner): outer NOTIFY warns callers the function is going
      away; inner callable handles forwarding.

    Unsupported combinations (six cases) produce ``UserWarning`` at decoration time; all others
    are silently accepted.  The three supported combinations are: ``ARGS_REMAP`` (outer) +
    ``ARGS_REMAP`` (inner), ``ARGS_REMAP`` (outer) + ``NOTIFY`` (inner), and ``NOTIFY`` (outer) +
    ``callable`` (inner).

    'z' has a callable target stacked over another callable-target @deprecated. Stacking a callable target over another callable target is not supported. This will raise `TypeError` at call time. Will be `TypeError` in `z`.   
stacklevelz' has a callable target stacked over @deprecated(ARGS_REMAP). The arg-rename warning will not fire at call time; the inner layer is bypassed. Collapse to: @deprecated(target=<callable>, args_mapping={...}). Will be `TypeError` in `a:  ' has a callable target stacked over @deprecated(NOTIFY). The inner function-deprecated warning will not fire at call time; the inner layer is bypassed while the callable target is still invoked. Collapse to a single @deprecated(target=<callable>) and remove the inner @deprecated(NOTIFY). Will be `TypeError` in `z' has @deprecated(ARGS_REMAP) stacked over a callable-target @deprecated. Update the inner @deprecated(target=<callable>, args_mapping={...}) instead of stacking. Will be `TypeError` in `z' has duplicate @deprecated(NOTIFY) layers. Update the existing decorator's `deprecated_in`, `remove_in`, or `template_mgs` instead. Will be `TypeError` in `z' has @deprecated(NOTIFY) stacked over @deprecated(ARGS_REMAP). Reverse the decorator order: put @deprecated(ARGS_REMAP, ...) outermost (on top) and @deprecated(NOTIFY, ...) below it. Will be `TypeError` in `zO' has an unsupported @deprecated stacking combination. Will be `TypeError` in `N)__deprecated__r7   r:   callablewarningsr   _V1_BREAK_VERSIONUserWarningr   
ARGS_REMAPNOTIFY)r6   r_   inner_targetnames       r-   _warn_stacking_misconfigurationrn      s=   $ ((//L??D(<"8v ( ):':"> 	
 
,	LJ4I4I$Iv ( ):':"> 	
 
,	LJ4E4E$Ev ( ):':"	>
 	
 
..	.8L3Iv ((9':"> 	
 
**	*|z?P?P/Pv ((9':"> 	
 
**	*|z?T?T/Tv ( ):':"> 	
 
..	.<:CXCX3XJ111ljFWFW6WJ---(<2Hv ((9':">		
    c                    |t        |t              rt        j                  |d      S t        |t              r|S t	        j
                  |      rt        | dd      }|j                  dd      }t        |      dk(  xr |d   j                  d	       }| j                  d
k(  r|j                  S |r&t        d| j                   d|j                   d      |S |S )u  Normalise the effective target callable before the wrapper closure captures it.

    Converts legacy sentinel values to :class:`~deprecate._types.TargetMode` enum members with a deprecation
    warning, and handles class targets:

    Legacy sentinel conversion (emits warning at decoration time):

    - ``target=None`` → :attr:`TargetMode.NOTIFY` + :class:`FutureWarning`
    - ``target=True`` → :attr:`TargetMode.ARGS_REMAP` + :class:`FutureWarning`
    - ``target=False`` → :attr:`TargetMode.NOTIFY` + :class:`UserWarning`

    Class target handling (unchanged from previous behaviour):

    1. ``source`` is ``__init__`` → remap ``target=NewCls`` to ``target=NewCls.__init__``
       (constructor forwarding; ``self`` is the new instance so the call is valid).
    2. ``source`` is a class method (non-``__init__``) → raise :exc:`TypeError`; passing a class as target for a
       bound method silently passes ``self`` of the wrong type.
    3. ``source`` is a module-level function → keep ``target=NewCls`` as-is; calling ``NewCls(**kwargs)`` creates
       a new instance directly.

    Args:
        source: The callable being decorated with ``@deprecated``.
        target: Raw ``target`` argument from the ``@deprecated`` call.

    Returns:
        Normalised target suitable for use inside ``wrapped_fn``.

    Raises:
        TypeError: When a class target is used on a non-``__init__`` class method.

    r   rc   r<   r;   r=   r>   r?   r   r@   r9   z3Cannot use a class as `target` for @deprecated on 'z['. Constructor forwarding via target=ClassName is only supported on `__init__`. Use target=z;.__init__ explicitly, or apply the decorator to `__init__`.)
isinstanceboolr   _from_legacyinspectisclassrD   rE   rF   rG   r:   r9   r)   r<   )r6   r7   rQ   rS   source_is_class_methods        r-   _normalize_targetrw     s    J ~FD1&&v!<< &*% vv~r: ''Q/	!$Y1!4!^Yq\=R=RS]=^9^??j(??"!EfFYFYEZ [$oo..ik 
  Mro   kwargsc                 J   t        |      D cg c]  }|d   	 }}t        j                  |      }|j                  }|j                  }|D cg c]	  }||vs| }}|r:|8|t        d| j                   d|       t        d| j                   d|       |S c c}w c c}w )u  Validate mapped keyword arguments and return the target callable.

    ``packing()`` normalises the target before ``wrapped_fn`` runs — class targets are remapped to
    ``target.__init__`` — so by the time this function is called, ``target`` is always a plain callable, never a class.

    Args:
        source: Deprecated callable being wrapped.
        target: Target callable to invoke (shall not be a class).
        kwargs: Keyword arguments after mapping and defaults.

    Returns:
        ``target`` unchanged, after validating that it accepts ``kwargs``.

    Example:
        >>> from deprecate.deprecation import _prepare_target_call
        >>> def source(a: int, b: int) -> int:
        ...     return a + b
        >>> def target(a: int, b: int) -> int:
        ...     return a - b
        >>> _prepare_target_call(source, target, {"c": 1})
        Traceback (most recent call last):
        ...
        TypeError: Failed mapping of `source`, arguments not accepted by target: ['c']

    r   zFailed mapping of `z%`, arguments not accepted by target: zh`, arguments not accepted by target (target accepts *args but these keyword arguments are not allowed): )r   rt   getfullargspecvarargsvarkwr)   r:   )	r6   r7   rx   argtarget_argstarget_full_arg_specvar_argsvar_kwmisseds	            r-   _prepare_target_callr   \  s    < &Gv%NOc3q6OKO"11&9#++H!''F#>cs+'=c>F>&.1&//1BBghngopqq!&//!2 399?B
 	
 M P
 ?s   B	B B funcfn_args.	fn_kwargsc                 Z   |s|S t        t        |       j                  j                               }t	        |      }t        d |D              }|st        |      t        |      kD  r|D cg c]+  }|j                  t        j                  j                  u s*|- }}t        |      t        |      k(  r0t        | j                   dt        |       dt        |       d      t        | j                   dt        |       dt        |       dt        |       d      t        |      }t        |      D ]m  \  }	}
|	t        |      k\  r |S ||	   }|j                  t        j                  j                   k(  r |S |j                  t"        t$        fv s_|
||j&                  <   o |S c c}w )a  Convert positional arguments to keyword arguments using function signature.

    This helper function takes positional arguments and converts them to keyword arguments by matching them with
    parameter names from the function signature.  This enables consistent argument handling in the deprecation wrapper.

    Args:
        func: Function whose signature provides parameter names.
        fn_args: Tuple of positional arguments passed to the function.
        fn_kwargs: Dictionary of keyword arguments already passed.

    Returns:
        Dictionary combining converted positional arguments and existing kwargs, where positional args are now mapped
        to their parameter names.  Conversion stops when encountering var-positional parameters (``*args``) because
        they cannot be safely represented as keyword arguments.

    Example:
        >>> from pprint import pprint
        >>> def example_func(a, b, c=3): pass
        >>> pprint(_update_kwargs_with_args(example_func, (1, 2), {'c': 5}))
        {'a': 1, 'b': 2, 'c': 5}

    c              3   j   K   | ]+  }|j                   t        j                  j                  k(   - y wNr1   rt   r   VAR_POSITIONAL.0r4   s     r-   	<genexpr>z+_update_kwargs_with_args.<locals>.<genexpr>  s&     `PUUZZ7+<+<+K+KK`   13z	() takes z  positional argument(s) but got z positional argument(s)z to )r+   r   
parametersvaluesr5   anyrF   defaultrt   r   emptyr)   r<   dict	enumerater1   r   r2   r3   rm   )r   r   r   r/   positional_paramshas_var_positionalr4   required_positional_paramsupdated_kwargsindexr}   s              r-   _update_kwargs_with_argsr     s   . .&1188:;F.v6`Y_``#g,5F1G"G9J%wemm_f_p_p_v_vNve%w"%w)*c2C.DD$$%Ys3D/E.FFfw<. 79    !3/I+J*K4PSTePfOg h..1'l^;RT
 	
 )_N( -
sCK  u::**999  ::/+@AA),N5::&- ' &xs   ++F(F(c                    t        |       }|D ci c],  }|d   t        j                  j                  k7  s$|d   |d   . }}t	        t        |j                               t        |j                               z         S c c}w )a?  Merge function default values with provided keyword arguments.

    This helper fills in default parameter values from the function signature for any parameters not explicitly
    provided.  Provided kwargs take precedence over defaults.

    Args:
        func: Function whose signature provides default parameter values.
        fn_kwargs: Dictionary of keyword arguments provided by caller.

    Returns:
        Dictionary with defaults merged with provided kwargs, where provided values override defaults.

    Example:
        >>> from pprint import pprint
        >>> def example_func(a=1, b=2, c=3): pass
        >>> pprint(_update_kwargs_with_defaults(example_func, {'b': 20}))
        {'a': 1, 'b': 20, 'c': 3}

    Note:
        Parameters without defaults (inspect.Parameter.empty) are not included in the result.

    r?   r   )r   rt   r   r   r   r+   items)r   r   func_arg_type_valr}   fn_defaultss        r-   _update_kwargs_with_defaultsr     su    . :$?->dc#a&GL]L]LcLcBc3q63q6>dKd[&&()D1B,CCDD es
   %A?A?streamrd   extrasc                     t        |      }|j                   d| }t        d||d|}||z  }	  | ||       y# t        $ r  | |       Y yw xY w)ud  Issue a deprecation warning using the specified stream and message template.

    This is the core warning issuer that formats and emits deprecation warnings.  It extracts source function metadata
    and combines it with provided template variables to generate the final warning message.

    Args:
        stream: Callable that outputs the warning (e.g., warnings.warn, logging.warning).
        source: The deprecated function/method being wrapped.
        template_mgs: Python format string with placeholders for message variables.
        stacklevel: Passed to ``warnings.warn`` so the warning points to the user's call site.  Default 4 accounts for
            the ``_raise_warn → _raise_warn_callable/_raise_warn_arguments → wrapped_fn → caller`` chain.
        **extras: Additional string values to substitute into the template (e.g., deprecated_in="1.0", remove_in="2.0").

    Note:
        Automatically extracts source_name and source_path from the source callable:
        - For regular functions: uses ``__name__``
        - For ``__init__`` methods: extracts class name from ``__qualname__``

    Example:
        >>> import warnings
        >>> def old_func(): pass
        >>> _raise_warn(
        ...     warnings.warn,
        ...     old_func,
        ...     "%(source_name)s deprecated in %(version)s",
        ...     version="1.0"
        ... )

    r=   )r   r   rc   N )_source_display_namerC   r   r)   )	r   r6   r%   rd   r   r   r   msg_argsmsgs	            r-   _raise_warnr     si    H 'v.K&&'q6KOOOH

!Csz* ss   
< AAc                 t    | j                   dk(  r| j                  j                  d      d   S | j                   S )zJReturn display name: class name for ``__init__``, function name otherwise.r9   r=   )r:   r<   rN   )r6   s    r-   r   r   
  s5    17J1N6$$S)"-cTZTcTccro   r   r    c           
          t        |      r$|j                  }|j                   d| }t        }	nd\  }}t        }	t        | ||xs |	|||||       y)a
  Issue deprecation warning for callable (function/class) deprecation.

    This specialized warning issuer handles deprecation of entire functions or classes that are being replaced by new
    implementations.  It automatically determines the appropriate message template based on whether a target callable
    is specified.

    Args:
        stream: Callable that outputs the warning (e.g., warnings.warn, logging.warning).
        source: The deprecated function/method being wrapped.
        target: The replacement implementation:
            - Callable: Forward to this function/class
            - None: No forwarding (warning only mode)
            - bool: Not applicable for this function (use _raise_warn_arguments instead)
        deprecated_in: Version when the source was marked deprecated (e.g., "1.0.0").
        remove_in: Version when the source will be removed (e.g., "2.0.0").
        template_mgs: Custom message template. If None, uses :data:`TEMPLATE_WARNING_CALLABLE` when a target
            callable is provided, otherwise :data:`TEMPLATE_WARNING_NO_TARGET`.
        stacklevel: Passed through to :func:`_raise_warn`; default 4 points to the user's call site.

    Template Variables Available:
        - source_name: Function name (e.g., "old_func")
        - source_path: Full path (e.g., "mymodule.old_func")
        - target_name: Target function name (only if target is callable)
        - target_path: Full target path (only if target is callable)
        - deprecated_in: Version parameter value
        - remove_in: Version parameter value

    Example:
        >>> import warnings
        >>> def new_func(): pass
        >>> def old_func(): pass
        >>> _raise_warn_callable(
        ...     stream=warnings.warn,
        ...     source=old_func,
        ...     target=new_func,
        ...     deprecated_in="1.0",
        ...     remove_in="2.0"
        ... )
        >>> # Outputs: "The `old_func` was deprecated since v1.0 in favor of
        >>> #           `__main__.new_func`. It will be removed in v2.0."

    r=   )r;   r;   )r   r6   r%   rd   r   r    r!   r"   N)rf   r:   rC   TEMPLATE_WARNING_CALLABLETEMPLATE_WARNING_NO_TARGETr   )
r   r6   r7   r   r    r%   rd   r!   r"   template_warns
             r-   _raise_warn_callabler     sf    f oo**+1[M:1#) [2!2]#	ro   	argumentsc                     dj                  |j                         D cg c]  \  }}t        |t        |      dz   c}}      }	t	        | ||xs t
        ||||	       yc c}}w )a  Issue deprecation warning for deprecated function arguments.

    This specialized warning issuer handles deprecation of specific function parameters that are being renamed or
    removed.  It generates a mapping string showing the old-to-new argument names.

    Args:
        stream: Callable that outputs the warning (e.g., warnings.warn, logging.warning).
        source: The function/method whose arguments are deprecated.
        arguments: Mapping from deprecated argument names to new names (e.g., ``{'old_arg': 'new_arg',
            'removed_arg': None}``).
        deprecated_in: Version when arguments were marked deprecated (e.g., "1.0.0").
        remove_in: Version when arguments will be removed (e.g., "2.0.0").
        template_mgs: Custom message template. If None, uses default template.
        stacklevel: Passed through to :func:`_raise_warn`; default 4 points to the user's call site.

    Template Variables Available:
        - source_name: Function name (e.g., "my_func")
        - source_path: Full path (e.g., "mymodule.my_func")
        - argument_map: Formatted string showing mappings (e.g., "`old` -> `new`")
        - deprecated_in: Version parameter value
        - remove_in: Version parameter value

    Example:
        >>> import warnings
        >>> def my_func(old_arg=1, new_arg=1): pass
        >>> _raise_warn_arguments(
        ...     warnings.warn,
        ...     my_func,
        ...     {'old_arg': 'new_arg'},
        ...     "1.0",
        ...     "2.0"
        ... )
        >>> # Outputs: "The `my_func` uses deprecated arguments: `old_arg` -> `new_arg`.
        >>> #           They were deprecated since v1.0 and will be removed in v2.0."

    z, )old_argnew_arg)rd   r   r    r#   N)joinr   TEMPLATE_ARGUMENT_MAPPINGstrr   TEMPLATE_WARNING_ARGUMENTS)
r   r6   r   r   r    r%   rd   abargs_maps
             r-   _raise_warn_argumentsr   U  sj    Z yydmdsdsduv\`\]_`3!PSTUPV6WWvwH22# ws   A!

wrapper_fnnormalized_targetargsdep_cfg).N	num_warnssource_has_var_positionalsource_is_stackedc           	         t        t        |       j                  xj                  dz  c_        |j                  rF|rDj
                  s8t        j                  d|j                   dt         dt        d       d_        t        |      }t        |||      }|t        j                  u xs t        |      }i }|j                   rO|t        j"                  u st        |      r2|j                   j%                         D ci c]  \  }}||v s|| }}}|s2|s0|j&                  r|t        j"                  u s|
st)        d||i d	      S |rt+        fd
|D        d      }nj,                  }t.        dz   }|r|dk  s||k  r|rFt1        ||||j2                  |j4                  |j6                  |       xj,                  dz  c_        ne|rct9        ||||j2                  |j4                  |j6                  |       |D ].  }j:                  j=                  |d      dz   j:                  |<   0 |r|j                   r|t        j"                  u st        |      r|j                   t?        |      }jA                         D ch c]  }|s|	 c}t?              t        |      r<tC        |      D ch c]&  }|d   tD        jF                  jH                  ur|d   ( c}ntK        ||      }dtL        dtN        ffd}|j%                         D ci c]  \  }}||v s	 ||      s|| }}}ntK        ||      }|j                   r|t        j"                  u st        |      rn|j                   D cg c]  }|j                   |   r| }}|j%                         D ci c]*  \  }}||vs|j                   j=                  |      xs ||, }}}|j&                  r8|t        j"                  u st        |      r|jQ                  |j&                         d}t        |      rtS        |||      }t)        d||||	      S c c}}w c c}w c c}w c c}}w c c}w c c}}w )u
  Compute the dispatch plan shared by the sync and async wrappers inside :func:`deprecated`.

    Extracted verbatim from the body of ``wrapped_fn`` / ``async_wrapped_fn`` so that the wrappers differ only by
    ``await`` on the final source/target call.  All closure variables that the wrapper needs are passed explicitly so
    this helper has no dependency on the enclosing ``packing`` scope and can be unit-tested in isolation.

    Side effects (carried over from the original inline logic):

    - Mutates ``wrapper_fn._state`` — bumps ``called``, optionally bumps ``warned_calls`` / ``warned_args``, and sets
      ``warned_misconfigured`` on the first misconfiguration warning.
    - Emits the one-time misconfiguration ``UserWarning`` via :func:`warnings.warn` when ``dep_cfg.misconfigured`` is
      set, ``stream`` is non-``None``, and the state has not yet seen it.
    - Emits the deprecation warning through ``stream`` when the per-call quota allows it — callable-reason via
      :func:`_raise_warn_callable`, argument-rename-reason via :func:`_raise_warn_arguments`.

    Args:
        wrapper_fn: The wrapping function itself, used to read mutable ``_state`` via the
            :class:`_DeprecatedCallable` protocol.  Passing the wrapper instead of a bare state lets the wrapper
            preserve its existing ``cast(_DeprecatedCallable, ...)._state`` access pattern.
        source: The decorated callable.
        target: The raw ``target`` argument given to ``@deprecated`` — preserved for warning emission so callable
            targets that are classes are named by their user-facing name rather than ``__init__``.
        normalized_target: The normalised target (a :class:`TargetMode` member or callable) returned by
            :func:`_normalize_target`.
        args: The positional arguments the caller passed to the wrapper.
        kwargs: The keyword arguments the caller passed to the wrapper.
        dep_cfg: The frozen :class:`DeprecationConfig` for this wrapper.  ``args_mapping``, ``args_extra``,
            ``deprecated_in``, ``remove_in``, and ``template_mgs`` are all read from this object.
        stream: Warning stream (typically :func:`warnings.warn` partial), or ``None`` to suppress.
        num_warns: Maximum number of times to emit the warning per wrapper / per renamed argument.
        source_has_var_positional: ``True`` when ``source`` declares ``*args`` — affects fast-path dispatch in the
            wrapper but is also needed inside this helper for the short-circuit branch.
        source_is_stacked: ``True`` when ``source`` is itself a ``@deprecated`` wrapper.

    Returns:
        A :class:`_CallPlan` describing the resolved dispatch outcome.

    r>   ra   zr' has an invalid deprecation configuration; verify your `@deprecated(target=...)` arguments. Will be TypeError in r=   rb   rc   TN)short_circuitoriginal_kwargsresolved_kwargsreason_argumenttarget_funcc              3   V   K   | ]   }j                   j                  |d        " yw)r   N)warned_argsrK   )r   r}   states     r-   r   z#_build_call_plan.<locals>.<genexpr>  s$     R3**..sA6Rs   &)r   )r   )r   r6   r7   r   r    r%   rd   )r   r6   r   r   r    r%   rd   r?   kr&   c                 H    | v xr j                  |       v }| vxr | S r   )rK   )r   remapped_amrename_sourcesrename_targetstarget_defaultss     r-   is_default_droppedz,_build_call_plan.<locals>.is_default_dropped  s1    .P3771:3P.?x<?ro   F)*r   r   _statecalledmisconfiguredwarned_misconfiguredrg   r   r:   rh   ri   r   r   r   rk   rf   args_mappingrj   r   
args_extrar   minwarned_callsr   r   r   r    r%   r   r   rK   setr   r   rt   r   r   r   r   rr   updater   ) r   r6   r7   r   r   rx   r   r   r   r   r   r   reason_callabler   r   r   	nb_warned_stacklevel_to_callerr}   caller_keysvfull_defaultsr   r   	args_skipvalr   r   r   r   r   r   s                               @@@@@r-   _build_call_planr     sZ   f $j188E	LLAL0J0J  !VVgUhhik		
 &*" 6lO%fdF;F':+<+<<[IZ@[O02O!2j6K6K!KxXiOj,3,@,@,F,F,HXDAqAQWK1a4XX ##(9Z=R=R(R!+"
 	
 R/R\]^	&&	 :A=9q=I	$9 !%33!++$110 !#!)%33!++$110 ' K).):):)>)>sA)F)J!!#&K  %6*:O:O%OS[\mSn&&Cf+K),;Aa;N XN )*  AARS#1vW%6%6%<%<< F# #18HM@c @d @ @ (5':':'<jtq![@PTfghTiadjFj1&&AF!2j6K6K!KxXiOj$+$8$8ZS@T@TUX@YSZ	ZNTllnu(#s`ckt`t7''++C07C#=uu0J4I4IIXVgMhg(() 15K!"*63DfM'' E Y| <
# k [usB   QQQQ=+Q"Q!7Q!Q'Q'1Q,>"Q,r;   r>   Fautor   r   skip_ifupdate_docstringdocstring_style)r   rstmkdocsmarkdownc                     	
 t        
      	 ddt        t        t        t        t
        t        f   dt        dt        f
 	fdS )u  Decorate a function/method with warning message and forward calls to target.

    This decorator marks a function or method as deprecated and can automatically forward all calls to a replacement
    implementation.  It supports argument mapping, custom warning messages, and flexible warning control.

    For **generator functions** (``def gen(): yield``) and **async generator functions** (``async def gen(): yield``),
    the deprecation warning fires at call time — when the (async) generator object is created — not at first
    iteration.  The generator body executes lazily as normal when iterated (``next()`` / ``async for``).

    Args:
        target: How to handle the deprecation. Defaults to :attr:`~deprecate.TargetMode.NOTIFY` (warn-only; source
            body executes unchanged). Pass an explicit value to forward calls or remap arguments:

            - ``Callable``: Forward all calls to this callable (function, method, or class target). The
              decorated function's body is **not executed** under normal forwarding — use ``pass`` or ``...``
              as the body. **Exception**: when ``skip_if`` evaluates ``True`` at call time, the source body
              executes as a fallback, so keep a working implementation if you combine ``target=Callable``
              with ``skip_if``.
            - :attr:`~deprecate.TargetMode.ARGS_REMAP` (or legacy ``True``): Self-deprecation — deprecate argument
              names only, remapping them within the same function body
            - :attr:`~deprecate.TargetMode.NOTIFY` (default): Warning-only mode — no forwarding, source body executes
              normally

            Omitting ``target`` is the preferred way to express warn-only deprecation.  Passing ``target=None``
            is a legacy synonym that also resolves to :attr:`~deprecate.TargetMode.NOTIFY` but emits a
            :class:`FutureWarning` directing you to use the enum form.

        deprecated_in: Version when the function was deprecated (e.g., "1.0.0"). Default is empty string.
        remove_in: Version when the function will be removed (e.g., "2.0.0"). Default is empty string.
        stream: Function to output warnings (default: :func:`~deprecate.deprecation.deprecation_warning`, which is
            :func:`warnings.warn` with ``FutureWarning`` category). Set to ``None`` to disable warnings entirely.
        num_warns: Number of times to show warning per function or per deprecated argument:
            - ``1`` (default): Show warning once per function/argument
            - ``-1``: Show warning on every call
            - ``0``: Suppress deprecation warnings emitted for the decorated function/argument
            - ``N > 1``: Show warning N times total
        template_mgs: Custom warning message template with format specifiers:
            - ``source_name``: Function name (e.g., "my_func")
            - ``source_path``: Full path (e.g., "module.my_func")
            - ``target_name``: Target function name (only for callable targets)
            - ``target_path``: Full target path (only for callable targets)
            - ``deprecated_in``: Value of deprecated_in parameter
            - ``remove_in``: Value of remove_in parameter
            - ``argument_map``: String showing argument mapping (for args deprecation only)
            Example: ``"v%(deprecated_in)s: `%(source_name)s` was deprecated."``
        args_mapping: Map or skip arguments when forwarding:
            - ``{'old_arg': 'new_arg'}``: Rename argument
            - ``{'old_arg': None}``: Skip argument (don't forward it)
            - ``{}``: Empty mapping (no remapping)
            Works with both ``target=Callable`` and ``target=True``.
        args_extra: Additional arguments merged into kwargs before the call. Used when target is a Callable or
            :attr:`~deprecate._types.TargetMode.ARGS_REMAP` (with ``args_mapping``). Ignored when target is
            :attr:`~deprecate._types.TargetMode.NOTIFY`.
            Example: ``{'new_required_arg': 42}``
        skip_if: Conditionally skip deprecation warning and forwarding:
            - ``bool``: Static condition (True = skip deprecation)
            - ``Callable``: Function returning bool (checked at runtime, must return bool)
            If condition is True, original function executes without warning.
        update_docstring: If True, automatically inject a deprecation notice into the function's docstring (inserted
            before Google/NumPy-style sections when present, otherwise appended at the end).
        docstring_style: Output style for injected deprecation notice when ``update_docstring=True``. Supported values:
            - ``"auto"`` (default): Automatically choose a style based on the current environment (e.g., loaded
              modules, CLI/tooling context). This may resolve to either ``"rst"`` or ``"mkdocs"``/``"markdown"``
              at decoration time.
            - ``"rst"``: Explicitly force Sphinx-style ``.. deprecated::`` directive.
            - ``"mkdocs"`` or ``"markdown"``: Explicitly force a Markdown admonition of the form
              ``!!! warning "Deprecated in X"``.
            Validated eagerly at decoration time regardless of ``update_docstring``.

    Returns:
        Decorator function that wraps the source function/method.

    Warns:
        UserWarning: If applied directly to a class. The decorator delegates to
            :func:`~deprecate.proxy.deprecated_class` and emits this warning. Use ``@deprecated_class()`` directly
            to suppress it. Suppressed when ``stream=None``.
        UserWarning: If ``deprecated_in`` is absent, ``stream`` is not ``None``, no ``template_mgs`` is set,
            and the decorated source is not a class. Fired at decoration time (not call time) to catch missing
            version metadata early. Suppressed by passing ``stream=None`` or ``template_mgs``.

    Raises:
        TypeError: If the source is a class method and target is a method on a *different* class (cross-class
            method forwarding detected at decoration time via ``__qualname__`` comparison). Skipped silently
            when the target's qualname prefix names a class absent from the target's module globals.
        TypeError: If skip_if is a callable that doesn't return a bool.
        TypeError: If arguments in args_mapping don't exist in target function and target doesn't accept **kwargs.

    Example:
        >>> # Basic forwarding
        >>> def new_func(x: int) -> int:
        ...     return x * 2
        >>> @deprecated(target=new_func, deprecated_in="1.0", remove_in="2.0")
        ... def old_func(x: int) -> int:
        ...     pass

        >>> # Argument mapping
        >>> @deprecated(
        ...     target=new_func,
        ...     args_mapping={'old_name': 'new_name', 'unused': None}
        ... )
        ... def old_func(old_name: int, unused: str) -> int:
        ...     pass

        >>> # Self-deprecation
        >>> from deprecate import TargetMode
        >>> @deprecated(target=TargetMode.ARGS_REMAP, args_mapping={'old_arg': 'new_arg'})
        ... def my_func(old_arg: int = 0, new_arg: int = 0) -> int:
        ...     return new_arg * 2

        >>> # Warn-only (default — no target needed)
        >>> @deprecated(deprecated_in="1.0", remove_in="2.0")
        ... def legacy_func(x: int) -> int:
        ...     return x

    r6   _stacklevelr&   c                 
    t         t        t        f      r<   j                  |dz         }t         t              rt        |      S t        |      S t         t              r j
                  # j                   j
                  j                  k7  r j                  nd }t	         j
                     j
                  |dz         nd  j                   j                  |      S t         t              rt           j                  |dz               S t        %       sC#A%s?t        j                         s*t        j                  d j                    dt"        |       t        j                         rtdd l}|j'                  d      }|j(                  }d j                    d}$*t        j                  $      st        $t*              s|d	z  }#t        j                  |t"        |       $d
u }t        $t*              r$}	n`t-        $      rt        j                  $      r$}	n=$t        $t.              rt+        j0                  $|dz         }	nt*        j2                  }	|	t*        j2                  u xr t/        xs       }
|xs |
}}}|	t*        j2                  u r+t+        j4                  |	 j                   |dz          d }d }  ||	!#||&|
             S t-        $      r!t        j                  $      st7         $       t9         $      t;               rdt=                nd
d
}t        t*              r7t        $t*              r't+        j4                   j                   |dz         }t?        d tA               jB                  jE                         D              $t        $t.              rt+        j0                  $d       }nt        $t*              r$}n$}$d
u xs |}tG        ! j                   ||%	      }|t        jH                         rdtK               dtL        dtL        dtL        f" #$f
d       tO        tP              }||_)        tU               |_+        &rtY               S tK               dtL        dtL        dtL        f" #$f
d       tO        tP              }||_)        tU               |_+        &rtY               S )Nr>   z`@deprecated` on `z` has no `deprecated_in` set. Deprecation notices and generated documentation will omit the `deprecated_in` version. Pass `deprecated_in` for a meaningful deprecation notice.rc   r   zdeprecate.proxyz&Direct use of `@deprecated` on class `zy` is deprecated since `v0.6.0`. Use `@deprecated_class(...)` instead. This will become a `TypeError` in a future release.zs Note: non-class `target` values are ignored when deprecating classes; use `@deprecated_class(target=...)` instead.F)r   r   rd   )
r7   r   r    r   r   r   r   r   r   _misconfigured_overrideTc              3   j   K   | ]+  }|j                   t        j                  j                  k(   - y wr   r   r   s     r-   r   z.deprecated.<locals>.packing.<locals>.<genexpr><  s*      (
?DEJJ'++:::(
r   )	r   r    rm   r7   r   r   r   r   r%   r   rx   r&   c                    
K   t        
      r 
       n
t        
      }t        |t              st        dt	        |             |r | i | d {   S t        | |	      }|j                  r6r | i |j                   d {   S  di |j                   d {   S |j                  Pr4|j                  s|j                  n|j                  } | i | d {   S  di |j                   d {   S t        j                  |j                        r$ |j                  di |j                   d {   S  |j                  di |j                  S 7 7 7 7 7 l7 +w)N4User function 'skip_if' shall return bool, but got: r   r6   r7   r   r   rx   r   r   r   r   r   r   )rf   rr   rq   r)   typer   r   r   r   r   r   rt   iscoroutinefunction)r   rx   
shall_skipplancall_kwargs_dep_cfg_source_is_stacked_targetasync_wrapped_fnr   r   r6   r   r   r7   s        r-   r   z5deprecated.<locals>.packing.<locals>.async_wrapped_fnb  s    *27*;WYg
!*d3#&Z[_`j[kZl$mnn!'!8!888
 (/!!&-!$!'.G&8 %%0%+T%JT5I5I%JJJ!'!?$*>*>!???##+0BFBVBVd&:&:\`\p\p%+T%A[%AAA!'!?$*>*>!??? ..t/?/?@!1!1!1!ID4H4H!III't''?$*>*>??C 9*  K?
  B? Jsn   AE:E-=E:E0E:-E2.AE:/E40E:	E6
AE:E8!E:0E:2E:4E:6E:8E:c                    
 t        	      r 	       n
t        	      }t        |t              st        dt	        |             |r 
| i |S t        
| |      }|j                  r&r 
| i |j                  S  
di |j                  S |j                  @r,|j                  s|j                  n|j                  } 
| i |S  
di |j                  S t        j                  |j                        r0t        d|j                  j                   d
j                   d       |j                  di |j                  S )Nr   r   zAsync target `z2` cannot be invoked from a sync wrapper. Declare `z=` as `async def`, or replace the target with a sync callable.r   )rf   rr   rq   r)   r   r   r   r   r   r   r   rt   r   r:   )r   rx   r   r   r   r   r   r   r   r   r6   r   r   r7   
wrapped_fns        r-   r  z/deprecated.<locals>.packing.<locals>.wrapped_fn  so   &.w&7T']Jj$/"VW[\fWgVh ijjt.v.. $%") #*C"4D !!,!4@4+?+?@@5 4 455',>B>R>R$"6"6X\XlXlK!47;775 4 455**4+;+;<$T%5%5%>%>$? @!!' 11np  $4##;d&:&:;;ro   )-rq   classmethodstaticmethod__func__propertyfget__doc__fsetfdelr   r   r.   rt   ru   rg   r   r:   ri   	importlibimport_moduledeprecated_classr   rf   rr   rs   rk   	_validater^   rw   r   rn   r   r   r   r   r   r   r   r   r   r   re   r   r   r   )'r6   r   wrapped_innerexplicit_docr
  proxy_moduler  messageclass_misconfiguredforward_targetnotify_misconfigforce_misconfiguredforward_args_mappingforward_args_extra_function_misconfiguredstored_targetr   dep_metaasync_wrapped_fn_typedwrapped_fn_typedr   r   r   r   r   r  r   r   r   r   normalized_docstring_styler   packingr    r   r   r7   r%   r   s'   `                   @@@@@@r-   r  zdeprecated.<locals>.packing  s    f{L9:#FOO[1_EM1;FK1P;}-qVbcpVqqfh' /5kk.AV^^W]WbWbWjWjEj6>>quL9?9P[1_5VZ	  fo."76;;a#HII 	|, !3LQXQ`Q`agQhMM$V__$5 6M M & ??6"$223DEL+<< 98I Jm m  !'//&*A*U[]gJhD !g{{K
 #)E/&*-&,&!goof&=!':fd#; ",!8!8KZ[O!\!+!2!2  .1B1BBgtLLf\fGg"5"I9I $0 !+!2!22$$"OO!-)*Q (,$%)"#%+##1-!1 /(;   FGOOF$;,VV<#FF3 (!%+FG<!& #(gz*z&*/M&0&:&:|PZgruvgv'# %( (
HVW]H^HiHiHpHpHr(
 %
! >Z5!+!8!8D!QM
+"M"M%B+B$' %!'6%

  &&v.6]&@c &@S &@S &@ &@ &@P &**=?O%P"4<"1,9O")23CD## 
v(	<c (	<S (	<S (	< (	< 
(	<T   3Z@*2'"//.z:ro   )r?   )r   r   r   r  r  r  r   int)r7   r   r    r   r   r%   r   r   r   r   r   r  r  s   ```````````@@r-   
deprecatedr   >  s^    @ ";?!K Kh\8_TUKK 
K K KZ Nro   )Ar  rt   rH   rg   	functoolsr   r   r   r   typingr   r   r	   r
   r   r   r   deprecate._typesr   r   r   r   r   r   r   deprecate.docstring.injectr   r   deprecate.utilsr   r   rh   r   r  __annotations__r   r   r   r   r2   r3   FutureWarningdeprecation_warningr   r   ArgsMappingr$   r.   r+   r5   r^   rn   rr   rw   r   tupler   r   r   r   r   r   r   rk   r   r   ro   r-   <module>r+     s^    
  5 5  @ @    e M %& s &- \ 
 =  k  ++!77 d]; 3%& , $sCx. # 4 ,a4(9(9#: atGDUDU?V a
ZX Zx ZD ZzV
,? V
uU_aiUiOj V
os V
r<<$h
23< :x <~+++ cN+ 	+\18 1eCHo 1RVWZ\_W_R` 1eijmorjres 1hEx EDcN EtTWY\T\~ EB 4	,,, , 	,
 , 
,^d dc d #'3CCC $h
23C 	C
 C 3-C C 
CX #'3666 6 	6
 6 3-6 6 
6rmc"mS#Xm $hsCx0*<=m Xc3h/;<	m
 S/m cNm m Xi()m m  $m m mb 7A6G6G!4"&*.+/%*"DJO$h
23OO O X	O
 O 3-O ;'O c3h(O 4>"O O @AO xS!"HS#X$667Oro   