o
    ö˜I^:>  ã                   @   sb  d dl Z d dlmZ d dlmZ zd dlmZ W n ey'   d dlm	Z Y nw d dl
Z
d dlZddlmZmZ ddlmZ e  d	g d
¢¡Zdd„ Zdd„ Zdd„ Ze
jdd�G dd„ deƒƒZdd„ Zdd„ Zdd„ Zdd„ Zdd„ Ze
jddd �G d!d"„ d"eƒƒZe
jdd�G d#d$„ d$eƒƒZe
jddd �G d%d&„ d&eƒƒZ eƒ Z!d'd(„ Z"G d)d*„ d*eƒZ#dS )+é    N©Úwraps)Úcount)Úgetfullargspec)Ú
getargspecé   )ÚTransitionerÚ	Automaton)ÚpreserveNameÚArgSpec©ÚargsÚvarargsÚvarkwÚdefaultsÚ
kwonlyargsÚkwonlydefaultsÚannotationsc              
   C   s†   t | ƒ}tt|jƒ|jtjr|jn|j|j	r|j	ndtjr"t|j
ƒndtjr2|jr0t|j ¡ ƒndndtjr?t|j ¡ ƒd�S dd�S )zÑ
    Normalize inspect.ArgSpec across python versions
    and convert mutable attributes to immutable types.

    :param Callable func: A function.
    :return: The function's ArgSpec.
    :rtype: ArgSpec
    © r   )ÚgetArgsSpecr   Útupler   r   ÚsixÚPY3r   Úkeywordsr   r   r   Úitemsr   )ÚfuncÚspecr   r   ú5/usr/lib/python3/dist-packages/automat/_methodical.pyÚ_getArgSpec   s"   	ýÿö
ör   c                 C   s2   t | j| j | jrdnd | jrdnd | j ƒS )a0  
    Get the name of all arguments defined in a function signature.

    The name of * and ** arguments is normalized to "*args" and "**kwargs".

    :param ArgSpec spec: A function to interrogate for a signature.
    :return: The set of all argument names in `func`s signature.
    :rtype: Set[str]
    )z*argsr   )z**kwargs)Úsetr   r   r   r   r   )r   r   r   r   Ú_getArgNames2   s   
ÿþýüÿr    c                    s   t ˆ ƒ‡ fdd„ƒ}|S )a  
    Decorate a function so all its arguments must be passed by keyword.

    A useful utility for decorators that take arguments so that they don't
    accidentally get passed the thing they're decorating as their first
    argument.

    Only works for methods right now.
    c                    s   ˆ | fi |¤ŽS ©Nr   )ÚselfÚkw©Úfr   r   ÚgO   s   z_keywords_only.<locals>.gr   )r%   r&   r   r$   r   Ú_keywords_onlyE   s   
r'   T)Úfrozenc                   @   sD   e Zd ZdZejdd�Ze ¡ Zejdd�Ze	fdd„Z
dd„ ZdS )	ÚMethodicalStatez-
    A state for a L{MethodicalMachine}.
    F©Úreprc                 C   sj   t |jƒ}|D ]!}t |jƒ}| |¡s(tdj|jj|jjt|jƒt|jƒd�ƒ‚q| j 	| ||||¡ dS )ac  
        Declare a state transition within the :class:`automat.MethodicalMachine`
        associated with this :class:`automat.MethodicalState`:
        upon the receipt of the `input`, enter the `state`,
        emitting each output in `outputs`.

        :param MethodicalInput input: The input triggering a state transition.
        :param MethodicalState enter: The resulting state.
        :param Iterable[MethodicalOutput] outputs: The outputs to be triggered
            as a result of the declared state transition.
        :param Callable collector: The function to be used when collecting
            output return values.

        :raises TypeError: if any of the `outputs` signatures do not match
            the `inputs` signature.
        :raises ValueError: if the state transition from `self` via `input`
            has already been defined.
        zdmethod {input} signature {inputSignature} does not match output {output} signature {outputSignature})ÚinputÚoutputÚinputSignatureÚoutputSignatureN)
r    ÚargSpecÚissubsetÚ	TypeErrorÚformatÚmethodÚ__name__r   ÚmachineÚ_oneTransition)r"   r,   ÚenterÚoutputsÚ	collectorÚ	inputArgsr-   Ú
outputArgsr   r   r   Úupon^   s   


úÿÿ
zMethodicalState.uponc                 C   ó   | j jS r!   ©r4   r5   ©r"   r   r   r   Ú_name€   ó   zMethodicalState._nameN)r5   Ú
__module__Ú__qualname__Ú__doc__ÚattrÚibr6   r4   Ú
serializedÚlistr=   rA   r   r   r   r   r)   U   s    "r)   c                 C   s0   t | |dƒ}|du rt||jƒ}t| ||ƒ |S )z
    Get a L{Transitioner}
    N)Úgetattrr   ÚinitialStateÚsetattr)ÚoselfÚsymbolÚ	automatonÚtransitionerr   r   r   Ú_transitionerFromInstance„   s   þrQ   c                   C   s   d S r!   r   r   r   r   r   Ú_empty’   s   rR   c                   C   s   dS )Ú	docstringNr   r   r   r   r   Ú
_docstring•   s    rT   c                 C   s$   |j jtj jtj jfvrtdƒ‚d S )Nzfunction body must be empty)Ú__code__Úco_coderR   rT   Ú
ValueError)ÚinstÚ	attributer%   r   r   r   ÚassertNoCode˜   s
   ÿþrZ   c                    sÚ   t t|jdd… | ƒƒ}ˆjr| }n	‡fdd„|D ƒ}t |ƒ‰|D ]
\}}ˆ||f7 ‰q!t|jddd… |jddd… ƒ}‡fdd„|D ƒ}	|	 |¡ ˆjrT|	}
||
fS ˆjdd… ˆj ‰ ‡ fdd„|	 ¡ D ƒ}
||
fS )	a†  
    Filter out arguments that were passed to input that output won't accept.

    :param tuple args: The *args that input received.
    :param dict kwargs: The **kwargs that input received.
    :param ArgSpec inputSpec: The input's arg spec.
    :param ArgSpec outputSpec: The output's arg spec.
    :return: The args and kwargs that output will accept.
    :rtype: Tuple[tuple, dict]
    r   Nc                    s   g | ]\}}|ˆ j v r|‘qS r   )r   ©Ú.0ÚnÚv)Ú
outputSpecr   r   Ú
<listcomp>»   ó    z_filterArgs.<locals>.<listcomp>éÿÿÿÿc                    s   i | ]\}}|ˆ vr||“qS r   r   r[   )Úpassed_arg_namesr   r   Ú
<dictcomp>Â   ra   z_filterArgs.<locals>.<dictcomp>c                    s   i | ]\}}|ˆ v r||“qS r   r   r[   )Úall_accepted_namesr   r   rd   Ë   s    ÿ)	r   Úzipr   r   r   Úupdater   r   r   )r   ÚkwargsÚ	inputSpecr_   Ú
named_argsÚreturn_argsÚnameÚvaluer   Úfull_kwargsÚreturn_kwargsr   )re   r_   rc   r   Ú_filterArgs©   s    "
ürp   F)ÚeqÚhashc                   @   sv   e Zd ZdZejdd�Zejed�Zejdd�Z	eje 
e¡dd�Zejddd�Zejdd„ ƒZdd
d„Zdd„ Zd	S )ÚMethodicalInputz.
    An input for a L{MethodicalMachine}.
    Fr*   )Ú	validator)Údefaultr+   ©Úinitr+   c                 C   ó
   t | jƒS r!   ©r   r4   r@   r   r   r   Ú_buildArgSpecÜ   ó   
zMethodicalInput._buildArgSpecNc                    s8   t ˆ ˆjˆjƒ‰tˆjƒtˆjƒ‡ ‡‡fdd„ƒƒ}|S )zÁ
        Return a function that takes no arguments and returns values returned
        by output functions produced by the given L{MethodicalInput} in
        C{oself}'s current state.
        c                     s’   ˆj ˆ g| ¢R i |¤Ž ˆj}ˆ ˆ¡\}}ˆj| }g }|D ]%}|r)|| ¡ ƒ t| |ˆj|jƒ\}}	|ˆ g|¢R i |	¤Ž}
| |
¡ q||ƒS r!   )r4   Ú_stateÚ
transitionÚ
collectorsrA   rp   r0   Úappend)r   rh   ÚpreviousStater9   Ú	outTracerr:   Úvaluesr-   ÚaÚkrm   ©rM   r"   rP   r   r   ÚdoInputè   s   
z(MethodicalInput.__get__.<locals>.doInput)rQ   rN   rO   r
   r4   r   )r"   rM   Útyper†   r   r…   r   Ú__get__à   s   ÿzMethodicalInput.__get__c                 C   r>   r!   r?   r@   r   r   r   rA   ù   rB   zMethodicalInput._namer!   )r5   rC   rD   rE   rF   rG   rO   rZ   r4   rN   ÚFactoryÚdictr~   r0   ru   rz   rˆ   rA   r   r   r   r   rs   Ñ   s    

rs   c                   @   sZ   e Zd ZdZejdd�Ze ¡ Zejddd�Zej	dd„ ƒZ
ddd	„Zd
d„ Zdd„ ZdS )ÚMethodicalOutputz/
    An output for a L{MethodicalMachine}.
    Fr*   rv   c                 C   rx   r!   ry   r@   r   r   r   rz     r{   zMethodicalOutput._buildArgSpecNc                 C   s   t dj|j| jjd�ƒ‚)zX
        Outputs are private, so raise an exception when we attempt to get one.
        zf{cls}.{method} is a state-machine output method; to produce this output, call an input method instead.)Úclsr4   )ÚAttributeErrorr3   r5   r4   ©r"   rM   r‡   r   r   r   rˆ   
  s   ýÿzMethodicalOutput.__get__c                 O   s   | j |g|¢R i |¤ŽS )z-
        Call the underlying method.
        )r4   )r"   rM   r   rh   r   r   r   Ú__call__  s   zMethodicalOutput.__call__c                 C   r>   r!   r?   r@   r   r   r   rA     rB   zMethodicalOutput._namer!   )r5   rC   rD   rE   rF   rG   r6   r4   r0   ru   rz   rˆ   r�   rA   r   r   r   r   r‹   ý   s    

r‹   c                   @   s.   e Zd Zejdd�Zejdd�Zddd„ZdS )ÚMethodicalTracerFr*   Nc                    s    t || j| jƒ‰ ‡ fdd„}|S )Nc                    s   ˆ   | ¡ d S r!   )ÚsetTrace)Útracer©rP   r   r   r‘   )  s   z*MethodicalTracer.__get__.<locals>.setTrace)rQ   rN   rO   )r"   rM   r‡   r‘   r   r“   r   rˆ   &  s
   ÿzMethodicalTracer.__get__r!   )r5   rC   rD   rF   rG   rO   rN   rˆ   r   r   r   r   r�      s    r�   c                   C   s   dt ttƒƒ S )z,
    Create a unique Python identifier.
    Ú_symbol_)ÚstrÚnextÚcounterr   r   r   r   Úgensym0  s   r˜   c                   @   s€   e Zd ZdZdd„ Zddd„Ze		ddd	„ƒZed
d„ ƒZedd„ ƒZ	dd„ Z
edd„ ƒZedd„ ƒZedd„ ƒZdd„ ZdS )ÚMethodicalMachinezj
    A :class:`MethodicalMachine` is an interface to an `Automaton`
    that uses methods on a class.
    c                 C   s   t ƒ | _i | _tƒ | _d S r!   )r	   Ú
_automatonÚ	_reducersr˜   Ú_symbolr@   r   r   r   Ú__init__>  s   zMethodicalMachine.__init__Nc                 C   s   |durt dƒ‚| S )z°
        L{MethodicalMachine} is an implementation detail for setting up
        class-level state; applications should never need to access it on an
        instance.
        Nz.MethodicalMachine is an implementation detail.)r�   rŽ   r   r   r   rˆ   D  s
   ÿzMethodicalMachine.__get__Fc                    s   ‡ ‡‡fdd„}|S )a  
        Declare a state, possibly an initial state or a terminal state.

        This is a decorator for methods, but it will modify the method so as
        not to be callable any more.

        :param bool initial: is this state the initial state?
            Only one state on this :class:`automat.MethodicalMachine`
            may be an initial state; more than one is an error.

        :param bool terminal: Is this state a terminal state?
            i.e. a state that the machine can end up in?
            (This is purely informational at this point.)

        :param Hashable serialized: a serializable value
            to be used to represent this state to external systems.
            This value should be hashable;
            :py:func:`unicode` is a good type to use.
        c                    s   t ˆ| ˆd�}ˆ r|ˆj_|S )N)r6   r4   rH   )r)   rš   rK   )ÚstateMethodÚstate©Úinitialr"   rH   r   r   Ú	decoratorf  s   þz*MethodicalMachine.state.<locals>.decoratorr   )r"   r¡   ÚterminalrH   r¢   r   r    r   rŸ   P  s   zMethodicalMachine.statec                    ó   ‡ fdd„}|S )zM
        Declare an input.

        This is a decorator for methods.
        c                    s   t ˆ j| ˆ jd�S )N)rO   r4   rN   )rs   rš   rœ   )ÚinputMethodr@   r   r   r¢   w  s   þz*MethodicalMachine.input.<locals>.decoratorr   ©r"   r¢   r   r@   r   r,   p  s   zMethodicalMachine.inputc                    r¤   )zÚ
        Declare an output.

        This is a decorator for methods.

        This method will be called when the state machine transitions to this
        state as specified in the decorated `output` method.
        c                    s   t ˆ | d�S )N)r6   r4   )r‹   )ÚoutputMethodr@   r   r   r¢   ˆ  s   z+MethodicalMachine.output.<locals>.decoratorr   r¦   r   r@   r   r-   ~  s   
zMethodicalMachine.outputc                 C   s$   | j  |||t|ƒ¡ ||j|< dS )z.
        See L{MethodicalState.upon}.
        N)rš   ÚaddTransitionr   r~   )r"   Ú
startStateÚ
inputTokenÚendStateÚoutputTokensr:   r   r   r   r7   �  s   ÿz MethodicalMachine._oneTransitionc                    r¤   )ú


        c                    ó   t ˆ ƒ‡ ‡fdd„ƒ}|S )Nc                    s   t | ˆjˆjƒ}ˆ | |jjƒS r!   )rQ   rœ   rš   r|   rH   )rM   rP   ©Ú	decorateer"   r   r   Ú	serialize«  s   ÿzBMethodicalMachine.serializer.<locals>.decorator.<locals>.serializer   )r°   r±   r@   ©r°   r   r¢   ª  s   z/MethodicalMachine.serializer.<locals>.decoratorr   r¦   r   r@   r   Ú
serializer¥  s   zMethodicalMachine.serializerc                    r¤   )r­   c                    r®   )Nc                    sR   ˆ | g|¢R i |¤Ž}i }ˆj  ¡ D ]}|||j< qt| ˆjˆj ƒ}|| |_d S r!   )rš   ÚstatesrH   rQ   rœ   r|   )rM   r   rh   rŸ   ÚmappingÚ	eachStaterP   r¯   r   r   Úunserialize¹  s   
ÿ
zFMethodicalMachine.unserializer.<locals>.decorator.<locals>.unserializer   )r°   r·   r@   r²   r   r¢   ¸  s   	z1MethodicalMachine.unserializer.<locals>.decoratorr   r¦   r   r@   r   Úunserializer³  s   zMethodicalMachine.unserializerc                 C   s   t | j| jƒS r!   )r�   rš   rœ   r@   r   r   r   Ú	_setTraceÆ  s   zMethodicalMachine._setTracec                 C   s*   ddl m} || jdd„ dd„ dd„ d�S )a  
        Generate a L{graphviz.Digraph} that represents this machine's
        states and transitions.

        @return: L{graphviz.Digraph} object; for more information, please
            see the documentation for
            U{graphviz<https://graphviz.readthedocs.io/>}

        r   )ÚmakeDigraphc                 S   r>   r!   r?   )rŸ   r   r   r   Ú<lambda>×  ó    z-MethodicalMachine.asDigraph.<locals>.<lambda>c                 S   r>   r!   r?   )r,   r   r   r   r»   Ø  r¼   c                 S   r>   r!   r?   )r-   r   r   r   r»   Ù  r¼   )ÚstateAsStringÚinputAsStringÚoutputAsString)Ú
_visualizerº   rš   )r"   rº   r   r   r   Ú	asDigraphÊ  s   
üzMethodicalMachine.asDigraphr!   )FFN)r5   rC   rD   rE   r�   rˆ   r'   rŸ   r,   r-   r7   r³   r¸   Úpropertyr¹   rÁ   r   r   r   r   r™   8  s(    
ÿ




r™   )$ÚcollectionsÚ	functoolsr   Ú	itertoolsr   Úinspectr   r   ÚImportErrorr   rF   r   Ú_corer   r	   Ú_introspectionr
   Ú
namedtupler   r   r    r'   ÚsÚobjectr)   rQ   rR   rT   rZ   rp   rs   r‹   r�   r—   r˜   r™   r   r   r   r   Ú<module>   s@   þ
.(
+"