[tool.ruff] exclude = [ ".git", "__pycache__", "test.py", "tests", "venv", "env", ".venv", ".env", "src/backend/plugins/*", ] src = ["src/backend/InvenTree"] # line-length = 120 [tool.ruff.lint.extend-per-file-ignores] "__init__.py" = ["D104"] [tool.ruff.lint] select = ["A", "B", "C", "C4", "D", "F", "I", "N", "SIM", "PIE", "PLE", "PLW", "RUF", "UP", "W", #"DOC201", "DOC202", # enforce return docs "DOC402","DOC403", # enforce yield docs #"DOC501","DOC502", # enforce raise ] # Things that should be enabled in the future: # - LOG # - DJ # for Django stuff # - S # for security stuff (bandit) # - D401 - Imperative docstrings ignore = [ "PLE1205", # - PLE1205 - Too many arguments for logging format string "PLW2901", # - PLW2901 - Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target "PLW0602","PLW0603","PLW0604", # global variable things "RUF015", # - RUF015 - Prefer next({iterable}) over single element slice "RUF012", # - RUF012 - Mutable class attributes should be annotated with typing.ClassVar "RUF052", # - RUF052 - Local dummy variable is accessed "SIM117", # - SIM117 - Use a single with statement with multiple contexts instead of nested with statements "SIM102", # - SIM102 - Use a single if statement instead of nested if statements "SIM105", # - SIM105 - Use contextlib.suppress({exception}) instead of try-except-pass "C901", # - C901 - function is too complex "N999", # - N802 - function name should be lowercase "N802", # - N806 - variable should be lowercase "N806", # - N812 - lowercase imported as non-lowercase "N812", # - RUF032 - decimal-from-float-literal "RUF032", # - RUF045 - implicit-class-var-in-dataclass "RUF045", # - UP045 - Use `X | None` instead of `Optional[X]` "UP045", # TODO These should be followed up and fixed # - B904 Within an `except` clause, raise exceptions "B904", # Remove fast "A002", "B018" ] [tool.ruff.lint.pydocstyle] convention = "google" ignore-var-parameters = true [tool.ruff.lint.isort] split-on-trailing-comma = false combine-as-imports = false section-order = [ "future", "standard-library", "django", "third-party", "first-party", "local-folder", ] [tool.ruff.lint.isort.sections] "django" = ["django"] [tool.ruff.format] quote-style = "single" indent-style = "space" skip-magic-trailing-comma = true line-ending = "auto" [tool.uv.pip] python-version = "3.12" no-strip-extras=true generate-hashes=true [tool.ty.environment] extra-paths = ["src/backend/InvenTree"] [tool.ty.rules] unresolved-attribute="ignore" # 837 # need Plugin Mixin typing call-non-callable="ignore" # 8 ## invalid-assignment="ignore" # 40 # need to wait for better django field stubs invalid-method-override="ignore" # 103 invalid-return-type="ignore" # 44 ## invalid-argument-type="ignore" # 49 no-matching-overload="ignore" # 10 # need to wait for betterdjango field stubs # warn about unused ignore comments unused-ignore-comment = "error" [tool.coverage.run] source = ["src/backend/InvenTree", "InvenTree"] # sys.monitoring based measurement (Python 3.12+) is much faster than the default tracer. # Note: sysmon does not support 'dynamic_context', so per-test contexts are not recorded. # On older Python versions, coverage falls back to the default core (with a warning). core = "sysmon" omit = ["*/test_migrations.py", "*/migrations/*"] [tool.djlint] ignore = "D018,H006,H008,H020,H021,H023,H025,H030,H031,T002" [tool.isort] src_paths=["src/backend/InvenTree", ] skip_glob ="*/migrations/*.py" known_django="django" sections=["FUTURE","STDLIB","DJANGO","THIRDPARTY","FIRSTPARTY","LOCALFOLDER"] [tool.codespell] ignore-words-list = ["assertIn","SME","intoto","fitH"] [tool.pytest] django_find_project = false pythonpath = ["src/backend/InvenTree"] DJANGO_SETTINGS_MODULE = "InvenTree.settings" python_files = ["test*.py",] timeout = "120" [tool.importlinter] # Architectural import boundaries for the backend, enforced by import-linter (prek). root_packages = [ "InvenTree", "audit", "build", "common", "company", "data_exporter", "generic", "importer", "machine", "order", "part", "plugin", "plugins", "report", "stock", "users", "web", ] include_external_packages = false [[tool.importlinter.contracts]] # Plugins are only allowed to use the documented, stable import targets: # `plugin` , `plugin.mixins`, `plugin.machine` name = "Plugins only import the public plugin API" type = "forbidden" source_modules = ["plugin.builtin", "plugin.samples", "plugins"] forbidden_modules = [ "machine", "plugin", "plugin._internal", "plugin.admin", "plugin.api", "plugin.apps", "plugin.base", "plugin.broken", "plugin.builtin", "plugin.events", # "plugin.machine", - allowed "plugin.migrations", # "plugin.mixins", - allowed "plugin.mock", "plugin.models", "plugin.samples", "plugin.serializers", "plugin.staticfiles", "plugin.template", "plugin.test_api", "plugin.test_plugin", "plugin.test_staticfiles", "plugin.testing", "plugin.urls", ] allow_indirect_imports = true # [[tool.importlinter.contracts]] # name = "Plugin mixins must be layered" # type = "independence" # modules=[ # "plugin.base.*" # ] [[tool.importlinter.contracts]] # `generic` holds shared enums, events and state machines name = "Generic app does not depend on feature apps" type = "forbidden" source_modules = ["generic"] forbidden_modules = [ "build", "company", "importer", "machine", "order", "part", "report", "stock", "users", "web", ] allow_indirect_imports = true ignore_imports = [ "generic.states.tests -> build.status_codes", "generic.states.test_transition -> order.models", "generic.states.test_transition -> order.status_codes", "generic.states.api_helpers -> users.permissions", "generic.states.test_transition -> users.models", ] [[tool.importlinter.contracts]] # Ban dependency cycles between sibling modules/subpackages name = "No dependency cycles inside an app" type = "acyclic_siblings" ancestors = [ "company", "data_exporter", "generic", "report", "stock", "web", ] ignore_imports = ["generic.templatetags.generic -> generic.states.tags"]