o
    i                     @  s`  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	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mZmZmZ d dlZd d	lmZ d
dlmZmZmZ d
dlmZm Z m!Z! d
dl"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z) d
dl*m+Z+ d
dl,m-Z- dZ.eddG dd dee)e$e(f Z/G dd dee)e$e(f Z0eddG dd dee)e(f Z1dS )    )annotationsN)AsyncIteratorSequence)AbstractContextManager	ExitStackasynccontextmanager)	dataclassfield)cached_property)Path)AnyGenericcastoverload)typing_objects   )_utils
exceptionsmermaid)AbstractSpanget_traceparentlogfire_span)BaseNodeDepsTEndGraphRunContextNodeDefRunEndTStateT)BaseStatePersistence)SimpleStatePersistence)GraphGraphRunGraphRunResultF)initc                	   @  sV  e Zd ZU dZded< ded< eddZded	< eddZd
ed< eddZded< de	j
e	j
ddd]ddZdddddd^d#d$Zdddddd^d%d&Zedddddd'd_d+d,Zedddd-d`d/d0Zddd1dad4d5Zdddddejddd6dbdAdBZ	dcdddFdGZddHdedKdLZdfdMdNZedgdPdQZdhdUdVZdWdX Zdid[d\ZdS )jr!   u  Definition of a graph.

    In `pydantic-graph`, a graph is a collection of nodes that can be run in sequence. The nodes define
    their outgoing edges — e.g. which nodes may be run next, and thereby the structure of the graph.

    Here's a very simple example of a graph which increments a number by 1, but makes sure the number is never
    42 at the end.

    ```py {title="never_42.py" noqa="I001"}
    from __future__ import annotations

    from dataclasses import dataclass

    from pydantic_graph import BaseNode, End, Graph, GraphRunContext

    @dataclass
    class MyState:
        number: int

    @dataclass
    class Increment(BaseNode[MyState]):
        async def run(self, ctx: GraphRunContext) -> Check42:
            ctx.state.number += 1
            return Check42()

    @dataclass
    class Check42(BaseNode[MyState, None, int]):
        async def run(self, ctx: GraphRunContext) -> Increment | End[int]:
            if ctx.state.number == 42:
                return Increment()
            else:
                return End(ctx.state.number)

    never_42_graph = Graph(nodes=(Increment, Check42))
    ```
    _(This example is complete, it can be run "as is")_

    See [`run`][pydantic_graph.graph.Graph.run] For an example of running graph, and
    [`mermaid_code`][pydantic_graph.graph.Graph.mermaid_code] for an example of generating a mermaid diagram
    from the graph.
    
str | Nonenamez*dict[str, NodeDef[StateT, DepsT, RunEndT]]	node_defsFreprtype[StateT] | _utils.Unset_state_typetype[RunEndT] | _utils.Unset_run_end_typeboolauto_instrumentNT)r&   
state_typerun_end_typer/   nodes0Sequence[type[BaseNode[StateT, DepsT, RunEndT]]]r0   r1   c                C  sN   || _ || _|| _|| _tt }i | _|D ]}| 	|| q| 
  dS )a  Create a graph from a sequence of nodes.

        Args:
            nodes: The nodes which make up the graph, nodes need to be unique and all be generic in the same
                state type.
            name: Optional name for the graph, if not provided the name will be inferred from the calling frame
                on the first call to a graph method.
            state_type: The type of the state for the graph, this can generally be inferred from `nodes`.
            run_end_type: The type of the result of running the graph, this can generally be inferred from `nodes`.
            auto_instrument: Whether to create a span for the graph run and the execution of each node's run method.
        N)r&   r+   r-   r/   r   get_parent_namespaceinspectcurrentframer'   _register_node_validate_edges)selfr2   r&   r0   r1   r/   parent_namespacenode r<   Z/var/www/html/karishye-ai-python/venv/lib/python3.10/site-packages/pydantic_graph/graph.py__init__J   s   zGraph.__init__statedepspersistence
infer_name
start_node BaseNode[StateT, DepsT, RunEndT]r@   r   rA   r   rB   ,BaseStatePersistence[StateT, RunEndT] | NonerC   returnGraphRunResult[StateT, RunEndT]c          	   	     s   |r| j du r| t  | j||||dd4 I dH }|2 z3 dH W }q 6 W d  I dH  n1 I dH s8w   Y  |j}|dusHJ d|S )a  Run the graph from a starting node until it ends.

        Args:
            start_node: the first node to run, since the graph definition doesn't define the entry point in the graph,
                you need to provide the starting node.
            state: The initial state of the graph.
            deps: The dependencies of the graph.
            persistence: State persistence interface, defaults to
                [`SimpleStatePersistence`][pydantic_graph.SimpleStatePersistence] if `None`.
            infer_name: Whether to infer the graph name from the calling frame.

        Returns:
            A `GraphRunResult` containing information about the run, including its final result.

        Here's an example of running the graph from [above][pydantic_graph.graph.Graph]:

        ```py {title="run_never_42.py" noqa="I001" requires="never_42.py"}
        from never_42 import Increment, MyState, never_42_graph

        async def main():
            state = MyState(1)
            await never_42_graph.run(Increment(), state=state)
            print(state)
            #> MyState(number=2)

            state = MyState(41)
            await never_42_graph.run(Increment(), state=state)
            print(state)
            #> MyState(number=43)
        ```
        NFr?   zGraphRun should have a result)r&   _infer_namer5   r6   iterresult)	r9   rD   r@   rA   rB   rC   	graph_run_noderK   r<   r<   r=   runj   s   (
(z	Graph.runc             	   C  s:   |r| j du r| t  t | j||||ddS )ar  Synchronously run the graph.

        This is a convenience method that wraps [`self.run`][pydantic_graph.Graph.run] with `loop.run_until_complete(...)`.
        You therefore can't use this method inside async code or if there's an active event loop.

        Args:
            start_node: the first node to run, since the graph definition doesn't define the entry point in the graph,
                you need to provide the starting node.
            state: The initial state of the graph.
            deps: The dependencies of the graph.
            persistence: State persistence interface, defaults to
                [`SimpleStatePersistence`][pydantic_graph.SimpleStatePersistence] if `None`.
            infer_name: Whether to infer the graph name from the calling frame.

        Returns:
            The result type from ending the run and the history of the run.
        NFr?   )r&   rI   r5   r6   r   get_event_looprun_until_completerN   )r9   rD   r@   rA   rB   rC   r<   r<   r=   run_sync   s
   zGraph.run_sync)r@   rA   rB   spanrC   rR   +AbstractContextManager[AbstractSpan] | None/AsyncIterator[GraphRun[StateT, DepsT, RunEndT]]c             	   C s   |r| j du rt  }r| |j |du rt }||  t A}d}	|du r=| jr<d| j  }
|	t
|
| d}	n|	|}	|	du rHdnt|	}ttttf | |||||dV  W d   dS 1 sgw   Y  dS )a  A contextmanager which can be used to iterate over the graph's nodes as they are executed.

        This method returns a `GraphRun` object which can be used to async-iterate over the nodes of this `Graph` as
        they are executed. This is the API to use if you want to record or interact with the nodes as the graph
        execution unfolds.

        The `GraphRun` can also be used to manually drive the graph execution by calling
        [`GraphRun.next`][pydantic_graph.graph.GraphRun.next].

        The `GraphRun` provides access to the full run history, state, deps, and the final result of the run once
        it has completed.

        For more details, see the API documentation of [`GraphRun`][pydantic_graph.graph.GraphRun].

        Args:
            start_node: the first node to run. Since the graph definition doesn't define the entry point in the graph,
                you need to provide the starting node.
            state: The initial state of the graph.
            deps: The dependencies of the graph.
            persistence: State persistence interface, defaults to
                [`SimpleStatePersistence`][pydantic_graph.SimpleStatePersistence] if `None`.
            span: The span to use for the graph run. If not provided, a new span will be created.
            infer_name: Whether to infer the graph name from the calling frame.

        Returns: A GraphRun that can be async iterated over to drive the graph to completion.
        Nz
run graph graph)rV   rD   rB   r@   rA   traceparent)r&   r5   r6   rI   f_backr    set_graph_typesr   r/   enter_contextr   r   r"   r   r   r   )r9   rD   r@   rA   rB   rR   rC   framestackentered_span	span_namerW   r<   r<   r=   rJ      s2   %


"z
Graph.iter)rA   rR   rC   %BaseStatePersistence[StateT, RunEndT]c          
   
   C s   |r| j du rt  }r| |j ||  | I dH }|du r)td|j	
|j | jr=|du r=td| d}t 2}|du rGdn||}|du rRdnt|}	ttttf | |j	||j||j|	dV  W d   dS 1 suw   Y  dS )a  A contextmanager to iterate over the graph's nodes as they are executed, created from a persistence object.

        This method has similar functionality to [`iter`][pydantic_graph.graph.Graph.iter],
        but instead of passing the node to run, it will restore the node and state from state persistence.

        Args:
            persistence: The state persistence interface to use.
            deps: The dependencies of the graph.
            span: The span to use for the graph run. If not provided, a new span will be created.
            infer_name: Whether to infer the graph name from the calling frame.

        Returns: A GraphRun that can be async iterated over to drive the graph to completion.
        Nz2Unable to restore snapshot from state persistence.zrun graph {graph.name}rU   )rV   rD   rB   r@   rA   snapshot_idrW   )r&   r5   r6   rI   rX   rY   	load_nextr   GraphRuntimeErrorr;   set_snapshot_ididr/   r   r   rZ   r   r"   r   r   r   r@   )
r9   rB   rA   rR   rC   r[   snapshotr\   r]   rW   r<   r<   r=   iter_from_persistence  s0   


"zGraph.iter_from_persistence)r@   rC   r;   Nonec                  s>   |r| j du r| t  ||  |||I dH  dS )a  Initialize a new graph run in persistence without running it.

        This is useful if you want to set up a graph run to be run later, e.g. via
        [`iter_from_persistence`][pydantic_graph.graph.Graph.iter_from_persistence].

        Args:
            node: The node to run first.
            persistence: State persistence interface.
            state: The start state of the graph.
            infer_name: Whether to infer the graph name from the calling frame.
        N)r&   rI   r5   r6   rY   snapshot_node)r9   r;   rB   r@   rC   r<   r<   r=   
initialize6  s
   
zGraph.initialize)rD   titleedge_labelsnoteshighlighted_nodeshighlight_cssrC   	direction6Sequence[mermaid.NodeIdent] | mermaid.NodeIdent | Nonerj   -str | None | typing_extensions.Literal[False]rk   rl   rm   rn   strro   $mermaid.StateDiagramDirection | Nonec          	   
   C  sN   |r| j du r| t  |du r| j r| j }tj| ||||p!d|||dS )av  Generate a diagram representing the graph as [mermaid](https://mermaid.js.org/) diagram.

        This method calls [`pydantic_graph.mermaid.generate_code`][pydantic_graph.mermaid.generate_code].

        Args:
            start_node: The node or nodes which can start the graph.
            title: The title of the diagram, use `False` to not include a title.
            edge_labels: Whether to include edge labels.
            notes: Whether to include notes on each node.
            highlighted_nodes: Optional node or nodes to highlight.
            highlight_css: The CSS to use for highlighting nodes.
            infer_name: Whether to infer the graph name from the calling frame.
            direction: The direction of flow.

        Returns:
            The mermaid code for the graph, which can then be rendered as a diagram.

        Here's an example of generating a diagram for the graph from [above][pydantic_graph.graph.Graph]:

        ```py {title="mermaid_never_42.py" requires="never_42.py"}
        from never_42 import Increment, never_42_graph

        print(never_42_graph.mermaid_code(start_node=Increment))
        '''
        ---
        title: never_42_graph
        ---
        stateDiagram-v2
          [*] --> Increment
          Increment --> Check42
          Check42 --> Increment
          Check42 --> [*]
        '''
        ```

        The rendered diagram will look like this:

        ```mermaid
        ---
        title: never_42_graph
        ---
        stateDiagram-v2
          [*] --> Increment
          Increment --> Check42
          Check42 --> Increment
          Check42 --> [*]
        ```
        N)rD   rm   rn   rj   rk   rl   ro   )r&   rI   r5   r6   r   generate_code)	r9   rD   rj   rk   rl   rm   rn   rC   ro   r<   r<   r=   mermaid_codeO  s   <zGraph.mermaid_codekwargs/typing_extensions.Unpack[mermaid.MermaidConfig]bytesc                 K  sF   |r| j du r| t  d|vr| j r| j |d< tj| fi |S )a  Generate a diagram representing the graph as an image.

        The format and diagram can be customized using `kwargs`,
        see [`pydantic_graph.mermaid.MermaidConfig`][pydantic_graph.mermaid.MermaidConfig].

        !!! note "Uses external service"
            This method makes a request to [mermaid.ink](https://mermaid.ink) to render the image, `mermaid.ink`
            is a free service not affiliated with Pydantic.

        Args:
            infer_name: Whether to infer the graph name from the calling frame.
            **kwargs: Additional arguments to pass to `mermaid.request_image`.

        Returns:
            The image bytes.
        Nrj   )r&   rI   r5   r6   r   request_image)r9   rC   rv   r<   r<   r=   mermaid_image  s
   
zGraph.mermaid_image)rC   path
Path | strc               K  sL   |r| j du r| t  d|vr| j r| j |d< tj|| fi | dS )a  Generate a diagram representing the graph and save it as an image.

        The format and diagram can be customized using `kwargs`,
        see [`pydantic_graph.mermaid.MermaidConfig`][pydantic_graph.mermaid.MermaidConfig].

        !!! note "Uses external service"
            This method makes a request to [mermaid.ink](https://mermaid.ink) to render the image, `mermaid.ink`
            is a free service not affiliated with Pydantic.

        Args:
            path: The path to save the image to.
            infer_name: Whether to infer the graph name from the calling frame.
            **kwargs: Additional arguments to pass to `mermaid.save_image`.
        Nrj   )r&   rI   r5   r6   r   
save_image)r9   r{   rC   rv   r<   r<   r=   mermaid_save  s
   
zGraph.mermaid_savec                 C  s   dd | j  D S )zGet the nodes in the graph.c                 S  s   g | ]}|j qS r<   )r;   ).0node_defr<   r<   r=   
<listcomp>  s    z#Graph.get_nodes.<locals>.<listcomp>)r'   valuesr9   r<   r<   r=   	get_nodes  s   zGraph.get_nodes"tuple[type[StateT], type[RunEndT]]c                 C  s   t | jrt | jr| j| jfS | j}| j}| j D ]L}t|jD ]C}t	|t
u rht|}t |s>|r>|d }t |sTt|dkrT|d }t|sT|}t |rft |rf||f    S  nq%qt |sqd }t |sxd }||fS )Nr         )r   is_setr+   r-   r'   r   typing_extensionsget_original_basesr;   
get_originr   get_argslenr   is_never)r9   r0   r1   r   baseargstr<   r<   r=   inferred_types  s0   



zGraph.inferred_types&type[BaseNode[StateT, DepsT, RunEndT]]r:   dict[str, Any] | Nonec                 C  sJ   |  }| j| }rtd| d|j d| ||| j|< d S )Nz	Node ID `u   ` is not unique — found on z and )get_node_idr'   getr   GraphSetupErrorr;   get_node_def)r9   r;   r:   node_idexisting_noder<   r<   r=   r7     s   zGraph._register_nodec                 C  s   | j  }i }| j  D ]\}}|j D ]}||vr(||g d| d qq|rWdd | D }t|dkrEt|d  dd	dd	 |D }td
| d S )N`c                 S  s&   g | ]\}}d | dt | qS )r   z` is referenced by )r   	comma_and)r   kvr<   r<   r=   r     s   & z)Graph._validate_edges.<locals>.<listcomp>r   r   z but not included in the graph.
c                 s  s    | ]}d | V  qdS ) Nr<   )r   ber<   r<   r=   	<genexpr>
  s    z(Graph._validate_edges.<locals>.<genexpr>zANodes are referenced in the graph but not included in the graph:
)
r'   keysitemsnext_node_edges
setdefaultappendr   r   r   join)r9   known_node_ids	bad_edgesr   r   edgebad_edges_listbr<   r<   r=   r8     s"   
zGraph._validate_edgesfunction_frametypes.FrameType | Nonec                 C  s   | j du s	J d|dur@|j }rB|j D ]\}}|| u r%|| _  dS q|j|jkrD|j D ]\}}|| u r?|| _  dS q1dS dS dS dS )zInfer the agent name from the call frame.

        Usage should be `self._infer_name(inspect.currentframe())`.

        Copied from `Agent`.
        NzName already set)r&   rX   f_localsr   	f_globals)r9   r   parent_framer&   itemr<   r<   r=   rI     s    zGraph._infer_name)
r2   r3   r&   r%   r0   r*   r1   r,   r/   r.   )rD   rE   r@   r   rA   r   rB   rF   rC   r.   rG   rH   )rD   rE   r@   r   rA   r   rB   rF   rR   rS   rC   r.   rG   rT   )
rB   r_   rA   r   rR   rS   rC   r.   rG   rT   )
r;   rE   rB   r_   r@   r   rC   r.   rG   rg   )rD   rp   rj   rq   rk   r.   rl   r.   rm   rp   rn   rr   rC   r.   ro   rs   rG   rr   )T)rC   r.   rv   rw   rG   rx   )r{   r|   rC   r.   rv   rw   rG   rg   )rG   r3   )rG   r   )r;   r   r:   r   rG   rg   )r   r   rG   rg   )__name__
__module____qualname____doc____annotations__r	   r+   r-   r/   r   UNSETr>   rN   rQ   r   rJ   rf   ri   r   DEFAULT_HIGHLIGHT_CSSru   rz   r~   r   r
   r   r7   r8   rI   r<   r<   r<   r=   r!      sp   
 *$9!B7L

 r!   c                   @  s   e Zd ZdZddd/ddZed0ddZed1ddZddd2ddZed3dd Zed4d"d#Z		d5d6d&d'Z
d7d)d*Zd3d+d,Zd1d-d.ZdS )8r"   a  A stateful, async-iterable run of a [`Graph`][pydantic_graph.graph.Graph].

    You typically get a `GraphRun` instance from calling
    `async with [my_graph.iter(...)][pydantic_graph.graph.Graph.iter] as graph_run:`. That gives you the ability to iterate
    through nodes as they run, either by `async for` iteration or by repeatedly calling `.next(...)`.

    Here's an example of iterating over the graph from [above][pydantic_graph.graph.Graph]:
    ```py {title="iter_never_42.py" noqa="I001" requires="never_42.py"}
    from copy import deepcopy
    from never_42 import Increment, MyState, never_42_graph

    async def main():
        state = MyState(1)
        async with never_42_graph.iter(Increment(), state=state) as graph_run:
            node_states = [(graph_run.next_node, deepcopy(graph_run.state))]
            async for node in graph_run:
                node_states.append((node, deepcopy(graph_run.state)))
            print(node_states)
            '''
            [
                (Increment(), MyState(number=1)),
                (Increment(), MyState(number=1)),
                (Check42(), MyState(number=2)),
                (End(data=2), MyState(number=2)),
            ]
            '''

        state = MyState(41)
        async with never_42_graph.iter(Increment(), state=state) as graph_run:
            node_states = [(graph_run.next_node, deepcopy(graph_run.state))]
            async for node in graph_run:
                node_states.append((node, deepcopy(graph_run.state)))
            print(node_states)
            '''
            [
                (Increment(), MyState(number=41)),
                (Increment(), MyState(number=41)),
                (Check42(), MyState(number=42)),
                (Increment(), MyState(number=42)),
                (Check42(), MyState(number=43)),
                (End(data=43), MyState(number=43)),
            ]
            '''
    ```

    See the [`GraphRun.next` documentation][pydantic_graph.graph.GraphRun.next] for an example of how to manually
    drive the graph run.
    N)r`   rV   Graph[StateT, DepsT, RunEndT]rD   rE   rB   r_   r@   r   rA   r   rW   r%   r`   c                C  s4   || _ || _|| _|| _|| _|| _|| _d| _dS )aO  Create a new run for a given graph, starting at the specified node.

        Typically, you'll use [`Graph.iter`][pydantic_graph.graph.Graph.iter] rather than calling this directly.

        Args:
            graph: The [`Graph`][pydantic_graph.graph.Graph] to run.
            start_node: The node where execution will begin.
            persistence: State persistence interface.
            state: A shared state object or primitive (like a counter, dataclass, etc.) that is available
                to all nodes via `ctx.state`.
            deps: Optional dependencies that each node can access via `ctx.deps`, e.g. database connections,
                configuration, or logging clients.
            traceparent: The traceparent for the span used for the graph run.
            snapshot_id: The ID of the snapshot the node came from.
        FN)rV   rB   _snapshot_idr@   rA   _GraphRun__traceparent
_next_node_is_started)r9   rV   rD   rB   r@   rA   rW   r`   r<   r<   r=   r>   V  s   
zGraphRun.__init__required typing_extensions.Literal[False]rG   c                C     d S Nr<   r9   r   r<   r<   r=   _traceparentz     zGraphRun._traceparentrr   c                 C  r   r   r<   r   r<   r<   r=   r   |  r   Tr   r.   c                C     | j d u r|rtd| j S )Nz&No span was created for this graph run)r   r   rb   r   r<   r<   r=   r   ~     
/BaseNode[StateT, DepsT, RunEndT] | End[RunEndT]c                 C  s   | j S )zThe next node that will be run in the graph.

        This is the next node that will be used during async iteration, or if a node is not passed to `self.next(...)`.
        )r   r   r<   r<   r=   	next_node  s   zGraphRun.next_node&GraphRunResult[StateT, RunEndT] | Nonec                 C  s8   t | jtsdS tttf | jj| j| j| j	dddS )zLThe final result of the graph run if the run is completed, otherwise `None`.NFr   )r@   rB   rW   )

isinstancer   r   r#   r   r   datar@   rB   r   r   r<   r<   r=   rK     s   

zGraphRun.resultr;   'BaseNode[StateT, DepsT, RunEndT] | Nonec              
     s  |du rt ttttf | j}| }n| }|| jkr-| j	|| j
|I dH  || _t|ts:td|d| }|| jjvrMtd| dt L}| jjrdd| }|t|||d | j|4 I dH  t| j
| jd}||I dH | _W d  I dH  n1 I dH sw   Y  W d   n1 sw   Y  t| jtr| j | _| j| j
| jI dH  | jS t| jtr| j | _| j| j
| jI dH  | jS td	t| jj d
)aW  Manually drive the graph run by passing in the node you want to run next.

        This lets you inspect or mutate the node before continuing execution, or skip certain nodes
        under dynamic conditions. The graph run should stop when you return an [`End`][pydantic_graph.nodes.End] node.

        Here's an example of using `next` to drive the graph from [above][pydantic_graph.graph.Graph]:
        ```py {title="next_never_42.py" noqa="I001" requires="never_42.py"}
        from copy import deepcopy
        from pydantic_graph import End
        from never_42 import Increment, MyState, never_42_graph

        async def main():
            state = MyState(48)
            async with never_42_graph.iter(Increment(), state=state) as graph_run:
                next_node = graph_run.next_node  # start with the first node
                node_states = [(next_node, deepcopy(graph_run.state))]

                while not isinstance(next_node, End):
                    if graph_run.state.number == 50:
                        graph_run.state.number = 42
                    next_node = await graph_run.next(next_node)
                    node_states.append((next_node, deepcopy(graph_run.state)))

                print(node_states)
                '''
                [
                    (Increment(), MyState(number=48)),
                    (Check42(), MyState(number=49)),
                    (End(data=49), MyState(number=49)),
                ]
                '''
        ```

        Args:
            node: The node to run next in the graph. If not specified, uses `self.next_node`, which is initialized to
                the `start_node` of the run and updated each time a new node is returned.

        Returns:
            The next node returned by the graph logic, or an [`End`][pydantic_graph.nodes.End] node if
            the run has completed.
        Nz6`next` must be called with a `BaseNode` instance, got .zNode `z` is not in the graph.z	run node )r   r;   )r@   rA   zInvalid node return type: `z `. Expected `BaseNode` or `End`.)r   r   r   r   r   r   get_snapshot_idr   rB   snapshot_node_if_newr@   r   	TypeErrorr   rV   r'   r   rb   r   r/   rZ   r   
record_runr   rA   rN   r   snapshot_endrh   typer   )r9   r;   node_snapshot_idr   r\   r^   ctxr<   r<   r=   next  sD   ,



(	zGraphRun.next>AsyncIterator[BaseNode[StateT, DepsT, RunEndT] | End[RunEndT]]c                 C  s   | S r   r<   r   r<   r<   r=   	__aiter__  r   zGraphRun.__aiter__c                   s6   | j s
d| _ | jS t| jtrt| | jI dH S )z8Use the last returned node as the input to `Graph.next`.TN)r   r   r   r   StopAsyncIterationr   r   r<   r<   r=   	__anext__  s   zGraphRun.__anext__c                 C  s   d| j jpd dS )Nz<GraphRun graph=z	[unnamed]>)rV   r&   r   r<   r<   r=   __repr__   s   zGraphRun.__repr__)rV   r   rD   rE   rB   r_   r@   r   rA   r   rW   r%   r`   r%   r   r   rG   r%   rG   rr   r   r.   rG   r%   )rG   r   )rG   r   r   )r;   r   rG   r   )rG   r   )r   r   r   r   r>   r   r   propertyr   rK   r   r   r   r   r<   r<   r<   r=   r"   $  s$    :$
[
r"   c                   @  sn   e Zd ZU dZded< ded< eddZded	< 	
ddddZedddZ	edddZ	dddddZ	d
S )r#   z$The final result of running a graph.r   outputr   r@   Fr(   r_   rB   NrW   r%   c                 C  s   || _ || _|| _|| _d S r   )r   r@   rB   _GraphRunResult__traceparent)r9   r   r@   rB   rW   r<   r<   r=   r>     s   
zGraphRunResult.__init__r   r   rG   c                C  r   r   r<   r   r<   r<   r=   r     r   zGraphRunResult._traceparentrr   c                 C  r   r   r<   r   r<   r<   r=   r     r   Tr   r.   c                C  r   )Nz'No span was created for this graph run.)r   r   rb   r   r<   r<   r=   r     r   r   )r   r   r@   r   rB   r_   rW   r%   r   r   r   )
r   r   r   r   r   r	   rB   r>   r   r   r<   r<   r<   r=   r#     s   
 r#   )2
__future__r   _annotationsr5   typescollections.abcr   r   
contextlibr   r   r   dataclassesr   r	   	functoolsr
   pathlibr   typingr   r   r   r   r   typing_inspectionr    r   r   r   r   r   r   r2   r   r   r   r   r   r   r   rB   r   persistence.in_memr    __all__r!   r"   r#   r<   r<   r<   r=   <module>   s6    $     a