pydantic-graph 0.7.5__py3-none-any.whl → 1.24.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,90 @@
1
+ """Utility types and functions for type manipulation and introspection.
2
+
3
+ This module provides helper classes and functions for working with Python's type system,
4
+ including workarounds for type checker limitations and utilities for runtime type inspection.
5
+ """
6
+
7
+ from dataclasses import dataclass
8
+ from typing import Any, Generic, cast, get_args, get_origin
9
+
10
+ from typing_extensions import TypeAliasType, TypeVar
11
+
12
+ T = TypeVar('T', infer_variance=True)
13
+ """Generic type variable with inferred variance."""
14
+
15
+
16
+ class TypeExpression(Generic[T]):
17
+ """A workaround for type checker limitations when using complex type expressions.
18
+
19
+ This class serves as a wrapper for types that cannot normally be used in positions
20
+ requiring `type[T]`, such as `Any`, `Union[...]`, or `Literal[...]`. It provides a
21
+ way to pass these complex type expressions to functions expecting concrete types.
22
+
23
+ Example:
24
+ Instead of `output_type=Union[str, int]` (which may cause type errors),
25
+ use `output_type=TypeExpression[Union[str, int]]`.
26
+
27
+ Note:
28
+ This is a workaround for the lack of TypeForm in the Python type system.
29
+ """
30
+
31
+ pass
32
+
33
+
34
+ TypeOrTypeExpression = TypeAliasType('TypeOrTypeExpression', type[TypeExpression[T]] | type[T], type_params=(T,))
35
+ """Type alias allowing both direct types and TypeExpression wrappers.
36
+
37
+ This alias enables functions to accept either regular types (when compatible with type checkers)
38
+ or TypeExpression wrappers for complex type expressions. The correct type should be inferred
39
+ automatically in either case.
40
+ """
41
+
42
+
43
+ def unpack_type_expression(type_: TypeOrTypeExpression[T]) -> type[T]:
44
+ """Extract the actual type from a TypeExpression wrapper or return the type directly.
45
+
46
+ Args:
47
+ type_: Either a direct type or a TypeExpression wrapper.
48
+
49
+ Returns:
50
+ The unwrapped type, ready for use in runtime type operations.
51
+ """
52
+ if get_origin(type_) is TypeExpression:
53
+ return get_args(type_)[0]
54
+ return cast(type[T], type_)
55
+
56
+
57
+ @dataclass
58
+ class Some(Generic[T]):
59
+ """Container for explicitly present values in Maybe type pattern.
60
+
61
+ This class represents a value that is definitely present, as opposed to None.
62
+ It's part of the Maybe pattern, similar to Option/Maybe in functional programming,
63
+ allowing distinction between "no value" (None) and "value is None" (Some(None)).
64
+ """
65
+
66
+ value: T
67
+ """The wrapped value."""
68
+
69
+
70
+ Maybe = TypeAliasType('Maybe', Some[T] | None, type_params=(T,))
71
+ """Optional-like type that distinguishes between absence and None values.
72
+
73
+ Unlike Optional[T], Maybe[T] can differentiate between:
74
+ - No value present: represented as None
75
+ - Value is None: represented as Some(None)
76
+
77
+ This is particularly useful when None is a valid value in your domain.
78
+ """
79
+
80
+
81
+ def get_callable_name(callable_: Any) -> str:
82
+ """Extract a human-readable name from a callable object.
83
+
84
+ Args:
85
+ callable_: Any callable object (function, method, class, etc.).
86
+
87
+ Returns:
88
+ The callable's __name__ attribute if available, otherwise its string representation.
89
+ """
90
+ return getattr(callable_, '__name__', str(callable_))
@@ -15,6 +15,28 @@ class GraphSetupError(TypeError):
15
15
  super().__init__(message)
16
16
 
17
17
 
18
+ class GraphBuildingError(ValueError):
19
+ """An error raised during graph-building."""
20
+
21
+ message: str
22
+ """The error message."""
23
+
24
+ def __init__(self, message: str):
25
+ self.message = message
26
+ super().__init__(message)
27
+
28
+
29
+ class GraphValidationError(ValueError):
30
+ """An error raised during graph validation."""
31
+
32
+ message: str
33
+ """The error message."""
34
+
35
+ def __init__(self, message: str):
36
+ self.message = message
37
+ super().__init__(message)
38
+
39
+
18
40
  class GraphRuntimeError(RuntimeError):
19
41
  """Error caused by an issue during graph execution."""
20
42
 
pydantic_graph/graph.py CHANGED
@@ -6,33 +6,20 @@ from collections.abc import AsyncIterator, Sequence
6
6
  from contextlib import AbstractContextManager, ExitStack, asynccontextmanager
7
7
  from dataclasses import dataclass, field
8
8
  from functools import cached_property
9
+ from pathlib import Path
9
10
  from typing import Any, Generic, cast, overload
10
11
 
11
- import logfire_api
12
12
  import typing_extensions
13
13
  from typing_inspection import typing_objects
14
14
 
15
15
  from . import _utils, exceptions, mermaid
16
- from ._utils import AbstractSpan, get_traceparent
16
+ from ._utils import AbstractSpan, get_traceparent, logfire_span
17
17
  from .nodes import BaseNode, DepsT, End, GraphRunContext, NodeDef, RunEndT, StateT
18
18
  from .persistence import BaseStatePersistence
19
19
  from .persistence.in_mem import SimpleStatePersistence
20
20
 
21
- # while waiting for https://github.com/pydantic/logfire/issues/745
22
- try:
23
- import logfire._internal.stack_info
24
- except ImportError:
25
- pass
26
- else:
27
- from pathlib import Path
28
-
29
- logfire._internal.stack_info.NON_USER_CODE_PREFIXES += (str(Path(__file__).parent.absolute()),) # pyright: ignore[reportPrivateImportUsage]
30
-
31
-
32
21
  __all__ = 'Graph', 'GraphRun', 'GraphRunResult'
33
22
 
34
- _logfire = logfire_api.Logfire(otel_scope='pydantic-graph')
35
-
36
23
 
37
24
  @dataclass(init=False)
38
25
  class Graph(Generic[StateT, DepsT, RunEndT]):
@@ -44,7 +31,7 @@ class Graph(Generic[StateT, DepsT, RunEndT]):
44
31
  Here's a very simple example of a graph which increments a number by 1, but makes sure the number is never
45
32
  42 at the end.
46
33
 
47
- ```py {title="never_42.py" noqa="I001" py="3.10"}
34
+ ```py {title="never_42.py" noqa="I001"}
48
35
  from __future__ import annotations
49
36
 
50
37
  from dataclasses import dataclass
@@ -141,7 +128,7 @@ class Graph(Generic[StateT, DepsT, RunEndT]):
141
128
 
142
129
  Here's an example of running the graph from [above][pydantic_graph.graph.Graph]:
143
130
 
144
- ```py {title="run_never_42.py" noqa="I001" py="3.10" requires="never_42.py"}
131
+ ```py {title="run_never_42.py" noqa="I001" requires="never_42.py"}
145
132
  from never_42 import Increment, MyState, never_42_graph
146
133
 
147
134
  async def main():
@@ -251,8 +238,12 @@ class Graph(Generic[StateT, DepsT, RunEndT]):
251
238
  with ExitStack() as stack:
252
239
  entered_span: AbstractSpan | None = None
253
240
  if span is None:
254
- if self.auto_instrument:
255
- entered_span = stack.enter_context(logfire_api.span('run graph {graph.name}', graph=self))
241
+ if self.auto_instrument: # pragma: no branch
242
+ # Separate variable because we actually don't want logfire's f-string magic here,
243
+ # we want the span_name to be preformatted for other backends
244
+ # as requested in https://github.com/pydantic/pydantic-ai/issues/3173.
245
+ span_name = f'run graph {self.name}'
246
+ entered_span = stack.enter_context(logfire_span(span_name, graph=self))
256
247
  else:
257
248
  entered_span = stack.enter_context(span)
258
249
  traceparent = None if entered_span is None else get_traceparent(entered_span)
@@ -301,7 +292,7 @@ class Graph(Generic[StateT, DepsT, RunEndT]):
301
292
  snapshot.node.set_snapshot_id(snapshot.id)
302
293
 
303
294
  if self.auto_instrument and span is None: # pragma: no branch
304
- span = logfire_api.span('run graph {graph.name}', graph=self)
295
+ span = logfire_span('run graph {graph.name}', graph=self)
305
296
 
306
297
  with ExitStack() as stack:
307
298
  entered_span = None if span is None else stack.enter_context(span)
@@ -372,7 +363,7 @@ class Graph(Generic[StateT, DepsT, RunEndT]):
372
363
 
373
364
  Here's an example of generating a diagram for the graph from [above][pydantic_graph.graph.Graph]:
374
365
 
375
- ```py {title="mermaid_never_42.py" py="3.10" requires="never_42.py"}
366
+ ```py {title="mermaid_never_42.py" requires="never_42.py"}
376
367
  from never_42 import Increment, never_42_graph
377
368
 
378
369
  print(never_42_graph.mermaid_code(start_node=Increment))
@@ -562,7 +553,7 @@ class GraphRun(Generic[StateT, DepsT, RunEndT]):
562
553
  through nodes as they run, either by `async for` iteration or by repeatedly calling `.next(...)`.
563
554
 
564
555
  Here's an example of iterating over the graph from [above][pydantic_graph.graph.Graph]:
565
- ```py {title="iter_never_42.py" noqa="I001" py="3.10" requires="never_42.py"}
556
+ ```py {title="iter_never_42.py" noqa="I001" requires="never_42.py"}
566
557
  from copy import deepcopy
567
558
  from never_42 import Increment, MyState, never_42_graph
568
559
 
@@ -678,7 +669,7 @@ class GraphRun(Generic[StateT, DepsT, RunEndT]):
678
669
  under dynamic conditions. The graph run should stop when you return an [`End`][pydantic_graph.nodes.End] node.
679
670
 
680
671
  Here's an example of using `next` to drive the graph from [above][pydantic_graph.graph.Graph]:
681
- ```py {title="next_never_42.py" noqa="I001" py="3.10" requires="never_42.py"}
672
+ ```py {title="next_never_42.py" noqa="I001" requires="never_42.py"}
682
673
  from copy import deepcopy
683
674
  from pydantic_graph import End
684
675
  from never_42 import Increment, MyState, never_42_graph
@@ -736,11 +727,15 @@ class GraphRun(Generic[StateT, DepsT, RunEndT]):
736
727
  raise exceptions.GraphRuntimeError(f'Node `{node}` is not in the graph.')
737
728
 
738
729
  with ExitStack() as stack:
739
- if self.graph.auto_instrument:
740
- stack.enter_context(_logfire.span('run node {node_id}', node_id=node_id, node=node))
730
+ if self.graph.auto_instrument: # pragma: no branch
731
+ # Separate variable because we actually don't want logfire's f-string magic here,
732
+ # we want the span_name to be preformatted for other backends
733
+ # as requested in https://github.com/pydantic/pydantic-ai/issues/3173.
734
+ span_name = f'run node {node_id}'
735
+ stack.enter_context(logfire_span(span_name, node_id=node_id, node=node))
741
736
 
742
737
  async with self.persistence.record_run(node_snapshot_id):
743
- ctx = GraphRunContext(self.state, self.deps)
738
+ ctx = GraphRunContext(state=self.state, deps=self.deps)
744
739
  self._next_node = await node.run(ctx)
745
740
 
746
741
  if isinstance(self._next_node, End):
pydantic_graph/mermaid.py CHANGED
@@ -5,11 +5,11 @@ import re
5
5
  from collections.abc import Iterable, Sequence
6
6
  from pathlib import Path
7
7
  from textwrap import indent
8
- from typing import TYPE_CHECKING, Annotated, Any, Literal
8
+ from typing import TYPE_CHECKING, Annotated, Any, Literal, TypeAlias
9
9
 
10
10
  import httpx
11
11
  from annotated_types import Ge, Le
12
- from typing_extensions import TypeAlias, TypedDict, Unpack
12
+ from typing_extensions import TypedDict, Unpack
13
13
 
14
14
  from .nodes import BaseNode
15
15
 
pydantic_graph/nodes.py CHANGED
@@ -4,10 +4,10 @@ import copy
4
4
  from abc import ABC, abstractmethod
5
5
  from dataclasses import dataclass, is_dataclass
6
6
  from functools import cache
7
- from typing import Any, ClassVar, Generic, get_type_hints
7
+ from typing import Any, ClassVar, Generic, get_origin, get_type_hints
8
8
  from uuid import uuid4
9
9
 
10
- from typing_extensions import Never, Self, TypeVar, get_origin
10
+ from typing_extensions import Never, Self, TypeVar
11
11
 
12
12
  from . import _utils, exceptions
13
13
 
@@ -24,12 +24,10 @@ DepsT = TypeVar('DepsT', default=None, contravariant=True)
24
24
  """Type variable for the dependencies of a graph and node."""
25
25
 
26
26
 
27
- @dataclass
27
+ @dataclass(kw_only=True)
28
28
  class GraphRunContext(Generic[StateT, DepsT]):
29
29
  """Context for a graph."""
30
30
 
31
- # TODO: Can we get rid of this struct and just pass both these things around..?
32
-
33
31
  state: StateT
34
32
  """The state of the graph."""
35
33
  deps: DepsT
@@ -121,7 +119,6 @@ class BaseNode(ABC, Generic[StateT, DepsT, NodeRunEndT]):
121
119
  if return_type_origin is End:
122
120
  end_edge = edge
123
121
  elif return_type_origin is BaseNode:
124
- # TODO: Should we disallow this?
125
122
  returns_base_node = True
126
123
  elif issubclass(return_type_origin, BaseNode):
127
124
  next_node_edges[return_type.get_node_id()] = edge
@@ -129,12 +126,12 @@ class BaseNode(ABC, Generic[StateT, DepsT, NodeRunEndT]):
129
126
  raise exceptions.GraphSetupError(f'Invalid return type: {return_type}')
130
127
 
131
128
  return NodeDef(
132
- cls,
133
- cls.get_node_id(),
134
- cls.get_note(),
135
- next_node_edges,
136
- end_edge,
137
- returns_base_node,
129
+ node=cls,
130
+ node_id=cls.get_node_id(),
131
+ note=cls.get_note(),
132
+ next_node_edges=next_node_edges,
133
+ end_edge=end_edge,
134
+ returns_base_node=returns_base_node,
138
135
  )
139
136
 
140
137
  def deep_copy(self) -> Self:
@@ -182,7 +179,7 @@ class Edge:
182
179
  """Label for the edge."""
183
180
 
184
181
 
185
- @dataclass
182
+ @dataclass(kw_only=True)
186
183
  class NodeDef(Generic[StateT, DepsT, NodeRunEndT]):
187
184
  """Definition of a node.
188
185
 
@@ -4,7 +4,7 @@ from abc import ABC, abstractmethod
4
4
  from contextlib import AbstractAsyncContextManager
5
5
  from dataclasses import dataclass, field
6
6
  from datetime import datetime
7
- from typing import TYPE_CHECKING, Annotated, Any, Generic, Literal, Union
7
+ from typing import TYPE_CHECKING, Annotated, Any, Generic, Literal
8
8
 
9
9
  import pydantic
10
10
  from typing_extensions import TypeVar
@@ -41,7 +41,7 @@ SnapshotStatus = Literal['created', 'pending', 'running', 'success', 'error']
41
41
  """
42
42
 
43
43
 
44
- @dataclass
44
+ @dataclass(kw_only=True)
45
45
  class NodeSnapshot(Generic[StateT, RunEndT]):
46
46
  """History step describing the execution of a node in a graph."""
47
47
 
@@ -66,7 +66,7 @@ class NodeSnapshot(Generic[StateT, RunEndT]):
66
66
  self.id = self.node.get_snapshot_id()
67
67
 
68
68
 
69
- @dataclass
69
+ @dataclass(kw_only=True)
70
70
  class EndSnapshot(Generic[StateT, RunEndT]):
71
71
  """History step describing the end of a graph run."""
72
72
 
@@ -95,7 +95,7 @@ class EndSnapshot(Generic[StateT, RunEndT]):
95
95
  return self.result
96
96
 
97
97
 
98
- Snapshot = Union[NodeSnapshot[StateT, RunEndT], EndSnapshot[StateT, RunEndT]]
98
+ Snapshot = NodeSnapshot[StateT, RunEndT] | EndSnapshot[StateT, RunEndT]
99
99
  """A step in the history of a graph run.
100
100
 
101
101
  [`Graph.run`][pydantic_graph.graph.Graph.run] returns a list of these steps describing the execution of the graph,
@@ -31,7 +31,7 @@ class CustomNodeSchema:
31
31
  nodes_type = nodes[0]
32
32
  else:
33
33
  nodes_annotated = [Annotated[node, pydantic.Tag(node.get_node_id())] for node in nodes]
34
- nodes_type = Annotated[Union[tuple(nodes_annotated)], pydantic.Discriminator(self._node_discriminator)]
34
+ nodes_type = Annotated[Union[tuple(nodes_annotated)], pydantic.Discriminator(self._node_discriminator)] # noqa: UP007
35
35
 
36
36
  schema = handler(nodes_type)
37
37
  schema['serialization'] = core_schema.wrap_serializer_function_ser_schema(
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations as _annotations
2
2
 
3
- import asyncio
4
3
  import secrets
5
4
  from collections.abc import AsyncIterator
6
5
  from contextlib import AsyncExitStack, asynccontextmanager
@@ -9,6 +8,7 @@ from pathlib import Path
9
8
  from time import perf_counter
10
9
  from typing import Any
11
10
 
11
+ import anyio
12
12
  import pydantic
13
13
 
14
14
  from .. import _utils as _graph_utils, exceptions
@@ -155,24 +155,23 @@ class FileStatePersistence(BaseStatePersistence[StateT, RunEndT]):
155
155
  """
156
156
  lock_file = self.json_file.parent / f'{self.json_file.name}.pydantic-graph-persistence-lock'
157
157
  lock_id = secrets.token_urlsafe().encode()
158
- await asyncio.wait_for(_get_lock(lock_file, lock_id), timeout=timeout)
158
+
159
+ with anyio.fail_after(timeout):
160
+ while not await _file_append_check(lock_file, lock_id):
161
+ await anyio.sleep(0.01)
162
+
159
163
  try:
160
164
  yield
161
165
  finally:
162
166
  await _graph_utils.run_in_executor(lock_file.unlink, missing_ok=True)
163
167
 
164
168
 
165
- async def _get_lock(lock_file: Path, lock_id: bytes):
166
- # TODO replace with inline code and `asyncio.timeout` when we drop 3.9
167
- while not await _graph_utils.run_in_executor(_file_append_check, lock_file, lock_id):
168
- await asyncio.sleep(0.01)
169
-
170
-
171
- def _file_append_check(file: Path, content: bytes) -> bool:
172
- if file.exists():
169
+ async def _file_append_check(file: Path, content: bytes) -> bool:
170
+ path = anyio.Path(file)
171
+ if await path.exists():
173
172
  return False
174
173
 
175
- with file.open(mode='ab') as f:
176
- f.write(content + b'\n')
174
+ async with await anyio.open_file(path, mode='ab') as f:
175
+ await f.write(content + b'\n')
177
176
 
178
- return file.read_bytes().startswith(content)
177
+ return (await path.read_bytes()).startswith(content)
@@ -65,7 +65,7 @@ class SimpleStatePersistence(BaseStatePersistence[StateT, RunEndT]):
65
65
  start = perf_counter()
66
66
  try:
67
67
  yield
68
- except Exception:
68
+ except Exception: # pragma: no cover
69
69
  self.last_snapshot.duration = perf_counter() - start
70
70
  self.last_snapshot.status = 'error'
71
71
  raise
@@ -76,7 +76,7 @@ class SimpleStatePersistence(BaseStatePersistence[StateT, RunEndT]):
76
76
  async def load_next(self) -> NodeSnapshot[StateT, RunEndT] | None:
77
77
  if isinstance(self.last_snapshot, NodeSnapshot) and self.last_snapshot.status == 'created':
78
78
  self.last_snapshot.status = 'pending'
79
- return self.last_snapshot
79
+ return copy.deepcopy(self.last_snapshot)
80
80
 
81
81
  async def load_all(self) -> list[Snapshot[StateT, RunEndT]]:
82
82
  raise NotImplementedError('load is not supported for SimpleStatePersistence')
@@ -143,7 +143,7 @@ class FullStatePersistence(BaseStatePersistence[StateT, RunEndT]):
143
143
  async def load_next(self) -> NodeSnapshot[StateT, RunEndT] | None:
144
144
  if snapshot := next((s for s in self.history if isinstance(s, NodeSnapshot) and s.status == 'created'), None):
145
145
  snapshot.status = 'pending'
146
- return snapshot
146
+ return copy.deepcopy(snapshot)
147
147
 
148
148
  async def load_all(self) -> list[Snapshot[StateT, RunEndT]]:
149
149
  return self.history
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydantic-graph
3
- Version: 0.7.5
3
+ Version: 1.24.0
4
4
  Summary: Graph and state machine library
5
5
  Project-URL: Homepage, https://ai.pydantic.dev/graph/tree/main/pydantic_graph
6
6
  Project-URL: Source, https://github.com/pydantic/pydantic-ai
@@ -9,7 +9,7 @@ Project-URL: Changelog, https://github.com/pydantic/pydantic-ai/releases
9
9
  Author-email: Samuel Colvin <samuel@pydantic.dev>, Marcelo Trylesinski <marcelotryle@gmail.com>, David Montague <david@pydantic.dev>, Alex Hall <alex@pydantic.dev>, Douwe Maan <douwe@pydantic.dev>
10
10
  License-Expression: MIT
11
11
  License-File: LICENSE
12
- Classifier: Development Status :: 4 - Beta
12
+ Classifier: Development Status :: 5 - Production/Stable
13
13
  Classifier: Environment :: Console
14
14
  Classifier: Environment :: MacOS X
15
15
  Classifier: Intended Audience :: Developers
@@ -21,14 +21,13 @@ Classifier: Operating System :: Unix
21
21
  Classifier: Programming Language :: Python
22
22
  Classifier: Programming Language :: Python :: 3
23
23
  Classifier: Programming Language :: Python :: 3 :: Only
24
- Classifier: Programming Language :: Python :: 3.9
25
24
  Classifier: Programming Language :: Python :: 3.10
26
25
  Classifier: Programming Language :: Python :: 3.11
27
26
  Classifier: Programming Language :: Python :: 3.12
28
27
  Classifier: Programming Language :: Python :: 3.13
29
28
  Classifier: Topic :: Internet
30
29
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
31
- Requires-Python: >=3.9
30
+ Requires-Python: >=3.10
32
31
  Requires-Dist: httpx>=0.27
33
32
  Requires-Dist: logfire-api>=3.14.1
34
33
  Requires-Dist: pydantic>=2.10
@@ -56,7 +55,7 @@ Full documentation is available at [ai.pydantic.dev/graph](https://ai.pydantic.d
56
55
 
57
56
  Here's a basic example:
58
57
 
59
- ```python {noqa="I001" py="3.10"}
58
+ ```python {noqa="I001"}
60
59
  from __future__ import annotations
61
60
 
62
61
  from dataclasses import dataclass
@@ -0,0 +1,28 @@
1
+ pydantic_graph/__init__.py,sha256=qkrSmWLpnNhD7mLBWV70iS46vy2vFiU2zUModG31wPQ,593
2
+ pydantic_graph/_utils.py,sha256=f0B1VIRxfAslj5UIfBVRzXhIJkDXyF8P3B9V22Q7o7U,6782
3
+ pydantic_graph/exceptions.py,sha256=aeaBf2H18dV7YCNZKZmiXiI6Fyys2qQdunZwd7TSCPk,1648
4
+ pydantic_graph/graph.py,sha256=rEm_5PzRs-5k6Y0mmaF5SGhF0wPA2JSclNAEZtBUZpA,33942
5
+ pydantic_graph/mermaid.py,sha256=u8xM8eEAOWV0TkqEAPJJ9jL2XEZnJ_H7yNGhulg7SL4,10045
6
+ pydantic_graph/nodes.py,sha256=CkY3lrC6jqZtzwhSRjFzmM69TdFFFrr58XSDU4THKHA,7450
7
+ pydantic_graph/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ pydantic_graph/beta/__init__.py,sha256=VVmbEFaCSXYHwXqS4pANg4B3cn_c86tT62tW_EXcuyw,751
9
+ pydantic_graph/beta/decision.py,sha256=x-Ta549b-j5hyBPUWFdwRQDRaJqnBHF1pfBP9L8I3vI,11239
10
+ pydantic_graph/beta/graph.py,sha256=-T-HbVyBC3qgg_-dXURnCbI6K_mqj25jDVh_RMlVsS8,42811
11
+ pydantic_graph/beta/graph_builder.py,sha256=2sD7TR8oGg4Gatrms0jE17NXzQN7drzUvaJKs5BvILU,43329
12
+ pydantic_graph/beta/id_types.py,sha256=FZ3rYSubF6g_Ocv0faL3yJsy1lNN9AGZl9f_izvORUg,2814
13
+ pydantic_graph/beta/join.py,sha256=rzCumDX_YgaU_a5bisfbjbbOuI3IwSZsCZs9TC0T9E4,8002
14
+ pydantic_graph/beta/mermaid.py,sha256=vpB9laZeTaS-P6BJplyN7DLFz0ppRVafGjBfqRiTh-s,7128
15
+ pydantic_graph/beta/node.py,sha256=cTEGKiT3Lutg-PWxBbZDihpnBTVoPMSyCbfB50fjKeY,3071
16
+ pydantic_graph/beta/node_types.py,sha256=Ha1QPbAHqmJ1ARb359b8LOJK-jZDMO_ZyHkYv9Zbglw,3399
17
+ pydantic_graph/beta/parent_forks.py,sha256=lMCT3slwDuZtiLZImqXuW-i0ZftONCWGr7RTpCAe9dY,9691
18
+ pydantic_graph/beta/paths.py,sha256=LkFvgnyNa1lHdFkN83F7Dgsdg9Q2y0zYrLyqprQiQiY,16068
19
+ pydantic_graph/beta/step.py,sha256=n0JstmxM6Z2rCc2EPUrSAp4MS4IjM2mZsE0ymeekzxU,8683
20
+ pydantic_graph/beta/util.py,sha256=F7IkSC0U-tU1yOxncslyOrZ5HlrZIdafBJARsPetIHQ,3153
21
+ pydantic_graph/persistence/__init__.py,sha256=NLBGvUWhem23EdMHHxtX0XgTS2vyixmuWtWmZKj_U58,8968
22
+ pydantic_graph/persistence/_utils.py,sha256=6ySxCc1lFz7bbLUwDLkoZWNqi8VNLBVU4xxJbKI23fQ,2264
23
+ pydantic_graph/persistence/file.py,sha256=XZy295cGc86HfUl_KuB-e7cECZW3bubiEdyJMVQ1OD0,6906
24
+ pydantic_graph/persistence/in_mem.py,sha256=MmahaVpdzmDB30Dm3ZfSCZBqgmx6vH4HXdBaWwVF0K0,6799
25
+ pydantic_graph-1.24.0.dist-info/METADATA,sha256=MuevkYyRJr96QAs8gcaDetAButYgPY35d89YQ7Ruluw,3895
26
+ pydantic_graph-1.24.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
27
+ pydantic_graph-1.24.0.dist-info/licenses/LICENSE,sha256=vA6Jc482lEyBBuGUfD1pYx-cM7jxvLYOxPidZ30t_PQ,1100
28
+ pydantic_graph-1.24.0.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- pydantic_graph/__init__.py,sha256=qkrSmWLpnNhD7mLBWV70iS46vy2vFiU2zUModG31wPQ,593
2
- pydantic_graph/_utils.py,sha256=ILCwHA0dbtza9THIuoI-LT2IJWSGVp1yFu3uVxb44R4,4482
3
- pydantic_graph/exceptions.py,sha256=OUz0YaUHG9CqHYvV4uU4mwF-E2GQCLWKjsWZBu3sMe8,1164
4
- pydantic_graph/graph.py,sha256=gA6PhG_ObnazqP16Wydoj86guyemfyBnRyYVK9zATwQ,33694
5
- pydantic_graph/mermaid.py,sha256=4ejbx5ikAx_AW_KxoTY8c-lEp1CHyj8YppJsMn26kzo,10045
6
- pydantic_graph/nodes.py,sha256=wPrB1EjMRF_l8K-UK62YSOoNdpp51w5R3Iai5qdXzG8,7495
7
- pydantic_graph/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- pydantic_graph/persistence/__init__.py,sha256=7cWYcSjXHYeRMZ0Q6uPdaU1yCbM_DS9BJQppt1WTmlk,8953
9
- pydantic_graph/persistence/_utils.py,sha256=g-AFyJ3ku1m4gH2Ko51qr1Lnx03IciZeztUQvQSKgAE,2249
10
- pydantic_graph/persistence/file.py,sha256=aJ6GhuZRcsKPvYaf6uuQpnA4i_e3Wkd_4Zo7MBTo3-s,7014
11
- pydantic_graph/persistence/in_mem.py,sha256=OAY8KNolwqRhN10I4R9JCXTim1uE88Hz_-LplvqAcKk,6749
12
- pydantic_graph-0.7.5.dist-info/METADATA,sha256=oir_-Eai4TDepWYaEMkVqgLocgDYkld4nX4pn59Hf_Q,3940
13
- pydantic_graph-0.7.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
- pydantic_graph-0.7.5.dist-info/licenses/LICENSE,sha256=vA6Jc482lEyBBuGUfD1pYx-cM7jxvLYOxPidZ30t_PQ,1100
15
- pydantic_graph-0.7.5.dist-info/RECORD,,