U
    [e:>                  
   @   sn  d dl Z d dlmZ d dlmZ zd dlmZ W n  ek
rP   d dlm	Z Y nX d dl
Z
d dlZddl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
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/d0 d0eZ#dS )1    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	r2|j	ndtjrDt|j
ndtjrd|jr`t|j qfdndtjrzt|j n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   r   r   r   r   r   r   )getArgsSpecr   tupler   r   sixPY3r   keywordsr   r   r   itemsr   )funcspecr   r   U/var/www/html/services/stratfitenv/lib/python3.8/site-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|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 ]B}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outputZinputSignatureZoutputSignatureN)
r   argSpecissubset	TypeErrorformatmethod__name__r   machine_oneTransition)r!   r+   Zenteroutputs	collectorZ	inputArgsr,   Z
outputArgsr   r   r   upon^   s    


	zMethodicalState.uponc                 C   s   | j jS r    r1   r2   r!   r   r   r   _name   s    zMethodicalState._nameN)r2   
__module____qualname____doc__attribr3   r1   
serializedlistr7   r:   r   r   r   r   r(   U   s   "r(   c                 C   s0   t | |d}|dkr,t||j}t| || |S )z
    Get a L{Transitioner}
    N)getattrr   initialStatesetattr)oselfsymbol	automatontransitionerr   r   r   _transitionerFromInstance   s    rI   c                   C   s   d S r    r   r   r   r   r   _empty   s    rJ   c                   C   s   dS )Z	docstringNr   r   r   r   r   
_docstring   s    rK   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_coderJ   rK   
ValueError)inst	attributer$   r   r   r   assertNoCode   s    rQ   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   rR   )passed_arg_namesr   r   
<dictcomp>   s       z_filterArgs.<locals>.<dictcomp>c                    s   i | ]\}}| kr||qS r   r   rR   )all_accepted_namesr   r   rZ      s     )	r   zipr   r   r   updater   r   r   )r   kwargsZ	inputSpecrV   Z
named_argsZreturn_argsnamevaluer   Zfull_kwargsZreturn_kwargsr   )r[   rV   rY   r   _filterArgs   s    "
ra   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   s
   t | jS r    r   r1   r9   r   r   r   _buildArgSpec   s    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  f| | j}\}}j| }g }|D ]D}|rL||  t| |j|j\}}	| f||	}
||
 q8||S r    )r1   _stateZ
transition
collectorsr:   ra   r-   append)r   r^   ZpreviousStater5   Z	outTracerr6   valuesr,   akr`   rE   r!   rH   r   r   doInput   s    
z(MethodicalInput.__get__.<locals>.doInput)rI   rF   rG   r
   r1   r   )r!   rE   typerr   r   rq   r   __get__   s    zMethodicalInput.__get__c                 C   s   | j jS r    r8   r9   r   r   r   r:      s    zMethodicalInput._name)N)r2   r;   r<   r=   r>   r?   rG   rQ   r1   rF   Factorydictrl   r-   rf   rj   rt   r:   r   r   r   r   rd      s   

rd   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)   rg   c                 C   s
   t | jS r    ri   r9   r   r   r   rj     s    zMethodicalOutput._buildArgSpecNc                 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.)clsr1   N)AttributeErrorr0   r2   r1   r!   rE   rs   r   r   r   rt   
  s    zMethodicalOutput.__get__c                 O   s   | j |f||S )z-
        Call the underlying method.
        )r1   )r!   rE   r   r^   r   r   r   __call__  s    zMethodicalOutput.__call__c                 C   s   | j jS r    r8   r9   r   r   r   r:     s    zMethodicalOutput._name)N)r2   r;   r<   r=   r>   r?   r3   r1   r-   rf   rj   rt   r{   r:   r   r   r   r   rw      s   

rw   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)ZtracerrH   r   r   r}   )  s    z*MethodicalTracer.__get__.<locals>.setTrace)rI   rF   rG   )r!   rE   rs   r}   r   r~   r   rt   &  s
    zMethodicalTracer.__get__)N)r2   r;   r<   r>   r?   rG   rF   rt   r   r   r   r   r|      s   r|   c                   C   s   dt tt S )z,
    Create a unique Python identifier.
    Z_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	   
_automatonZ	_reducersr   _symbolr9   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.)ry   rz   r   r   r   rt   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)r3   r1   r@   )r(   r   rC   )ZstateMethodstateinitialr!   r@   r   r   	decoratorf  s    z*MethodicalMachine.state.<locals>.decoratorr   )r!   r   Zterminalr@   r   r   r   r   r   P  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)rG   r1   rF   )rd   r   r   )ZinputMethodr9   r   r   r   w  s    z*MethodicalMachine.input.<locals>.decoratorr   r!   r   r   r9   r   r+   p  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)r3   r1   )rw   )ZoutputMethodr9   r   r   r     s    z+MethodicalMachine.output.<locals>.decoratorr   r   r   r9   r   r,   ~  s    
zMethodicalMachine.outputc                 C   s$   | j |||t| ||j|< dS )z.
        See L{MethodicalState.upon}.
        N)r   ZaddTransitionr   rl   )r!   Z
startStateZ
inputTokenZendStateZoutputTokensr6   r   r   r   r4     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    )rI   r   r   rk   r@   )rE   rH   	decorateer!   r   r   	serialize  s    zBMethodicalMachine.serializer.<locals>.decorator.<locals>.serializer   )r   r   r9   r   r   r     s    z/MethodicalMachine.serializer.<locals>.decoratorr   r   r   r9   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statesr@   rI   r   rk   )rE   r   r^   r   mappingZ	eachStaterH   r   r   r   unserialize  s      
zFMethodicalMachine.unserializer.<locals>.decorator.<locals>.unserializer   )r   r   r9   r   r   r     s    	z1MethodicalMachine.unserializer.<locals>.decoratorr   r   r   r9   r   unserializer  s    zMethodicalMachine.unserializerc                 C   s   t | j| jS r    )r|   r   r   r9   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    r8   )r   r   r   r   <lambda>      z-MethodicalMachine.asDigraph.<locals>.<lambda>c                 S   s   | j jS r    r8   )r+   r   r   r   r     r   c                 S   s   | j jS r    r8   )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)r2   r;   r<   r=   r   rt   r&   r   r+   r,   r4   r   r   propertyr   r   r   r   r   r   r   8  s&   
  




r   )$collections	functoolsr   	itertoolsr   inspectr   r   ImportErrorr   r>   r   Z_corer   r	   Z_introspectionr
   
namedtupler   r   r   r&   sobjectr(   rI   rJ   rK   rQ   ra   rd   rw   r|   r   r   r   r   r   r   r   <module>   sF     
.(+
"