diff --git a/gpiodevice/__init__.py b/gpiodevice/__init__.py index deaba64..b5aca77 100644 --- a/gpiodevice/__init__.py +++ b/gpiodevice/__init__.py @@ -12,15 +12,15 @@ CHIP_GLOB = "/dev/gpiochip*" +# Deprecated friendly_errors: bool = False @errors.collect -def check_pins_available(chip: gpiod.Chip, pins) -> bool: +def check_pins_available(chip: gpiod.Chip, pins, fatal: bool = True) -> bool: """Check if a list of pins are in use on a given gpiochip device. - Raise a RuntimeError with a friendly list of in-use pins and their consumer if - any are in used. + If any pins are used: raises a helpful list of pins and their consumer if fatal == True, otherwise returns False. """ if pins is None: @@ -42,18 +42,20 @@ def check_pins_available(chip: gpiod.Chip, pins) -> bool: used += 1 yield errors.GPIOError(f"{label}: (line {pin}, {line_info.name}) currently claimed by {line_info.consumer}") - if used and friendly_errors: + if used and fatal: raise errors.ErrorDigest("some pins we need are in use!") return used == 0 @errors.collect -def find_chip_by_label(labels: (list[str], tuple[str], str), pins: dict[str, (int, str)] = None): +def find_chip_by_label(labels: (list[str], tuple[str], str), pins: dict[str, (int, str)] = None, fatal: bool = True): """Try to find a gpiochip device matching one of a set of labels. Raise a RuntimeError with a friendly error digest if one is not found. + If no suitable gpiochip is found: raises a helpful digest of errors if fatal == True, otherwise returns None. + """ if isinstance(labels, str): labels = (labels,) @@ -73,21 +75,26 @@ def find_chip_by_label(labels: (list[str], tuple[str], str), pins: dict[str, (in else: yield errors.GPIONotFound(f"{path}: this is not the GPIO we're looking for! ({label})") - if friendly_errors: + if fatal: raise errors.ErrorDigest("suitable gpiochip device not found!") return None @errors.collect -def find_chip_by_pins(pins: (list[str], tuple[str], str), ignore_claimed: bool = False): +def find_chip_by_pins(pins: (list[str], tuple[str], str), ignore_claimed: bool = False, fatal: bool = True): """Try to find a gpiochip device that includes all of the named pins. Does not care whether pins are in use or not. "pins" can be a single string, a list/tuple or a comma-separated string of names. + If no suitable gpiochip is found: raises a helpful digest of errors if fatal == True, otherwise returns None. + """ + if isinstance(pins, int): + pins = (pins,) + if isinstance(pins, str): if "," in pins: pins = [pin.strip() for pin in pins.split(",")] @@ -106,6 +113,11 @@ def find_chip_by_pins(pins: (list[str], tuple[str], str), ignore_claimed: bool = failed = False for pin_id in pins: + if isinstance(pin_id, int): + failed = True + yield errors.GPIOError(f'{path}: {pin_id} is an int and has been skipped, did you mean "PIN{pin_id}" or "GPIO{pin_id}"?') + continue + try: offset = chip.line_offset_from_id(pin_id) yield errors.GPIOFound(f"{pin_id}: (line {offset}) found - {path} ({label})!") @@ -123,7 +135,7 @@ def find_chip_by_pins(pins: (list[str], tuple[str], str), ignore_claimed: bool = if not failed: return chip - if friendly_errors: + if fatal: raise errors.ErrorDigest("suitable gpiochip not found!") return None diff --git a/gpiodevice/errors.py b/gpiodevice/errors.py index c1bd712..cf2e2ac 100644 --- a/gpiodevice/errors.py +++ b/gpiodevice/errors.py @@ -34,7 +34,7 @@ def __init__(self, message: str, icon: str = "✅"): GPIOBaseError.__init__(self, message, icon) -def collect(fn): +def collect(fn, fatal=False): def wrapper(*args, **kwargs): errors = [] diff --git a/tests/conftest.py b/tests/conftest.py index c80e11e..5febbbc 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,3 +10,12 @@ def gpiod(): sys.modules["gpiod"] = gpiopd yield gpiod del sys.modules["gpiod"] + + +@pytest.fixture(scope="function", autouse=True) +def cleanup(): + yield + try: + del sys.modules["gpiodevice"] + except KeyError: + pass diff --git a/tests/test_features.py b/tests/test_features.py new file mode 100644 index 0000000..b7eae58 --- /dev/null +++ b/tests/test_features.py @@ -0,0 +1,22 @@ +import pytest + + +def test_find_chip_by_pins_int(gpiod): + import gpiodevice + + with pytest.raises(SystemExit): + gpiodevice.find_chip_by_pins(1) + + +def test_find_chip_by_pins_quiet(gpiod): + import gpiodevice + + assert gpiodevice.find_chip_by_pins(1, fatal=False) is None + assert gpiodevice.find_chip_by_pins("GPIO1", fatal=False) is None + + +def test_find_chip_by_pins_str(gpiod): + import gpiodevice + + with pytest.raises(SystemExit): + gpiodevice.find_chip_by_pins("GPIO1") diff --git a/tests/test_setup.py b/tests/test_setup.py deleted file mode 100644 index 38a1cb2..0000000 --- a/tests/test_setup.py +++ /dev/null @@ -1,4 +0,0 @@ -def test_version(gpiod): - import gpiodevice - - assert gpiodevice.find_chip_by_label("test") is None