U
    [h                     @  s   d Z ddlmZ ddlZddlmZ ddlmZ ddlmZ ddlm	Z	 ddlm
Z
 dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ededef dZG dd deZG dd deZG dd dZdS )z7State tracking utilities used by :class:`_orm.Session`.    )annotationsN)Enum)Any)Callable)cast)Iterator)NoReturn)Optional)Tuple)TypeVar)Union   )exc)util)Literal_F.)Zboundc                   @  s   e Zd ZdS )_StateChangeStateN)__name__
__module____qualname__ r   r   B./venv/lib/python3.8/site-packages/sqlalchemy/orm/state_changes.pyr      s   r   c                   @  s   e Zd ZdZdZdZdS )_StateChangeStates   r      N)r   r   r   ANY	NO_CHANGECHANGE_IN_PROGRESSr   r   r   r   r   #   s   r   c                   @  sx   e Zd ZU dZejZded< ejZ	ded< dZ
ded< ddd	d
ddZeddddddZejdddddZdS )_StateChangea!  Supplies state assertion decorators.

    The current use case is for the :class:`_orm.SessionTransaction` class. The
    :class:`_StateChange` class itself is agnostic of the
    :class:`_orm.SessionTransaction` class so could in theory be generalized
    for other systems as well.

    r   _next_state_stateNzOptional[Callable[..., Any]]_current_fnstrr   )operation_namestatereturnc                 C  s   t jd| d|ddd S )NzCan't run operation 'z()' when Session is in state iscecode)sa_excIllegalStateChangeError)selfr#   r$   r   r   r   _raise_for_prerequisite_state7   s    z*_StateChange._raise_for_prerequisite_statezEUnion[Literal[_StateChangeStates.ANY], Tuple[_StateChangeState, ...]]zCallable[[_F], _F])prerequisite_statesmoves_tor%   c                   sT   |st d|tjk	td|tjk	 tjdddddd fdd}|S )a  Method decorator declaring valid states.

        :param prerequisite_states: sequence of acceptable prerequisite
         states.   Can be the single constant _State.ANY to indicate no
         prerequisite state

        :param moves_to: the expected state at the end of the method, assuming
         no exceptions raised.   Can be the constant _State.NO_CHANGE to
         indicate state should not change at the end of the method.

        zno prequisite states sentzTuple[_StateChangeState, ...]r   r   )fnr+   argkwr%   c           	        s~  |j }r |kr || j| |j}|j} r4n|}|tjk	r r||k	r|r|tjtjfkrt	j
d| j d|j dddn"t	j
d| j dd|dd| |_tj|_zz| |f||}W n    Y nX |j |kr|W ~S |j |krt	j
d| j d	d
ddnL|rJt	j
d|j d| j d|j ddnt	j
d| j d|j ddW 5 ||_||_X d S )NzMethod 'z"()' can't be called here; method 'zN()' is already in progress and this would cause an unexpected state change to r&   r'   zCant run operation 'z()' here; will move to state z where we are expecting z()' failed to change state to z as expectedzWhile method 'z()' was running, method 'z)()' caused an unexpected state change to )r    r,   r   r   r!   r   r   r   r   r)   r*   )	r/   r+   r0   r1   Zcurrent_stateZ
next_stateZexisting_fnZexpect_stateZ	ret_valueZexpect_state_changeZhas_prerequisite_statesr.   Zprerequisite_state_collectionr   r   _go]   sf    
	
z(_StateChange.declare_states.<locals>._go)AssertionErrorr   r   r   r   r   Z	decorator)clsr-   r.   r3   r   r2   r   declare_states@   s     
"Mz_StateChange.declare_stateszIterator[Any])expectedr%   c                 c  sh   | j tjkstd|| _ z>z
dV  W n    Y n"X | j|k	rVtjd| jddW 5 tj| _ X dS )zxcalled within a method that changes states.

        method must also use the ``@declare_states()`` decorator.

        zAUnexpected call to _expect_state outside of state-changing methodNzUnexpected state change to r&   r'   )r   r   r   r4   r    r)   r*   )r+   r7   r   r   r   _expect_state   s    


 
z_StateChange._expect_state)r   r   r   __doc__r   r   r   __annotations__r   r    r!   r,   classmethodr6   
contextlibcontextmanagerr8   r   r   r   r   r   )   s   
		lr   )r9   Z
__future__r   r<   enumr   typingr   r   r   r   r   r	   r
   r   r    r   r)   r   Zutil.typingr   r   r   r   r   r   r   r   r   <module>   s&   