[ty] Add flow diagram for import resolution

The diagram is written in the Dot language, which can
be converted to SVG (or any other image) by GraphViz.

I thought it was a good idea to write this down in
preparation for adding routines that list modules.
Code reuse is likely to be difficult and I wanted to
be sure I understood how it worked.
This commit is contained in:
Andrew Gallant 2025-07-29 13:18:16 -04:00 committed by Andrew Gallant
parent 941be52358
commit 88a679945c
3 changed files with 447 additions and 0 deletions

View file

@ -0,0 +1,141 @@
// This is a Dot representation of a flow diagram meant to describe Python's
// import resolution rules. This particular diagram starts with one particular
// search path and one particular module name. (Typical import resolution
// implementation will try multiple search paths.)
//
// This diagram also assumes that stubs are allowed. The ty implementation
// of import resolution makes this a configurable parameter, but it should
// be straight-forward to adapt this flow diagram to one where no stubs
// are allowed. (i.e., Remove `.pyi` checks and remove the `package-stubs`
// handling.)
//
// This flow diagram exists to act as a sort of specification. At the time
// of writing (2025-07-29), it was written to capture the implementation of
// resolving a *particular* module name. We wanted to add another code path for
// *listing* available module names. Since code reuse is somewhat difficult
// between these two access patterns, I wrote this flow diagram as a way of 1)
// learning how module resolution works and 2) to provide a "source of truth"
// that we can compare implementations to.
//
// To convert this file into an actual image, you'll need the `dot` program
// (which is typically part of a `graphviz` package in a Linux distro):
//
// dot -Tsvg import-resolution-diagram.dot > import-resolution-diagram.svg
//
// And then view it in a web browser (or some other svg viewer):
//
// firefox ./import-resolution-diagram.svg
//
// [Dot]: https://graphviz.org/doc/info/lang.html
digraph python_import_resolution {
labelloc="t";
label=<
<b>Python import resolution flow diagram for a single module name in a single "search path"</b>
<br/>(assumes that the module name is valid and that stubs are allowed)
>;
// These are the final affirmative states we can end up in. A
// module is a regular `foo.py` file module. A package is a
// directory containing an `__init__.py`. A namespace package is a
// directory that does *not* contain an `__init__.py`.
module [label="Single-file Module",peripheries=2];
package [label="Package",peripheries=2];
namespace_package [label="Namespace Package",peripheries=2];
not_found [label="Module Not Found",peripheries=2];
// The final states are wrapped in a subgraph with invisible edges
// to convince GraphViz to give a more human digestible rendering.
// Without this, the nodes are scattered every which way and the
// flow diagram is pretty hard to follow. This encourages (but does
// not guarantee) GraphViz to put these nodes "close" together, and
// this generally gets us something grokable.
subgraph final {
rank = same;
module -> package -> namespace_package -> not_found [style=invis];
}
START [label=<<b>START</b>>];
START -> non_shadowable;
non_shadowable [label=<
Is the search path not the standard library and<br/>
the module name is `types` or some other built-in?
>];
non_shadowable -> not_found [label="Yes"];
non_shadowable -> stub_package_check [label="No"];
stub_package_check [label=<
Is the search path in the standard library?
>];
stub_package_check -> stub_package_set [label="No"];
stub_package_check -> determine_parent_kind [label="Yes"];
stub_package_set [label=<
Set `module_name` to `{top-package}-stubs.{rest}`
>];
stub_package_set -> determine_parent_kind;
determine_parent_kind [label=<
Does every parent package of `module_name`<br/>
correspond to a directory that contains an<br/>
`__init__.py` or an `__init__.pyi`?
>];
determine_parent_kind -> maybe_package [label="Yes"];
determine_parent_kind -> namespace_parent1 [label="No"];
namespace_parent1 [label=<
Is the direct parent package<br/>
a directory that contains<br/>
an `__init__.py` or `__init__.pyi`?
>];
namespace_parent1 -> bail [label="Yes"];
namespace_parent1 -> namespace_parent2 [label="No"];
namespace_parent2 [label=<
Does the direct parent package<br/>
have a sibling file with the same<br/>
basename and a `py` or `pyi` extension?<br/>
>];
namespace_parent2 -> bail [label="Yes"];
namespace_parent2 -> namespace_parent3 [label="No"];
namespace_parent3 [label=<
Is every parent above the direct<br/>
parent package a normal package or<br/>
otherwise satisfy the previous two<br/>
namespace package requirements?
>];
namespace_parent3 -> bail [label="No"];
namespace_parent3 -> maybe_package [label="Yes"];
maybe_package [label=<
After replacing `.` with `/` in module name,<br/>
does `{path}/__init__.py` or `{path}/__init__.pyi` exist?
>];
maybe_package -> package [label="Yes"];
maybe_package -> maybe_module [label="No"];
maybe_module [label=<
Does `{path}.py` or `{path}.pyi` exist?
>];
maybe_module -> module [label="Yes"];
maybe_module -> maybe_namespace [label="No"];
maybe_namespace [label=<
Is `{path}` a directory?
>];
maybe_namespace -> namespace_package [label="Yes"];
maybe_namespace -> bail [label="No"];
bail [label=<
Is `module_name` set to a stub package candidate?
>];
bail -> not_found [label="No"];
bail -> retry [label="Yes"];
retry [label=<
Reset `module_name` to original
>];
retry -> determine_parent_kind;
}

View file

@ -0,0 +1,296 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 13.0.1 (0)
-->
<!-- Title: python_import_resolution Pages: 1 -->
<svg width="1463pt" height="1417pt"
viewBox="0.00 0.00 1463.00 1417.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1413.5)">
<title>python_import_resolution</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-1413.5 1458.95,-1413.5 1458.95,4 -4,4"/>
<text xml:space="preserve" text-anchor="start" x="337.85" y="-1393.2" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;</text>
<text xml:space="preserve" text-anchor="start" x="373.85" y="-1393.2" font-family="Times,serif" font-weight="bold" font-size="14.00">Python import resolution flow diagram for a single module name in a single &quot;search path&quot;</text>
<text xml:space="preserve" text-anchor="start" x="1081.1" y="-1393.2" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;</text>
<text xml:space="preserve" text-anchor="start" x="476.23" y="-1379.2" font-family="Times,serif" font-size="14.00">(assumes that the module name is valid and that stubs are allowed) &#160;&#160;&#160;</text>
<!-- module -->
<g id="node1" class="node">
<title>module</title>
<ellipse fill="none" stroke="black" cx="105.71" cy="-22" rx="101.71" ry="18"/>
<ellipse fill="none" stroke="black" cx="105.71" cy="-22" rx="105.71" ry="22"/>
<text xml:space="preserve" text-anchor="middle" x="105.71" y="-17.32" font-family="Times,serif" font-size="14.00">Single&#45;file Module</text>
</g>
<!-- package -->
<g id="node2" class="node">
<title>package</title>
<ellipse fill="none" stroke="black" cx="302.71" cy="-22" rx="52.26" ry="18"/>
<ellipse fill="none" stroke="black" cx="302.71" cy="-22" rx="56.26" ry="22"/>
<text xml:space="preserve" text-anchor="middle" x="302.71" y="-17.32" font-family="Times,serif" font-size="14.00">Package</text>
</g>
<!-- module&#45;&gt;package -->
<!-- namespace_package -->
<g id="node3" class="node">
<title>namespace_package</title>
<ellipse fill="none" stroke="black" cx="511.71" cy="-22" rx="113.29" ry="18"/>
<ellipse fill="none" stroke="black" cx="511.71" cy="-22" rx="117.29" ry="22"/>
<text xml:space="preserve" text-anchor="middle" x="511.71" y="-17.32" font-family="Times,serif" font-size="14.00">Namespace Package</text>
</g>
<!-- package&#45;&gt;namespace_package -->
<!-- not_found -->
<g id="node4" class="node">
<title>not_found</title>
<ellipse fill="none" stroke="black" cx="1200.71" cy="-22" rx="104.35" ry="18"/>
<ellipse fill="none" stroke="black" cx="1200.71" cy="-22" rx="108.35" ry="22"/>
<text xml:space="preserve" text-anchor="middle" x="1200.71" y="-17.32" font-family="Times,serif" font-size="14.00">Module Not Found</text>
</g>
<!-- namespace_package&#45;&gt;not_found -->
<!-- START -->
<g id="node5" class="node">
<title>START</title>
<ellipse fill="none" stroke="black" cx="1147.71" cy="-1355.5" rx="47.53" ry="18"/>
<text xml:space="preserve" text-anchor="start" x="1121.84" y="-1351.82" font-family="Times,serif" font-weight="bold" font-size="14.00">START</text>
</g>
<!-- non_shadowable -->
<g id="node6" class="node">
<title>non_shadowable</title>
<ellipse fill="none" stroke="black" cx="1147.71" cy="-1270.44" rx="307.24" ry="30.05"/>
<text xml:space="preserve" text-anchor="start" x="961.71" y="-1274.39" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;Is the search path not the standard library and</text>
<text xml:space="preserve" text-anchor="start" x="938.46" y="-1257.14" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;the module name is `types` or some other built&#45;in? &#160;&#160;&#160;</text>
</g>
<!-- START&#45;&gt;non_shadowable -->
<g id="edge4" class="edge">
<title>START&#45;&gt;non_shadowable</title>
<path fill="none" stroke="black" d="M1147.71,-1337.29C1147.71,-1329.95 1147.71,-1321.06 1147.71,-1312.21"/>
<polygon fill="black" stroke="black" points="1151.21,-1312.25 1147.71,-1302.25 1144.21,-1312.25 1151.21,-1312.25"/>
</g>
<!-- non_shadowable&#45;&gt;not_found -->
<g id="edge5" class="edge">
<title>non_shadowable&#45;&gt;not_found</title>
<path fill="none" stroke="black" d="M1192.48,-1240.23C1213.37,-1222.8 1233.71,-1198.54 1233.71,-1170.14 1233.71,-1170.14 1233.71,-1170.14 1233.71,-114.25 1233.71,-93.46 1226.05,-71.52 1218.11,-54.36"/>
<polygon fill="black" stroke="black" points="1221.41,-53.14 1213.86,-45.7 1215.12,-56.22 1221.41,-53.14"/>
<text xml:space="preserve" text-anchor="middle" x="1245.71" y="-609.2" font-family="Times,serif" font-size="14.00">Yes</text>
</g>
<!-- stub_package_check -->
<g id="node7" class="node">
<title>stub_package_check</title>
<ellipse fill="none" stroke="black" cx="892.71" cy="-1169.14" rx="261.65" ry="18"/>
<text xml:space="preserve" text-anchor="start" x="714.21" y="-1164.47" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;Is the search path in the standard library? &#160;&#160;&#160;</text>
</g>
<!-- non_shadowable&#45;&gt;stub_package_check -->
<g id="edge6" class="edge">
<title>non_shadowable&#45;&gt;stub_package_check</title>
<path fill="none" stroke="black" d="M1074.3,-1240.85C1033.86,-1225.11 984.5,-1205.89 947.46,-1191.46"/>
<polygon fill="black" stroke="black" points="948.87,-1188.25 938.28,-1187.89 946.33,-1194.78 948.87,-1188.25"/>
<text xml:space="preserve" text-anchor="middle" x="1030.34" y="-1209.09" font-family="Times,serif" font-size="14.00">No</text>
</g>
<!-- stub_package_set -->
<g id="node8" class="node">
<title>stub_package_set</title>
<ellipse fill="none" stroke="black" cx="892.71" cy="-1079.89" rx="312.68" ry="18"/>
<text xml:space="preserve" text-anchor="start" x="677.84" y="-1075.22" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;Set `module_name` to `{top&#45;package}&#45;stubs.{rest}` &#160;&#160;&#160;</text>
</g>
<!-- stub_package_check&#45;&gt;stub_package_set -->
<g id="edge7" class="edge">
<title>stub_package_check&#45;&gt;stub_package_set</title>
<path fill="none" stroke="black" d="M892.71,-1150.9C892.71,-1139.07 892.71,-1123.1 892.71,-1109.39"/>
<polygon fill="black" stroke="black" points="896.21,-1109.61 892.71,-1099.61 889.21,-1109.61 896.21,-1109.61"/>
<text xml:space="preserve" text-anchor="middle" x="902.84" y="-1119.84" font-family="Times,serif" font-size="14.00">No</text>
</g>
<!-- determine_parent_kind -->
<g id="node9" class="node">
<title>determine_parent_kind</title>
<ellipse fill="none" stroke="black" cx="833.71" cy="-982.64" rx="269.05" ry="42.25"/>
<text xml:space="preserve" text-anchor="start" x="651.46" y="-995.22" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;Does every parent package of `module_name`</text>
<text xml:space="preserve" text-anchor="start" x="664.96" y="-977.97" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;correspond to a directory that contains an</text>
<text xml:space="preserve" text-anchor="start" x="691.59" y="-960.72" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;`__init__.py` or an `__init__.pyi`? &#160;&#160;&#160;</text>
</g>
<!-- stub_package_check&#45;&gt;determine_parent_kind -->
<g id="edge8" class="edge">
<title>stub_package_check&#45;&gt;determine_parent_kind</title>
<path fill="none" stroke="black" d="M729.85,-1154.72C652.04,-1144.58 570.67,-1127.2 546.71,-1097.89 511.98,-1055.39 550.89,-1028.61 610.12,-1011.78"/>
<polygon fill="black" stroke="black" points="610.79,-1015.22 619.54,-1009.24 608.97,-1008.46 610.79,-1015.22"/>
<text xml:space="preserve" text-anchor="middle" x="558.71" y="-1075.22" font-family="Times,serif" font-size="14.00">Yes</text>
</g>
<!-- stub_package_set&#45;&gt;determine_parent_kind -->
<g id="edge9" class="edge">
<title>stub_package_set&#45;&gt;determine_parent_kind</title>
<path fill="none" stroke="black" d="M881.89,-1061.42C877.15,-1053.77 871.32,-1044.35 865.37,-1034.74"/>
<polygon fill="black" stroke="black" points="868.45,-1033.07 860.21,-1026.42 862.5,-1036.76 868.45,-1033.07"/>
</g>
<!-- maybe_package -->
<g id="node10" class="node">
<title>maybe_package</title>
<ellipse fill="none" stroke="black" cx="427.71" cy="-395.05" rx="328.45" ry="30.05"/>
<text xml:space="preserve" text-anchor="start" x="254.09" y="-399" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;After replacing `.` with `/` in module name,</text>
<text xml:space="preserve" text-anchor="start" x="203.46" y="-381.75" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;does `{path}/__init__.py` or `{path}/__init__.pyi` exist? &#160;&#160;&#160;</text>
</g>
<!-- determine_parent_kind&#45;&gt;maybe_package -->
<g id="edge10" class="edge">
<title>determine_parent_kind&#45;&gt;maybe_package</title>
<path fill="none" stroke="black" d="M620.67,-956.53C500.71,-936.22 374.71,-901.62 374.71,-845.89 374.71,-845.89 374.71,-845.89 374.71,-531.8 374.71,-497.63 389.47,-461.73 403.41,-435.43"/>
<polygon fill="black" stroke="black" points="406.39,-437.27 408.15,-426.82 400.26,-433.89 406.39,-437.27"/>
<text xml:space="preserve" text-anchor="middle" x="386.71" y="-690.27" font-family="Times,serif" font-size="14.00">Yes</text>
</g>
<!-- namespace_parent1 -->
<g id="node11" class="node">
<title>namespace_parent1</title>
<ellipse fill="none" stroke="black" cx="833.71" cy="-844.89" rx="212.31" ry="42.25"/>
<text xml:space="preserve" text-anchor="start" x="714.84" y="-857.47" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;Is the direct parent package</text>
<text xml:space="preserve" text-anchor="start" x="727.59" y="-840.22" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;a directory that contains</text>
<text xml:space="preserve" text-anchor="start" x="691.59" y="-822.97" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;an `__init__.py` or `__init__.pyi`? &#160;&#160;&#160;</text>
</g>
<!-- determine_parent_kind&#45;&gt;namespace_parent1 -->
<g id="edge11" class="edge">
<title>determine_parent_kind&#45;&gt;namespace_parent1</title>
<path fill="none" stroke="black" d="M833.71,-940.17C833.71,-927.14 833.71,-912.56 833.71,-898.84"/>
<polygon fill="black" stroke="black" points="837.21,-899.09 833.71,-889.09 830.21,-899.09 837.21,-899.09"/>
<text xml:space="preserve" text-anchor="middle" x="843.84" y="-909.09" font-family="Times,serif" font-size="14.00">No</text>
</g>
<!-- maybe_package&#45;&gt;package -->
<g id="edge18" class="edge">
<title>maybe_package&#45;&gt;package</title>
<path fill="none" stroke="black" d="M301.68,-366.89C269.45,-352.16 243.71,-329.51 243.71,-294.75 243.71,-294.75 243.71,-294.75 243.71,-114.25 243.71,-90.15 258.4,-67.38 273.12,-50.62"/>
<polygon fill="black" stroke="black" points="275.47,-53.24 279.71,-43.53 270.34,-48.47 275.47,-53.24"/>
<text xml:space="preserve" text-anchor="middle" x="255.71" y="-199.82" font-family="Times,serif" font-size="14.00">Yes</text>
</g>
<!-- maybe_module -->
<g id="node15" class="node">
<title>maybe_module</title>
<ellipse fill="none" stroke="black" cx="521.71" cy="-293.75" rx="249.55" ry="18"/>
<text xml:space="preserve" text-anchor="start" x="351.84" y="-289.07" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;Does `{path}.py` or `{path}.pyi` exist? &#160;&#160;&#160;</text>
</g>
<!-- maybe_package&#45;&gt;maybe_module -->
<g id="edge19" class="edge">
<title>maybe_package&#45;&gt;maybe_module</title>
<path fill="none" stroke="black" d="M455.41,-364.8C468.86,-350.58 484.87,-333.67 497.79,-320.03"/>
<polygon fill="black" stroke="black" points="500.01,-322.77 504.34,-313.1 494.92,-317.96 500.01,-322.77"/>
<text xml:space="preserve" text-anchor="middle" x="496.02" y="-333.7" font-family="Times,serif" font-size="14.00">No</text>
</g>
<!-- bail -->
<g id="node12" class="node">
<title>bail</title>
<ellipse fill="none" stroke="black" cx="860.71" cy="-115.25" rx="306.9" ry="18"/>
<text xml:space="preserve" text-anchor="start" x="649.96" y="-110.58" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;Is `module_name` set to a stub package candidate? &#160;&#160;&#160;</text>
</g>
<!-- namespace_parent1&#45;&gt;bail -->
<g id="edge12" class="edge">
<title>namespace_parent1&#45;&gt;bail</title>
<path fill="none" stroke="black" d="M878.81,-803.16C904.14,-775.71 930.71,-737.1 930.71,-695.95 930.71,-695.95 930.71,-695.95 930.71,-203.5 930.71,-178.3 912.73,-156.23 894.99,-140.59"/>
<polygon fill="black" stroke="black" points="897.48,-138.11 887.55,-134.41 893.01,-143.49 897.48,-138.11"/>
<text xml:space="preserve" text-anchor="middle" x="942.71" y="-390.38" font-family="Times,serif" font-size="14.00">Yes</text>
</g>
<!-- namespace_parent2 -->
<g id="node13" class="node">
<title>namespace_parent2</title>
<ellipse fill="none" stroke="black" cx="659.71" cy="-694.95" rx="242.54" ry="54.45"/>
<text xml:space="preserve" text-anchor="start" x="529.59" y="-716.15" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;Does the direct parent package</text>
<text xml:space="preserve" text-anchor="start" x="526.21" y="-698.9" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;have a sibling file with the same</text>
<text xml:space="preserve" text-anchor="start" x="496.21" y="-681.65" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;basename and a `py` or `pyi` extension?</text>
<text xml:space="preserve" text-anchor="start" x="650.71" y="-664.4" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;</text>
</g>
<!-- namespace_parent1&#45;&gt;namespace_parent2 -->
<g id="edge13" class="edge">
<title>namespace_parent1&#45;&gt;namespace_parent2</title>
<path fill="none" stroke="black" d="M786.17,-803.47C768.72,-788.63 748.58,-771.5 729.58,-755.35"/>
<polygon fill="black" stroke="black" points="731.98,-752.79 722.09,-748.98 727.44,-758.13 731.98,-752.79"/>
<text xml:space="preserve" text-anchor="middle" x="772.42" y="-771.34" font-family="Times,serif" font-size="14.00">No</text>
</g>
<!-- bail&#45;&gt;not_found -->
<g id="edge24" class="edge">
<title>bail&#45;&gt;not_found</title>
<path fill="none" stroke="black" d="M924.27,-97.19C981.44,-81.85 1065.5,-59.29 1125.91,-43.08"/>
<polygon fill="black" stroke="black" points="1126.68,-46.49 1135.44,-40.52 1124.87,-39.73 1126.68,-46.49"/>
<text xml:space="preserve" text-anchor="middle" x="1061.2" y="-65.95" font-family="Times,serif" font-size="14.00">No</text>
</g>
<!-- retry -->
<g id="node17" class="node">
<title>retry</title>
<ellipse fill="none" stroke="black" cx="860.71" cy="-22" rx="213.78" ry="18"/>
<text xml:space="preserve" text-anchor="start" x="716.34" y="-17.32" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;Reset `module_name` to original &#160;&#160;&#160;</text>
</g>
<!-- bail&#45;&gt;retry -->
<g id="edge25" class="edge">
<title>bail&#45;&gt;retry</title>
<path fill="none" stroke="black" d="M860.71,-97.09C860.71,-84.3 860.71,-66.53 860.71,-51.61"/>
<polygon fill="black" stroke="black" points="864.21,-51.91 860.71,-41.91 857.21,-51.91 864.21,-51.91"/>
<text xml:space="preserve" text-anchor="middle" x="872.71" y="-65.95" font-family="Times,serif" font-size="14.00">Yes</text>
</g>
<!-- namespace_parent2&#45;&gt;bail -->
<g id="edge14" class="edge">
<title>namespace_parent2&#45;&gt;bail</title>
<path fill="none" stroke="black" d="M794.49,-649.24C842.41,-624.2 884.71,-587.02 884.71,-533.8 884.71,-533.8 884.71,-533.8 884.71,-203.5 884.71,-183.2 878.6,-161.17 872.55,-144.33"/>
<polygon fill="black" stroke="black" points="875.82,-143.08 868.98,-134.99 869.28,-145.58 875.82,-143.08"/>
<text xml:space="preserve" text-anchor="middle" x="896.71" y="-333.7" font-family="Times,serif" font-size="14.00">Yes</text>
</g>
<!-- namespace_parent3 -->
<g id="node14" class="node">
<title>namespace_parent3</title>
<ellipse fill="none" stroke="black" cx="629.71" cy="-532.8" rx="227.16" ry="54.45"/>
<text xml:space="preserve" text-anchor="start" x="496.96" y="-554" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;Is every parent above the direct</text>
<text xml:space="preserve" text-anchor="start" x="481.59" y="-536.75" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;parent package a normal package or</text>
<text xml:space="preserve" text-anchor="start" x="488.34" y="-519.5" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;otherwise satisfy the previous two</text>
<text xml:space="preserve" text-anchor="start" x="477.09" y="-502.25" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;namespace package requirements? &#160;&#160;&#160;</text>
</g>
<!-- namespace_parent2&#45;&gt;namespace_parent3 -->
<g id="edge15" class="edge">
<title>namespace_parent2&#45;&gt;namespace_parent3</title>
<path fill="none" stroke="black" d="M649.64,-640.17C647.13,-626.77 644.41,-612.25 641.81,-598.38"/>
<polygon fill="black" stroke="black" points="645.32,-598.1 640.04,-588.92 638.44,-599.39 645.32,-598.1"/>
<text xml:space="preserve" text-anchor="middle" x="655.74" y="-609.2" font-family="Times,serif" font-size="14.00">No</text>
</g>
<!-- namespace_parent3&#45;&gt;maybe_package -->
<g id="edge17" class="edge">
<title>namespace_parent3&#45;&gt;maybe_package</title>
<path fill="none" stroke="black" d="M554.21,-481.06C529.7,-464.59 503.04,-446.67 480.54,-431.56"/>
<polygon fill="black" stroke="black" points="482.69,-428.78 472.43,-426.1 478.78,-434.59 482.69,-428.78"/>
<text xml:space="preserve" text-anchor="middle" x="534.66" y="-447.05" font-family="Times,serif" font-size="14.00">Yes</text>
</g>
<!-- namespace_parent3&#45;&gt;bail -->
<g id="edge16" class="edge">
<title>namespace_parent3&#45;&gt;bail</title>
<path fill="none" stroke="black" d="M754.07,-486.86C789.03,-465.83 817.71,-436.31 817.71,-396.05 817.71,-396.05 817.71,-396.05 817.71,-203.5 817.71,-181.34 829.02,-158.97 840.03,-142.43"/>
<polygon fill="black" stroke="black" points="842.62,-144.83 845.52,-134.64 836.9,-140.8 842.62,-144.83"/>
<text xml:space="preserve" text-anchor="middle" x="827.84" y="-289.07" font-family="Times,serif" font-size="14.00">No</text>
</g>
<!-- maybe_module&#45;&gt;module -->
<g id="edge20" class="edge">
<title>maybe_module&#45;&gt;module</title>
<path fill="none" stroke="black" d="M465.44,-275.74C429.3,-263.58 382.11,-245.35 343.71,-222.5 338.06,-219.13 202.5,-104.78 138.54,-50.75"/>
<polygon fill="black" stroke="black" points="141.07,-48.3 131.17,-44.52 136.55,-53.65 141.07,-48.3"/>
<text xml:space="preserve" text-anchor="middle" x="289.08" y="-155.2" font-family="Times,serif" font-size="14.00">Yes</text>
</g>
<!-- maybe_namespace -->
<g id="node16" class="node">
<title>maybe_namespace</title>
<ellipse fill="none" stroke="black" cx="521.71" cy="-204.5" rx="169.06" ry="18"/>
<text xml:space="preserve" text-anchor="start" x="409.21" y="-199.82" font-family="Times,serif" font-size="14.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;Is `{path}` a directory? &#160;&#160;&#160;</text>
</g>
<!-- maybe_module&#45;&gt;maybe_namespace -->
<g id="edge21" class="edge">
<title>maybe_module&#45;&gt;maybe_namespace</title>
<path fill="none" stroke="black" d="M521.71,-275.51C521.71,-263.68 521.71,-247.7 521.71,-234"/>
<polygon fill="black" stroke="black" points="525.21,-234.22 521.71,-224.22 518.21,-234.22 525.21,-234.22"/>
<text xml:space="preserve" text-anchor="middle" x="531.84" y="-244.45" font-family="Times,serif" font-size="14.00">No</text>
</g>
<!-- maybe_namespace&#45;&gt;namespace_package -->
<g id="edge22" class="edge">
<title>maybe_namespace&#45;&gt;namespace_package</title>
<path fill="none" stroke="black" d="M520.76,-186.19C519.09,-156.13 515.64,-93.8 513.51,-55.47"/>
<polygon fill="black" stroke="black" points="517.03,-55.71 512.98,-45.91 510.04,-56.09 517.03,-55.71"/>
<text xml:space="preserve" text-anchor="middle" x="529.71" y="-110.58" font-family="Times,serif" font-size="14.00">Yes</text>
</g>
<!-- maybe_namespace&#45;&gt;bail -->
<g id="edge23" class="edge">
<title>maybe_namespace&#45;&gt;bail</title>
<path fill="none" stroke="black" d="M584.29,-187.4C640.48,-172.93 723.17,-151.65 783.47,-136.13"/>
<polygon fill="black" stroke="black" points="784.17,-139.56 792.99,-133.68 782.43,-132.78 784.17,-139.56"/>
<text xml:space="preserve" text-anchor="middle" x="731.7" y="-155.2" font-family="Times,serif" font-size="14.00">No</text>
</g>
<!-- retry&#45;&gt;determine_parent_kind -->
<g id="edge26" class="edge">
<title>retry&#45;&gt;determine_parent_kind</title>
<path fill="none" stroke="black" d="M1001.81,-35.84C1093.37,-48.22 1195.71,-71.6 1195.71,-114.25 1195.71,-845.89 1195.71,-845.89 1195.71,-845.89 1195.71,-889.15 1103.96,-923.26 1012.84,-946.47"/>
<polygon fill="black" stroke="black" points="1012.05,-943.05 1003.2,-948.87 1013.75,-949.84 1012.05,-943.05"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

View file

@ -1,3 +1,13 @@
/*!
This module principally provides two routines for resolving a particular module
name to a `Module`: [`resolve_module`] and [`resolve_real_module`]. You'll
usually want the former, unless you're certain you want to forbid stubs, in
which case, use the latter.
For implementors, see `import-resolution-diagram.svg` for a flow diagram that
specifies ty's implementation of Python's import resolution algorithm.
*/
use std::borrow::Cow;
use std::fmt;
use std::iter::FusedIterator;