[go: up one dir, main page]

File: helpers.py

package info (click to toggle)
luma.core 2.4.2-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 1,040 kB
  • sloc: python: 6,186; makefile: 204
file content (132 lines) | stat: -rw-r--r-- 3,620 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# -*- coding: utf-8 -*-
# Copyright (c) 2017-2022 Richard Hull and contributors
# See LICENSE.rst for details.

"""
Test helpers.
"""

import platform
from pathlib import Path

import pytest
from PIL import ImageChops, ImageFont
from unittest.mock import mock_open


rpi_gpio_missing = f'RPi.GPIO is not supported on this platform: {platform.system()}'
spidev_missing = f'spidev is not supported on this platform: {platform.system()}'


def get_reference_file(fname):
    """
    Get absolute path for ``fname``.

    :param fname: Filename.
    :type fname: str or pathlib.Path
    :rtype: str
    """
    return str(Path(__file__).resolve().parent.joinpath('reference', fname))


def get_reference_image(fname):
    """
    :param fname: Filename.
    :type fname: str or pathlib.Path
    """
    return get_reference_file(Path('images').joinpath(fname))


def get_reference_font(fname, fsize=12):
    """
    :param fname: Filename of the font.
    :type fname: str or pathlib.Path
    """
    path = get_reference_file(Path('font').joinpath(fname))
    return ImageFont.truetype(path, fsize)


def get_reference_pillow_font(fname):
    """
    Load :py:class:`PIL.ImageFont` type font from provided fname

    :param fname: The name of the file that contains the PIL.ImageFont
    :type fname: str
    :rtype: :py:class:`PIL.ImageFont`
    """
    path = get_reference_file(Path('font').joinpath(fname))
    return ImageFont.load(path)


# font used in (most) tests
#test_font = get_reference_pillow_font('courB08.pil')


def get_spidev():
    try:
        import spidev
        return spidev
    except ImportError:
        pytest.skip(spidev_missing)


def assert_identical_image(reference, target, img_path):
    """
    :param img_path: Location of image.
    :type img_path: str
    """
    bbox = ImageChops.difference(reference, target).getbbox()
    #target.save(img_path)
    assert bbox is None, f'{img_path} is not identical to generated image'


def i2c_error(path_name, err_no):
    expected_error = OSError()
    expected_error.errno = err_no
    expected_error.filename = path_name

    def fake_open(a, b):
        raise expected_error
    return fake_open


def fib(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b


# Attribution: https://gist.github.com/adammartinez271828/137ae25d0b817da2509c1a96ba37fc56
def multi_mock_open(*file_contents):
    """Create a mock "open" that will mock open multiple files in sequence
    Args:
        *file_contents ([str]): a list of file contents to be returned by open
    Returns:
        (MagicMock) a mock opener that will return the contents of the first
            file when opened the first time, the second file when opened the
            second time, etc.
    """
    mock_files = [mock_open(read_data=content) for content in file_contents]
    mock_opener = mock_files[-1]
    mock_opener.side_effect = [mock_file.return_value for mock_file in mock_files]

    return mock_opener


def skip_unsupported_platform(err):
    pytest.skip(f'{type(err).__name__} ({str(err)})')


def _positional_args_list(mock):
    return [call[0] for call in mock.call_args_list]


def assert_only_cleans_whats_setup(gpio):
    setups = _positional_args_list(gpio.setup)
    cleanups = _positional_args_list(gpio.cleanup)
    for cleanup in cleanups:
        assert len(cleanup) > 0, 'calling gpio.cleanup without specifying pins cleans all pins'
    pins_set_up = {args[0] for args in setups}
    pins_clean = {args[0] for args in setups}
    assert pins_clean == pins_set_up, f"set pins {pins_set_up} but cleaned pins {pins_clean}"