stm32loader icon indicating copy to clipboard operation
stm32loader copied to clipboard

Fix build with python 3.12

Open ghpzin opened this issue 1 year ago • 0 comments

Fixes incorrect use of assert with mock object that became error on python 3.12: https://github.com/python/cpython/issues/100690

Error while running tests before this fix:
============================= test session starts ==============================
platform linux -- Python 3.12.4, pytest-8.2.2, pluggy-1.5.0
rootdir: /build/stm32loader-0.7.1
configfile: pyproject.toml
collected 49 items                                                             

tests/unit/test_arguments.py .....                                       [ 10%]
tests/unit/test_bootloader.py ..............................FFF......... [ 95%]
.                                                                        [ 97%]
tests/unit/test_hexfile.py .                                             [100%]

=================================== FAILURES ===================================
__________ test_get_uid_for_known_family_reads_at_correct_address[F1] __________

connection = <MagicMock id='140737318300720'>, family = 'F1'

    @pytest.mark.parametrize(
        "family", ["F1", "F3", "F7"],
    )
    def test_get_uid_for_known_family_reads_at_correct_address(connection, family):
        bootloader = Stm32Bootloader(connection, device_family=family)
        bootloader.read_memory = MagicMock()
        bootloader.get_uid()
        uid_address = bootloader.UID_ADDRESS[family]
>       assert bootloader.read_memory.called_once_with(uid_address)

tests/unit/test_bootloader.py:216: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <MagicMock id='140737318289632'>, name = 'called_once_with'

    def __getattr__(self, name):
        if name in {'_mock_methods', '_mock_unsafe'}:
            raise AttributeError(name)
        elif self._mock_methods is not None:
            if name not in self._mock_methods or name in _all_magics:
                raise AttributeError("Mock object has no attribute %r" % name)
        elif _is_magic(name):
            raise AttributeError(name)
        if not self._mock_unsafe and (not self._mock_methods or name not in self._mock_methods):
            if name.startswith(('assert', 'assret', 'asert', 'aseert', 'assrt')) or name in _ATTRIB_DENY_LIST:
>               raise AttributeError(
                    f"{name!r} is not a valid assertion. Use a spec "
                    f"for the mock if {name!r} is meant to be an attribute.")
E               AttributeError: 'called_once_with' is not a valid assertion. Use a spec for the mock if 'called_once_with' is meant to be an attribute.. Did you mean: 'assert_called_once_with'?

/nix/store/l014xp1qxdl6gim3zc0jv3mpxhbp346s-python3-3.12.4/lib/python3.12/unittest/mock.py:663: AttributeError
__________ test_get_uid_for_known_family_reads_at_correct_address[F3] __________

connection = <MagicMock id='140737324790560'>, family = 'F3'

    @pytest.mark.parametrize(
        "family", ["F1", "F3", "F7"],
    )
    def test_get_uid_for_known_family_reads_at_correct_address(connection, family):
        bootloader = Stm32Bootloader(connection, device_family=family)
        bootloader.read_memory = MagicMock()
        bootloader.get_uid()
        uid_address = bootloader.UID_ADDRESS[family]
>       assert bootloader.read_memory.called_once_with(uid_address)

tests/unit/test_bootloader.py:216: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <MagicMock id='140737318384608'>, name = 'called_once_with'

    def __getattr__(self, name):
        if name in {'_mock_methods', '_mock_unsafe'}:
            raise AttributeError(name)
        elif self._mock_methods is not None:
            if name not in self._mock_methods or name in _all_magics:
                raise AttributeError("Mock object has no attribute %r" % name)
        elif _is_magic(name):
            raise AttributeError(name)
        if not self._mock_unsafe and (not self._mock_methods or name not in self._mock_methods):
            if name.startswith(('assert', 'assret', 'asert', 'aseert', 'assrt')) or name in _ATTRIB_DENY_LIST:
>               raise AttributeError(
                    f"{name!r} is not a valid assertion. Use a spec "
                    f"for the mock if {name!r} is meant to be an attribute.")
E               AttributeError: 'called_once_with' is not a valid assertion. Use a spec for the mock if 'called_once_with' is meant to be an attribute.. Did you mean: 'assert_called_once_with'?

/nix/store/l014xp1qxdl6gim3zc0jv3mpxhbp346s-python3-3.12.4/lib/python3.12/unittest/mock.py:663: AttributeError
__________ test_get_uid_for_known_family_reads_at_correct_address[F7] __________

connection = <MagicMock id='140737318373664'>, family = 'F7'

    @pytest.mark.parametrize(
        "family", ["F1", "F3", "F7"],
    )
    def test_get_uid_for_known_family_reads_at_correct_address(connection, family):
        bootloader = Stm32Bootloader(connection, device_family=family)
        bootloader.read_memory = MagicMock()
        bootloader.get_uid()
        uid_address = bootloader.UID_ADDRESS[family]
>       assert bootloader.read_memory.called_once_with(uid_address)

tests/unit/test_bootloader.py:216: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <MagicMock id='140737318299712'>, name = 'called_once_with'

    def __getattr__(self, name):
        if name in {'_mock_methods', '_mock_unsafe'}:
            raise AttributeError(name)
        elif self._mock_methods is not None:
            if name not in self._mock_methods or name in _all_magics:
                raise AttributeError("Mock object has no attribute %r" % name)
        elif _is_magic(name):
            raise AttributeError(name)
        if not self._mock_unsafe and (not self._mock_methods or name not in self._mock_methods):
            if name.startswith(('assert', 'assret', 'asert', 'aseert', 'assrt')) or name in _ATTRIB_DENY_LIST:
>               raise AttributeError(
                    f"{name!r} is not a valid assertion. Use a spec "
                    f"for the mock if {name!r} is meant to be an attribute.")
E               AttributeError: 'called_once_with' is not a valid assertion. Use a spec for the mock if 'called_once_with' is meant to be an attribute.. Did you mean: 'assert_called_once_with'?

/nix/store/l014xp1qxdl6gim3zc0jv3mpxhbp346s-python3-3.12.4/lib/python3.12/unittest/mock.py:663: AttributeError
=========================== short test summary info ============================
FAILED tests/unit/test_bootloader.py::test_get_uid_for_known_family_reads_at_correct_address[F1] - AttributeError: 'called_once_with' is not a valid assertion. Use a spec for...
FAILED tests/unit/test_bootloader.py::test_get_uid_for_known_family_reads_at_correct_address[F3] - AttributeError: 'called_once_with' is not a valid assertion. Use a spec for...
FAILED tests/unit/test_bootloader.py::test_get_uid_for_known_family_reads_at_correct_address[F7] - AttributeError: 'called_once_with' is not a valid assertion. Use a spec for...
========================= 3 failed, 46 passed in 0.88s =========================

Second arg (12) seems to come from inside get_uid, which I assume is the one that was tested with this mock: https://github.com/florisla/stm32loader/blob/c56da3ddf552df033f5445963b0a0fce0259125f/stm32loader/bootloader.py#L530

ghpzin avatar Aug 10 '24 11:08 ghpzin