
    ir!                       S SK Jr  S SKrS SKrS SKrS SKJrJrJrJ	r	J
r
JrJrJrJr  \(       a  S SKJr   S SKJr   S SKJr  S SKJr  SS	KJr  SS
KJrJr  SSKJr  Sr " S S\5      r SS jr!SS jr"SS jr#SS jr$SS jr%SS jr&SS jr'\RP                  \RR                  -   r*SSS jjr+g! \ a	    S SKJr   Nf = f! \ a	    S SKJr   Nf = f)     )annotationsN)	TYPE_CHECKING	AnnotatedAnyCallableOptionalcastget_args
get_originget_type_hintsStepFunction)Union)	UnionType)	BaseModel   )WorkflowValidationError)Event	EventType)ResourceDefinitiong{Gz?c                  L    \ rS rSr% SrS\S'   S\S'   S\S'   S	\S
'   S\S'   Srg)StepSignatureSpec,   zIA Pydantic model representing the signature of a step function or method.zdict[str, list[EventType]]accepted_events	list[Any]return_typesz
str | Nonecontext_parameterz
Any | Nonecontext_state_type	resources N)__name__
__module____qualname____firstlineno____doc____annotations____static_attributes__r        I/home/james-whalen/.local/lib/python3.13/site-packages/workflows/utils.pyr   r   ,   s#    S//!!""r(   r   c                "   [        U 5      (       d!  [        S[        U 5      R                   35      e[        R
                  " U 5      n[        U SS9n0 nSnSn/ nUR                  R                  5        GH  u  pxUS;   a  M  UR                  XxR                  5      n	[        U	5      bG  [        U	5      n
[        U	5      n[        U
S5      (       a   U
R                  S:X  a  UnU(       a  US   nM|  [        U	5      [        L a'  [        U	5      u  pUR                  [!        X}S	95        M  [        U	S5      (       a  U	R                  S:X  a  UnM  [#        X5      n[%        S
 U 5       5      (       d  M  XU'   GM     ['        U[)        U 5      UUUS9$ )a  
Given a function, ensure the signature is compatible with a workflow step.

Args:
    fn (Callable): The function to inspect.

Returns:
    StepSignatureSpec: A specification object containing:
        - accepted_events: Dictionary mapping parameter names to their event types
        - return_types: List of return type annotations
        - context_parameter: Name of the context parameter if present

Raises:
    TypeError: If fn is not a callable object

z Expected a callable object, got T)include_extrasN)selfclsr!   Contextr   )nameresourcec              3     #    U  HB  nU[         :H  =(       d-    [        R                  " U5      =(       a    [        U[         5      v   MD     g 7fN)r   inspectisclass
issubclass).0param_ts     r)   	<genexpr>$inspect_signature.<locals>.<genexpr>t   sB      
 ' u I(GZ-GI&s   A
A)r   r   r   r   r   )callable	TypeErrortyper!   r3   	signaturer   
parametersitemsget
annotationr   r
   hasattrr   appendr   _get_param_typesallr   _get_return_types)fnsig
type_hintsr   r   r   r   r/   trA   originargs_r0   param_typess                  r)   inspect_signaturerO   6   s   " B<<:48;L;L:MNOO


B
C48J24OI >>'')?"^^D,,7
 j!-
+FJ'D vz**v)/K$(!)-a& j!Y.":.KA/TMN :z**z/B/Bi/O $ 'q5 
 '
 
 

 %0D!O *R '&r*+- r(   c                    [        U R                  5      nUS:X  a  Sn[        U5      eUS:  a  SU S3n[        U5      eU R                  (       d  Sn[        U5      eg)z
Validate that a step signature specification meets workflow requirements.

Args:
    spec (StepSignatureSpec): The signature specification to validate.

Raises:
    WorkflowValidationError: If the signature is invalid for a workflow step.

r   zGStep signature must have at least one parameter annotated as type Eventr   zJStep signature must contain exactly one parameter of type Event but found .zKReturn types of workflows step functions must be annotated with their type.N)lenr   r   r   )specnum_of_eventsmsgs      r)   validate_step_signaturerV      sn     ,,-MW%c**		Z[hZiijk%c**[%c** r(   c                    SSK Jn  0 n[        R                  " U [        R                  S9nU H%  u  pE[        US5      (       d  M  [        X5      X$'   M'     U$ )z
Given a class, return the list of its methods that were defined as steps.

Args:
    _class (object): The class to inspect for step methods.

Returns:
    dict[str, Callable]: A dictionary mapping step names to their corresponding methods.

r   r   	predicate_step_config)workflows.decoratorsr   r3   
getmembers
isfunctionrB   r	   )_classr   step_methodsall_methodsr/   methods         r)   get_steps_from_classrb      sR     2,.L$$Vw7I7IJK#6>**!%l!;L $ r(   c                    SSK Jn  0 n[        R                  " U [        R                  S9nU H%  u  pE[        US5      (       d  M  [        X5      X$'   M'     U$ )z
Given a workflow instance, return the list of its methods that were defined as steps.

Args:
    workflow (object): The workflow instance to inspect.

Returns:
    dict[str, Callable]: A dictionary mapping step names to their corresponding methods.

r   r   rX   rZ   )r[   r   r3   r\   ismethodrB   r	   )workflowr   r_   r`   r/   ra   s         r)   get_steps_from_instancerf      sR     2,.L$$X9I9IJK#6>**!%l!;L $ r(   c                8   UR                  U R                  U R                  5      nU[        R                  R
                  L a  [        /$ [        U5      [        [        [        4;   a+  [        U5       Vs/ s H  o3[        S5      Ld  M  UPM     sn$ U/$ s  snf )a  
Extract and process the types of a parameter.

This helper function handles Union and Optional types, returning a list of the actual types.
For Union[A, None] (Optional[A]), it returns [A].

Args:
    param (inspect.Parameter): The parameter to analyze.
    type_hints (dict): The resolved type hints for the function.

Returns:
    list[Any]: A list of extracted types, excluding None from Unions/Optionals.

N)r@   r/   rA   r3   	Parameteremptyr   r   r   r   r   r
   r<   )paramrI   typrJ   s       r)   rD   rD      s{     ..U%5%5
6C
g%%%u#5(I66#C=@=aT$Z,?=@@5L As   6BBc                    [        U 5      nUR                  S5      nUc  / $ [        U5      nU[        [        4;   a+  [        U5       Vs/ s H  oD[        S5      Ld  M  UPM     sn$ U/$ s  snf )zZ
Extract the return type hints from a function.

Handles Union, Optional, and List types.
returnN)r   r@   r   r   r   r
   r<   )funcrI   return_hintrK   rJ   s        r)   rF   rF      sq      %J..*K	$F%###K0H0aT$Z4G0HH} Is   
A+A+c                    U (       d  Sn[        U5      eU R                  S5      n[        U5      S:X  a  gSU;  a  gUS   S:H  $ )a  
Determines whether a certain qualified name points to a free function.

A free function is either a module-level function or a nested function.
This implementation follows PEP-3155 for handling nested function detection.

Args:
    qualname (str): The qualified name to analyze.

Returns:
    bool: True if the name represents a free function, False otherwise.

Raises:
    ValueError: If the qualified name is empty.

z"The qualified name cannot be emptyrQ   r   Tz<locals>F)
ValueErrorsplitrR   )qualnamerU   tokss      r)   is_free_functionrv      sL    " 2o>>#D
4yA~	4	Bx:%%r(   c                D    SR                  S [        U 5       5       5      $ )z9Returns a unique identifier with the format 'kY2xP9hTnQ'. c              3  V   #    U  H  n[         R                  " [        5      v   M!     g 7fr2   )secretschoice	_alphabet)r6   rM   s     r)   r8   _nanoid.<locals>.<genexpr>  s     Bk7>>),,ks   '))joinrange)sizes    r)   _nanoidr     s    77BeDkBBBr(   )rG   r   rm   r   )rS   r   rm   None)r^   objectrm   dict[str, StepFunction])re   r   rm   r   )rj   zinspect.ParameterrI   dictrm   r   )rn   r   rm   r   )rt   strrm   bool)
   )r   intrm   r   ),
__future__r   rz   stringr3   typingr   r   r   r   r   r	   r
   r   r   r[   r   r   ImportErrortyping_extensionstypesr   pydanticr   errorsr   eventsr   r   r0   r   BUSY_WAIT_DELAYr   rO   rV   rb   rf   rD   rF   rv   ascii_lettersdigitsr|   r   r    r(   r)   <module>r      s    #   
 
 
 1(
*  + $ (	 L^+0...&&@   6==0	C}  ('(  *)*s"   B/ C /B>=B>CC