[build-system] requires = ["setuptools~=75.5.0", "wheel~=0.45.0"] build-backend = "setuptools.build_meta" [project] name = "Supervisor" dynamic = ["version", "dependencies"] license = { text = "Apache-2.0" } description = "Open-source private cloud os for Home-Assistant based on HassOS" readme = "README.md" authors = [ { name = "The Home Assistant Authors", email = "hello@home-assistant.io" }, ] keywords = ["docker", "home-assistant", "api"] requires-python = ">=3.12.0" [project.urls] "Homepage" = "https://www.home-assistant.io/" "Source Code" = "https://github.com/home-assistant/supervisor" "Bug Reports" = "https://github.com/home-assistant/supervisor/issues" "Docs: Dev" = "https://developers.home-assistant.io/" "Discord" = "https://www.home-assistant.io/join-chat/" "Forum" = "https://community.home-assistant.io/" [tool.setuptools] platforms = ["any"] zip-safe = false include-package-data = true [tool.setuptools.packages.find] include = ["supervisor*"] [tool.pylint.MAIN] py-version = "3.12" # Use a conservative default here; 2 should speed up most setups and not hurt # any too bad. Override on command line as appropriate. jobs = 2 persistent = false extension-pkg-allow-list = ["ciso8601"] [tool.pylint.BASIC] class-const-naming-style = "any" good-names = ["id", "i", "j", "k", "ex", "Run", "_", "fp", "T", "os"] [tool.pylint."MESSAGES CONTROL"] # Reasons disabled: # format - handled by ruff # abstract-method - with intro of async there are always methods missing # cyclic-import - doesn't test if both import on load # duplicate-code - unavoidable # locally-disabled - it spams too much # too-many-* - are not enforced for the sake of readability # too-few-* - same as too-many-* # unused-argument - generic callbacks and setup methods create a lot of warnings disable = [ "format", "abstract-method", "cyclic-import", "duplicate-code", "locally-disabled", "no-else-return", "not-context-manager", "too-few-public-methods", "too-many-arguments", "too-many-branches", "too-many-instance-attributes", "too-many-lines", "too-many-locals", "too-many-public-methods", "too-many-return-statements", "too-many-statements", "unused-argument", "consider-using-with", # Handled by ruff # Ref: "await-outside-async", # PLE1142 "bad-str-strip-call", # PLE1310 "bad-string-format-type", # PLE1307 "bidirectional-unicode", # PLE2502 "continue-in-finally", # PLE0116 "duplicate-bases", # PLE0241 "format-needs-mapping", # F502 "function-redefined", # F811 # Needed because ruff does not understand type of __all__ generated by a function # "invalid-all-format", # PLE0605 "invalid-all-object", # PLE0604 "invalid-character-backspace", # PLE2510 "invalid-character-esc", # PLE2513 "invalid-character-nul", # PLE2514 "invalid-character-sub", # PLE2512 "invalid-character-zero-width-space", # PLE2515 "logging-too-few-args", # PLE1206 "logging-too-many-args", # PLE1205 "missing-format-string-key", # F524 "mixed-format-string", # F506 "no-method-argument", # N805 "no-self-argument", # N805 "nonexistent-operator", # B002 "nonlocal-without-binding", # PLE0117 "not-in-loop", # F701, F702 "notimplemented-raised", # F901 "return-in-init", # PLE0101 "return-outside-function", # F706 "syntax-error", # E999 "too-few-format-args", # F524 "too-many-format-args", # F522 "too-many-star-expressions", # F622 "truncated-format-string", # F501 "undefined-all-variable", # F822 "undefined-variable", # F821 "used-prior-global-declaration", # PLE0118 "yield-inside-async-function", # PLE1700 "yield-outside-function", # F704 "anomalous-backslash-in-string", # W605 "assert-on-string-literal", # PLW0129 "assert-on-tuple", # F631 "bad-format-string", # W1302, F "bad-format-string-key", # W1300, F "bare-except", # E722 "binary-op-exception", # PLW0711 "cell-var-from-loop", # B023 # "dangerous-default-value", # B006, ruff catches new occurrences, needs more work "duplicate-except", # B014 "duplicate-key", # F601 "duplicate-string-formatting-argument", # F "duplicate-value", # F "eval-used", # PGH001 "exec-used", # S102 # "expression-not-assigned", # B018, ruff catches new occurrences, needs more work "f-string-without-interpolation", # F541 "forgotten-debug-statement", # T100 "format-string-without-interpolation", # F # "global-statement", # PLW0603, ruff catches new occurrences, needs more work "global-variable-not-assigned", # PLW0602 "implicit-str-concat", # ISC001 "import-self", # PLW0406 "inconsistent-quotes", # Q000 "invalid-envvar-default", # PLW1508 "keyword-arg-before-vararg", # B026 "logging-format-interpolation", # G "logging-fstring-interpolation", # G "logging-not-lazy", # G "misplaced-future", # F404 "named-expr-without-context", # PLW0131 "nested-min-max", # PLW3301 # "pointless-statement", # B018, ruff catches new occurrences, needs more work "raise-missing-from", # TRY200 # "redefined-builtin", # A001, ruff is way more stricter, needs work "try-except-raise", # TRY302 "unused-argument", # ARG001, we don't use it "unused-format-string-argument", #F507 "unused-format-string-key", # F504 "unused-import", # F401 "unused-variable", # F841 "useless-else-on-loop", # PLW0120 "wildcard-import", # F403 "bad-classmethod-argument", # N804 "consider-iterating-dictionary", # SIM118 "empty-docstring", # D419 "invalid-name", # N815 "line-too-long", # E501, disabled globally "missing-class-docstring", # D101 "missing-final-newline", # W292 "missing-function-docstring", # D103 "missing-module-docstring", # D100 "multiple-imports", #E401 "singleton-comparison", # E711, E712 "subprocess-run-check", # PLW1510 "superfluous-parens", # UP034 "ungrouped-imports", # I001 "unidiomatic-typecheck", # E721 "unnecessary-direct-lambda-call", # PLC3002 "unnecessary-lambda-assignment", # PLC3001 "unneeded-not", # SIM208 "useless-import-alias", # PLC0414 "wrong-import-order", # I001 "wrong-import-position", # E402 "comparison-of-constants", # PLR0133 "comparison-with-itself", # PLR0124 # "consider-alternative-union-syntax", # UP007, typing extension "consider-merging-isinstance", # PLR1701 # "consider-using-alias", # UP006, typing extension "consider-using-dict-comprehension", # C402 "consider-using-generator", # C417 "consider-using-get", # SIM401 "consider-using-set-comprehension", # C401 "consider-using-sys-exit", # PLR1722 "consider-using-ternary", # SIM108 "literal-comparison", # F632 "property-with-parameters", # PLR0206 "super-with-arguments", # UP008 "too-many-branches", # PLR0912 "too-many-return-statements", # PLR0911 "too-many-statements", # PLR0915 "trailing-comma-tuple", # COM818 "unnecessary-comprehension", # C416 "use-a-generator", # C417 "use-dict-literal", # C406 "use-list-literal", # C405 "useless-object-inheritance", # UP004 "useless-return", # PLR1711 # "no-self-use", # PLR6301 # Optional plugin, not enabled ] [tool.pylint.REPORTS] score = false [tool.pylint.TYPECHECK] ignored-modules = ["distutils"] [tool.pylint.FORMAT] expected-line-ending-format = "LF" [tool.pylint.EXCEPTIONS] overgeneral-exceptions = ["builtins.BaseException", "builtins.Exception"] [tool.pylint.DESIGN] max-positional-arguments = 10 [tool.pytest.ini_options] testpaths = ["tests"] norecursedirs = [".git"] log_format = "%(asctime)s.%(msecs)03d %(levelname)-8s %(threadName)s %(name)s:%(filename)s:%(lineno)s %(message)s" log_date_format = "%Y-%m-%d %H:%M:%S" asyncio_mode = "auto" filterwarnings = [ "error", "ignore:pkg_resources is deprecated as an API:DeprecationWarning:dirhash", "ignore::pytest.PytestUnraisableExceptionWarning", ] [tool.ruff] lint.select = [ "B002", # Python does not support the unary prefix increment "B007", # Loop control variable {name} not used within loop body "B014", # Exception handler with duplicate exception "B023", # Function definition does not bind loop variable {name} "B026", # Star-arg unpacking after a keyword argument is strongly discouraged "B904", # Use raise from to specify exception cause "C", # complexity "COM818", # Trailing comma on bare tuple prohibited "D", # docstrings "DTZ003", # Use datetime.now(tz=) instead of datetime.utcnow() "DTZ004", # Use datetime.fromtimestamp(ts, tz=) instead of datetime.utcfromtimestamp(ts) "E", # pycodestyle "F", # pyflakes/autoflake "G", # flake8-logging-format "I", # isort "ICN001", # import concentions; {name} should be imported as {asname} "N804", # First argument of a class method should be named cls "N805", # First argument of a method should be named self "N815", # Variable {name} in class scope should not be mixedCase "PGH004", # Use specific rule codes when using noqa "PLC0414", # Useless import alias. Import alias does not rename original package. "PLC", # pylint "PLE", # pylint "PLR", # pylint "PLW", # pylint "Q000", # Double quotes found but single quotes preferred "RUF006", # Store a reference to the return value of asyncio.create_task "S102", # Use of exec detected "S103", # bad-file-permissions "S108", # hardcoded-temp-file "S306", # suspicious-mktemp-usage "S307", # suspicious-eval-usage "S313", # suspicious-xmlc-element-tree-usage "S314", # suspicious-xml-element-tree-usage "S315", # suspicious-xml-expat-reader-usage "S316", # suspicious-xml-expat-builder-usage "S317", # suspicious-xml-sax-usage "S318", # suspicious-xml-mini-dom-usage "S319", # suspicious-xml-pull-dom-usage "S320", # suspicious-xmle-tree-usage "S601", # paramiko-call "S602", # subprocess-popen-with-shell-equals-true "S604", # call-with-shell-equals-true "S608", # hardcoded-sql-expression "S609", # unix-command-wildcard-injection "SIM105", # Use contextlib.suppress({exception}) instead of try-except-pass "SIM117", # Merge with-statements that use the same scope "SIM118", # Use {key} in {dict} instead of {key} in {dict}.keys() "SIM201", # Use {left} != {right} instead of not {left} == {right} "SIM208", # Use {expr} instead of not (not {expr}) "SIM212", # Use {a} if {a} else {b} instead of {b} if not {a} else {a} "SIM300", # Yoda conditions. Use 'age == 42' instead of '42 == age'. "SIM401", # Use get from dict with default instead of an if block "T100", # Trace found: {name} used "T20", # flake8-print "TID251", # Banned imports "TRY004", # Prefer TypeError exception for invalid type "TRY302", # Remove exception handler; error is immediately re-raised "UP", # pyupgrade "W", # pycodestyle ] lint.ignore = [ "D202", # No blank lines allowed after function docstring "D203", # 1 blank line required before class docstring "D213", # Multi-line docstring summary should start at the second line "D406", # Section name should end with a newline "D407", # Section name underlining "E501", # line too long "E731", # do not assign a lambda expression, use a def # Ignore ignored, as the rule is now back in preview/nursery, which cannot # be ignored anymore without warnings. # https://github.com/astral-sh/ruff/issues/7491 # "PLC1901", # Lots of false positives # False positives https://github.com/astral-sh/ruff/issues/5386 "PLC0208", # Use a sequence type instead of a `set` when iterating over values "PLR0911", # Too many return statements ({returns} > {max_returns}) "PLR0912", # Too many branches ({branches} > {max_branches}) "PLR0913", # Too many arguments to function call ({c_args} > {max_args}) "PLR0915", # Too many statements ({statements} > {max_statements}) "PLR2004", # Magic value used in comparison, consider replacing {value} with a constant variable "PLW2901", # Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target "UP006", # keep type annotation style as is "UP007", # keep type annotation style as is # Ignored due to performance: https://github.com/charliermarsh/ruff/issues/2923 "UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)` # May conflict with the formatter, https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules "W191", "E111", "E114", "E117", "D206", "D300", "Q000", "Q001", "Q002", "Q003", "COM812", "COM819", "ISC001", "ISC002", # Disabled because ruff does not understand type of __all__ generated by a function "PLE0605", ] [tool.ruff.lint.flake8-import-conventions.extend-aliases] voluptuous = "vol" [tool.ruff.lint.flake8-pytest-style] fixture-parentheses = false [tool.ruff.lint.flake8-tidy-imports.banned-api] "pytz".msg = "use zoneinfo instead" [tool.ruff.lint.isort] force-sort-within-sections = true section-order = [ "future", "standard-library", "third-party", "first-party", "local-folder", ] forced-separate = ["tests"] known-first-party = ["supervisor", "tests"] combine-as-imports = true split-on-trailing-comma = false [tool.ruff.lint.per-file-ignores] # DBus Service Mocks must use typing and names understood by dbus-fast "tests/dbus_service_mocks/*.py" = ["F722", "F821", "N815"] [tool.ruff.lint.mccabe] max-complexity = 25