This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
PyImport2Pkg is a Python tool that performs reverse mapping from Python import statements to pip package names. It solves the problem of identifying which packages to install when given code with imports like import cv2 → pip install opencv-python.
# Install in development mode
.venv/Scripts/pip install -e ".[dev]"
# Run all tests
.venv/Scripts/pytest tests/ -v
# Run all tests with short traceback
.venv/Scripts/pytest tests/ -v --tb=short
# Run specific test file
.venv/Scripts/pytest tests/test_parser.py -v
# Run specific test class or method
.venv/Scripts/pytest tests/test_parser.py::TestParserBasicImports -v
.venv/Scripts/pytest tests/test_parser.py::TestParserBasicImports::test_simple_import -v
# Run integration tests
.venv/Scripts/pytest tests/test_integration.py::TestIntegration -v
# Run database tests
.venv/Scripts/pytest tests/test_database.py -v --tb=short
# CLI commands
.venv/Scripts/pyimport2pkg analyze ./path/to/project
.venv/Scripts/pyimport2pkg query cv2
.venv/Scripts/pyimport2pkg build-db --max-packages 5000
.venv/Scripts/pyimport2pkg build-db --resume # Resume interrupted build
.venv/Scripts/pyimport2pkg build-db --retry-failed # Retry only failed packages
.venv/Scripts/pyimport2pkg build-status # Check build progress
.venv/Scripts/pyimport2pkg db-infoThe tool follows a pipeline architecture:
Scanner → Parser → Filter → Mapper → Resolver → Exporter
| Module | Purpose |
|---|---|
scanner.py |
Recursively finds Python files, excludes .venv, __pycache__, etc. |
parser.py |
Uses AST to extract imports with context (conditional, try-except, function-level) |
filter.py |
Removes stdlib and local project modules; handles Python version differences |
mapper.py |
Maps module names to package names using priority: namespace → hardcoded → database → guess |
resolver.py |
Handles one-to-many conflicts (e.g., cv2 → multiple opencv variants) using strategies |
exporter.py |
Generates requirements.txt, JSON, or simple list output |
database.py |
Builds SQLite mapping database from PyPI top packages; supports incremental updates and resume |
The Mapper queries sources in this order:
- Namespace packages (if submodules exist) -
google.cloud.storage→google-cloud-storage - Hardcoded mappings -
cv2→opencv-python,PIL→Pillow - Namespace packages (top-level only)
- Database lookup - From
top_level.txtin wheel files - Guess - Assume module name equals package name
# models.py
ImportInfo # Parsed import with context (file, line, is_optional, is_relative)
MappingResult # Module mapped to package candidates
PackageCandidate # Single package option with download count
AnalysisResult # Complete analysis result with required/optional packages and stats
# Enums
ImportType # STANDARD, FROM, DYNAMIC
ImportContext # TOP_LEVEL, CONDITIONAL, TRY_EXCEPT, FUNCTION, CLASS
ResolveStrategy # MOST_POPULAR, FIRST, ALLmappings/hardcoded.py- Classic mismatches (CLASSIC_MISMATCHES), PyWin32 modules (PTH_INJECTED_MODULES), and platform-specific packages (PLATFORM_SPECIFIC)mappings/namespace.py- Nested dict forgoogle.*,azure.*,zope.*,sphinxcontrib.*namespaces
The Resolver class supports multiple strategies for handling one-to-many mappings:
- MOST_POPULAR (default) - Choose package with highest download count
- FIRST - Choose first candidate (recommended by hardcoded/namespace mappings)
- ALL - Keep all candidates for manual selection
Platform-specific handling: Automatically selects correct package variant for Windows (pywin32), macOS, Linux, etc.
- Smart incremental updates - Only downloads new packages when expanding database
- Resume capability - Can pause/resume database builds using
--resume - Retry failed - Target only failed packages with
--retry-failed - Parallel processing - 50 concurrent workers by default
- Batch writes - Optimized SQLite writes for 10-50x speedup
- Progress tracking - Saves progress every 100 packages
- Graceful interrupts - Ctrl+C saves progress before exiting
- ~300 tests across 9 test files
- Each module has corresponding
test_<module>.py test_integration.pycontains end-to-end pipeline tests- Sample project in
tests/fixtures/sample_project/
Test files:
test_scanner.py- File discovery and exclusion patternstest_parser.py- AST-based import extraction and context detectiontest_filter.py- Stdlib filtering and Python version handlingtest_mappings.py- Hardcoded and namespace package mappingstest_mapper.py- Module-to-package mapping logictest_resolver.py- Conflict resolution strategiestest_exporter.py- Output format generationtest_database.py- Database operations and queriestest_integration.py- End-to-end pipeline workflows
- Namespace packages take priority over hardcoded mappings when submodules are present
from xxx import yyyonly capturesxxxas the module (cannot infer ifyyyis a submodule)- Conditional/try-except imports are marked as
is_optional=True - Python version awareness - stdlib list varies by target version; backport detection for
dataclasses,tomllib, etc.