Repository navigation
Commit c3d2644
authored
Break the exir capture <-> program/verifier import cycle (#24799)
### Summary
`exir/capture/__init__.py` loads `_capture.py`, which imported
`executorch.exir.program` and `executorch.exir.verification.verifier` at
module scope. `verifier.py`, `program/_program.py` and
`_serialize/_serialize.py` all import `executorch.exir.capture._config`,
so each of them ran `capture/__init__.py` and looped back into itself
while still half-initialised.
Normally `exir/__init__.py` loads `capture` first, so the cycle stays
hidden. Under lazy imports (e.g. Cinder lazy imports on Python 3.14) the
first import can enter through one of those modules instead, for example
via `backends/xnnpack/xnnpack_preprocess.py` -> `verifier`, and fails:
```
ImportError: cannot import name 'EXIRATenDialectVerifierBase' from partially initialized module 'executorch.exir.verification.verifier' (most likely due to a circular import)
```
`_capture.py` uses `ExirExportedProgram`, `_transform`,
`HackedUpExportedProgramDONOTUSE` and `EXIRATenDialectVerifierBase` only
inside `capture()` and `_capture_legacy_do_not_use()`, so those imports
move into the two functions, with a `TYPE_CHECKING` import for the
return annotations. No public import paths change.
The separate `exir/backend/backend_api.py` <->
`exir/program/_program.py` cycle is not addressed here.
This PR was authored with AI assistance (Claude Code).
### Test plan
New `exir/tests/test_import_order.py` (collected by OSS pytest, plus a
Buck target) imports `executorch.exir.verification.verifier`,
`executorch.exir.program` and `executorch.exir._serialize._serialize` in
a fresh interpreter whose `executorch.exir` is a bare package, so
`exir/__init__.py` doesn't run first. On main all three fail with a
circular-import error; with this change all three pass. That stub
imports eagerly, so on main it reports a different name than the
lazy-import traceback above (e.g. `EXIRATenDialectVerifier` from
`_program.py`); same cycle.
Smoke-tested `capture()` (with and without `enable_aot`).
`_capture_legacy_do_not_use()` already fails on main with
`ExportedProgram.__init__() got an unexpected keyword argument
'verifier'`, and fails the same way with this change.
`python -m unittest executorch.exir.verification.test.test_verifier
executorch.exir.tests.test_passes
executorch.backends.xnnpack.test.ops.test_add
executorch.backends.xnnpack.test.ops.test_conv2d`: same results as main
(3 errors, `test_to_out_variant_none_output` and two `test_qs8_conv*`,
which also error on main in my environment).
Not yet verified in a real Cinder lazy-imports Python 3.14 runtime.
cc @JacobSzwejbka @angelayi1 parent 02e0d3a commit c3d2644
3 files changed
Lines changed: 64 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
| 12 | + | |
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | | - | |
18 | | - | |
19 | 17 | | |
20 | 18 | | |
21 | 19 | | |
22 | 20 | | |
23 | 21 | | |
24 | 22 | | |
25 | 23 | | |
26 | | - | |
27 | 24 | | |
28 | 25 | | |
29 | 26 | | |
| |||
46 | 43 | | |
47 | 44 | | |
48 | 45 | | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
49 | 51 | | |
50 | 52 | | |
51 | 53 | | |
| |||
59 | 61 | | |
60 | 62 | | |
61 | 63 | | |
62 | | - | |
| 64 | + | |
63 | 65 | | |
64 | 66 | | |
65 | 67 | | |
| |||
69 | 71 | | |
70 | 72 | | |
71 | 73 | | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
72 | 77 | | |
73 | 78 | | |
74 | 79 | | |
| |||
167 | 172 | | |
168 | 173 | | |
169 | 174 | | |
170 | | - | |
| 175 | + | |
171 | 176 | | |
172 | 177 | | |
173 | 178 | | |
174 | 179 | | |
175 | 180 | | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
176 | 185 | | |
177 | 186 | | |
178 | 187 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
114 | 114 | | |
115 | 115 | | |
116 | 116 | | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
117 | 127 | | |
118 | 128 | | |
119 | 129 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
0 commit comments