Skip to main content

Rust-based CLI to streamline Python gRPC/Protobuf workflows

Project description

python-proto-importer

Crates.io PyPI PyPI Downloads CI codecov

A Rust-powered CLI that brings production-grade reliability to Python gRPC/Protobuf code generation. Generate, validate, and maintain protobuf-based Python code with confidence.

日本語版: 日本語ドキュメント

Why python-proto-importer?

Solve the Absolute Import Problem

The Core Problem: Standard protoc generates Python files with absolute imports (e.g., import foo.bar_pb2), which breaks when you move generated code to different locations in your project. This forces you to place generated files in specific locations, limiting your project structure flexibility.

Our Solution: Automatically converts all imports to relative imports based on your pyproject.toml configuration. This means you can place generated code anywhere in your project structure and it will work correctly. While other tools exist to address this problem, our integrated approach ensures it works seamlessly with the rest of the validation pipeline.

Built-in Quality Assurance

Unlike standard protoc workflows, this tool validates generated code before it reaches your project. When mypy-protobuf or complex proto definitions produce incorrect stubs, you'll know immediately—not when your CI fails.

The Problem: Standard protoc/mypy-protobuf can generate broken .pyi files that crash your type checker with cryptic errors.

Our Solution: Every generation run includes automatic type validation, ensuring the generated code is correct before you use it.

Clear Error Boundaries

Generation-time errors vs. Usage-time errors—know the difference instantly.

  • ✅ Tool succeeds = Generated code is valid
  • ❌ Tool fails = Problem in generation process (not your code!)
  • 📊 Your type checker fails later = Issue in how you're using the generated code

Optimal Validation Environment

Your project's mypy/pyright settings might not be ideal for validating generated protobuf code. This tool maintains its own optimized type-checking configuration specifically tuned for protobuf validation, ensuring consistent quality regardless of your project settings.

Blazing Fast Performance

Built with Rust for maximum performance. File operations, import rewriting, and validation run at native speed, making it ideal for large codebases and CI/CD pipelines where every second counts.

Quick Start

Installation

# Via pip (recommended)
pip install python-proto-importer

# Via cargo
cargo install python-proto-importer

Basic Setup

  1. Create a pyproject.toml configuration:
[tool.python_proto_importer]
inputs = ["proto/**/*.proto"]  # Your proto files
out = "generated"              # Output directory
  1. Generate Python code:
proto-importer build

That's it! Your generated code is now validated and ready to use.

Core Features

Smart Import Management

  • Automatic relative imports: Generated code uses relative imports, making it portable across different project structures
  • Intelligent rewriting: Only touches protobuf imports, preserving external dependencies like google.protobuf

Package Structure Control

  • Automatic __init__.py generation: No more missing init files breaking imports
  • Namespace package support: Full PEP 420 compatibility when needed

Comprehensive Verification

  • Import validation: Every generated module is test-imported
  • Type checking: Optional mypy/pyright validation with optimal settings
  • Pre-flight checks: proto-importer doctor diagnoses your environment

Production-Ready Workflow

  • Single command: Generate, postprocess, and validate in one step
  • Declarative configuration: All settings in pyproject.toml
  • CI/CD friendly: Designed for automation

Commands

proto-importer build

Generate Python code from proto files with full validation pipeline.

proto-importer build                  # Standard build
proto-importer build --no-verify      # Skip verification
proto-importer build --pyproject custom.toml  # Custom config

proto-importer doctor

Diagnose your environment and check dependencies.

proto-importer doctor

Output shows:

  • Python environment (python/uv)
  • Required dependencies (grpcio-tools)
  • Optional tools (mypy-protobuf, mypy, pyright)
  • Helpful hints for missing components

proto-importer check

Run verification only (no generation).

proto-importer check

proto-importer clean

Remove generated output directory.

proto-importer clean --yes

⚙️ Configuration

All configuration lives in pyproject.toml under [tool.python_proto_importer].

Essential Options

Option Type Default Description
inputs array [] Glob patterns for proto files to compile
out string "generated/python" Output directory for generated files
include array ["."] Proto import paths (protoc's --proto_path)
python_exe string "python3" Python executable ("python3", "python", "uv")

Type Stub Generation

Option Type Default Description
mypy boolean false Generate .pyi stubs via mypy-protobuf
mypy_grpc boolean false Generate gRPC stubs (_grpc.pyi)

Post-processing Options

Configure under [tool.python_proto_importer.postprocess]:

Option Type Default Description
relative_imports boolean true Convert to relative imports
create_package boolean true Create __init__.py files
exclude_google boolean true Don't rewrite google.protobuf imports
pyright_header boolean false Add Pyright suppression headers

Verification Options

Configure under [tool.python_proto_importer.verify]:

[tool.python_proto_importer.verify]
mypy_cmd = ["mypy", "--strict", "generated"]
pyright_cmd = ["pyright", "generated/**/*.pyi"]

Configuration Examples

Minimal Setup

[tool.python_proto_importer]
inputs = ["proto/**/*.proto"]
out = "generated"

Production Setup with Type Checking

[tool.python_proto_importer]
backend = "protoc"
python_exe = "uv"  # or ".venv/bin/python"
include = ["proto"]
inputs = ["proto/**/*.proto"]
out = "src/generated"
mypy = true
mypy_grpc = true

[tool.python_proto_importer.postprocess]
relative_imports = true
create_package = true
exclude_google = true

[tool.python_proto_importer.verify]
# Focus on .pyi files to avoid noise from generated .py files
pyright_cmd = ["uv", "run", "pyright", "src/generated/**/*.pyi"]
mypy_cmd = ["uv", "run", "mypy", "--strict", "src/generated"]

Namespace Packages (PEP 420)

[tool.python_proto_importer]
inputs = ["proto/**/*.proto"]
out = "generated"

[tool.python_proto_importer.postprocess]
create_package = false  # No __init__.py files

Understanding include vs inputs

This is crucial for correct configuration:

include - Search Paths

Where protoc looks for .proto files and their dependencies.

inputs - Files to Compile

Which .proto files to actually compile (glob patterns).

Example Structure

project/
├── pyproject.toml           # Configuration file (the reference point)
├── api/
│   └── service.proto        # Your service (compile this)
├── third_party/
│   └── google/
│       └── api/
│           └── annotations.proto  # Dependency (don't compile)
└── generated/               # Output here

Correct Configuration

[tool.python_proto_importer]
include = [".", "third_party"]  # Can see all protos
inputs = ["api/**/*.proto"]      # Only compile your protos
out = "generated"

Key Point: Dependencies need to be in include (so protoc can find them) but NOT in inputs (you don't want to regenerate them).

Advanced Usage

Using with uv

uv is a fast Python package manager:

[tool.python_proto_importer]
python_exe = "uv"

[tool.python_proto_importer.verify]
mypy_cmd = ["uv", "run", "mypy", "--strict", "generated"]
pyright_cmd = ["uv", "run", "pyright", "generated"]

CI/CD Integration

GitHub Actions

- name: Setup
  run: |
    pip install python-proto-importer grpcio-tools mypy-protobuf

- name: Generate Proto
  run: proto-importer build

- name: Run Tests
  run: pytest tests/

Pre-commit Hook

repos:
  - repo: local
    hooks:
      - id: proto-build
        name: Build Proto Files
        entry: proto-importer build
        language: system
        files: \.proto$

Troubleshooting

Import Errors After Generation

  1. Check package structure:

    proto-importer check
    
  2. Verify include paths cover all dependencies

  3. Ensure PYTHONPATH includes the parent of your output directory

Type Checker Warnings

For generated .py files with dynamic attributes, focus type checking on .pyi files:

[tool.python_proto_importer.verify]
pyright_cmd = ["pyright", "generated/**/*.pyi"]  # Only check stubs

"Shadowing" Errors

When using multiple include paths with same-named files:

  • Use more specific inputs patterns
  • Restructure proto files to avoid naming conflicts

How It Works

The tool follows a comprehensive pipeline to ensure reliable code generation:

graph TD
    A["proto-importer build"] --> B["📝 Load pyproject.toml"]
    B --> C["🔍 Discover .proto files"]
    C --> D["⚙️ Execute protoc"]
    D --> E["📦 Generate Python files"]
    E --> F{{"Post-processing"}}
    
    F --> G["📍 Convert absolute → relative imports"]
    F --> H["📁 Create __init__.py files"]
    F --> I["🔧 Add type suppressions"]
    
    G --> J{{"✅ Verification"}}
    H --> J
    I --> J
    
    J --> K["🧪 Import dry-run test"]
    J --> L["🔍 Type checker validation"]
    
    K --> M["Success!"]
    L --> M
    
    style A fill:#e1f5fe
    style M fill:#e8f5e8
    style F fill:#fff3e0
    style J fill:#fce4ec

Import Transformation Example

graph LR
    A["Generated Code<br/>absolute imports"] --> B["Transformation"] --> C["Final Code<br/>relative imports"]
    
    A1["import api.service_pb2<br/>from api import user_pb2"] --> B1["Import Rewriter"] --> C1["from . import service_pb2<br/>from . import user_pb2"]
    
    style A fill:#ffebee
    style B fill:#e3f2fd
    style C fill:#e8f5e8

Key Steps:

  1. Generation: Runs protoc with your configuration
  2. Post-processing:
    • Converts absolute imports to relative
    • Creates __init__.py files
    • Adds type checker suppressions if configured
  3. Verification:
    • Attempts to import every generated module
    • Runs configured type checkers
    • Reports clear, actionable errors

🚧 Current Limitations

  • v0.1: Only protoc backend (buf support planned for v0.2)
  • Import rewriting covers common patterns (_pb2.py, _pb2_grpc.py, .pyi files)
  • Import validation only checks .py files (.pyi validated via type checkers)

Contributing

We welcome contributions! See CONTRIBUTING.md for development setup.

Quick Development Setup

# Install development dependencies
cargo install cargo-make

# Run full validation
makers all  # Runs format, lint, build, test

# Or individually
makers format
makers lint
makers test

📜 License

Apache-2.0. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python_proto_importer-0.1.4.tar.gz (58.3 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

python_proto_importer-0.1.4-cp38-abi3-win_amd64.whl (1.9 MB view details)

Uploaded CPython 3.8+Windows x86-64

python_proto_importer-0.1.4-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.4 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ x86-64

python_proto_importer-0.1.4-cp38-abi3-macosx_11_0_arm64.whl (2.1 MB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

File details

Details for the file python_proto_importer-0.1.4.tar.gz.

File metadata

File hashes

Hashes for python_proto_importer-0.1.4.tar.gz
Algorithm Hash digest
SHA256 cc65f736bb8b1c802660d9b45f3ae7ba209fa3803de19f236b79736335459688
MD5 b9943f7f9de26b59e66b71c241fd9bc4
BLAKE2b-256 2b7ae91cc68d016bfcb8a41278640ce10b923571684d26caff4a6794bcf6d964

See more details on using hashes here.

File details

Details for the file python_proto_importer-0.1.4-cp38-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for python_proto_importer-0.1.4-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 7b24285f3a7609e863188b283bdd43bbdcc5378cea1137995986dbf223395d08
MD5 6235fcbff04a2a2fb6f10d8cb81898a4
BLAKE2b-256 1cb96d4a72b96f25efd1ea244558d65803e56bb512e4d3e9f8999e7dae1a3794

See more details on using hashes here.

File details

Details for the file python_proto_importer-0.1.4-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for python_proto_importer-0.1.4-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 55747d96a0203c691e1819acd79da72f90e1a6a6cdf3814549c056d49152c902
MD5 0d4b53505ffdf4584c8f0601ff613d92
BLAKE2b-256 56b93559c9f97c5b571fa6525ecf2a32eb284b9f82cb567d4c79bd0751f0d06c

See more details on using hashes here.

File details

Details for the file python_proto_importer-0.1.4-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for python_proto_importer-0.1.4-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c33010f47a58eb295a278f8cd489e26feea58acc4a1b9088de14e63732aa8b39
MD5 f1388fbe64f16a49c6dd749cd5f16ab1
BLAKE2b-256 1bee715bb59dfa4127c10626235fb2f0bc86526e8300441e8872612814aa4dbb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page