Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 0 additions & 30 deletions .github/workflows/matchers/flake8.json

This file was deleted.

45 changes: 6 additions & 39 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,47 +1,14 @@
repos:
- repo: https://github.com/asottile/pyupgrade
rev: v3.3.1
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.16.9
hooks:
- id: pyupgrade
args: [--py38-plus]

- repo: https://github.com/PyCQA/autoflake
rev: v2.0.2
hooks:
- id: autoflake

- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
args:
- --quiet
- --safe

- repo: https://github.com/pycqa/flake8
rev: 6.1.0
hooks:
- id: flake8
additional_dependencies:
- flake8-docstrings==1.5.0
- pydocstyle==5.1.1
- Flake8-pyproject==1.2.3

- repo: https://github.com/PyCQA/isort
rev: 5.12.0
hooks:
- id: isort
- id: ruff-check
args: ["--fix", "--exit-non-zero-on-fix"]
- id: ruff-format

- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
rev: v2.4.3
hooks:
- id: codespell
additional_dependencies: [tomli]
args: ["--toml", "pyproject.toml"]

- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.261
hooks:
- id: ruff
args:
- --fix
64 changes: 43 additions & 21 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,49 @@ testing = [
[tool.setuptools-git-versioning]
enabled = true

[tool.isort]
profile = "black"
# will group `import x` and `from x import` of the same module.
force_sort_within_sections = true
known_first_party = ["zigpy_deconz", "tests"]
forced_separate = "tests"
combine_as_imports = true
[tool.ruff]
target-version = "py38"
line-length = 88

[tool.ruff.lint]
select = [
"B", # flake8-bugbear
"C", # complexity
"D", # pydocstyle
"E", # pycodestyle
"F", # pyflakes/autoflake
"I", # isort
"SIM", # flake8-simplify
"UP", # pyupgrade
"W", # pycodestyle
]
ignore = [
"E501", # line too long
"D101", # Missing docstring in public class
"D102", # Missing docstring in public method
"D103", # Missing docstring in public function
"D202", # No blank lines allowed after function docstring
]

[tool.ruff.lint.per-file-ignores]
"tests/*" = [
"F811",
"F401",
"F403",
"SIM117", # merging needs parenthesized `with`, but requires-python is still >=3.8
]

[tool.ruff.lint.mccabe]
max-complexity = 25

[tool.ruff.lint.pydocstyle]
convention = "pep257"

[tool.ruff.lint.isort]
force-sort-within-sections = true
known-first-party = ["zigpy_deconz", "tests"]
forced-separate = ["tests"]
combine-as-imports = true

[tool.mypy]
ignore_errors = true
Expand All @@ -49,20 +85,6 @@ ignore_errors = true
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"

[tool.flake8]
exclude = [".venv", ".git", ".tox", "docs", "venv", "bin", "lib", "deps", "build"]
# To work with Black
max-line-length = 88
# W503: Line break occurred before a binary operator
# E203: Whitespace before ':'
# E501: line too long
# D202 No blank lines allowed after function docstring
ignore = [
"W503", "E203", "E501", "D202",
"D103", "D102", "D101", # TODO: remove these once docstrings are added
]
per-file-ignores = ["tests/*:F811,F401,F403"]

[tool.codespell]
ignore-words-list = ["IntStruct"]
skip = ["./.*", "tests/*", "pyproject.toml"]
Expand Down
6 changes: 1 addition & 5 deletions requirements_test.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# Test dependencies.

asynctest
isort
black
flake8
codecov
colorlog
codespell
Expand All @@ -16,5 +13,4 @@ pytest-timeout
pytest-asyncio>=0.17
pytest>=7.1.3
zigpy>=0.54.1
ruff==0.0.261
Flake8-pyproject
ruff==0.16.9
8 changes: 1 addition & 7 deletions tests/async_mock.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
"""Mock utilities that are async aware."""
import sys

if sys.version_info[:2] < (3, 8):
from asynctest.mock import * # noqa

AsyncMock = CoroutineMock # noqa: F405
else:
from unittest.mock import * # noqa
from unittest.mock import * # noqa
14 changes: 6 additions & 8 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,7 @@ async def test_unknown_command(api, caplog):
assert 0xFF not in deconz_api.COMMAND_SCHEMAS

with caplog.at_level(logging.WARNING):
api.data_received(b"\xFF\xAA\xBB")
api.data_received(b"\xff\xaa\xbb")

assert (
"Unknown command received: Command(command_id=<CommandId.undefined_0xff: 255>,"
Expand All @@ -754,8 +754,7 @@ async def test_bad_command_parsing(api, caplog):
)

assert (
"Failed to parse command Command(command_id="
"<CommandId.aps_data_indication: 23>"
"Failed to parse command Command(command_id=<CommandId.aps_data_indication: 23>"
) in caplog.text

caplog.clear()
Expand Down Expand Up @@ -1068,11 +1067,10 @@ async def test_firmware_responding_with_wrong_type_with_correct_seq(
},
)

with caplog.at_level(logging.DEBUG):
with pytest.raises(asyncio.TimeoutError):
# We wait beyond 500ms to make sure it triggers
async with asyncio_timeout(0.6):
await api.send_command(deconz_api.CommandId.aps_data_confirm)
with caplog.at_level(logging.DEBUG), pytest.raises(asyncio.TimeoutError):
# We wait beyond 500ms to make sure it triggers
async with asyncio_timeout(0.6):
await api.send_command(deconz_api.CommandId.aps_data_confirm)

assert (
"Firmware responded incorrectly (Response is mismatched! Sent"
Expand Down
2 changes: 1 addition & 1 deletion tests/test_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ async def test_energy_scan_conbee_3(app):
"ScannedChannels": Channels.ALL_CHANNELS,
"TotalTransmissions": 0,
"TransmissionFailures": 0,
"EnergyValues": [i for i in range(11, 26 + 1)],
"EnergyValues": list(range(11, 26 + 1)),
}.values()
),
]
Expand Down
4 changes: 2 additions & 2 deletions tests/test_network_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ async def write_parameter(param, *args):
elif channel_mask is not None:
assert params["channel_mask"] == (network_info.channel_mask,)
else:
assert False
raise AssertionError()

assert params["use_predefined_nwk_panid"] == (True,)
assert params["nwk_panid"] == (network_info.pan_id,)
Expand Down Expand Up @@ -340,7 +340,7 @@ async def read_param(param, *args):
except KeyError:
raise zigpy_deconz.exception.CommandError(
zigpy_deconz.api.Status.UNSUPPORTED, f"Unsupported: {param!r} {args!r}"
)
) from None

if isinstance(value, Exception):
raise value
Expand Down
1 change: 0 additions & 1 deletion tests/test_types.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Tests for zigpy_deconz.types module."""


import pytest
import zigpy.types as zigpy_t

Expand Down
30 changes: 15 additions & 15 deletions tests/test_uart.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ def test_send(gw):
gw.send(data)

packet = b""
packet += b"\xC0" # END
packet += b"\xc0" # END
packet += b"test" # data
packet += b"\x40\xFE" # checksum
packet += b"\xC0" # END
packet += b"\x40\xfe" # checksum
packet += b"\xc0" # END

gw._transport.write.assert_called_once_with(packet)

Expand All @@ -60,7 +60,7 @@ def test_close(gw):


def test_data_received_chunk_frame(gw):
data = b"\x07\x01\x00\x08\x00\xaa\x00\x02\x44\xFF\xC0"
data = b"\x07\x01\x00\x08\x00\xaa\x00\x02\x44\xff\xc0"
gw.data_received(data[:-4])
assert gw._api.data_received.call_count == 0
gw.data_received(data[-4:])
Expand All @@ -69,7 +69,7 @@ def test_data_received_chunk_frame(gw):


def test_data_received_full_frame(gw):
data = b"\x07\x01\x00\x08\x00\xaa\x00\x02\x44\xFF\xC0"
data = b"\x07\x01\x00\x08\x00\xaa\x00\x02\x44\xff\xc0"
gw.data_received(data)
assert gw._api.data_received.call_count == 1
assert gw._api.data_received.call_args[0][0] == data[:-3]
Expand All @@ -82,27 +82,27 @@ def test_data_received_incomplete_frame(gw):


def test_data_received_runt_frame(gw):
data = b"\x02\x44\xC0"
data = b"\x02\x44\xc0"
gw.data_received(data)
assert gw._api.data_received.call_count == 0


def test_data_received_extra(gw):
data = b"\x07\x01\x00\x08\x00\xaa\x00\x02\x44\xFF\xC0\x00"
data = b"\x07\x01\x00\x08\x00\xaa\x00\x02\x44\xff\xc0\x00"
gw.data_received(data)
assert gw._api.data_received.call_count == 1
assert gw._api.data_received.call_args[0][0] == data[:-4]
assert gw._buffer == b"\x00"


def test_data_received_wrong_checksum(gw):
data = b"\x07\x01\x00\x08\x00\xaa\x00\x02\x44\xFE\xC0"
data = b"\x07\x01\x00\x08\x00\xaa\x00\x02\x44\xfe\xc0"
gw.data_received(data)
assert gw._api.data_received.call_count == 0


def test_data_received_error(gw, caplog):
data = b"\x07\x01\x00\x08\x00\xaa\x00\x02\x44\xFF\xC0"
data = b"\x07\x01\x00\x08\x00\xaa\x00\x02\x44\xff\xc0"

gw._api.data_received.side_effect = [RuntimeError("error")]

Expand All @@ -116,28 +116,28 @@ def test_data_received_error(gw, caplog):


def test_unescape(gw):
data = b"\x00\xDB\xDC\x00\xDB\xDD\x00\x00\x00"
data_unescaped = b"\x00\xC0\x00\xDB\x00\x00\x00"
data = b"\x00\xdb\xdc\x00\xdb\xdd\x00\x00\x00"
data_unescaped = b"\x00\xc0\x00\xdb\x00\x00\x00"
r = gw._unescape(data)
assert r == data_unescaped


def test_unescape_error(gw):
data = b"\x00\xDB\xDC\x00\xDB\xDD\x00\x00\x00\xDB"
data = b"\x00\xdb\xdc\x00\xdb\xdd\x00\x00\x00\xdb"
r = gw._unescape(data)
assert r is None


def test_escape(gw):
data = b"\x00\xC0\x00\xDB\x00\x00\x00"
data_escaped = b"\x00\xDB\xDC\x00\xDB\xDD\x00\x00\x00"
data = b"\x00\xc0\x00\xdb\x00\x00\x00"
data_escaped = b"\x00\xdb\xdc\x00\xdb\xdd\x00\x00\x00"
r = gw._escape(data)
assert r == data_escaped


def test_checksum(gw):
data = b"\x07\x01\x00\x08\x00\xaa\x00\x02"
checksum = b"\x44\xFF"
checksum = b"\x44\xff"
r = gw._checksum(data)
assert r == checksum

Expand Down
24 changes: 12 additions & 12 deletions zigpy_deconz/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@

try:
LOGGER.debug("Sending %s%s (seq=%s)", cmd, kwargs, seq)
self._uart.send(command.replace(seq=seq).serialize())

Check warning on line 584 in zigpy_deconz/api.py

View workflow job for this annotation

GitHub Actions / shared-ci / Run tests Python 3.14

coroutine 'AsyncMockMixin._execute_mock_call' was never awaited

Check warning on line 584 in zigpy_deconz/api.py

View workflow job for this annotation

GitHub Actions / shared-ci / Run tests Python 3.14

coroutine 'AsyncMockMixin._execute_mock_call' was never awaited

Check warning on line 584 in zigpy_deconz/api.py

View workflow job for this annotation

GitHub Actions / shared-ci / Run tests Python 3.13

coroutine 'AsyncMockMixin._execute_mock_call' was never awaited

Check warning on line 584 in zigpy_deconz/api.py

View workflow job for this annotation

GitHub Actions / shared-ci / Run tests Python 3.13

coroutine 'AsyncMockMixin._execute_mock_call' was never awaited

Check warning on line 584 in zigpy_deconz/api.py

View workflow job for this annotation

GitHub Actions / shared-ci / Run tests Python 3.12

coroutine 'AsyncMockMixin._execute_mock_call' was never awaited

Check warning on line 584 in zigpy_deconz/api.py

View workflow job for this annotation

GitHub Actions / shared-ci / Run tests Python 3.12

coroutine 'AsyncMockMixin._execute_mock_call' was never awaited

Check warning on line 584 in zigpy_deconz/api.py

View workflow job for this annotation

GitHub Actions / shared-ci / Run tests Python 3.11

coroutine 'AsyncMockMixin._execute_mock_call' was never awaited

Check warning on line 584 in zigpy_deconz/api.py

View workflow job for this annotation

GitHub Actions / shared-ci / Run tests Python 3.11

coroutine 'AsyncMockMixin._execute_mock_call' was never awaited

async with asyncio_timeout(COMMAND_TIMEOUT):
return await fut
Expand Down Expand Up @@ -664,19 +664,19 @@
MISMATCHED_RESPONSE_TIMEOUT,
)
# The firmware *sometimes* responds with the correct response later
self._mismatched_response_timers[
command.seq
] = asyncio.get_event_loop().call_later(
MISMATCHED_RESPONSE_TIMEOUT,
fut.set_exception,
MismatchedResponseError(
command.command_id,
params,
(
f"Response is mismatched! Sent {wrong_fut_cmd_id},"
f" received {command.command_id}"
self._mismatched_response_timers[command.seq] = (
asyncio.get_event_loop().call_later(
MISMATCHED_RESPONSE_TIMEOUT,
fut.set_exception,
MismatchedResponseError(
command.command_id,
params,
(
f"Response is mismatched! Sent {wrong_fut_cmd_id},"
f" received {command.command_id}"
),
),
),
)
)

# Make sure we do not resolve the future
Expand Down
Loading
Loading