--- name: mypy-setup description: Set up Mypy type checking configuration for a Python project argument-hint: [--strict] [--django] [--format=] [--install] --- # mypy-setup **Category**: Python Development ## Usage ```bash /mypy-setup [--strict] [--django] [--format=] [--install] ``` ## Arguments | Argument | Required | Description | |----------|----------|-------------| | `--strict` | No | Use strict type checking configuration | | `--django` | No | Add Django-specific configuration and plugin | | `--format=` | No | Config format (default: ini) | | `--install` | No | Install Mypy and required plugins | ## Purpose Set up Mypy static type checking in a Python project: 1. **Create Configuration**: Generate mypy.ini or pyproject.toml config 2. **Install Dependencies**: Install Mypy and type stub packages 3. **Configure IDE**: Add Mypy settings for VS Code/PyCharm 4. **Setup CI/CD**: Generate GitHub Actions workflow 5. **Add Pre-commit**: Configure pre-commit hook for Mypy ## Execution Instructions for Claude Code When this command is run, Claude Code should: ### 1. Parse Arguments ``` STRICT_MODE = true if --strict specified DJANGO_MODE = true if --django specified FORMAT = value after --format= (default: "ini") INSTALL = true if --install specified ``` ### 2. Detect Project Type Scan the project to determine: ```bash # Check for Django HAS_DJANGO=false if [ -f "manage.py" ] || grep -q "django" requirements.txt 2>/dev/null; then HAS_DJANGO=true echo "✓ Django project detected" fi # Check for existing config HAS_CONFIG=false if [ -f "mypy.ini" ] || [ -f ".mypy.ini" ] || grep -q "\[tool.mypy\]" pyproject.toml 2>/dev/null; then HAS_CONFIG=true echo "⚠ Existing Mypy configuration found" fi # Check Python version PYTHON_VERSION=$(python --version | cut -d' ' -f2 | cut -d'.' -f1,2) echo "Python version: $PYTHON_VERSION" ``` ### 3. Install Mypy (if --install) ```bash if [ "$INSTALL" = true ]; then echo "Installing Mypy..." # Use uv if available, otherwise pip if command -v uv &> /dev/null; then PKG_MANAGER="uv pip install" else PKG_MANAGER="pip install" fi # Install Mypy $PKG_MANAGER mypy # Install Django plugin if needed if [ "$DJANGO_MODE" = true ] || [ "$HAS_DJANGO" = true ]; then $PKG_MANAGER django-stubs mypy-django-plugin fi # Install common type stubs $PKG_MANAGER types-requests types-PyYAML types-redis echo "✓ Mypy installed successfully" fi ``` ### 4. Generate Configuration File #### Option A: mypy.ini (default) ```bash if [ "$FORMAT" = "ini" ]; then cat > mypy.ini << 'EOF' [mypy] # Python version python_version = 3.11 # Import discovery namespace_packages = True explicit_package_bases = True ignore_missing_imports = False # Platform configuration platform = linux # Disallow dynamic typing disallow_any_generics = True disallow_subclassing_any = True # Disallow untyped code disallow_untyped_calls = True disallow_untyped_defs = True disallow_incomplete_defs = True check_untyped_defs = True disallow_untyped_decorators = True # None and Optional handling no_implicit_optional = True strict_optional = True # Warnings warn_redundant_casts = True warn_unused_ignores = True warn_no_return = True warn_return_any = True warn_unreachable = True # Strictness flags strict_equality = True strict_concatenate = True # Error messages show_error_codes = True show_column_numbers = True show_error_context = True pretty = True # Miscellaneous warn_unused_configs = True # Per-module options for gradual typing [mypy-tests.*] disallow_untyped_defs = False [mypy-migrations.*] ignore_errors = True EOF if [ "$STRICT_MODE" = true ]; then # Already strict by default echo "✓ Created strict mypy.ini" else # Relax some settings for gradual adoption cat >> mypy.ini << 'EOF' # Relaxed settings for gradual adoption # Remove these overrides as you add type hints [mypy] disallow_untyped_calls = False disallow_untyped_defs = False disallow_incomplete_defs = False EOF echo "✓ Created mypy.ini (gradual mode)" echo " Gradually enable stricter checks as you add type hints" fi # Add Django configuration if [ "$DJANGO_MODE" = true ] || [ "$HAS_DJANGO" = true ]; then cat >> mypy.ini << 'EOF' # Django configuration [mypy] plugins = mypy_django_plugin.main [mypy.plugins.django-stubs] django_settings_module = "config.settings" # Update with your settings module EOF echo "✓ Added Django plugin configuration" echo " Update django_settings_module in mypy.ini" fi fi ``` #### Option B: pyproject.toml ```bash if [ "$FORMAT" = "toml" ]; then # Check if pyproject.toml exists if [ ! -f "pyproject.toml" ]; then cat > pyproject.toml << 'EOF' [build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" EOF fi # Add Mypy configuration cat >> pyproject.toml << 'EOF' [tool.mypy] python_version = "3.11" namespace_packages = true explicit_package_bases = true ignore_missing_imports = false # Strictness disallow_any_generics = true disallow_subclassing_any = true disallow_untyped_calls = true disallow_untyped_defs = true disallow_incomplete_defs = true check_untyped_defs = true disallow_untyped_decorators = true # None/Optional no_implicit_optional = true strict_optional = true # Warnings warn_redundant_casts = true warn_unused_ignores = true warn_no_return = true warn_return_any = true warn_unreachable = true # Output show_error_codes = true show_column_numbers = true show_error_context = true pretty = true # Per-module options [[tool.mypy.overrides]] module = "tests.*" disallow_untyped_defs = false [[tool.mypy.overrides]] module = "migrations.*" ignore_errors = true EOF if [ "$DJANGO_MODE" = true ] || [ "$HAS_DJANGO" = true ]; then cat >> pyproject.toml << 'EOF' [tool.mypy] plugins = ["mypy_django_plugin.main"] [tool.django-stubs] django_settings_module = "config.settings" EOF fi echo "✓ Created [tool.mypy] section in pyproject.toml" fi ``` ### 5. Create .mypy.ini in home directory (optional) For user-specific defaults: ```bash cat > ~/.mypy.ini << 'EOF' [mypy] # User-wide Mypy defaults warn_unused_ignores = True show_error_codes = True pretty = True EOF ``` ### 6. Add to .gitignore ```bash if [ -f ".gitignore" ]; then if ! grep -q ".mypy_cache" .gitignore; then echo "" >> .gitignore echo "# Mypy cache" >> .gitignore echo ".mypy_cache/" >> .gitignore echo "✓ Added .mypy_cache to .gitignore" fi fi ``` ### 7. Generate VS Code Settings ```bash mkdir -p .vscode if [ ! -f ".vscode/settings.json" ]; then cat > .vscode/settings.json << 'EOF' { "python.linting.enabled": true, "python.linting.mypyEnabled": true, "python.linting.mypyArgs": [ "--show-error-codes", "--show-column-numbers" ] } EOF echo "✓ Created .vscode/settings.json for Mypy" else echo "⚠ .vscode/settings.json already exists" echo " Add Mypy configuration manually if needed" fi ``` ### 8. Generate Pre-commit Hook ```bash if [ -f ".pre-commit-config.yaml" ]; then # Check if Mypy already configured if ! grep -q "mirrors-mypy" .pre-commit-config.yaml; then cat >> .pre-commit-config.yaml << 'EOF' - repo: https://github.com/pre-commit/mirrors-mypy rev: v1.8.0 hooks: - id: mypy args: [--show-error-codes] additional_dependencies: - types-requests - types-PyYAML EOF if [ "$DJANGO_MODE" = true ] || [ "$HAS_DJANGO" = true ]; then cat >> .pre-commit-config.yaml << 'EOF' - django-stubs - mypy-django-plugin EOF fi echo "✓ Added Mypy to .pre-commit-config.yaml" else echo "⚠ Mypy already in .pre-commit-config.yaml" fi else # Create new pre-commit config cat > .pre-commit-config.yaml << 'EOF' repos: - repo: https://github.com/pre-commit/mirrors-mypy rev: v1.8.0 hooks: - id: mypy args: [--show-error-codes] additional_dependencies: - types-requests - types-PyYAML EOF if [ "$DJANGO_MODE" = true ] || [ "$HAS_DJANGO" = true ]; then cat >> .pre-commit-config.yaml << 'EOF' - django-stubs - mypy-django-plugin EOF fi echo "✓ Created .pre-commit-config.yaml with Mypy" fi ``` ### 9. Generate GitHub Actions Workflow ```bash mkdir -p .github/workflows cat > .github/workflows/type-check.yml << 'EOF' name: Type Check on: push: branches: [main, develop] pull_request: branches: [main, develop] jobs: mypy: runs-on: ubuntu-latest strategy: matrix: python-version: ["3.11", "3.12"] steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip pip install mypy EOF if [ "$DJANGO_MODE" = true ] || [ "$HAS_DJANGO" = true ]; then cat >> .github/workflows/type-check.yml << 'EOF' pip install django-stubs mypy-django-plugin EOF fi cat >> .github/workflows/type-check.yml << 'EOF' if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Type check with Mypy run: mypy . - name: Upload Mypy report if: failure() uses: actions/upload-artifact@v4 with: name: mypy-report path: .mypy_cache/ EOF echo "✓ Created .github/workflows/type-check.yml" ``` ### 10. Generate Summary Report ``` Mypy Setup Complete! ==================== Configuration: • Config file: mypy.ini • Mode: Strict • Django plugin: Enabled • Python version: 3.11 Files Created: ✓ mypy.ini ✓ .vscode/settings.json ✓ .pre-commit-config.yaml ✓ .github/workflows/type-check.yml Next Steps: 1. Review and adjust mypy.ini settings 2. Update Django settings module path (if applicable) 3. Run: /mypy-check to test configuration 4. Install pre-commit: pre-commit install 5. Add type hints to your code gradually Gradual Adoption Strategy: 1. Start with new files (keep disallow_untyped_defs = True) 2. Add type hints to critical paths (services, models) 3. Enable stricter checks per module: [mypy-myapp.services.*] disallow_untyped_defs = True 4. Expand coverage over time Resources: • Mypy docs: https://mypy.readthedocs.io/ • Cheat sheet: https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html • Django stubs: https://github.com/typeddjango/django-stubs Run '/mypy-check' to verify your setup! ``` ### 11. Interactive Setup (if no args) If no arguments provided, ask user questions: ``` Mypy Setup Wizard ================= 1. Configuration format? [1] mypy.ini (recommended) [2] pyproject.toml 2. Strictness level? [1] Strict (recommended for new projects) [2] Gradual (for existing projects) 3. Project type? [1] Django [2] FastAPI [3] Generic Python 4. Install Mypy and plugins? [Y/n] 5. Setup IDE integration (VS Code)? [Y/n] 6. Add pre-commit hook? [Y/n] 7. Create GitHub Actions workflow? [Y/n] ``` --- ## Examples ```bash # Basic setup (interactive) /mypy-setup # Strict mode with mypy.ini /mypy-setup --strict # Django project with installation /mypy-setup --django --install # Use pyproject.toml format /mypy-setup --format=toml # Full setup for Django /mypy-setup --strict --django --format=toml --install ``` ## Configuration Templates ### Minimal (Gradual Adoption) ```ini [mypy] python_version = 3.11 warn_return_any = True warn_unused_configs = True show_error_codes = True # Start here, gradually enable more ``` ### Balanced (Recommended) ```ini [mypy] python_version = 3.11 disallow_untyped_defs = True warn_return_any = True warn_unused_configs = True no_implicit_optional = True show_error_codes = True [mypy-tests.*] disallow_untyped_defs = False ``` ### Strict (New Projects) ```ini [mypy] python_version = 3.11 strict = True show_error_codes = True ``` ## Related Skills | Skill | Purpose | |-------|---------| | `python-experts:python-mypy` | Mypy type checking patterns | | `python-experts:python-style` | Python coding standards | ## Related Commands | Command | Purpose | |---------|---------| | `/mypy-check` | Run type checking | | `/python-experts:review-django-commands` | Review Django commands | ## Troubleshooting ### Django Settings Not Found ```bash # Update in mypy.ini [mypy.plugins.django-stubs] django_settings_module = "your_project.settings" ``` ### Import Errors ```bash # Install missing type stubs mypy --install-types ``` ### Too Many Errors Initially Start with: ```ini [mypy] ignore_missing_imports = True check_untyped_defs = False ``` Then gradually remove these.