"""There are several specific :class:`Exception` classes to allow usercode to react to specific scenarios related to CAN busses:: Exception (Python standard library) +-- ... +-- CanError (python-can) +-- CanInterfaceNotImplementedError +-- CanInitializationError +-- CanOperationError +-- CanTimeoutErrorKeep in mind that some functions and methods may raise different exceptions.For example, validating typical arguments and parameters might result in a:class:`ValueError`. This should always be documented for the function at hand."""importsysfromcontextlibimportcontextmanagerfromtypingimportOptional,Typeifsys.version_info>=(3,9):fromcollections.abcimportGeneratorelse:fromtypingimportGenerator
[docs]classCanError(Exception):"""Base class for all CAN related exceptions. If specified, the error code is automatically appended to the message: .. testsetup:: canerror from can import CanError, CanOperationError .. doctest:: canerror >>> # With an error code (it also works with a specific error): >>> error = CanOperationError(message="Failed to do the thing", error_code=42) >>> str(error) 'Failed to do the thing [Error Code 42]' >>> >>> # Missing the error code: >>> plain_error = CanError(message="Something went wrong ...") >>> str(plain_error) 'Something went wrong ...' :param error_code: An optional error code to narrow down the cause of the fault :arg error_code: An optional error code to narrow down the cause of the fault """def__init__(self,message:str="",error_code:Optional[int]=None,)->None:self.error_code=error_codesuper().__init__(messageiferror_codeisNoneelsef"{message} [Error Code {error_code}]")
[docs]classCanInterfaceNotImplementedError(CanError,NotImplementedError):"""Indicates that the interface is not supported on the current platform. Example scenarios: - No interface with that name exists - The interface is unsupported on the current operating system or interpreter - The driver could not be found or has the wrong version """
[docs]classCanInitializationError(CanError):"""Indicates an error the occurred while initializing a :class:`can.BusABC`. If initialization fails due to a driver or platform missing/being unsupported, a :exc:`~can.exceptions.CanInterfaceNotImplementedError` is raised instead. If initialization fails due to a value being out of range, a :class:`ValueError` is raised. Example scenarios: - Try to open a non-existent device and/or channel - Try to use an invalid setting, which is ok by value, but not ok for the interface - The device or other resources are already used """
[docs]classCanOperationError(CanError):"""Indicates an error while in operation. Example scenarios: - A call to a library function results in an unexpected return value - An invalid message was received - The driver rejected a message that was meant to be sent - Cyclic redundancy check (CRC) failed - A message remained unacknowledged - A buffer is full """
[docs]classCanTimeoutError(CanError,TimeoutError):"""Indicates the timeout of an operation. Example scenarios: - Some message could not be sent after the timeout elapsed - No message was read within the given time """
[docs]@contextmanagerdeferror_check(error_message:Optional[str]=None,exception_type:Type[CanError]=CanOperationError,)->Generator[None,None,None]:"""Catches any exceptions and turns them into the new type while preserving the stack trace."""try:yieldexceptExceptionaserror:# pylint: disable=broad-exceptiferror_messageisNone:raiseexception_type(str(error))fromerrorelse:raiseexception_type(error_message)fromerror