U
    b6{i[C  ã                
   @  sè  U d dl mZ d dlZd dlZd dlmZmZ d dlmZ d dl	m
Z d dlmZ d dlmZmZmZmZmZ ejdk r†d d	lmZ nd d	lmZ d
dlmZmZmZmZ d
dlmZ e ddddddddg¡Zdd„ Z dd„ Z!dd„ Z"edd�G dd„ de#ƒƒZ$dd d!d"d#œd$d%„Z%d&d'„ Z&d(d)„ Z'd*d+d,œd-d.„Z(d/d0„ Z)ed1ƒZ*ed2ƒZ+ed3d4�G d5d6„ d6e#ƒƒZ,edd�G d7d8„ d8e#ƒƒZ-ee.gdf Z/d9Z0d:e1d;< d<d=d>œd?d@„Z2ed3d4�G dAdB„ dBe#ƒƒZ3eƒ Z4dCdD„ Z5G dEdF„ dFe#ƒZ6dS )Gé    )ÚannotationsN)Ú	dataclassÚfield©Úwraps)Úgetfullargspec)Úcount)ÚAnyÚCallableÚHashableÚIterableÚTypeVar)é   é
   )Ú	TypeAliasé   )Ú	AutomatonÚOutputTracerÚTracerÚTransitioner)ÚpreserveNameÚArgSpecÚargsÚvarargsÚvarkwÚdefaultsÚ
kwonlyargsÚkwonlydefaultsr   c              
   C  sX   t | ƒ}tt|jƒ|j|j|jr&|jndt|jƒ|jrDt|j 	¡ ƒndt|j
 	¡ ƒ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   r   r   r   r   r   r   )ÚgetArgsSpecr   Útupler   r   r   r   r   r   Úitemsr   )ÚfuncÚspecr   r   ú7/tmp/pip-unpacked-wheel-3c4m1_88/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$   Ú_getArgNames9   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|ŽS ©Nr   )ÚselfÚkw©Úfr   r$   ÚgW   s    z_keywords_only.<locals>.gr   )r,   r-   r   r+   r$   Ú_keywords_onlyL   s    r.   T)Úfrozenc                   @  sp   e Zd ZU dZedd�Zded< eƒ Zded< edd�Zded	< d
d
e	fddddddœdd„Z
ddœdd„Zd
S )ÚMethodicalStatez-
    A state for a L{MethodicalMachine}.
    F©ÚreprÚMethodicalMachineÚmachineúCallable[..., Any]ÚmethodÚboolÚ
serializedNÚMethodicalInputzMethodicalState | Nonez!Iterable[MethodicalOutput] | NonezCallable[[Iterable[T]], object]ÚNone)ÚinputÚenterÚoutputsÚ	collectorÚreturnc                 C  s‚   |dkr| }|dkrg }t |jƒ}|D ]B}t |jƒ}| |¡s&tdj|jj|jjt|jƒt|jƒd�ƒ‚q&| j 	| ||||¡ dS )aÿ  
        Declare a state transition within the L{MethodicalMachine} associated
        with this L{MethodicalState}: upon the receipt of the `input`, enter
        the `state`, emitting each output in `outputs`.

        @param input: The input triggering a state transition.

        @param enter: The resulting state.

        @param outputs: The outputs to be triggered as a result of the declared
            state transition.

        @param 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.
        Nzdmethod {input} signature {inputSignature} does not match output {output} signature {outputSignature})r;   ÚoutputZinputSignatureZoutputSignature)
r'   ÚargSpecÚissubsetÚ	TypeErrorÚformatr6   Ú__name__r   r4   Ú_oneTransition)r)   r;   r<   r=   r>   Z	inputArgsr@   Z
outputArgsr   r   r$   Úuponh   s"    


úÿ
zMethodicalState.uponÚstr©r?   c                 C  s   | j jS r(   ©r6   rE   ©r)   r   r   r$   Ú_name˜   s    zMethodicalState._name)rE   Ú
__module__Ú__qualname__Ú__doc__r   r4   Ú__annotations__r6   r8   ÚlistrG   rL   r   r   r   r$   r0   ^   s   
û0r0   ÚobjectrH   ú=Automaton[MethodicalState, MethodicalInput, MethodicalOutput]z@Transitioner[MethodicalState, MethodicalInput, MethodicalOutput])ÚoselfÚsymbolÚ	automatonr?   c                 C  s0   t | |dƒ}|dkr,t||jƒ}t| ||ƒ |S )z
    Get a L{Transitioner}
    N)Úgetattrr   ÚinitialStateÚsetattr)rT   rU   rV   Útransitionerr   r   r$   Ú_transitionerFromInstanceœ   s    þr[   c                   C  s   d S r(   r   r   r   r   r$   Ú_empty®   s    r\   c                   C  s   dS )Z	docstringNr   r   r   r   r$   Ú
_docstring²   s    r]   r5   r:   )r,   r?   c                 C  s$   | j jtj jtj jfkr tdƒ‚d S )Nzfunction body must be empty)Ú__code__Úco_coder\   r]   Ú
ValueErrorr+   r   r   r$   ÚassertNoCode¶   s    ra   c                   sÔ   t t|jdd… | ƒƒ}ˆjr$| }n‡fdd„|D ƒ}t |ƒ‰|D ]\}}ˆ||f7 ‰qBt|jddd… |jddd… ƒ}‡fdd„|D ƒ}	|	 |¡ ˆjr¢|	}
n*ˆ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 kr|‘qS r   )r   ©Ú.0ÚnÚv)Ú
outputSpecr   r$   Ú
<listcomp>Ø   s     
 z_filterArgs.<locals>.<listcomp>éÿÿÿÿc                   s   i | ]\}}|ˆ kr||“qS r   r   rb   )Úpassed_arg_namesr   r$   Ú
<dictcomp>ß   s       z_filterArgs.<locals>.<dictcomp>c                   s   i | ]\}}|ˆ kr||“qS r   r   rb   )Úall_accepted_namesr   r$   rj   è   s      )	r    Úzipr   r   r   Úupdater   r   r!   )r   ÚkwargsZ	inputSpecrf   Z
named_argsZreturn_argsÚnameÚvaluer   Zfull_kwargsZreturn_kwargsr   )rk   rf   ri   r$   Ú_filterArgsÆ   s"    "

ÿrq   ÚTÚRF)Úeqc                   @  sœ   e Zd ZU dZedd�Zded< eƒ Zded< edd�Zded	< ee	dd
�Z
ded< eddd�Zded< ddœdd„Zdddddœdd„Zddœdd„ZdS )r9   z.
    An input for a L{MethodicalMachine}.
    Fr1   rS   rV   r5   r6   rH   rU   )Údefault_factoryr2   z1dict[MethodicalState, Callable[[Iterable[T]], R]]Ú
collectors)Úinitr2   r   rA   r:   rI   c                 C  s   t | jƒ| _t| jƒ d S r(   )r%   r6   rA   ra   rK   r   r   r$   Ú__post_init__  s    zMethodicalInput.__post_init__NrR   ©rT   Útyper?   c                   sB   t ˆ ˆjˆjƒ‰tˆjƒtˆjƒddddœ‡ ‡‡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.
        rR   )r   rn   r?   c                    s†   ˆj ˆ f| ž|Ž ˆj}ˆ ˆ¡\}}ˆj| }g }|D ]D}|d k	rL||ƒ t| |ˆj|jƒ\}}	|ˆ f|ž|	Ž}
| |
¡ q8||ƒS r(   )r6   Ú_stateZ
transitionrv   rq   rA   Úappend)r   rn   ZpreviousStater=   Z	outTracerr>   Úvaluesr@   ÚaÚkrp   ©rT   r)   rZ   r   r$   ÚdoInput  s    
z(MethodicalInput.__get__.<locals>.doInput)r[   rU   rV   r   r6   r   )r)   rT   rz   r�   r   r€   r$   Ú__get__  s
    zMethodicalInput.__get__c                 C  s   | j jS r(   rJ   rK   r   r   r$   rL   "  s    zMethodicalInput._name)N)rE   rM   rN   rO   r   rV   rP   r6   rU   Údictrv   rA   rx   r‚   rL   r   r   r   r$   r9   ó   s   
ÿ ÿr9   c                   @  sp   e Zd ZU dZedd�Zded< ded< edddd�Zd	ed
< ddœdd„Zddd„Z	dd„ Z
ddœdd„ZdS )ÚMethodicalOutputz/
    An output for a L{MethodicalMachine}.
    Fr1   r3   r4   r5   r6   )rw   r2   Úcomparer   rA   r:   rI   c                 C  s   t | jƒ| jd< d S )NrA   )r%   r6   Ú__dict__rK   r   r   r$   rx   0  s    zMethodicalOutput.__post_init__Nc                 C  s   t dj|j| jjd�ƒ‚dS )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.)Úclsr6   N)ÚAttributeErrorrD   rE   r6   ©r)   rT   rz   r   r   r$   r‚   3  s     þÿzMethodicalOutput.__get__c                 O  s   | j |f|ž|ŽS )z-
        Call the underlying method.
        )r6   )r)   rT   r   rn   r   r   r$   Ú__call__>  s    zMethodicalOutput.__call__rH   c                 C  s   | j jS r(   rJ   rK   r   r   r$   rL   D  s    zMethodicalOutput._name)N)rE   rM   rN   rO   r   r4   rP   rA   rx   r‚   rŠ   rL   r   r   r   r$   r„   &  s   

r„   z4Callable[[str, str, str], StringOutputTracer | None]r   ÚStringTracerúStringTracer | NonezATracer[MethodicalState, MethodicalInput, MethodicalOutput] | None)Úwrappedr?   c                   s(   ˆ d krd S dddddœ‡ fdd„}|S )Nr0   r9   z%OutputTracer[MethodicalOutput] | None)Ústater;   r@   r?   c                   s0   ˆ|   ¡ |  ¡ |  ¡ ƒ‰ ˆ d k	r,‡ fdd„S d S )Nc                   s   ˆ |   ¡ ƒS r(   ©rL   )Úout©Úresultr   r$   Ú<lambda>Y  ó    z,wrapTracer.<locals>.tracer.<locals>.<lambda>r�   )rŽ   r;   r@   ©r�   r‘   r$   ÚtracerR  s    zwrapTracer.<locals>.tracerr   )r�   r–   r   r•   r$   Ú
wrapTracerL  s    
r—   c                   @  sF   e Zd ZU edd�Zded< edd�Zded< dddd	d
œdd„ZdS )ÚMethodicalTracerFr1   rS   rV   rH   rU   NrR   zCallable[[StringTracer], None]ry   c                   s(   t || j| jƒ‰ dddœ‡ fdd„}|S )NrŒ   r:   )r–   r?   c                   s   ˆ   t| ƒ¡ d S r(   )ÚsetTracer—   )r–   ©rZ   r   r$   r™   k  s    z*MethodicalTracer.__get__.<locals>.setTrace)r[   rU   rV   )r)   rT   rz   r™   r   rš   r$   r‚   f  s    zMethodicalTracer.__get__)N)rE   rM   rN   r   rV   rP   rU   r‚   r   r   r   r$   r˜   _  s   
ÿ ÿr˜   c                   C  s   dt ttƒƒ S )z,
    Create a unique Python identifier.
    Z_symbol_)rH   ÚnextÚcounterr   r   r   r$   Úgensymt  s    r�   c                   @  sŒ   e Zd ZdZdd„ Zddd„Zedddd	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œdd„ƒZdd„ ZdS )r3   ze
    A L{MethodicalMachine} is an interface to an L{Automaton} that uses methods
    on a class.
    c                 C  s   t ƒ | _i | _tƒ | _d S r(   )r   Ú
_automatonZ	_reducersr�   Ú_symbolrK   r   r   r$   Ú__init__�  s    zMethodicalMachine.__init__Nc                 C  s   |dk	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‚   †  s    zMethodicalMachine.__get__Fr7   r   )ÚinitialÚterminalr8   c                   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 initial: is this state the initial state?  Only one state on
            this L{automat.MethodicalMachine} may be an initial state; more
            than one is an error.

        @param 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 serialized: a serializable value to be used to represent this
            state to external systems.  This value should be hashable; L{str}
            is a good type to use.
        c                   s   t ˆ| ˆd�}ˆ r|ˆj_|S )N)r4   r6   r8   )r0   rž   rX   )ZstateMethodrŽ   ©r¡   r)   r8   r   r$   Ú	decorator§  s      ÿz*MethodicalMachine.state.<locals>.decoratorr   )r)   r¡   r¢   r8   r¤   r   r£   r$   rŽ   �  s    zMethodicalMachine.statec                   s   ‡ fdd„}|S )zM
        Declare an input.

        This is a decorator for methods.
        c                   s   t ˆ j| ˆ jd�S )N)rV   r6   rU   )r9   rž   rŸ   )ZinputMethodrK   r   r$   r¤   ¹  s
      ÿz*MethodicalMachine.input.<locals>.decoratorr   ©r)   r¤   r   rK   r$   r;   ±  s    zMethodicalMachine.inputc                   s   ‡ fdd„}|S )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)r4   r6   )r„   )ZoutputMethodrK   r   r$   r¤   Ë  s    z+MethodicalMachine.output.<locals>.decoratorr   r¥   r   rK   r$   r@   À  s    zMethodicalMachine.outputc                 C  s$   | j  |||t|ƒ¡ ||j|< dS )z.
        See L{MethodicalState.upon}.
        N)rž   ZaddTransitionr    rv   )r)   Z
startStateZ
inputTokenZendStateZoutputTokensr>   r   r   r$   rF   Ð  s       ÿz MethodicalMachine._oneTransitionc                   s   ‡ fdd„}|S )ú c                   s   t ˆ ƒ‡ ‡fdd„ƒ}|S )Nc                   s   t | ˆjˆjƒ}ˆ | |jjƒS r(   )r[   rŸ   rž   r{   r8   )rT   rZ   ©Ú	decorateer)   r   r$   Ú	serializeì  s      ÿzBMethodicalMachine.serializer.<locals>.decorator.<locals>.serializer   )r¨   r©   rK   ©r¨   r$   r¤   ë  s    z/MethodicalMachine.serializer.<locals>.decoratorr   r¥   r   rK   r$   Ú
serializerç  s    
zMethodicalMachine.serializerc                   s   ‡ fdd„}|S )r¦   c                   s   t ˆ ƒ‡ ‡fdd„ƒ}|S )Nc                   sL   ˆ | f|ž|Ž}i }ˆj  ¡ D ]}|||j< qt| ˆjˆj ƒ}|| |_d S r(   )rž   Zstatesr8   r[   rŸ   r{   )rT   r   rn   rŽ   ÚmappingZ	eachStaterZ   r§   r   r$   Úunserializeü  s      ÿ
zFMethodicalMachine.unserializer.<locals>.decorator.<locals>.unserializer   )r¨   r­   rK   rª   r$   r¤   û  s    z1MethodicalMachine.unserializer.<locals>.decoratorr   r¥   r   rK   r$   Úunserializer÷  s    zMethodicalMachine.unserializerr˜   rI   c                 C  s   t | j| jƒS r(   )r˜   rž   rŸ   rK   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  s   | j jS r(   rJ   )rŽ   r   r   r$   r“     r”   z-MethodicalMachine.asDigraph.<locals>.<lambda>c                 S  s   | j jS r(   rJ   )r;   r   r   r$   r“     r”   c                 S  s   | j jS r(   rJ   )r@   r   r   r$   r“      r”   )ZstateAsStringZinputAsStringZoutputAsString)Z
_visualizer°   rž   )r)   r°   r   r   r$   Ú	asDigraph  s    
üzMethodicalMachine.asDigraph)N)FFN)rE   rM   rN   rO   r    r‚   r.   rŽ   r;   r@   rF   r«   r®   Úpropertyr¯   r±   r   r   r   r$   r3   {  s(   

     ÿ 



r3   )7Ú
__future__r   ÚcollectionsÚsysZdataclassesr   r   Ú	functoolsr   Úinspectr   r   Ú	itertoolsr   Útypingr	   r
   r   r   r   Úversion_infoZtyping_extensionsr   Z_corer   r   r   r   Z_introspectionr   Ú
namedtupler   r%   r'   r.   rR   r0   r[   r\   r]   ra   rq   rr   rs   r9   r„   rH   ZStringOutputTracerr‹   rP   r—   r˜   rœ   r�   r3   r   r   r   r$   Ú<module>   s`    
ùþ=)2!