From def89d84727dde90c0e03d6b73017240827d6af2 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Wed, 7 Aug 2024 03:32:55 -0700 Subject: [PATCH] add I2CScan operation --- circuitpython_mocks/_mixins.py | 2 ++ circuitpython_mocks/busio/__init__.py | 15 ++++++++++++--- circuitpython_mocks/busio/operations.py | 18 ++++++++++++++++++ docs/busio.rst | 1 + tests/test_i2c.py | 14 ++++++++++++-- tests/test_i2c_fixture.py | 2 -- 6 files changed, 45 insertions(+), 7 deletions(-) diff --git a/circuitpython_mocks/_mixins.py b/circuitpython_mocks/_mixins.py index 714ad13..7e819ab 100644 --- a/circuitpython_mocks/_mixins.py +++ b/circuitpython_mocks/_mixins.py @@ -6,6 +6,7 @@ I2CRead, I2CWrite, I2CTransfer, + I2CScan, SPIRead, SPIWrite, SPITransfer, @@ -72,6 +73,7 @@ def __init__(self, **kwargs) -> None: I2CRead, I2CWrite, I2CTransfer, + I2CScan, SPIRead, SPIWrite, SPITransfer, diff --git a/circuitpython_mocks/busio/__init__.py b/circuitpython_mocks/busio/__init__.py index 059ba36..778fcdd 100644 --- a/circuitpython_mocks/busio/__init__.py +++ b/circuitpython_mocks/busio/__init__.py @@ -30,6 +30,7 @@ I2CRead, I2CWrite, I2CTransfer, + I2CScan, SPIRead, SPIWrite, SPITransfer, @@ -82,9 +83,17 @@ def __init__( super().__init__() def scan(self) -> List[int]: - """Returns an empty list. - Use :py:meth:`pytest.MonkeyPatch.setattr()` to change this output.""" - return [] + """Returns a list of I2C device addresses. + + .. mock-expects:: + + This function will check against `I2CScan` + :py:attr:`~circuitpython_mocks._mixins.Expecting.expectations`. + """ + assert self.expectations, "no expectation found for I2C.scan()" + op = self.expectations.popleft() + assert isinstance(op, I2CScan), f"I2CScan operation expected, found {repr(op)}" + return op.expected def readfrom_into( self, diff --git a/circuitpython_mocks/busio/operations.py b/circuitpython_mocks/busio/operations.py index a4588bd..23538f1 100644 --- a/circuitpython_mocks/busio/operations.py +++ b/circuitpython_mocks/busio/operations.py @@ -1,3 +1,4 @@ +from typing import List import sys import circuitpython_typing as cir_py_types @@ -140,6 +141,23 @@ def __repr__(self) -> str: ) +class I2CScan: + """A class to identify a scan operation over a + :py:class:`~circuitpython_mocks.busio.I2C` bus. + + The given ``expected`` value will be the result of `I2C.scan()`. + """ + + def __init__(self, expected: List[int]) -> None: + for val in expected: + assert val <= 0x7F, f"scan result {val} is not a valid I2C address" + self.expected = expected + + def __repr__(self) -> str: + stringify = ", ".join(["%02X" % x for x in self.expected]) + return f"" + + class SPIRead(_Read): """A class to identify a read operation over a :py:class:`~circuitpython_mocks.busio.SPI` bus.""" diff --git a/docs/busio.rst b/docs/busio.rst index b7401da..c04ef58 100644 --- a/docs/busio.rst +++ b/docs/busio.rst @@ -30,6 +30,7 @@ .. autoclass:: circuitpython_mocks.busio.operations.I2CRead .. autoclass:: circuitpython_mocks.busio.operations.I2CWrite .. autoclass:: circuitpython_mocks.busio.operations.I2CTransfer + .. autoclass:: circuitpython_mocks.busio.operations.I2CScan SPI operations ************** diff --git a/tests/test_i2c.py b/tests/test_i2c.py index 3aaa510..9796e4e 100644 --- a/tests/test_i2c.py +++ b/tests/test_i2c.py @@ -1,7 +1,7 @@ import pytest from collections import deque from circuitpython_mocks import busio, board -from circuitpython_mocks.busio.operations import I2CTransfer +from circuitpython_mocks.busio.operations import I2CTransfer, I2CScan @pytest.mark.parametrize( @@ -19,8 +19,18 @@ def test_singleton(board_i2c: busio.I2C, busio_i2c: busio.I2C): assert isinstance(board_i2c.expectations, deque) assert board_i2c == busio_i2c - board_i2c.expectations.append(I2CTransfer(address, bytearray(1), bytearray(1))) + board_i2c.expectations.extend( + [ + I2CScan([address]), + I2CTransfer(address, bytearray(1), bytearray(1)), + ] + ) assert busio_i2c.expectations == board_i2c.expectations + + assert busio_i2c.try_lock() + assert address in board_i2c.scan() + busio_i2c.unlock() + buffer = bytearray(1) assert board_i2c.try_lock() assert not busio_i2c.try_lock() diff --git a/tests/test_i2c_fixture.py b/tests/test_i2c_fixture.py index 0847ce4..0cb04a7 100644 --- a/tests/test_i2c_fixture.py +++ b/tests/test_i2c_fixture.py @@ -15,8 +15,6 @@ def test_i2c(mock_blinka_imports): address = 0x42 # do setup with I2C(board.SCL, board.SDA) as i2c_bus: - assert i2c_bus.scan() == [] - # set expectation for probing performed by I2CDevice.__init__() i2c_bus.expectations.append(I2CWrite(address, b"")) # set expectations for I2C bus