Source code for circuitpython_mocks._mixins
from collections import deque
from typing import Deque, Union, TYPE_CHECKING
try:
from typing import Self
except ImportError: # pragma: no cover
from typing_extensions import Self
if TYPE_CHECKING:
from circuitpython_mocks.busio.operations import (
I2CRead,
I2CWrite,
I2CTransfer,
I2CScan,
SPIRead,
SPIWrite,
SPITransfer,
UARTRead,
UARTWrite,
UARTFlush,
)
from circuitpython_mocks.digitalio.operations import SetState, GetState
class ContextManaged:
"""An object that automatically deinitializes hardware with a context manager."""
def __enter__(self) -> Self:
return self
def __exit__(self, exc_type, exc_value, traceback) -> None:
self.deinit()
def deinit(self) -> None:
"""Free any hardware used by the object."""
return
class Lockable(ContextManaged):
"""An object that must be locked to prevent collisions on a microcontroller
resource."""
_locked = False
def try_lock(self) -> bool:
"""Attempt to grab the lock. Return `True` on success, `False` if the lock is
already taken."""
if self._locked:
return False
self._locked = True
return True
def unlock(self) -> None:
"""Release the lock so others may use the resource."""
if self._locked:
self._locked = False
[docs]
class Expecting:
"""A base class for the mock classes used to assert expected behaviors.
.. seealso::
:title: Mocks that derive from this mixin class
- `busio.I2C`
- `board.I2C()`
- `board.STEMMA_I2C()`
- `busio.SPI`
- `board.SPI()`
- `board.SPI1()`
- `busio.UART`
- `board.UART()`
- `digitalio.DigitalInOut`
"""
def __init__(self, **kwargs) -> None:
self.expectations: Deque[
Union[
I2CRead,
I2CWrite,
I2CTransfer,
I2CScan,
SPIRead,
SPIWrite,
SPITransfer,
UARTRead,
UARTWrite,
UARTFlush,
SetState,
GetState,
]
] = deque()
"""A double-ended queue (:py:class:`~collections.deque`) used to assert
expected behavior.
.. example::
Examples that use `expectations` can be found in the
- :doc:`busio/index` documentation
- :doc:`digitalio` documentation
- :py:func:`~circuitpython_mocks.fixtures.mock_blinka_imports`
(pytest fixture) documentation
.. _this package's tests files:
https://github.com/2bndy5/CircuitPython-mocks/tree/main/tests
All examples' source is located in `this package's tests files`_.
"""
super().__init__(**kwargs)
[docs]
def done(self):
"""A function that asserts all `expectations` have been used.
This is automatically called from the destructor."""
assert not self.expectations, (
"Some expectations were unused:\n "
+ "\n ".join([repr(x) for x in self.expectations])
)
def __del__(self):
self.done()