graph
¶
Utilities for working with types as graphs.
Typical Usage
>>> import dataclasses
>>> from typelib import graph
>>> graph.static_order(dict[str, str])
[TypeNode(type=<class 'str'>, var=None, cyclic=False), TypeNode(type=dict[str, str], var=None, cyclic=False)]
>>>
>>> @dataclasses.dataclass
... class Class:
... attr: str
...
>>> graph.static_order(Class)
[TypeNode(type=<class 'str'>, var='attr', cyclic=False), TypeNode(type=<class '__main__.Class'>, var=None, cyclic=False)]
TypeNode
dataclass
¶
get_type_graph
¶
get_type_graph(t: type) -> TopologicalSorter[TypeNode]
Get a directed graph of the type(s) this annotation represents,
Parameters:
-
t
(type
) –A type annotation.
Returns:
Note
A key aspect of building a directed graph of a given type is pre-emptive
detection and termination of cycles in the graph. If we detect a cycle, we
will wrap the type in a typing.ForwardRef
and mark the
TypeNode
instance as cyclic=True
.
Consumers of the graph can "delay" the resolution of a forward reference until
the graph's static_order()
has been exhausted, at which point they have
enough type information to resolve into the real type. (At least one layer down).
Resolution of cyclic/recursive types is always (necessarily) lazy and should only resolve one level deep on each attempt, otherwise we will find ourselves stuck in a closed loop which never terminates (infinite recursion).
Source code in src/typelib/graph.py
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
|
itertypes
¶
Iterate over the type-graph represented by t
from edges to root.
Parameters:
Yields:
Note
We will build a graph of types with the given type t
as the root node,
then iterate from the outermost leaves back to the root using BFS.
This is computationally expensive, so you are encouraged to use
static_order
instead of
itertypes
.
Source code in src/typelib/graph.py
static_order
¶
Get an ordered iterable of types which resolve into the root type provided.
Parameters:
Note
The order of types is guaranteed to rank from edges to root. If there are multiple edges, the order of those edges is not guaranteed.
This function is memoized to avoid the cost of re-computing a type annotation multiple times at runtime, which would be wasted effort, as types don't change at runtime.
To avoid memoization, you can make use of itertypes
.