Problem
On Python 3.11+, imports protected by except* ImportError remain in the graph but are labeled as ordinary imports rather than ImportKind.CONDITIONAL_IMPORT.
try:
import optional_pkg
except* ImportError:
pass
The equivalent except ImportError block is classified as conditional. In the current extractor, parsing the example above produces an ast.TryStar; _import_analysis_nodes retains only ast.Try among try nodes, and _find_conditional_import_ranges also accepts only ast.Try. A local reproduction returned an Import node and no conditional ranges. This behavior predates PRs #60–#62; it was exposed during their edge-case review, not caused by those optimizations.
Why it matters
The dependency is not missing. Its context metadata is wrong, so graph consumers or rules that distinguish ordinary from optional/conditional imports can misinterpret it. We should correct classification without broadening dynamic analysis or changing import resolution.
Suggested implementation
- Retain
ast.TryStar as an import-analysis context node where the runtime provides it, while keeping Python 3.10 compatibility (no unconditional ast.TryStar reference at import time).
- Apply the existing ImportError/ModuleNotFoundError handler and statement-range logic to both
ast.Try and ast.TryStar.
- Keep the current semantics: imports in the protected body and matching handler body are conditional; unrelated handlers and
finally are not.
Acceptance tests
- On Python 3.11+,
except* ImportError and except* ModuleNotFoundError label the guarded import as CONDITIONAL_IMPORT while preserving its syntax kind and resolved target.
- A non-import-error
except* handler does not classify imports as conditional.
- Mixed handlers classify only the relevant handler body; nesting,
else, and finally follow the same rules as ordinary try blocks.
- Existing ordinary
try/except ImportError tests and the Python 3.10–3.13 CI matrix remain green.
Problem
On Python 3.11+, imports protected by
except* ImportErrorremain in the graph but are labeled as ordinary imports rather thanImportKind.CONDITIONAL_IMPORT.The equivalent
except ImportErrorblock is classified as conditional. In the current extractor, parsing the example above produces anast.TryStar;_import_analysis_nodesretains onlyast.Tryamong try nodes, and_find_conditional_import_rangesalso accepts onlyast.Try. A local reproduction returned anImportnode and no conditional ranges. This behavior predates PRs #60–#62; it was exposed during their edge-case review, not caused by those optimizations.Why it matters
The dependency is not missing. Its context metadata is wrong, so graph consumers or rules that distinguish ordinary from optional/conditional imports can misinterpret it. We should correct classification without broadening dynamic analysis or changing import resolution.
Suggested implementation
ast.TryStaras an import-analysis context node where the runtime provides it, while keeping Python 3.10 compatibility (no unconditionalast.TryStarreference at import time).ast.Tryandast.TryStar.finallyare not.Acceptance tests
except* ImportErrorandexcept* ModuleNotFoundErrorlabel the guarded import asCONDITIONAL_IMPORTwhile preserving its syntax kind and resolved target.except*handler does not classify imports as conditional.else, andfinallyfollow the same rules as ordinarytryblocks.try/except ImportErrortests and the Python 3.10–3.13 CI matrix remain green.