diff --git a/can/io/generic.py b/can/io/generic.py index de8e91700..daead706e 100644 --- a/can/io/generic.py +++ b/can/io/generic.py @@ -1,24 +1,35 @@ -""" -Contains a generic class for file IO. -""" +"""Contains generic base classes for file IO.""" from abc import ABCMeta -from typing import Any, Optional, cast, Union, TextIO, BinaryIO, Type +from typing import ( + Optional, + cast, + Iterable, + Union, + TextIO, + BinaryIO, + Type, + ContextManager, +) +from typing_extensions import Literal +from types import TracebackType import can import can.typechecking -class BaseIOHandler(metaclass=ABCMeta): +class BaseIOHandler(ContextManager, metaclass=ABCMeta): """A generic file handler that can be used for reading and writing. Can be used as a context manager. - :attr Optional[FileLike] file: - the file-like object that is kept internally, or None if none + :attr file: + the file-like object that is kept internally, or `None` if none was opened """ + file: Optional[can.typechecking.FileLike] + def __init__(self, file: can.typechecking.AcceptedIOType, mode: str = "rt") -> None: """ :param file: a path-like object to open a file, a file-like object @@ -39,7 +50,12 @@ def __init__(self, file: can.typechecking.AcceptedIOType, mode: str = "rt") -> N def __enter__(self) -> "BaseIOHandler": return self - def __exit__(self, exc_type: Type, exc_val: Any, exc_tb: Any) -> Any: + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Literal[False]: self.stop() return False @@ -63,5 +79,5 @@ class FileIOMessageWriter(MessageWriter, metaclass=ABCMeta): # pylint: disable=too-few-public-methods -class MessageReader(BaseIOHandler, metaclass=ABCMeta): +class MessageReader(BaseIOHandler, Iterable, metaclass=ABCMeta): """The base class for all readers.""" diff --git a/can/typechecking.py b/can/typechecking.py index d29f1ccaf..1aaf03ac4 100644 --- a/can/typechecking.py +++ b/can/typechecking.py @@ -6,10 +6,10 @@ if typing.TYPE_CHECKING: import os -import mypy_extensions +import typing_extensions -CanFilter = mypy_extensions.TypedDict("CanFilter", {"can_id": int, "can_mask": int}) -CanFilterExtended = mypy_extensions.TypedDict( +CanFilter = typing_extensions.TypedDict("CanFilter", {"can_id": int, "can_mask": int}) +CanFilterExtended = typing_extensions.TypedDict( "CanFilterExtended", {"can_id": int, "can_mask": int, "extended": bool} ) CanFilters = typing.Sequence[typing.Union[CanFilter, CanFilterExtended]] @@ -33,7 +33,7 @@ BusConfig = typing.NewType("BusConfig", typing.Dict[str, typing.Any]) -AutoDetectedConfig = mypy_extensions.TypedDict( +AutoDetectedConfig = typing_extensions.TypedDict( "AutoDetectedConfig", {"interface": str, "channel": Channel} ) diff --git a/examples/simple_log_converter.py b/examples/simple_log_converter.py index f01546375..e82669f54 100755 --- a/examples/simple_log_converter.py +++ b/examples/simple_log_converter.py @@ -18,7 +18,7 @@ def main(): with can.LogReader(sys.argv[1]) as reader: with can.Logger(sys.argv[2]) as writer: - for msg in reader: + for msg in reader: # pylint: disable=not-an-iterable writer.on_message_received(msg) diff --git a/setup.py b/setup.py index d8b76b250..1b56379cf 100644 --- a/setup.py +++ b/setup.py @@ -84,7 +84,7 @@ # "setuptools", "wrapt~=1.10", 'windows-curses;platform_system=="Windows" and platform_python_implementation=="CPython"', - "mypy_extensions>=0.4.0,<0.5.0", + "typing_extensions>=3.10.0.0", 'pywin32;platform_system=="Windows" and platform_python_implementation=="CPython"', 'msgpack~=1.0.0;platform_system!="Windows"', ],