
    Ji.                         d dl Z d dlZd dlmZ d dlmZmZmZmZm	Z	 d dl
mZmZ d dlmZ d dlmZ ddlmZ d	Z G d
 de      Z ej,                  de        G d de      Z edee      Z G d dee         Zy)    N)asynccontextmanager)AnyAsyncGeneratorGenericOptionalType)	BaseModelValidationError)TypeVar)DictLikeModel   )BaseSerializeri  c                       e Zd Zy)UnserializableKeyWarningN)__name__
__module____qualname__     o/var/www/html/BankruptcyAI-uat/bankruptcy-ai/venv/lib/python3.12/site-packages/workflows/context/state_store.pyr   r      s    r   r   oncec                   (     e Zd ZdZdef fdZ xZS )	DictStatea"  
    Dynamic, dict-like Pydantic model for workflow state.

    Used as the default state model when no typed state is provided. Behaves
    like a mapping while retaining Pydantic validation and serialization.

    Examples:
        ```python
        from workflows.context.state_store import DictState

        state = DictState()
        state["foo"] = 1
        state.bar = 2  # attribute-style access works for nested structures
        ```

    See Also:
        - [InMemoryStateStore][workflows.context.state_store.InMemoryStateStore]
    paramsc                 $    t        |   di | y )Nr   )super__init__)selfr   	__class__s     r   r   zDictState.__init__,   s    "6"r   )r   r   r   __doc__r   r   __classcell__)r   s   @r   r   r      s    &# # #r   r   MODEL_T)bounddefaultc                      e Zd ZU dZdZee   ed<   defdZdefdZ	dedd	fd
Z
dddeeef   fdZedeeef   ddddfd       Zedeed	f   fd       Zefdedee   defdZdededd	fdZddZdededefdZdedededd	fdZy	)InMemoryStateStorea  
    Async, in-memory, type-safe state manager for workflows.

    This store holds a single Pydantic model instance representing global
    workflow state. When the generic parameter is omitted, it defaults to
    [DictState][workflows.context.state_store.DictState] for flexible,
    dictionary-like usage.

    Thread-safety is ensured with an internal `asyncio.Lock`. Consumers can
    either perform atomic reads/writes via `get_state` and `set_state`, or make
    in-place, transactional edits via the `edit_state` context manager.

    Examples:
        Typed state model:

        ```python
        from pydantic import BaseModel
        from workflows.context.state_store import InMemoryStateStore

        class MyState(BaseModel):
            count: int = 0

        store = InMemoryStateStore(MyState())
        async with store.edit_state() as state:
            state.count += 1
        ```

        Dynamic state with `DictState`:

        ```python
        from workflows.context.state_store import InMemoryStateStore, DictState

        store = InMemoryStateStore(DictState())
        await store.set("user.profile.name", "Ada")
        name = await store.get("user.profile.name")
        ```

    See Also:
        - [Context.store][workflows.context.context.Context.store]
    )memory
state_typeinitial_statec                 d    || _         t        j                         | _        t	        |      | _        y )N)_stateasyncioLock_locktyper(   )r   r)   s     r   r   zInMemoryStateStore.__init__d   s"    #\\^
}-r   returnc                 >   K   | j                   j                         S w)zReturn a shallow copy of the current state model.

        Returns:
            MODEL_T: A `.model_copy()` of the internal Pydantic model.
        )r+   
model_copyr   s    r   	get_statezInMemoryStateStore.get_statei   s      {{%%''s   stateNc                   K   t        |t        | j                              s!t        dt        | j                               | j                  4 d{    || _        ddd      d{    y7 7 # 1 d{  7  sw Y   yxY ww)zReplace the current state model.

        Args:
            state (MODEL_T): New state of the same type as the existing model.

        Raises:
            ValueError: If the type differs from the existing state type.
        zState must be of type N)
isinstancer/   r+   
ValueErrorr.   r   r5   s     r   	set_statezInMemoryStateStore.set_stateq   su      %dkk!235d4;;6G5HIJJ:: 	  	 DK	  	  	  	  	  	  	 sH   AB	A0B	A4B	*A2+B	2B	4B:A=;BB	
serializerr   c                    t        | j                  t              r{i }| j                  j                         D ]  \  }}	 |j	                  |      ||<    d|it        | j                        j                  t        | j                        j                  dS |j	                  | j                        }|t        | j                        j                  t        | j                        j                  dS # t
        $ rH}|| j                  v r$t        j                  d| dt               Y d}~t        d| d|       d}~ww xY w)	a<  Serialize the state and model metadata for persistence.

        For `DictState`, each individual item is serialized using the provided
        serializer since values can be arbitrary Python objects. For other
        Pydantic models, defers to the serializer (e.g. JSON) which can leverage
        model-aware encoding.

        Args:
            serializer (BaseSerializer): Strategy used to encode values.

        Returns:
            dict[str, Any]: A payload suitable for
            [from_dict][workflows.context.state_store.InMemoryStateStore.from_dict].
        z4Skipping serialization of known unserializable key: zY -- This is expected but will require this item to be set manually after deserialization.)categoryNz(Failed to serialize state value for key : _data)
state_datar(   state_module)r7   r+   r   items	serialize	Exceptionknown_unserializable_keyswarningswarnr   r8   r/   r   r   )r   r;   serialized_datakeyvalueeserialized_states          r   to_dictzInMemoryStateStore.to_dict   s:     dkk9- O"kk//1 
U+5+?+?+FOC(   '8"4;;/88 $T[[ 1 < <   *33DKK@ /"4;;/88 $T[[ 1 < < + ! 
d<<< RSVRW Xt t%=
 !$B3%r!M 
s   C11	E:-D=,D==ErL   zInMemoryStateStore[MODEL_T]c                    |s | t                     S |j                  di       }|j                  dd      }|dk(  rN|j                  di       }i }|j                         D ]  \  }}	 |j                  |      ||<    t        |      }
n|j                  |      }
 | |
      S # t        $ r}	t        d| d|	       d}	~	ww xY w)	a  Restore a state store from a serialized payload.

        Args:
            serialized_state (dict[str, Any]): The payload produced by
                [to_dict][workflows.context.state_store.InMemoryStateStore.to_dict].
            serializer (BaseSerializer): Strategy to decode stored values.

        Returns:
            InMemoryStateStore[MODEL_T]: A store with the reconstructed model.
        r@   r(   r   r?   z*Failed to deserialize state value for key r>   N)r?   )r   getrB   deserializerD   r8   )clsrL   r;   r@   r(   _data_serializeddeserialized_datarI   rJ   rK   state_instances              r   	from_dictzInMemoryStateStore.from_dict   s      y{##%)),;
%)),D
 $)~~gr: ".446 
U-7-C-CE-J%c* '->?N'33J?N>"" ! $DSEA3O s   'B##	C,B==Cc                   K   | j                   4 d{    | j                  }| || _        ddd      d{    y7 -7 # 1 d{  7  sw Y   yxY ww)a  Edit state transactionally under a lock.

        Yields the mutable model and writes it back on exit. This pattern avoids
        read-modify-write races and keeps updates atomic.

        Yields:
            MODEL_T: The current state model for in-place mutation.
        N)r.   r+   r9   s     r   
edit_statezInMemoryStateStore.edit_state   sS      :: 	  	 KKEKDK	  	  	  	  	  	  	 sA   AAAAAAAAAAAApathr$   c                   K   |r|j                  d      ng }t        |      t        kD  rt        dt         d      | j                  4 d{    	 | j
                  }|D ]  }| j                  ||      } 	 ddd      d{    |S 7 =# t        $ r0 |t        ur|cY cddd      d{  7   S d| d}t        |      w xY w7 D# 1 d{  7  sw Y   S xY ww)a:  Get a nested value using dot-separated paths.

        Supports dict keys, list indices, and attribute access transparently at
        each segment.

        Args:
            path (str): Dot-separated path, e.g. "user.profile.name".
            default (Any): If provided, return this when the path does not
                exist; otherwise, raise `ValueError`.

        Returns:
            Any: The resolved value.

        Raises:
            ValueError: If the path is invalid and no default is provided or if
                the path depth exceeds limits.
        .Path length exceeds 	 segmentsNzPath 'z' not found in state)	splitlen	MAX_DEPTHr8   r.   r+   _traverse_steprD   Ellipsis)r   rX   r$   segmentsrJ   segmentmsgs          r   rO   zInMemoryStateStore.get   s     $ '+4::c?x=9$3I;iHII:: 
	& 
	&	&![[' @G //w?E@
	& 
	& 
	&
  &(*"N
	& 
	& 
	& tf$89 o%&
	& 
	& 
	& 
	& s~   AC!BC!C%B8C9C!C	C!C C!C!-B0.C!4CC	C!CCCC!rJ   c                   K   |st        d      |j                  d      }t        |      t        kD  rt        dt         d      | j                  4 d{    | j
                  }|dd D ]  }	 | j                  ||      } | j                  ||d   |       ddd      d{    y7 T# t        t        t        t        f$ r i }| j                  |||       |}Y sw xY w7 =# 1 d{  7  sw Y   yxY ww)a  Set a nested value using dot-separated paths.

        Intermediate containers are created as needed. Dicts, lists, tuples, and
        Pydantic models are supported where appropriate.

        Args:
            path (str): Dot-separated path to write.
            value (Any): Value to assign.

        Raises:
            ValueError: If the path is empty or exceeds the maximum depth.
        zPath cannot be emptyrZ   r[   r\   N)r8   r]   r^   r_   r.   r+   r`   KeyErrorAttributeError
IndexError	TypeError_assign_step)r   rX   rJ   rb   currentrc   intermediates          r   setzInMemoryStateStore.set  s      344::c?x=9$3I;iHII:: 	< 	<kkG $CR= ++"11'7CG+ gx|U;	< 	< 	< !.*iH +(*L%%gwE*G	+	< 	< 	< 	<sl   AC:B+C:C%0B-C%C:%C#&C:-0C C%C  C%#C:%C7+C.,C73C:c                    K   	 | j                  | j                  j                                d{    y7 # t        $ r t	        d      w xY ww)zReset the state to its type defaults.

        Raises:
            ValueError: If the model type cannot be instantiated from defaults
                (i.e., fields missing default values).
        Nz'State must have defaults for all fields)r:   r+   r   r
   r8   r3   s    r   clearzInMemoryStateStore.clear1  sG     	H..!6!6!8999 	HFGG	Hs%   A,8 68 A8 AAobjrc   c                     t        |t              r||   S 	 t        |      }||   S # t        t        t
        f$ r Y nw xY wt        ||      S )zCFollow one segment into *obj* (dict key, list index, or attribute).)r7   dictintr8   rj   ri   getattr)r   rq   rc   idxs       r   r`   z!InMemoryStateStore._traverse_step=  sU    c4 w<	g,Cs8OIz2 		 sG$$s   ' >>c                     t        |t              r|||<   y	 t        |      }|||<   y# t        t        t
        f$ r Y nw xY wt        |||       y)zJAssign *value* to *segment* of *obj* (dict key, list index, or attribute).N)r7   rs   rt   r8   rj   ri   setattr)r   rq   rc   rJ   rv   s        r   rk   zInMemoryStateStore._assign_stepL  sY    c4  CL	g,CCHIz2 		 	We$s   ) A A )r0   N)r   r   r   r    rE   r   r"   __annotations__r   r4   r:   rs   strr   rM   classmethodrU   r   r   rW   ra   r   rO   rn   rp   r`   rk   r   r   r   r&   r&   4   s<   'V !,W.g .
( ( W    ."2 .tCH~ .` %##CH~%#;K%#	&%# %#N  .$"?      =E "c "HSM " "H"<c "<# "<$ "<H
H%# % % %% %c %# %$ %r   r&   )r,   rF   
contextlibr   typingr   r   r   r   r   pydanticr	   r
   typing_extensionsr   workflows.eventsr   serializersr   r_   Warningr   simplefilterr   r"   r&   r   r   r   <module>r      su      * ? ? / % * '		w 	   f6 7# #2 )9i
@g%) g%r   