3
YN.                 @   s,  d dl mZ d dlmZ yd dlmZ W n  ek
rH   d dlmZ Y nX d dl	Z	ddl
mZmZ ddlm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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 )#    )wraps)count)getfullargspec)
getargspecN   )Transitioner	Automaton)preserveNamec                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 )N )selfkw)fr
   5/usr/lib/python3/dist-packages/automat/_methodical.pyg   s    z_keywords_only.<locals>.g)r   )r   r   r
   )r   r   _keywords_only   s    
r   T)frozenc               @   sD   e Zd ZdZejddZej 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   s`   t |j}x<|D ]4}t |j}||krtdj|jj|jj||dqW | jj| |||| dS )z
        Declare a state transition within the L{MethodicalMachine} associated
        with this L{MethodicalState}: upon the receipt of the input C{input},
        enter the state C{enter}, emitting each output in C{outputs}.
        zdmethod {input} signature {inputSignature} does not match output {output} signature {outputSignature})inputoutputZinputSignatureZoutputSignatureN)getArgsSpecmethod	TypeErrorformat__name__machine_oneTransition)r   r   Zenteroutputs	collectorZ	inputSpecr   Z
outputSpecr
   r
   r   upon+   s    


zMethodicalState.uponc             C   s   | j jS )N)r   r   )r   r
   r
   r   _name@   s    zMethodicalState._nameN)r   
__module____qualname____doc__attribr   r   
serializedlistr   r    r
   r
   r
   r   r   "   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   _transitionerFromInstanceD   s    r/   c               C   s   d S )Nr
   r
   r
   r
   r   _emptyR   s    r0   c               C   s   dS )Z	docstringNr
   r
   r
   r
   r   
_docstringU   s    r1   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_coder0   r1   
ValueError)ZinstZ	attributer   r
   r
   r   assertNoCodeX   s    r5   F)Zcmphashc               @   sZ   e Zd ZdZejddZejedZejddZ	ejej
eddZdddZd	d
 ZdS )MethodicalInputz.
    An input for a L{MethodicalMachine}.
    F)r   )Z	validator)defaultr   Nc                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        	         st   j  f| | j}j\}}j| }g }x6|D ].}|rN||j  | f| |}|j| q:W ||S )N)r   _stateZ
transition
collectorsr    append)	argskwargsZpreviousStater   Z	outTracerr   valuesr   value)r+   r   r.   r
   r   doInput|   s    

z(MethodicalInput.__get__.<locals>.doInput)r/   r,   r-   r	   r   r   )r   r+   typer@   r
   )r+   r   r.   r   __get__t   s
    zMethodicalInput.__get__c             C   s   | j jS )N)r   r   )r   r
   r
   r   r       s    zMethodicalInput._name)N)r   r!   r"   r#   r$   r%   r-   r5   r   r,   ZFactorydictr:   rB   r    r
   r
   r
   r   r7   i   s   
r7   c               @   s>   e Zd ZdZejddZej ZdddZdd Z	d	d
 Z
dS )MethodicalOutputz/
    An output for a L{MethodicalMachine}.
    F)r   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.)clsr   N)AttributeErrorr   r   r   )r   r+   rA   r
   r
   r   rB      s    zMethodicalOutput.__get__c             O   s   | j |f||S )z-
        Call the underlying method.
        )r   )r   r+   r<   r=   r
   r
   r   __call__   s    zMethodicalOutput.__call__c             C   s   | j jS )N)r   r   )r   r
   r
   r   r       s    zMethodicalOutput._name)N)r   r!   r"   r#   r$   r%   r   r   rB   rG   r    r
   r
   r
   r   rD      s   
rD   c               @   s.   e Zd ZejddZejddZdddZdS )MethodicalTracerF)r   Nc                s    t || j| j  fdd}|S )Nc                s    j |  d S )N)setTrace)Ztracer)r.   r
   r   rI      s    z*MethodicalTracer.__get__.<locals>.setTrace)r/   r,   r-   )r   r+   rA   rI   r
   )r.   r   rB      s    zMethodicalTracer.__get__)N)r   r!   r"   r$   r%   r-   r,   rB   r
   r
   r
   r   rH      s   rH   c               C   s   dt tt S )z,
    Create a unique Python identifier.
    Z_symbol_)strnextcounterr
   r
   r
   r   gensym   s    rM   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 )MethodicalMachineze
    A L{MethodicalMachine} is an interface to an L{Automaton} that uses methods
    on a class.
    c             C   s   t  | _i | _t | _d S )N)r   
_automatonZ	_reducersrM   _symbol)r   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.)rF   )r   r+   rA   r
   r
   r   rB      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 initial: is this state the initial state?  Only one state on
            this L{MethodicalMachine} may be an initial state; more than one is
            an error.
        @type initial: L{bool}

        @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.)
        @type terminal: L{bool}

        @param serialized: a serializable value to be used to represent this
            state to external systems.  This value should be hashable;
            L{unicode} is a good type to use.
        @type serialized: a hashable (comparable) value
        c                s   t | d} r|j_|S )N)r   r   r&   )r   rO   r)   )ZstateMethodstate)initialr   r&   r
   r   	decorator   s    z*MethodicalMachine.state.<locals>.decoratorr
   )r   rS   Zterminalr&   rT   r
   )rS   r   r&   r   rR      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)r-   r   r,   )r7   rO   rP   )ZinputMethod)r   r
   r   rT     s    z*MethodicalMachine.input.<locals>.decoratorr
   )r   rT   r
   )r   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 L{MethodicalMachine.output} method.
        c                s   t  | dS )N)r   r   )rD   )ZoutputMethod)r   r
   r   rT     s    z+MethodicalMachine.output.<locals>.decoratorr
   )r   rT   r
   )r   r   r     s    
zMethodicalMachine.outputc             C   s$   | j j|||t| ||j|< dS )z.
        See L{MethodicalState.upon}.
        N)rO   ZaddTransitiontupler:   )r   Z
startStateZ
inputTokenZendStateZoutputTokensr   r
   r
   r   r     s    
z MethodicalMachine._oneTransitionc                s    fdd}|S )z


        c                s   t   fdd}|S )Nc                s   t | jj} | |jjS )N)r/   rP   rO   r9   r&   )r+   r.   )	decorateer   r
   r   	serialize;  s    zBMethodicalMachine.serializer.<locals>.decorator.<locals>.serialize)r   )rV   rW   )r   )rV   r   rT   :  s    z/MethodicalMachine.serializer.<locals>.decoratorr
   )r   rT   r
   )r   r   
serializer5  s    zMethodicalMachine.serializerc                s    fdd}|S )z


        c                s   t   fdd}|S )Nc                sP    | f||}i }xj j D ]}|||j< q W t| jj }|| |_d S )N)rO   Zstatesr&   r/   rP   r9   )r+   r<   r=   rR   mappingZ	eachStater.   )rV   r   r
   r   unserializeI  s    
zFMethodicalMachine.unserializer.<locals>.decorator.<locals>.unserialize)r   )rV   rZ   )r   )rV   r   rT   H  s    
z1MethodicalMachine.unserializer.<locals>.decoratorr
   )r   rT   r
   )r   r   unserializerC  s    zMethodicalMachine.unserializerc             C   s   t | j| jS )N)rH   rO   rP   )r   r
   r
   r   	_setTraceV  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 )N)r   r   )rR   r
   r
   r   <lambda>g  s    z-MethodicalMachine.asDigraph.<locals>.<lambda>c             S   s   | j jS )N)r   r   )r   r
   r
   r   r^   h  s    c             S   s   | j jS )N)r   r   )r   r
   r
   r   r^   i  s    )ZstateAsStringZinputAsStringZoutputAsString)Z
_visualizer]   rO   )r   r]   r
   r
   r   	asDigraphZ  s    
zMethodicalMachine.asDigraph)N)FFN)r   r!   r"   r#   rQ   rB   r   rR   r   r   r   rX   r[   propertyr\   r_   r
   r
   r
   r   rN      s   
  rN   )	functoolsr   	itertoolsr   inspectr   r   ImportErrorr   r$   Z_corer   r   Z_introspectionr	   r   sobjectr   r/   r0   r1   r5   r7   rD   rH   rL   rM   rN   r
   r
   r
   r   <module>   s0   !&