diff --git a/docs/_generate_requests_docstrings.py b/docs/_generate_requests_docstrings.py index 5666ee7..112f99c 100644 --- a/docs/_generate_requests_docstrings.py +++ b/docs/_generate_requests_docstrings.py @@ -12,7 +12,7 @@ import importlib.util import inspect import os -from typing import Any, Optional, Type +from typing import Any from pydantic import BaseModel @@ -23,7 +23,7 @@ def __init__(self, name: str, lineno: int, col_offset: int, original_text: str): self.lineno = lineno self.col_offset = col_offset self.original_text = original_text - self.docstring: Optional[str] = None + self.docstring: str | None = None def add_docstring(self, docstring: str) -> None: """Add a docstring to the class.""" @@ -49,7 +49,7 @@ def format_docstring(docstring: str, indent: str) -> str: return '\n'.join(indented_lines) -def get_docstring_from_parent(cls: type) -> Optional[str]: +def get_docstring_from_parent(cls: type) -> str | None: """Get the docstring from the parent class.""" for base in cls.__bases__: if base.__doc__: @@ -57,7 +57,7 @@ def get_docstring_from_parent(cls: type) -> Optional[str]: return None -def get_field_docstring(cls: Type[BaseModel], field_name: str) -> str: +def get_field_docstring(cls: type[BaseModel], field_name: str) -> str: """Get the docstring of a field from the class.""" for name, obj in inspect.getmembers(cls): if name == field_name: @@ -65,7 +65,7 @@ def get_field_docstring(cls: Type[BaseModel], field_name: str) -> str: return "No docstring found." -def format_type(annotation: Type[Any] | None) -> str: +def format_type(annotation: type[Any] | None) -> str: """Format the type to show module and class name.""" if annotation is None: raise ValueError("Annotation cannot be None") @@ -79,7 +79,7 @@ def format_type(annotation: Type[Any] | None) -> str: return str(annotation) # Fallback for other types -def get_pydantic_fields(cls: Type[BaseModel]) -> str: +def get_pydantic_fields(cls: type[BaseModel]) -> str: """Get the fields of a Pydantic model and format them as Google-style Args.""" if not issubclass(cls, BaseModel): return "" @@ -109,7 +109,7 @@ def get_pydantic_fields(cls: Type[BaseModel]) -> str: def parse_file(file_path: str) -> list[ClassInfo]: """Parse the file and extract class definitions.""" - with open(file_path, 'r') as file: + with open(file_path) as file: lines = file.readlines() tree = ast.parse(''.join(lines)) @@ -146,7 +146,7 @@ def update_class_docstrings(file_path: str) -> None: full_docstring = parent_docstring + args_section class_info.add_docstring(full_docstring) - with open(file_path, 'r', encoding="utf-8") as file: + with open(file_path, encoding="utf-8") as file: lines = file.readlines() updated_lines = [] diff --git a/examples/usb/download_file.py b/examples/usb/download_file.py index ad30dc8..6f6e683 100644 --- a/examples/usb/download_file.py +++ b/examples/usb/download_file.py @@ -21,7 +21,7 @@ async def main() -> None: file_data = await client.download_file(file_location) end_s = time.time() duration = end_s - start_s - speed = round(len(file_data) / ((duration)) / 1000, 2) + speed = round(len(file_data) / duration / 1000, 2) print(f"Speed {speed} KB/s") diff --git a/smpclient/__init__.py b/smpclient/__init__.py index 75f5336..b843ec8 100644 --- a/smpclient/__init__.py +++ b/smpclient/__init__.py @@ -26,9 +26,10 @@ import asyncio import logging import traceback +from collections.abc import AsyncIterator from hashlib import sha256 from types import TracebackType -from typing import AsyncIterator, Final, Type +from typing import Final from pydantic import ValidationError from smp import header as smpheader @@ -414,7 +415,7 @@ async def __aenter__(self) -> "SMPClient": async def __aexit__( self, - exc_type: Type[BaseException] | None, + exc_type: type[BaseException] | None, exc_value: BaseException | None, tb: TracebackType | None, ) -> None: diff --git a/smpclient/extensions/intercreate.py b/smpclient/extensions/intercreate.py index 2fa3d7b..f32c61f 100644 --- a/smpclient/extensions/intercreate.py +++ b/smpclient/extensions/intercreate.py @@ -1,6 +1,7 @@ """Intercreate extensions of the `SMPClient`.""" -from typing import AsyncIterator, Final +from collections.abc import AsyncIterator +from typing import Final from smp import header as smpheader diff --git a/smpclient/generics.py b/smpclient/generics.py index 78065ab..89e7b3d 100644 --- a/smpclient/generics.py +++ b/smpclient/generics.py @@ -1,6 +1,6 @@ """Generics and Type Narrowing for SMP Requests and Responses.""" -from typing import Protocol, Type, TypeVar, Union +from typing import Protocol, TypeVar, Union from smp import error as smperror from smp import header as smphdr @@ -32,9 +32,9 @@ class ImageStatesRead(smpimg.ImageStatesReadRequest): ``` """ - _Response: Type[TRep] - _ErrorV1: Type[TEr1] - _ErrorV2: Type[TEr2] + _Response: type[TRep] + _ErrorV1: type[TEr1] + _ErrorV2: type[TEr2] @property def BYTES(self) -> bytes: # pragma: no cover diff --git a/smpclient/transport/ble.py b/smpclient/transport/ble.py index 2176b29..a6abfd3 100644 --- a/smpclient/transport/ble.py +++ b/smpclient/transport/ble.py @@ -4,7 +4,7 @@ import logging import re import sys -from typing import Final, Protocol +from typing import Final, Protocol, TypeGuard from uuid import UUID from bleak import BleakClient, BleakGATTCharacteristic, BleakScanner @@ -12,7 +12,7 @@ from bleak.backends.client import BaseBleakClient from bleak.backends.device import BLEDevice from smp import header as smphdr -from typing_extensions import TypeGuard, override +from typing_extensions import override from smpclient.exceptions import SMPClientException from smpclient.transport import SMPTransport, SMPTransportDisconnected diff --git a/smpclient/transport/serial.py b/smpclient/transport/serial.py index 5f56abb..5553f4a 100644 --- a/smpclient/transport/serial.py +++ b/smpclient/transport/serial.py @@ -227,7 +227,7 @@ async def read_serial(self, delimiter: bytes | None = None) -> bytes: try: first_match, remaining_data = self._serial_buffer.split(delimiter, 1) except ValueError: - return bytes() + return b'' self._serial_buffer = remaining_data return bytes(first_match) diff --git a/tests/fixtures/analyze-mcuboot-img.py b/tests/fixtures/analyze-mcuboot-img.py index 248057a..b53e84c 100644 --- a/tests/fixtures/analyze-mcuboot-img.py +++ b/tests/fixtures/analyze-mcuboot-img.py @@ -107,7 +107,7 @@ def main(): print('Initial image bytes:') start = img_header.hdr_size end = start + min(20, img_header.img_size) - print('\t' + ' '.join('{:02x}'.format(b) for b in contents[start:end])) + print('\t' + ' '.join(f'{b:02x}' for b in contents[start:end])) tlv_info_offset = img_header.hdr_size + img_header.img_size tlv_info = TLVInfo(*struct.unpack_from(TLV_INFO_FMT, contents, offset=tlv_info_offset)) @@ -117,11 +117,11 @@ def main(): tlv_num = 0 while tlv_off < tlv_end: tlv_hdr = TLVHeader(*struct.unpack_from(TLV_HDR_FMT, contents, offset=tlv_off)) - print('TLV {}:'.format(tlv_num), tlv_hdr) + print(f'TLV {tlv_num}:', tlv_hdr) if tlv_hdr.len <= 32: start = tlv_off + TLV_HDR_SIZE end = start + tlv_hdr.len - print('\t' + ' '.join('{:02x}'.format(b) for b in contents[start:end])) + print('\t' + ' '.join(f'{b:02x}' for b in contents[start:end])) tlv_off += TLV_HDR_SIZE + tlv_hdr.len tlv_num += 1 diff --git a/tests/test_requests.py b/tests/test_requests.py index 121c5f9..e57c7ed 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -1,7 +1,5 @@ """Test the `SMPRequest` `Protocol` implementations.""" -from typing import Type - import pytest from smp import enumeration_management as smpem from smp import error as smperr @@ -297,9 +295,9 @@ def test_requests( test_tuple: tuple[ smpmsg.Request, SMPRequest[TRep, TEr1, TEr2], - Type[smpmsg.Response], - Type[smperr.ErrorV1], - Type[smperr.ErrorV2], + type[smpmsg.Response], + type[smperr.ErrorV1], + type[smperr.ErrorV2], ], ) -> None: a, b, Response, ErrorV1, ErrorV2 = test_tuple diff --git a/tests/test_smp_client.py b/tests/test_smp_client.py index ee7e2d1..5df8a12 100644 --- a/tests/test_smp_client.py +++ b/tests/test_smp_client.py @@ -1,6 +1,5 @@ """Tests for `SMPClient`.""" -import sys from hashlib import sha256 from pathlib import Path from unittest.mock import AsyncMock, PropertyMock, call, patch @@ -39,23 +38,6 @@ from smpclient.requests.os_management import ResetWrite from smpclient.transport.serial import SMPSerialTransport -if sys.version_info < (3, 10): - from typing import Any - - async def anext(iterator: Any, default: Any = None) -> Any: - try: - return await iterator.__anext__() - except StopAsyncIteration: - if default is None: - raise - return default - - def aiter(iterable: Any) -> Any: - if hasattr(iterable, '__aiter__'): - return iterable.__aiter__() - else: - raise TypeError(f"{iterable} is not async iterable") - class SMPMockTransport: """Satisfies the `SMPTransport` `Protocol`.""" diff --git a/tests/test_smp_serial_transport.py b/tests/test_smp_serial_transport.py index c679138..df64dab 100644 --- a/tests/test_smp_serial_transport.py +++ b/tests/test_smp_serial_transport.py @@ -3,7 +3,8 @@ from __future__ import annotations import asyncio -from typing import Any, Generator +from collections.abc import Generator +from typing import Any from unittest.mock import AsyncMock, MagicMock, PropertyMock, patch import pytest