[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" [tool.setuptools.packages.find] include = ["app*", "models*", "middleware*", "storage*"] # ============================================================================= # 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", "scripts/rename_terminology.py", ] [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 = [ "E402", # module level import not at top — late imports used for circular import avoidance "E501", # line too long (handled by formatter) "E711", # comparison to None — intentional in SQLAlchemy filters "E712", # comparison to True/False — intentional in SQLAlchemy filters (e.g. col == True) "E722", # bare except — TODO: fix incrementally "B008", # do not perform function calls in argument defaults (FastAPI Depends) "B904", # raise from — TODO: fix incrementally "RET504", # unnecessary variable assignment before return "SIM102", # use a single if statement instead of nested if (sometimes less readable) "SIM105", # use contextlib.suppress — less readable in some cases "SIM108", # use ternary operator — less readable in some cases "SIM117", # combine with statements — less readable in some cases "N806", # variable in function should be lowercase — intentional for constants "N817", # CamelCase imported as acronym — intentional shorthand "N803", # argument name should be lowercase — required by external APIs (e.g. Apple Wallet) "N818", # exception name should end with Error — existing convention "F821", # undefined name — false positives on forward-reference type hints "F822", # undefined name in __all__ — lazy-loaded module attributes "UP042", # str+Enum → StrEnum — requires Python 3.11+ migration, do incrementally ] # External linter codes used in # noqa comments (architecture/security/performance validators) external = ["SEC", "PERF", "MOD", "EXC"] # 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"] # Test files: late imports, unused imports, naming, assertions "tests/**/*.py" = ["S101", "PLR2004", "E402", "F401", "F821", "F822", "N806", "N817", "N818", "B007", "B015", "B017"] "app/modules/*/tests/**/*.py" = ["S101", "PLR2004", "E402", "F401", "F821", "F822", "N806", "N817", "N818", "B007", "B015", "B017"] # Alembic migrations can have longer lines and specific patterns "alembic/versions/*.py" = ["E501", "F401"] # Scripts: late imports, intentional import-for-side-effect checks, loop vars, syntax "scripts/**/*.py" = ["E402", "F401", "I001", "B007", "B015", "B024", "B027"] "scripts/rename_terminology.py" = ["ALL"] # 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", "app/modules/tenancy/tests", "app/modules/catalog/tests", "app/modules/billing/tests", "app/modules/messaging/tests", "app/modules/orders/tests", "app/modules/customers/tests", "app/modules/marketplace/tests", "app/modules/inventory/tests", "app/modules/loyalty/tests", "app/modules/cms/tests", "app/modules/core/tests", "app/modules/payments/tests", "app/modules/checkout/tests", "app/modules/cart/tests", "app/modules/dev_tools/tests", "app/modules/monitoring/tests", "app/modules/analytics/tests", "app/modules/prospecting/tests", ] python_files = ["test_*.py", "*_test.py"] python_classes = ["Test*"] python_functions = ["test_*"] addopts = [ "-v", "--tb=short", "--strict-markers", "--strict-config", "--color=yes", "--durations=10", "--showlocals", "-ra", "--cov=app", "--cov=models", "--cov=middleware", "--cov-report=term-missing", "--cov-report=html:htmlcov", "--cov-fail-under=0", # Temporarily disabled during test rebuild ] markers = [ # Test level markers "unit: marks tests as unit tests - fast, isolated components", "integration: marks tests as integration tests - multiple components working together", "system: marks tests as system tests - full application behavior", "e2e: marks tests as end-to-end tests - complete user workflows", "slow: marks tests as slow running tests (deselect with '-m \"not slow\"')", "performance: marks tests as performance and load tests", # Context markers "auth: marks tests as authentication and authorization tests", "products: marks tests as product management functionality", "inventory: marks tests as inventory and stock management", "stores: marks tests as store management (plural - admin context)", "store: marks tests as store API tests (singular - store context)", "admin: marks tests as admin functionality and permissions", "marketplace: marks tests as marketplace import functionality", "stats: marks tests as statistics and reporting", "database: marks tests as tests that require database operations", "external: marks tests as tests that require external services", "api: marks tests as API endpoint tests", "security: marks tests as security-related tests", "ci: marks tests as tests that should only run in CI", "dev: marks tests as development-specific tests", # Module markers "loyalty: marks tests related to loyalty program module", "billing: marks tests related to billing and subscriptions module", "tenancy: marks tests related to multi-tenancy and store isolation", "orders: marks tests related to order management", "customers: marks tests related to customer management", "catalog: marks tests related to product catalog", "messaging: marks tests related to email and messaging", "letzshop: marks tests related to Letzshop marketplace integration", "cms: marks tests related to content management system", "core: marks tests related to core platform services", "payments: marks tests related to payment processing", "monitoring: marks tests related to monitoring and observability", "storefront: marks tests for storefront/customer-facing context", "platform: marks tests related to platform administration", "checkout: marks tests related to checkout module", "cart: marks tests related to shopping cart module", "dev_tools: marks tests related to developer tools module", "analytics: marks tests related to analytics module", "prospecting: marks tests related to prospecting and lead generation module", "inventory_module: marks tests related to inventory module", # Component markers "service: marks tests for service layer", "schema: marks tests for Pydantic schemas and database models", "middleware: marks tests for middleware components", "task: marks tests for background tasks", "email: marks tests involving email functionality", "invoice: marks tests for invoicing", "features: marks tests for feature flags", "context: marks tests for context/scope handling", "modules: marks tests for module system", "utils: marks tests for utility functions", ] filterwarnings = [ "ignore::UserWarning", "ignore::DeprecationWarning", "ignore::PendingDeprecationWarning", "ignore::sqlalchemy.exc.SAWarning", ] timeout = 300 timeout_method = "thread" log_cli = true log_cli_level = "INFO" log_cli_format = "%(asctime)s [%(levelname)8s] %(name)s: %(message)s" log_cli_date_format = "%Y-%m-%d %H:%M:%S" # ============================================================================= # 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:", ]