
    Vh;D                    l   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j<                  dg d      Zd Z d Z!d Z" ed       G d de#             Z$	 	 	 	 	 	 	 	 d,dZ%d Z&d Z'd-dZ(d Z) ed      Z* ed      Z+ ed       G d d e#             Z, ed       G d! d"e#             Z-ee.gdf   Z/d#Z0d$e1d%<   	 	 	 	 d.d&Z2 ed       G d' d(e#             Z3 e       Z4d) Z5 G d* d+e#      Z6y)/    )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                   t        |       }t        t        |j                        |j                  |j
                  |j                  r|j                  ndt        |j                        |j                  r#t        |j                  j                               ndt        |j                  j                                     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   r   r   r   r   itemsr   )funcspecs     C/home/dcms/DCMS/lib/python3.12/site-packages/automat/_methodical.py_getArgSpecr(   "   s     tD499jj"&--R)262E2EE$%%++-.2$**0023
 
    c                    t        | j                  | j                  z   | j                  rdndz   | j                  rdndz   t        d | j                  D              z         S )a  
    Get the name of all arguments defined in a function signature.

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

    Return type annotations are omitted, since we don't constrain input methods
    to have the same return type as output methods, nor output methods to have
    the same output type.

    :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**kwargsc              3  2   K   | ]  }|d    dk7  s|  yw)r   returnNr!   ).0as     r'   	<genexpr>z_getArgNames.<locals>.<genexpr>L   s     @aqtx/?@s   )setr   r   r   r   r#   r   )r&   s    r'   _getArgNamesr1   9   sb     		
//	:2	/ !JJ=B	0 @4++@
@		A r)   c                .     t                f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                     | fi |S Nr!   )selfkwfs     r'   gz_keywords_only.<locals>.g[   s    }}r)   r   )r7   r8   s   ` r'   _keywords_onlyr9   P   s"     1X  Hr)   T)frozenc                      e Zd ZU dZ ed      Zded<    e       Zded<    ed      Zded	<   d
d
e	f	 	 	 	 	 	 	 	 	 ddZ
ddZy
)MethodicalStatez-
    A state for a L{MethodicalMachine}.
    FreprMethodicalMachinemachineCallable[..., Any]methodbool
serializedNc                   || }|g }t        |j                        }|D ]  }t        |j                        }|j                  |      r*t        dj	                  |j
                  j                  |j
                  j                  t        |j
                        t        |j
                                     | j                  j                  | ||||       y)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})inputoutputinputSignatureoutputSignature)
r1   argSpecissubset	TypeErrorformatrB   __name__r"   r@   _oneTransition)r5   rF   enteroutputs	collector	inputArgsrG   
outputArgss           r'   uponzMethodicalState.uponl   s    8 =E?G /	 	F%fnn5J&&y1228&#ll33%}}55'25<<'@(3FMM(B	 39 3	 		 	##D%Kr)   c                .    | j                   j                  S r4   rB   rN   r5   s    r'   _namezMethodicalState._name       {{###r)   )
rF   MethodicalInputrP   zMethodicalState | NonerQ   z!Iterable[MethodicalOutput] | NonerR   zCallable[[Iterable[T]], object]r,   Noner,   str)rN   
__module____qualname____doc__r   r@   __annotations__rB   rD   listrU   rY   r!   r)   r'   r<   r<   b   s     "'E!2G2!&F(%(J(
 )-5959.L.L &.L 3	.L
 3.L 
.L`$r)   r<   c                j    t        | |d      }|#t        ||j                        }t        | ||       |S )z
    Get a L{Transitioner}
    N)getattrr   initialStatesetattr)oselfsymbol	automatontransitioners       r'   _transitionerFromInstancerl      sB     5&$/L#""
 	v|,r)   c                      y r4   r!   r!   r)   r'   _emptyrn      s    r)   c                      y)	docstringNr!   r!   r)   r'   
_docstringrq      s    r)   c                    | j                   j                  t        j                   j                  t        j                   j                  fvrt	        d      y )Nzfunction body must be empty)__code__co_codern   rq   
ValueError)r7   s    r'   assertNoCoderv      sC     	zz&//"9"9:;N;N;V;V!WW677 Xr)   c                h   t        t        |j                  dd |             }|j                  r| }n#|D cg c]  \  }}||j                  v s| }}}t        |      }|D ]  \  }	}
||	|
fz  } t        |j                  ddd   |j                  ddd         }|D ci c]  \  }}||vs|| }}}|j                  |       |j                  r|}||fS |j                  dd |j                  z   }|j                         D ci c]  \  }}||v s|| }}}||fS c c}}w c c}}w c c}}w )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   N)	r#   zipr   r   r   updater   r   r$   )r   kwargs	inputSpec
outputSpec
named_argsreturn_argsnvpassed_arg_namesnamevaluer   full_kwargsreturn_kwargsall_accepted_namess                  r'   _filterArgsr      sc    s9>>!"-t45J &0HTQ1
3GqHH V}! *eT5M)*9>>$B$'););DbD)ABH$,JDAq9I0I1a4JKJv# %% (__QR0:3H3HH(..0
QA9K4KAqD
 
 %%) I K
s#   D"D""D(/D(	D.D.TRF)eqc                      e Zd ZU dZ ed      Zded<    e       Zded<    ed      Zded	<    ee	d
      Z
ded<    edd      Zded<   ddZdddZddZy)r[   z.
    An input for a L{MethodicalMachine}.
    Fr=   =Automaton[MethodicalState, MethodicalInput, MethodicalOutput]rj   rA   rB   r^   ri   )default_factoryr>   z1dict[MethodicalState, Callable[[Iterable[T]], R]]
collectors)initr>   r   rJ   c                b    t        | j                        | _        t        | j                         y r4   )r(   rB   rJ   rv   rX   s    r'   __post_init__zMethodicalInput.__post_init__  s    "4;;/T[[!r)   Nc                     t         j                   j                        t         j                        t         j                        d f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                 H    j                   g| i | j                  }j                        \  }}j                  |   }g }|D ]N  }| ||       t	        | |j
                  |j
                        \  }}	 |g|i |	}
|j                  |
       P  ||      S r4   )rB   _state
transitionr   r   rJ   append)r   r{   previousStaterQ   	outTracerrR   valuesrG   r.   kr   rh   r5   rk   s              r'   doInputz(MethodicalInput.__get__.<locals>.doInput  s     DKK///(//M#/#:#:4#@ Wi6IF! %(f%"4v~~N1u.q.A.e$% V$$r)   )r   objectr{   r   r,   r   )rl   ri   rj   r   rB   r   )r5   rh   typer   rk   s   ``  @r'   __get__zMethodicalInput.__get__  sN     1T^^T	dkk	"	t{{		% 
 
#	% r)   c                .    | j                   j                  S r4   rW   rX   s    r'   rY   zMethodicalInput._name&  rZ   r)   r,   r\   r4   )rh   r   r   r\   r,   r   r]   )rN   r_   r`   ra   r   rj   rb   rB   ri   dictr   rJ   r   r   rY   r!   r)   r'   r[   r[      sy     PUPIL  "'F(U#FC#DI5EJA  %e4GW4"4$r)   r[   c                  v    e Zd ZU dZ ed      Zded<   ded<    eddd      Zd	ed
<   ddZddZ	d Z
ddZy)MethodicalOutputz/
    An output for a L{MethodicalMachine}.
    Fr=   r?   r@   rA   rB   )r   r>   comparer   rJ   c                H    t        | j                        | j                  d<   y )NrJ   )r(   rB   __dict__rX   s    r'   r   zMethodicalOutput.__post_init__4  s    #.t{{#;i r)   Nc                v    t        dj                  |j                  | j                  j                              )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.)clsrB   )AttributeErrorrM   rN   rB   r5   rh   r   s      r'   r   zMethodicalOutput.__get__7  s<     DDJFMM$++*>*> EK E
 	
r)   c                .     | j                   |g|i |S )z-
        Call the underlying method.
        )rB   )r5   rh   r   r{   s       r'   __call__zMethodicalOutput.__call__B  s     t{{5242622r)   c                .    | j                   j                  S r4   rW   rX   s    r'   rY   zMethodicalOutput._nameH  rZ   r)   r   r4   r]   )rN   r_   r`   ra   r   r@   rb   rJ   r   r   r   rY   r!   r)   r'   r   r   *  sF     "'E!2G2%eUCGWC<	
3$r)   r   z4Callable[[str, str, str], StringOutputTracer | None]r   StringTracerc                *      y 	 	 	 	 	 	 	 	 d fd}|S )Nc                ~     | j                         |j                         |j                               fdS y )Nc                0     | j                               S r4   rY   )outresults    r'   <lambda>z,wrapTracer.<locals>.tracer.<locals>.<lambda>]  s    vciik2 r)   r   )staterF   rG   r   wrappeds      @r'   tracerzwrapTracer.<locals>.tracerV  s4    
 v||~F22r)   )r   r<   rF   r[   rG   r<   r,   z%OutputTracer[MethodicalOutput] | Noner!   )r   r   s   ` r'   
wrapTracerr   P  s=        
/	 Mr)   c                  \    e Zd ZU  ed      Zded<    ed      Zded<   	 d		 	 	 	 	 d
dZy)MethodicalTracerFr=   r   rj   r^   ri   Nc                V    t        || j                  | j                        dfd}|S )Nc                :    j                  t        |              y r4   )setTracer   )r   rk   s    r'   r   z*MethodicalTracer.__get__.<locals>.setTraceo  s    !!*V"45r)   )r   StringTracer | Noner,   r\   )rl   ri   rj   )r5   rh   r   r   rk   s       @r'   r   zMethodicalTracer.__get__j  s'     1T^^T	6 r)   r4   )rh   r   r   r   r,   zCallable[[StringTracer], None])rN   r_   r`   r   rj   rb   ri   r   r!   r)   r'   r   r   c  sK    OTPIL  U#FC# -1#)	'r)   r   c                 8    dt        t        t                    z   S )z,
    Create a unique Python identifier.
    _symbol_)r^   nextcounterr!   r)   r'   gensymr   x  s     DM***r)   c                      e Zd ZdZd ZddZe	 d	 	 	 	 	 dd       Zed        Zed        Z	d Z
ed	        Zed
        Zedd       Zd Zy)r?   ze
    A L{MethodicalMachine} is an interface to an L{Automaton} that uses methods
    on a class.
    c                N    t               | _        i | _        t               | _        y r4   )r   
_automaton	_reducersr   _symbolrX   s    r'   __init__zMethodicalMachine.__init__  s    #+xr)   Nc                     |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.
        z.MethodicalMachine is an implementation detail.)r   r   s      r'   r   zMethodicalMachine.__get__  s      !QRRr)   c                      f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                J    t        |       }r|j                  _        |S )N)r@   rB   rD   )r<   r   rf   )stateMethodr   initialr5   rD   s     r'   	decoratorz*MethodicalMachine.state.<locals>.decorator  s*    #[ZE /4,Lr)   r!   )r5   r   terminalrD   r   s   `` ` r'   r   zMethodicalMachine.state  s    .	 r)   c                      fd}|S )zM
        Declare an input.

        This is a decorator for methods.
        c                H    t        j                  | j                        S )N)rj   rB   ri   )r[   r   r   )inputMethodr5   s    r'   r   z*MethodicalMachine.input.<locals>.decorator  s    "//+dll r)   r!   r5   r   s   ` r'   rF   zMethodicalMachine.input  s    	
 r)   c                      f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                    t        |       S )N)r@   rB   )r   )outputMethodr5   s    r'   r   z+MethodicalMachine.output.<locals>.decorator  s    #DFFr)   r!   r   s   ` r'   rG   zMethodicalMachine.output  s    	G r)   c                p    | j                   j                  |||t        |             ||j                  |<   y)z.
        See L{MethodicalState.upon}.
        N)r   addTransitionr#   r   )r5   
startState
inputTokenendStateoutputTokensrR   s         r'   rO   z MethodicalMachine._oneTransition  s6    $ 	%%
HeL.A	
 -6
j)r)   c                      fd}|S ) c                2     t                fd       }|S )Nc                    t        | j                  j                        } | |j                  j                        S r4   )rl   r   r   r   rD   )rh   rk   	decorateer5   s     r'   	serializezBMethodicalMachine.serializer.<locals>.decorator.<locals>.serialize  s7    84<<  !(;(;(F(FGGr)   r   )r   r   r5   s   ` r'   r   z/MethodicalMachine.serializer.<locals>.decorator  s$    9H H r)   r!   r   s   ` r'   
serializerzMethodicalMachine.serializer  s    	 r)   c                      fd}|S )r   c                2     t                fd       }|S )Nc                     | g|i |}i }j                   j                         D ]  }|||j                  <    t        | j                  j                         }||   |_        y r4   )r   statesrD   rl   r   r   )	rh   r   r{   r   mapping	eachStaterk   r   r5   s	          r'   unserializezFMethodicalMachine.unserializer.<locals>.decorator.<locals>.unserialize   sr    !%9$9&9!%!7!7!9 >I4=GI001>84<<  '.en#r)   r   )r   r   r5   s   ` r'   r   z1MethodicalMachine.unserializer.<locals>.decorator  s"    9	 	 r)   r!   r   s   ` r'   unserializerzMethodicalMachine.unserializer  s    	 r)   c                B    t        | j                  | j                        S r4   )r   r   r   rX   s    r'   	_setTracezMethodicalMachine._setTrace  s    >>r)   c                @    ddl m}  || j                  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                .    | j                   j                  S r4   rW   )r   s    r'   r   z-MethodicalMachine.asDigraph.<locals>.<lambda>"      (=(= r)   c                .    | j                   j                  S r4   rW   )rF   s    r'   r   z-MethodicalMachine.asDigraph.<locals>.<lambda>#  r   r)   c                .    | j                   j                  S r4   rW   )rG   s    r'   r   z-MethodicalMachine.asDigraph.<locals>.<lambda>$  s    &--*@*@ r)   )stateAsStringinputAsStringoutputAsString)
_visualizer   r   )r5   r   s     r'   	asDigraphzMethodicalMachine.asDigraph  s$     	,OO==@	
 	
r)   r4   )FFN)r   rC   r   rC   rD   r   )r,   r   )rN   r_   r`   ra   r   r   r9   r   rF   rG   rO   r   r   propertyr   r   r!   r)   r'   r?   r?     s    
 
 TX/3IQ @    6.    ( ? ?
r)   r?   )rh   r   ri   r^   rj   r   r,   z@Transitioner[MethodicalState, MethodicalInput, MethodicalOutput])r7   rA   r,   r\   )r   r   r,   zATracer[MethodicalState, MethodicalInput, MethodicalOutput] | None)7
__future__r   collectionssysdataclassesr   r   	functoolsr   inspectr   r"   	itertoolsr	   typingr
   r   r   r   r   version_infotyping_extensionsr   _corer   r   r   r   _introspectionr   
namedtupler   r(   r1   r9   r   r<   rl   rn   rq   rv   r   r   r   r[   r   r^   StringOutputTracerr   rb   r   r   r   r   r?   r!   r)   r'   <module>r     s   "  
 (  1  = =g+  @ @ (
 +
 
 ..$ $:$f :$ :$z M F	$	8 &&R CLCL e/$f /$ /$d $$v $ $B seTk* Pi P F& ev  " '+f
 f
r)   