diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b2dae492..9b257037 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,17 +26,10 @@ jobs: sudo apt-get update sudo apt-get install -y libgirepository1.0-dev python -m pip install --upgrade pip - pip install -e .[server] -r requirements-test.txt - - name: Flake8 - run: flake8 scripts/ matter_server/ - - name: Black - run: black --check scripts/ matter_server/ - - name: isort - run: isort --check scripts/ matter_server/ - - name: pylint - run: pylint matter_server/ - - name: mypy - run: mypy matter_server/ + pip install -e .[server] + pip install -e .[test] + - name: Lint/test with pre-commit + run: pre-commit run --all-files test: runs-on: ubuntu-latest @@ -60,6 +53,7 @@ jobs: sudo apt-get update sudo apt-get install -y libgirepository1.0-dev python -m pip install --upgrade pip - pip install -e .[server] -r requirements-test.txt + pip install -e .[server] + pip install -e .[test] - name: Pytest - run: pytest --durations 10 --cov-report term-missing --cov=matter_server --cov-report=xml tests/server/ + run: pytest --durations 10 --cov-report term-missing --cov=matter_server --cov-report=xml tests/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b4f55b13..dbb047a4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,51 +1,101 @@ # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks repos: - - repo: https://github.com/psf/black - rev: 23.1.0 - hooks: - - id: black - args: - - --quiet - files: ^(matter_server|scripts)/.+\.py$ - - repo: https://github.com/codespell-project/codespell - rev: v2.2.4 + - repo: local hooks: + - id: ruff-check + name: đŸļ Ruff Linter + language: system + types: [python] + entry: scripts/run-in-env.sh ruff check --fix + require_serial: true + stages: [commit, push, manual] + - id: ruff-format + name: đŸļ Ruff Formatter + language: system + types: [python] + entry: scripts/run-in-env.sh ruff format + require_serial: true + stages: [commit, push, manual] + - id: check-ast + name: 🐍 Check Python AST + language: system + types: [python] + entry: scripts/run-in-env.sh check-ast + - id: check-case-conflict + name: 🔠 Check for case conflicts + language: system + entry: scripts/run-in-env.sh check-case-conflict + - id: check-docstring-first + name: ℹī¸ Check docstring is first + language: system + types: [python] + entry: scripts/run-in-env.sh check-docstring-first + - id: check-executables-have-shebangs + name: 🧐 Check that executables have shebangs + language: system + types: [text, executable] + entry: scripts/run-in-env.sh check-executables-have-shebangs + stages: [commit, push, manual] + - id: check-json + name: īŊ› Check JSON files + language: system + types: [json] + entry: scripts/run-in-env.sh check-json + - id: check-merge-conflict + name: đŸ’Ĩ Check for merge conflicts + language: system + types: [text] + entry: scripts/run-in-env.sh check-merge-conflict + - id: check-symlinks + name: 🔗 Check for broken symlinks + language: system + types: [symlink] + entry: scripts/run-in-env.sh check-symlinks + - id: check-toml + name: ✅ Check TOML files + language: system + types: [toml] + entry: scripts/run-in-env.sh check-toml - id: codespell - args: [] - exclude_types: [csv, json] - exclude: ^tests/fixtures/ - additional_dependencies: - - tomli - - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 - hooks: - - id: flake8 - files: ^(matter_server|scripts)/.+\.py$ - - repo: https://github.com/PyCQA/isort - rev: 5.12.0 - hooks: - - id: isort - files: ^(matter_server|scripts)/.+\.py$ - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 - hooks: + name: ✅ Check code for common misspellings + language: system + types: [text] + entry: scripts/run-in-env.sh codespell + - id: detect-private-key + name: đŸ•ĩī¸ Detect Private Keys + language: system + types: [text] + entry: scripts/run-in-env.sh detect-private-key + - id: end-of-file-fixer + name: ⎐ Fix End of Files + language: system + types: [text] + entry: scripts/run-in-env.sh end-of-file-fixer + stages: [commit, push, manual] - id: no-commit-to-branch + name: 🛑 Don't commit to main branch + language: system + entry: scripts/run-in-env.sh no-commit-to-branch + pass_filenames: false + always_run: true args: - --branch=main + - id: pylint + name: 🌟 Starring code with pylint + language: system + types: [python] + entry: scripts/run-in-env.sh pylint - id: trailing-whitespace - - repo: local - hooks: + name: ✄ Trim Trailing Whitespace + language: system + types: [text] + entry: scripts/run-in-env.sh trailing-whitespace-fixer + stages: [commit, push, manual] - id: mypy name: mypy entry: scripts/run-in-env.sh mypy - types: [python] language: script - files: ^(matter_server)/.+\.py$ - - - id: pylint - name: pylint - entry: scripts/run-in-env.sh pylint -j 0 types: [python] - language: script - files: ^(matter_server)/.+\.py$ + require_serial: true + files: ^(matter_server|pylint)/.+\.py$ diff --git a/dashboard/public/index.html b/dashboard/public/index.html index ebd36493..f1050dbc 100644 --- a/dashboard/public/index.html +++ b/dashboard/public/index.html @@ -38,4 +38,3 @@ - diff --git a/dashboard/script/build b/dashboard/script/build index 46e5aa94..39216f0e 100755 --- a/dashboard/script/build +++ b/dashboard/script/build @@ -1,3 +1,5 @@ +#!/bin/bash -i + # Stop on errors set -e @@ -7,4 +9,3 @@ rm -rf dist NODE_ENV=production npm exec -- tsc NODE_ENV=production npm exec -- rollup -c cp -r public/* dist/web - diff --git a/dashboard/script/develop b/dashboard/script/develop index 271f3ddb..d72fabca 100755 --- a/dashboard/script/develop +++ b/dashboard/script/develop @@ -1,3 +1,5 @@ +#!/bin/bash -i + # Stop on errors set -e diff --git a/matter_server/client/models/clusters.py b/matter_server/client/models/clusters.py index 24017432..4e5eb05d 100644 --- a/matter_server/client/models/clusters.py +++ b/matter_server/client/models/clusters.py @@ -13,6 +13,7 @@ from chip.tlv import float32 # pylint: disable=invalid-name,arguments-renamed,no-self-argument +# mypy: ignore_errors=true @dataclass diff --git a/matter_server/common/helpers/json.py b/matter_server/common/helpers/json.py index 30fb0b1c..26a7453e 100644 --- a/matter_server/common/helpers/json.py +++ b/matter_server/common/helpers/json.py @@ -3,9 +3,9 @@ from base64 import b64encode from typing import Any +import orjson from chip.clusters.Types import Nullable from chip.tlv import float32, uint -import orjson JSON_ENCODE_EXCEPTIONS = (TypeError, ValueError) JSON_DECODE_EXCEPTIONS = (orjson.JSONDecodeError,) @@ -16,6 +16,7 @@ def json_encoder_default(obj: Any) -> Any: Hand other objects to the original method. """ + # pylint: disable=too-many-return-statements if getattr(obj, "do_not_serialize", None): return None if isinstance(obj, (set, tuple)): diff --git a/matter_server/common/models.py b/matter_server/common/models.py index 07962bce..a982c4d0 100644 --- a/matter_server/common/models.py +++ b/matter_server/common/models.py @@ -1,4 +1,5 @@ """Models that are (serializeable) shared between server and client.""" + from __future__ import annotations from dataclasses import dataclass, field @@ -178,6 +179,8 @@ class ServerInfoMessage: class CommissionableNodeData: """Object that is returned on the 'discover_commissionable_nodes' command.""" + # pylint: disable=too-many-instance-attributes + instance_name: str | None = None host_name: str | None = None port: int | None = None diff --git a/matter_server/server/device_controller.py b/matter_server/server/device_controller.py index bd8b4cb1..3dc856d0 100644 --- a/matter_server/server/device_controller.py +++ b/matter_server/server/device_controller.py @@ -5,14 +5,15 @@ from __future__ import annotations import asyncio +import logging from collections import deque from datetime import datetime from functools import partial -import logging from typing import TYPE_CHECKING, Any, Awaitable, Callable, Iterable, TypeVar, cast from chip.ChipDeviceCtrl import DeviceProxyWrapper -from chip.clusters import Attribute, Objects as Clusters +from chip.clusters import Attribute +from chip.clusters import Objects as Clusters from chip.clusters.Attribute import ValueDecodeFailure from chip.clusters.ClusterObjects import ALL_ATTRIBUTES, ALL_CLUSTERS, Cluster from chip.exceptions import ChipStackError @@ -93,7 +94,7 @@ ), ) -# pylint: disable=too-many-lines,too-many-locals,too-many-statements,too-many-branches +# pylint: disable=too-many-lines,too-many-locals,too-many-statements,too-many-branches,too-many-instance-attributes class MatterDeviceController: @@ -244,7 +245,7 @@ async def commission_with_code( attempts = 0 # we retry commissioning a few times as we've seen devices in the wild # that are a bit unstable. - # by retrying, we increase the chances of a successful commisssion + # by retrying, we increase the chances of a successful commission while attempts <= MAX_COMMISSION_RETRIES: attempts += 1 LOGGER.info( @@ -322,7 +323,7 @@ async def commission_on_network( attempts = 0 # we retry commissioning a few times as we've seen devices in the wild # that are a bit unstable. - # by retrying, we increase the chances of a successful commisssion + # by retrying, we increase the chances of a successful commission while attempts <= MAX_COMMISSION_RETRIES: attempts += 1 if ip_addr is None: diff --git a/matter_server/server/server.py b/matter_server/server/server.py index c19f3530..5a7a0170 100644 --- a/matter_server/server/server.py +++ b/matter_server/server/server.py @@ -1,11 +1,12 @@ """Implementation of a Websocket-based server to proxy Matter support (using CHIP SDK).""" + from __future__ import annotations import asyncio import ipaddress import logging -from typing import Any, Callable, Set, cast import weakref +from typing import Any, Callable, Set, cast from aiohttp import web @@ -55,6 +56,8 @@ async def _handle_shutdown(app: web.Application) -> None: class MatterServer: """Serve Matter stack over WebSockets.""" + # pylint: disable=too-many-instance-attributes + _runner: web.AppRunner | None = None _http: MultiHostTCPSite | None = None diff --git a/pyproject.toml b/pyproject.toml index ebe8eff9..1ae16b98 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,17 +1,10 @@ [build-system] -requires = ["setuptools>=62.3"] build-backend = "setuptools.build_meta" +requires = ["setuptools>=62.3"] [project] -name = "python-matter-server" -# The version is set by GH action on release -version = "0.0.0" -license = {text = "Apache-2.0"} -description = "Python Matter WebSocket Server" -readme = "README.md" -requires-python = ">=3.10" authors = [ - {name = "The Home Assistant Authors", email = "hello@home-assistant.io"} + {name = "The Home Assistant Authors", email = "hello@home-assistant.io"}, ] classifiers = [ "Development Status :: 3 - Alpha", @@ -19,6 +12,7 @@ classifiers = [ "Environment :: Console", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Topic :: Home Automation", ] dependencies = [ @@ -28,117 +22,243 @@ dependencies = [ "coloredlogs", "dacite", "orjson", - "home-assistant-chip-clusters==2024.1.0" + "home-assistant-chip-clusters==2024.1.0", ] +description = "Python Matter WebSocket Server" +license = {text = "Apache-2.0"} +name = "python-matter-server" +readme = "README.md" +requires-python = ">=3.10" +# The version is set by GH action on release! +version = "0.0.0" [project.optional-dependencies] server = [ "home-assistant-chip-core==2024.1.0", "cryptography==42.0.2", - "zeroconf==0.131.0" + "zeroconf==0.131.0", ] test = [ "black==23.12.1", + "codespell==2.2.6", "flake8==7.0.0", "flake8-docstrings==1.7.0", "isort==5.13.2", "mypy==1.8.0", + "pre-commit==3.6.0", + "pre-commit-hooks==4.5.0", "pylint==3.0.3", "pytest==7.4.4", + "pytest-asyncio==0.23.5", "pytest-aiohttp==1.0.5", "pytest-cov==4.1.0", + "ruff==0.2.1", + "safety==3.0.1", + "tomli==2.0.1", ] [project.scripts] matter-server = "matter_server.server.__main__:main" [tool.codespell] -ignore-words-list = "pase," +ignore-words-list = "requestor" +skip = "dashboard/package-lock.json,tests/fixtures/nodes/lighting-example-app.json" + +[tool.setuptools] +include-package-data = true +platforms = ["any"] +zip-safe = false + +[tool.setuptools.package-data] +matter_server = ["py.typed"] + +[tool.setuptools.packages.find] +include = ["matter_server*"] [tool.mypy] -python_version = "3.10" check_untyped_defs = true -#disallow_any_generics = true +disallow_any_generics = false # TEMPORARY DISABLED disallow_incomplete_defs = true +disallow_subclassing_any = true disallow_untyped_calls = true +disallow_untyped_decorators = true disallow_untyped_defs = true -mypy_path = "matter_server/" +follow_imports = "normal" +ignore_missing_imports = true no_implicit_optional = true -show_error_codes = true +no_implicit_reexport = true +platform = "linux" +python_version = "3.11" +strict_optional = true warn_incomplete_stub = true +warn_no_return = true warn_redundant_casts = true warn_return_any = true warn_unreachable = true warn_unused_configs = true warn_unused_ignores = true -[[tool.mypy.overrides]] -ignore_missing_imports = true -module = [ - "aiorun", +[tool.pylint.MAIN] +extension-pkg-allow-list = [ "chip.*", - "coloredlogs", + "orjson", +] +ignore-paths = [ + "scripts/beautify_diagnostics.py", # TEMPORARY DISABLED + "scripts/generate_devices.py", # TEMPORARY DISABLED ] - -[tool.pytest.ini_options] -asyncio_mode = "auto" - -[tool.setuptools] -platforms = ["any"] -zip-safe = false -include-package-data = true - -[tool.setuptools.package-data] -matter_server = ["py.typed"] - -[tool.setuptools.packages.find] -include = ["matter_server*"] - [tool.pylint.BASIC] -class-const-naming-style = "any" good-names = [ - "_", - "ev", - "ex", - "fp", - "i", - "id", - "j", - "k", - "Run", - "ip", + "_", + "T", ] +[tool.pylint.DESIGN] +max-args = 10 +max-attributes = 12 + [tool.pylint."MESSAGES CONTROL"] -# fixme - we are still a work in progress -# too-many-instance-attributes - just because it is unavoidable -# too-few-public-methods - just because it is unavoidable -# too-many-arguments - just because it is unavoidable disable = [ - "fixme", - "too-many-instance-attributes", - "too-few-public-methods", - "too-many-arguments" + "duplicate-code", # unavoidable + "format", # unavoidable + "unsubscriptable-object", # unavoidable + "unused-argument", # handled by ruff + "unspecified-encoding", # handled by ruff + "isinstance-second-argument-not-valid-type", # conflict with ruff + "fixme", # we're still developing + "too-few-public-methods", # unavoidable ] -[tool.isort] -# https://github.com/PyCQA/isort/wiki/isort-Settings -profile = "black" -# will group `import x` and `from x import` of the same module. -force_sort_within_sections = true -src_paths = [ - "matter_server/client", - "matter_server/common", - "matter_server/server", -] -known_first_party = [ - "matter_server", - "tests", -] -forced_separate = [ - "tests", +[tool.pylint.SIMILARITIES] +ignore-imports = true + +[tool.pylint.FORMAT] +max-line-length = 88 + +[tool.pytest.ini_options] +addopts = "--cov" +asyncio_mode = "auto" + +[tool.ruff] +fix = true +line-length = 88 +show-fixes = true +target-version = "py311" + +[tool.ruff.lint.pydocstyle] +# Use Google-style docstrings. +convention = "pep257" + +[tool.ruff.lint] +ignore = [ + "ANN002", # Just annoying, not really useful + "ANN003", # Just annoying, not really useful + "ANN101", # Self... explanatory + "ANN401", # Opinioated warning on disallowing dynamically typed expressions + "D203", # Conflicts with other rules + "D213", # Conflicts with other rules + "D417", # False positives in some occasions + "FIX002", # Just annoying, not really useful + "PLR2004", # Just annoying, not really useful + "PD011", # Just annoying, not really useful + "S101", # assert is often used to satisfy type checking + "TD002", # Just annoying, not really useful + "TD003", # Just annoying, not really useful + "TD004", # Just annoying, not really useful + "COM812", # Conflict with the Ruff formatter + "ISC001", # Conflict with the Ruff formatter + "I001", # TEMPORARY DISABLED + "TCH003", # TEMPORARY DISABLED + "UP035", # TEMPORARY DISABLED + "TCH002", # TEMPORARY DISABLED + "TID252", # TEMPORARY DISABLED + "N805", # TEMPORARY DISABLED + "EXE002", # TEMPORARY DISABLED + "T201", # TEMPORARY DISABLED + "ANN201", # TEMPORARY DISABLED + "UP032", # TEMPORARY DISABLED + "E711", # TEMPORARY DISABLED + "E501", # TEMPORARY DISABLED + "D104", # TEMPORARY DISABLED + "B018", # TEMPORARY DISABLED + "FBT003", # TEMPORARY DISABLED + "PT012", # TEMPORARY DISABLED + "UP007", # TEMPORARY DISABLED + "D400", # TEMPORARY DISABLED + "D204", # TEMPORARY DISABLED + "PLW2901", # TEMPORARY DISABLED + "RET507", # TEMPORARY DISABLED + "INP001", # TEMPORARY DISABLED + "ARG001", # TEMPORARY DISABLED + "RUF006", # TEMPORARY DISABLED + "SIM108", # TEMPORARY DISABLED + "ANN001", # TEMPORARY DISABLED + "SIM117", # TEMPORARY DISABLED + "TRY003", # TEMPORARY DISABLED + "UP037", # TEMPORARY DISABLED + "UP006", # TEMPORARY DISABLED + "UP041", # TEMPORARY DISABLED + "D202", # TEMPORARY DISABLED + "FBT002", # TEMPORARY DISABLED + "FBT001", # TEMPORARY DISABLED + "PTH123", # TEMPORARY DISABLED + "ANN204", # TEMPORARY DISABLED + "EM102", # TEMPORARY DISABLED + "PLR0915", # TEMPORARY DISABLED + "EM101", # TEMPORARY DISABLED + "EM102", # TEMPORARY DISABLED + "ERA001", # TEMPORARY DISABLED + "PYI036", # TEMPORARY DISABLED + "ANN204", # TEMPORARY DISABLED + "N818", # TEMPORARY DISABLED + "N815", # TEMPORARY DISABLED + "N801", # TEMPORARY DISABLED + "N813", # TEMPORARY DISABLED + "RUF012", # TEMPORARY DISABLED + "TCH001", # TEMPORARY DISABLED + "ANN102", # TEMPORARY DISABLED + "RSE102", # TEMPORARY DISABLED + "B007", # TEMPORARY DISABLED + "SIM102", # TEMPORARY DISABLED + "C901", # TEMPORARY DISABLED + "PLR0911", # TEMPORARY DISABLED + "PLR0912", # TEMPORARY DISABLED + "SLF001", # TEMPORARY DISABLED + "RUF010", # TEMPORARY DISABLED + "TRY300", # TEMPORARY DISABLED + "UP038", # TEMPORARY DISABLED + "PTH118", # TEMPORARY DISABLED + "PTH112", # TEMPORARY DISABLED + "PTH102", # TEMPORARY DISABLED + "TRY400", # TEMPORARY DISABLED + "DTZ001", # TEMPORARY DISABLED + "TRY201", # TEMPORARY DISABLED + "A002", # TEMPORARY DISABLED + "DTZ003", # TEMPORARY DISABLED + "N803", # TEMPORARY DISABLED + "ARG002", # TEMPORARY DISABLED + "S104", # TEMPORARY DISABLED + "UP015", # TEMPORARY DISABLED + "PTH113", # TEMPORARY DISABLED + "PTH107", # TEMPORARY DISABLED + "PTH104", # TEMPORARY DISABLED ] -combine_as_imports = true +select = ["ALL"] + +[tool.ruff.lint.flake8-pytest-style] +fixture-parentheses = false +mark-parentheses = false + +[tool.ruff.lint.isort] +known-first-party = ["matter_server"] + +[tool.ruff.lint.mccabe] +max-complexity = 25 +[tool.ruff.lint.pylint] +max-args = 10 +max-branches = 25 +max-returns = 15 +max-statements = 50 diff --git a/requirements-test.txt b/requirements-test.txt deleted file mode 100644 index 8d91aa9a..00000000 --- a/requirements-test.txt +++ /dev/null @@ -1,9 +0,0 @@ -black==23.12.1 -flake8==7.0.0 -flake8-docstrings==1.7.0 -isort==5.13.2 -mypy==1.8.0 -pylint==3.0.3 -pytest==7.4.4 -pytest-aiohttp==1.0.5 -pytest-cov==4.1.0 diff --git a/scripts/generate_devices.py b/scripts/generate_devices.py old mode 100755 new mode 100644 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 3cced51f..00000000 --- a/setup.cfg +++ /dev/null @@ -1,16 +0,0 @@ - -[flake8] -exclude = .venv,.git,.tox,docs,venv,bin,lib,deps,build -# To work with Black -max-line-length = 88 -# E501: line too long -# W503: Line break occurred before a binary operator -# E203: Whitespace before ':' -# D202 No blank lines allowed after function docstring -# W504 line break after binary operator -ignore = - E501, - W503, - E203, - D202, - W504 diff --git a/tests/common/test_parser.py b/tests/common/test_parser.py index b1f97f10..1859fb17 100644 --- a/tests/common/test_parser.py +++ b/tests/common/test_parser.py @@ -1,15 +1,18 @@ """Test parser functions that converts the incoming json from API into dataclass models.""" + import datetime from dataclasses import dataclass +from enum import Enum, IntEnum from typing import Optional -from enum import IntEnum, Enum import pytest from matter_server.common.helpers.util import dataclass_from_dict + class MatterIntEnum(IntEnum): """Basic Matter Test IntEnum""" + A = 0 B = 1 C = 2 @@ -17,6 +20,7 @@ class MatterIntEnum(IntEnum): class MatterEnum(Enum): """Basic Matter Test Enum""" + A = "a" B = "b" C = "c" @@ -57,7 +61,7 @@ def test_dataclass_from_dict(): "e": {"a": 2, "b": "test", "c": "test", "d": None}, "f": "2022-12-09T06:58:00Z", "g": "a", - "h": 2 + "h": 2, } res = dataclass_from_dict(BasicModel, raw) # test the basic values @@ -95,7 +99,7 @@ def test_dataclass_from_dict(): with pytest.raises(KeyError): raw2 = {**raw} del raw2["a"] - dataclass_from_dict(BasicModel, raw2) + dataclass_from_dict(BasicModel, raw2, strict=True) # test extra keys silently ignored in non-strict mode raw2 = {**raw} raw2["extrakey"] = "something" diff --git a/tests/common/test_utils.py b/tests/common/test_utils.py index 56656d7f..95cf314c 100644 --- a/tests/common/test_utils.py +++ b/tests/common/test_utils.py @@ -11,5 +11,3 @@ def test_convert_functions() -> None: == "2a00:11b7:1231:8400:56ef:44ff:fe49:afc6" ) assert convert_mac_address("ji4yiD/r91c=") == "8e:2e:32:88:3f:eb:f7:57" - - b"\xfe\x80\x00\x00\x00\x00\x00\x00\x04P\x1dB]@\x8eE" diff --git a/tests/fixtures/__init__.py b/tests/fixtures/__init__.py index 5f891f11..860c7f13 100644 --- a/tests/fixtures/__init__.py +++ b/tests/fixtures/__init__.py @@ -1,3 +1,5 @@ +"""Text fixtures for Matter server tests.""" + import pathlib FIXTURES_ROOT = pathlib.Path(__file__).parent diff --git a/tests/ruff.toml b/tests/ruff.toml new file mode 100644 index 00000000..83ab9fd7 --- /dev/null +++ b/tests/ruff.toml @@ -0,0 +1,13 @@ +# This extend our general Ruff rules specifically for tests +extend = "../pyproject.toml" + +lint.extend-select = [ + "PT", # Use @pytest.fixture without parentheses +] + +lint.extend-ignore = [ + "S101", # Use of assert detected. As these are tests... + "SLF001", # Tests will access private/protected members... + "TCH002", # pytest doesn't like this one... + "PT012", # annoying with tests +] diff --git a/tests/server/test_server.py b/tests/server/test_server.py index 8df54785..2636bbea 100644 --- a/tests/server/test_server.py +++ b/tests/server/test_server.py @@ -1,4 +1,5 @@ """Test the server.""" + from __future__ import annotations from collections.abc import AsyncGenerator, Generator @@ -41,7 +42,9 @@ def app_runner_fixture() -> Generator[MagicMock, None, None]: @pytest.fixture(name="multi_host_tcp_site") def multi_host_tcp_site_fixture() -> Generator[MagicMock, None, None]: """Return a mocked tcp site.""" - with patch("matter_server.server.server.MultiHostTCPSite", autospec=True) as multi_host_tcp_site: + with patch( + "matter_server.server.server.MultiHostTCPSite", autospec=True + ) as multi_host_tcp_site: yield multi_host_tcp_site @@ -130,7 +133,7 @@ async def test_server_start( assert server.vendor_id == 1234 assert server.fabric_id == 5678 assert server.port == 5580 - assert server.listen_addresses == None + assert server.listen_addresses is None assert APICommand.SERVER_INFO in server.command_handlers assert APICommand.SERVER_DIAGNOSTICS in server.command_handlers assert APICommand.GET_NODES in server.command_handlers