U
    Dvf3                     @   sH   d Z ddlmZ ddlmZmZ ddlZdadd Zdd Z	d	d
 Z
dS )z=Register functions as methods of Pandas DataFrame and Series.    )wraps)register_series_accessorregister_dataframe_accessorNc           
   
   C   s   t | j||~}|dkr*| |f||}nRt|gt| }|| j|||\}}	|dd }|	}| |f||}|| |W  5 Q R  S Q R X dS )a  Handle pandas extension call.

    This function is called when the user calls
    a pandas DataFrame object's method.
    The pandas extension mechanism passes args and kwargs
    of the original method call as it is applied to obj.

    Our implementation uses the global variable `method_call_ctx_factory`.

    `method_call_ctx_factory` can be either None or an abstract class.

    When `method_call_ctx_factory` is None,
    the implementation calls the registered method
    with unmodified args and kwargs and returns underlying method result.

    When `method_call_ctx_factory` is not None,
    `method_call_ctx_factory` is expected to refer to
    the function to create the context object.
    The context object will be used to process
    inputs and outputs of `method` calls.
    It is also possible that
    the context object method `handle_start_method_call`
    will modify original args and kwargs before `method` call.

    `method_call_ctx_factory` is a function
    that should have the following signature:

     `f(method_name: str, args: list, kwargs: dict) -> MethodCallCtx`


    MethodCallCtx is an abstract class:
    class MethodCallCtx(abc.ABC):

        @abstractmethod
        def __enter__(self) -> None:
            raise NotImplemented

        @abstractmethod
        def __exit__(self, exc_type, exc_value, traceback) -> None:
            raise NotImplemented

        @abstractmethod
        def handle_start_method_call(self, method_name: str, method_signature: inspect.Signature, method_args: list, method_kwargs: dict) -> tuple(list, dict):
            raise NotImplemented

        @abstractmethod
        def handle_end_method_call(self, ret: object) -> None:
            raise NotImplemented


    Args:
        method (callable): method object as registered by decorator
            register_dataframe_method (or register_series_method)
        method_signature: signature of method as returned by inspect.signature
        obj: Dataframe or Series
        args: The arguments to pass to the registered method.
        kwargs: The keyword arguments to pass to the registered method.

    Returns:
        object`: The result of calling of the method.
    N   )method_call_ctx_factory__name__tuplelistZhandle_start_method_callZhandle_end_method_call)
methodmethod_signatureobjargskwargsZmethod_call_ctxretZall_argsnew_argsZ
new_kwargs r   :/tmp/pip-unpacked-wheel-c6c42brj/pandas_flavor/register.pyhandle_pandas_extension_call   s.    @     
r   c                    s   t   fdd}| S )ap  Register a function as a method attached to the Pandas DataFrame.

    Example:

        @register_dataframe_method
        def print_column(df, col):
            '''Print the dataframe column given'''
            print(df[col])

    Args:
        method (callable): callable to register as a dataframe method.

    Returns:
        callable: The original method.
    c                     s(   G  fdddt }t j|  S )av  Inner function to register the method.

        This function is called when the user
        decorates a function with register_dataframe_method.

        Args:
            *args: The arguments to pass to the registered method.
            **kwargs: The keyword arguments to pass to the registered method.

        Returns:
            method: The original method.
        c                       s.   e Zd ZdZdd Ze  fddZdS )z@register_dataframe_method.<locals>.inner.<locals>.AccessorMethodz DataFrame Accessor method class.c                 S   s
   || _ dS )zInitialize the accessor method class.

                Args:
                    pandas_obj (pandas.DataFrame): The pandas DataFrame object.
                N_objselfZ
pandas_objr   r   r   __init__   s    zIregister_dataframe_method.<locals>.inner.<locals>.AccessorMethod.__init__c                    s,   t dkr | jf||S t | j||S aU  Call the accessor method.

                Args:
                    *args: The arguments to pass to the registered method.
                    **kwargs: The keyword arguments to pass
                        to the registered method.

                Returns:
                    object: The result of calling of the method.
                Nr   r   r   r   r   r   r
   r   r   r   __call__   s        zIregister_dataframe_method.<locals>.inner.<locals>.AccessorMethod.__call__Nr   
__module____qualname____doc__r   r   r   r   r   r   r   AccessorMethod   s   r"   )objectr   r   r   r   r"   r   r   r   innerv   s    z(register_dataframe_method.<locals>.innerinspect	signaturer
   r%   r   r   r   register_dataframe_methodc   s    
1r*   c                    s   t   fdd}| S )zRegister a function as a method attached to the Pandas Series.

    Args:
        method (callable): callable to register as a series method.

    Returns:
        callable: The original method.
    c                     s(   G  fdddt }t j|  S )a
  Inner function to register the method.

        Args:
            *args: The arguments to pass to the registered method.
            **kwargs: The keyword arguments to pass to the registered method.

        Returns:
            method: The original method.
        c                       s4   e Zd ZdZ jZdd Ze  fddZdS )z=register_series_method.<locals>.inner.<locals>.AccessorMethodzSeries Accessor method class.c                 S   s
   || _ dS )zInitialize the accessor method class.

                Args:
                    pandas_obj (pandas.Series): The pandas Series object.
                Nr   r   r   r   r   r      s    zFregister_series_method.<locals>.inner.<locals>.AccessorMethod.__init__c                    s,   t dkr | jf||S t | j||S r   r   r   r   r   r   r      s        zFregister_series_method.<locals>.inner.<locals>.AccessorMethod.__call__Nr   r   r   r   r   r"      s
   r"   )r#   r   r   r$   r   r   r   r%      s    !z%register_series_method.<locals>.innerr&   r)   r   r   r   register_series_method   s    

0r+   )r!   	functoolsr   Zpandas.api.extensionsr   r   r'   r   r   r*   r+   r   r   r   r   <module>   s   WG