Files
orion/pyproject.toml
Samir Boulahtit b8a46e1746 fix: protect critical re-export imports from linter removal
Problem:
- Ruff removed 'from app.core.database import Base' from models/database/base.py
- Import appeared "unused" (F401) but was actually a critical re-export
- Caused ImportError: cannot import name 'Base' at runtime
- Re-export pattern: import in one file to export from package

Solution:
1. Added F401 ignore for models/database/base.py in pyproject.toml
2. Created scripts/verify_critical_imports.py verification script
3. Integrated verification into make check and CI pipeline
4. Updated documentation with explanation

New Verification Script:
- Checks all critical re-export imports exist
- Detects import variations (parentheses, 'as' clauses)
- Handles SQLAlchemy declarative_base alternatives
- Runs as part of make check automatically

Protected Files:
- models/database/base.py - Re-exports Base for all models
- models/__init__.py - Exports Base for Alembic
- models/database/__init__.py - Exports Base from package
- All __init__.py files (already protected)

Makefile Changes:
- make verify-imports - Run import verification
- make check - Now includes verify-imports
- make ci - Includes verify-imports in pipeline

Documentation Updated:
- Code quality guide explains re-export protection
- Pre-commit workflow includes verification
- Examples of why re-exports matter

This prevents future issues where linters remove seemingly
"unused" imports that are actually critical for application structure.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 20:10:22 +01:00

162 lines
4.2 KiB
TOML

[build-system]
requires = ["setuptools>=45", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "letzshop-product-import"
version = "0.1.0"
description = "Multi-tenant e-commerce marketplace platform"
requires-python = ">=3.11"
# =============================================================================
# RUFF - Modern All-in-One Linter & Formatter
# =============================================================================
[tool.ruff]
line-length = 88
target-version = "py311"
# Exclude directories
exclude = [
".git",
".venv",
"venv",
"__pycache__",
".mypy_cache",
".pytest_cache",
".ruff_cache",
"build",
"dist",
"alembic/versions",
]
[tool.ruff.lint]
# Enable comprehensive rule sets
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort (import sorting)
"N", # pep8-naming
"UP", # pyupgrade (modern Python syntax)
"B", # flake8-bugbear (common bugs)
"C4", # flake8-comprehensions
"SIM", # flake8-simplify
"PIE", # flake8-pie
"RET", # flake8-return
"Q", # flake8-quotes
]
# Ignore specific rules
ignore = [
"E501", # line too long (handled by formatter)
"B008", # do not perform function calls in argument defaults (FastAPI Depends)
"RET504", # unnecessary variable assignment before return
"SIM102", # use a single if statement instead of nested if (sometimes less readable)
]
# Allow autofix for all rules
fixable = ["ALL"]
unfixable = []
# Per-file ignores
[tool.ruff.lint.per-file-ignores]
# Ignore import violations in __init__.py files (re-exports)
"__init__.py" = ["F401", "F403"]
# Base files that re-export (re-export Base from core.database)
"models/database/base.py" = ["F401"]
# Ignore specific rules in test files
"tests/**/*.py" = ["S101", "PLR2004"]
# Alembic migrations can have longer lines and specific patterns
"alembic/versions/*.py" = ["E501", "F401"]
# Import sorting configuration (replaces isort)
[tool.ruff.lint.isort]
known-first-party = ["app", "models", "middleware", "tasks", "storage", "scripts"]
section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"]
split-on-trailing-comma = true
# Formatter configuration (replaces black)
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"
# =============================================================================
# MYPY - Static Type Checker
# =============================================================================
[tool.mypy]
python_version = "3.11"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = false
ignore_missing_imports = true
exclude = [
"^\\.venv/",
"^venv/",
"^build/",
"^dist/",
"^alembic/versions/",
]
# Per-module options
[[tool.mypy.overrides]]
module = "tests.*"
ignore_errors = true
[[tool.mypy.overrides]]
module = "alembic.*"
ignore_errors = true
# =============================================================================
# PYTEST - Testing
# =============================================================================
[tool.pytest.ini_options]
minversion = "7.0"
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"-v",
"--strict-markers",
"--strict-config",
"--color=yes",
]
markers = [
"unit: Unit tests",
"integration: Integration tests",
"slow: Slow running tests",
]
filterwarnings = [
"ignore::DeprecationWarning",
]
# =============================================================================
# COVERAGE
# =============================================================================
[tool.coverage.run]
source = ["app", "models", "middleware", "tasks", "storage"]
omit = [
"*/tests/*",
"*/__pycache__/*",
"*/venv/*",
"*/.venv/*",
"*/alembic/*",
"*/scripts/*",
]
[tool.coverage.report]
precision = 2
show_missing = true
skip_covered = false
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
"if TYPE_CHECKING:",
"if typing.TYPE_CHECKING:",
]