Skip to content

Commit

Permalink
linting: update requirements, add more checks and fix minor issues.
Browse files Browse the repository at this point in the history
Signed-off-by: Romain Bezut <[email protected]>
  • Loading branch information
morian committed Oct 25, 2024
1 parent 52f0794 commit d4fdb21
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 36 deletions.
2 changes: 1 addition & 1 deletion aio_ld2410/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

__version__ = version
__all__ = [
'LD2410',
'AioLd2410Error',
'BaudRateIndex',
'CommandContextError',
Expand All @@ -39,7 +40,6 @@
'ConnectionClosedError',
'FirmwareVersion',
'GateSensitivityConfig',
'LD2410',
'LightControl',
'LightControlConfig',
'LightControlStatus',
Expand Down
45 changes: 28 additions & 17 deletions aio_ld2410/ld2410.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ def configuration(
"""
if not asyncio.iscoroutinefunction(func):
raise RuntimeError('@configuration decorator is only suitable for async methods.')
msg = '@configuration decorator is only suitable for async methods.'
raise RuntimeError(msg)

@functools.wraps(func)
async def _check_config_context(
Expand All @@ -82,7 +83,8 @@ async def _check_config_context(
**kwargs: _ParamSpec.kwargs,
) -> _T:
if not self.configuring:
raise CommandContextError('This method requires a configuration context')
msg = 'This method requires a configuration context'
raise CommandContextError(msg)
return await func(self, *args, **kwargs)

return _check_config_context
Expand Down Expand Up @@ -167,8 +169,8 @@ async def __aenter__(self) -> Self:
"""
if self.entered:
raise RuntimeError("LD2410's instance is already entered!")

msg = "LD2410's instance is already entered!"
raise RuntimeError(msg)
context = await AsyncExitStack().__aenter__()
try:
reader, writer = await self._open_serial_connection()
Expand Down Expand Up @@ -285,7 +287,8 @@ async def _request(
command = Command.build({'code': code, 'data': args})
async with self._request_lock:
if not self.connected:
raise ConnectionClosedError('We are not connected to the device anymore!')
msg = 'We are not connected to the device anymore!'
raise ConnectionClosedError(msg)

async with timeout(self._command_timeout):
frame = CommandFrame.build({'data': command})
Expand All @@ -302,7 +305,8 @@ async def _request(
reply = await replies.get()
replies.task_done()
if reply is None:
raise ConnectionClosedError('Device has disconnected')
msg = 'Device has disconnected'
raise ConnectionClosedError(msg)

valid_reply = bool(code == int(reply.code))
if not valid_reply:
Expand All @@ -311,7 +315,8 @@ async def _request(
# MyPy does not see that reply cannot be None on here.
reply = cast(ConstructReply, reply)
if int(reply.status) != ReplyStatus.SUCCESS:
raise CommandStatusError(f'Command {code} received bad status: {reply.status}')
msg = f'Command {code} received bad status: {reply.status}'
raise CommandStatusError(msg)

return reply

Expand Down Expand Up @@ -398,7 +403,8 @@ async def get_distance_resolution(self) -> int:
return 20
if index == ResolutionIndex.RESOLUTION_75CM:
return 75
raise CommandReplyError(f'Unhandled distance resolution index {index}')
msg = f'Unhandled distance resolution index {index}'
raise CommandReplyError(msg)

@configuration
async def get_firmware_version(self) -> FirmwareVersion:
Expand Down Expand Up @@ -585,7 +591,8 @@ async def restart_module(self, *, close_config_context: bool = False) -> None:
self._restarted = True

if close_config_context:
raise ModuleRestartedError("Module is being restarted from user's request.")
msg = "Module is being restarted from user's request."
raise ModuleRestartedError(msg)

@configuration
async def set_baud_rate(self, baud_rate: int) -> None:
Expand All @@ -610,7 +617,8 @@ async def set_baud_rate(self, baud_rate: int) -> None:
try:
index = BaudRateIndex.from_integer(baud_rate)
except KeyError:
raise CommandParamError(f'Unknown index for baud rate {baud_rate}') from None
msg = f'Unknown index for baud rate {baud_rate}'
raise CommandParamError(msg) from None

await self._request(CommandCode.BAUD_RATE_SET, {'index': int(index)})

Expand Down Expand Up @@ -650,9 +658,8 @@ async def set_bluetooth_password(self, password: str) -> None:
"""
if len(password) > 6 or not password.isascii():
raise CommandParamError(
'Bluetooth password must have less than 7 ASCII characters.'
)
msg = 'Bluetooth password must have less than 7 ASCII characters.'
raise CommandParamError(msg)
await self._request(CommandCode.BLUETOOTH_PASSWORD_SET, {'password': password})

@configuration
Expand Down Expand Up @@ -682,7 +689,8 @@ async def set_distance_resolution(self, resolution: int) -> None:
if resolution == 20:
index = ResolutionIndex.RESOLUTION_20CM
elif resolution != 75:
raise CommandParamError(f'Unknown index for distance resolution {resolution}')
msg = f'Unknown index for distance resolution {resolution}'
raise CommandParamError(msg)
await self._request(CommandCode.DISTANCE_RESOLUTION_SET, {'resolution': index})

@configuration
Expand Down Expand Up @@ -743,7 +751,8 @@ async def set_light_control(self, **kwargs: Unpack[LightControlConfig]) -> None:
data = LightControlConfig(**kwargs)
missing = LightControlConfig.__required_keys__.difference(data.keys())
if missing:
raise CommandParamError(f'Missing parameters: {set(missing)}')
msg = f'Missing parameters: {set(missing)}'
raise CommandParamError(msg)
await self._request(CommandCode.LIGHT_CONTROL_SET, data)

@configuration
Expand Down Expand Up @@ -783,7 +792,8 @@ async def set_parameters(self, **kwargs: Unpack[ParametersConfig]) -> None:
data = ParametersConfig(**kwargs)
missing = ParametersConfig.__required_keys__.difference(data.keys())
if missing:
raise CommandParamError(f'Missing parameters: {set(missing)}')
msg = f'Missing parameters: {set(missing)}'
raise CommandParamError(msg)
await self._request(CommandCode.PARAMETERS_WRITE, data)

@configuration
Expand Down Expand Up @@ -823,5 +833,6 @@ async def set_gate_sensitivity(self, **kwargs: Unpack[GateSensitivityConfig]) ->
data = GateSensitivityConfig(**kwargs)
missing = GateSensitivityConfig.__required_keys__.difference(data.keys())
if missing:
raise CommandParamError(f'Missing parameters: {set(missing)}')
msg = f'Missing parameters: {set(missing)}'
raise CommandParamError(msg)
await self._request(CommandCode.GATE_SENSITIVITY_SET, data)
4 changes: 2 additions & 2 deletions aio_ld2410/protocol/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class ResolutionIndex(IntEnum):
CommandCode.CONFIG_DISABLE: Pass,
# The following configuration is lost on restart.
CommandCode.CONFIG_ENABLE: Struct('value' / Const(1, Int16ul)),
## The following commands are only available on LD2410C.
# All the following commands are only available on LD2410C.
# The following command is only available through bluetooth.
CommandCode.BLUETOOTH_AUTHENTICATE: Struct(
'password' / PaddedString(6, 'ascii'),
Expand Down Expand Up @@ -225,7 +225,7 @@ class ResolutionIndex(IntEnum):
'protocol_version' / Int16ul,
'buffer_size' / Int16ul,
),
## The following replies can only be received on LD2410C.
# All the following replies can only be received on LD2410C.
CommandCode.BLUETOOTH_AUTHENTICATE: Pass,
CommandCode.BLUETOOTH_PASSWORD_SET: Pass,
CommandCode.DISTANCE_RESOLUTION_SET: Pass,
Expand Down
2 changes: 1 addition & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
furo==2024.8.6
sphinx==8.1.2
sphinx==8.1.3
sphinx_autodoc_typehints==2.5.0
sphinx_copybutton==0.5.2
sphinx_inline_tabs==2023.4.21
Expand Down
12 changes: 9 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,11 @@ select = [
'D', # pydocstyle
'DTZ', # flake8-datetimez
'E', # pycodestyle errors
'ERA', # eradicate
'F', # Pyflakes
'FA', # flake8-future-annotations
'I', # isort
'INP', # flake8-no-pep420
'LOG', # flake8-logging
'N', # pep8-naming
'PIE', # flake8-pie
Expand All @@ -123,7 +125,9 @@ select = [
'S', # flake8-bandit
'SIM', # flake8-simplify
'SLF', # flake8-self
'T20', # flake8-print
'TCH', # flake8-type-checking
'TRY', # tryceratops
'UP', # pyupgrade
'W', # pycodestyle warnings
]
Expand Down Expand Up @@ -158,9 +162,11 @@ max-complexity = 10

[tool.ruff.lint.per-file-ignores]
'docs/conf.py' = [
'A001', # Variable is shadowing a Python builtin
'E402', # Module level import not at top of file
'F401', # aio_ld2410.version imported but unused
'A001', # Variable is shadowing a Python builtin
'E402', # Module level import not at top of file
'E266', # Too many leading `#` before block comment
'INP001', # File is part of an implicit namespace package
'F401', # aio_ld2410.version imported but unused
]
'tests/*.py' = [
'D', # pydocstyle
Expand Down
4 changes: 0 additions & 4 deletions tests/protocol/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ def test_commands(code, trace):
frame_rebuild = CommandFrame.build({'data': command_rebuild})
assert frame_rebuild == raw

print(command)


@pytest.mark.parametrize(('code', 'trace'), _REPLY_TRACES.items())
def test_replies(code, trace):
Expand All @@ -111,5 +109,3 @@ def test_replies(code, trace):
# Rebuild the frame around the command and check it.
frame_rebuild = CommandFrame.build({'data': reply_rebuild})
assert frame_rebuild == raw

print(reply)
7 changes: 5 additions & 2 deletions tests/protocol/test_reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

@pytest.mark.parametrize(('type_', 'trace'), _TRACES.items())
def test_good_reports(type_, trace):
frame = ReportFrame.parse(bytes.fromhex(trace))
raw = bytes.fromhex(trace)
frame = ReportFrame.parse(raw)
report = Report.parse(frame.data)
print(report)
report_rebuild = Report.build(report)
frame_rebuild = ReportFrame.build({'data': report_rebuild})
assert frame_rebuild == raw
4 changes: 2 additions & 2 deletions tests/requirements-linting.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mypy==1.11.2
ruff==0.6.9
mypy==1.13.0
ruff==0.7.1
construct-typing==0.6.2
typing_extensions==4.12.2
4 changes: 2 additions & 2 deletions tests/requirements-testing.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
anyio==4.6.0
coverage==7.6.2
anyio==4.6.2.post1
coverage==7.6.4
pytest-cov==5.0.0
pytest-timeout==2.3.1
pytest==8.3.3
8 changes: 6 additions & 2 deletions tests/test_ld2410.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
import logging

# Python 3.9 and lower have a distinct class for asyncio.TimeoutError.
from asyncio import StreamReader, StreamWriter, TimeoutError
from asyncio import (
StreamReader,
StreamWriter,
TimeoutError as AsyncTimeoutError,
)
from dataclasses import asdict

import pytest
Expand Down Expand Up @@ -359,7 +363,7 @@ async def test_good_engineering_report(self, device):
async def test_no_report_while_config(self, device):
"""Check that we get no report while configuring."""
async with device.configure():
with pytest.raises(TimeoutError):
with pytest.raises(AsyncTimeoutError):
# 500ms is enough since we generate a report every 100ms.
await asyncio.wait_for(device.get_next_report(), timeout=0.5)

Expand Down

0 comments on commit d4fdb21

Please sign in to comment.