Skip to content

Commit

Permalink
QA: Apply black reformatting.
Browse files Browse the repository at this point in the history
  • Loading branch information
Gadgetoid committed Nov 2, 2023
1 parent 7015e38 commit 19a917e
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 79 deletions.
68 changes: 35 additions & 33 deletions gpio/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
__version__ = '1.0.0'
__version__ = "1.0.0"

from threading import Lock

try:
from collections.abc import Iterable
except ImportError:
Expand All @@ -13,11 +14,11 @@
_open_pins = {}


GPIO_ROOT = '/sys/class/gpio'
GPIO_EXPORT = os.path.join(GPIO_ROOT, 'export')
GPIO_UNEXPORT = os.path.join(GPIO_ROOT, 'unexport')
FMODE = 'w+' # w+ overwrites and truncates existing files
IN, OUT = 'in', 'out'
GPIO_ROOT = "/sys/class/gpio"
GPIO_EXPORT = os.path.join(GPIO_ROOT, "export")
GPIO_UNEXPORT = os.path.join(GPIO_ROOT, "unexport")
FMODE = "w+" # w+ overwrites and truncates existing files
IN, OUT = "in", "out"
LOW, HIGH = 0, 1


Expand All @@ -35,14 +36,15 @@ class GPIOPin(object):
Raises:
RuntimeError: if pin is already configured
"""

def __init__(self, pin, direction=None, initial=LOW, active_low=None):
# .configured() will raise a TypeError if "pin" is not convertible to int
if GPIOPin.configured(pin, False) is not None:
raise RuntimeError("pin {} is already configured".format(pin))

self.value = None
self.pin = int(pin)
self.root = os.path.join(GPIO_ROOT, 'gpio{0}'.format(self.pin))
self.root = os.path.join(GPIO_ROOT, "gpio{0}".format(self.pin))

if not os.path.exists(self.root):
with _export_lock:
Expand All @@ -51,7 +53,7 @@ def __init__(self, pin, direction=None, initial=LOW, active_low=None):
f.flush()

# Using unbuffered binary IO is ~ 3x faster than text
self.value = open(os.path.join(self.root, 'value'), 'wb+', buffering=0)
self.value = open(os.path.join(self.root, "value"), "wb+", buffering=0)

# I hate manually calling .setup()!
self.setup(direction, initial, active_low)
Expand Down Expand Up @@ -95,46 +97,46 @@ def configured(pin, assert_configured=True):
return _open_pins.get(pin)

def get_direction(self):
'''Get the direction of pin
"""Get the direction of pin
Returns:
str: "in" or "out"
'''
with open(os.path.join(self.root, 'direction'), FMODE) as f:
"""
with open(os.path.join(self.root, "direction"), FMODE) as f:
return f.read().strip()

def set_direction(self, mode):
'''Set the direction of pin
"""Set the direction of pin
Args:
mode (str): use either gpio.OUT or gpio.IN
'''
"""
if mode not in (IN, OUT, LOW, HIGH):
raise ValueError("Unsupported pin mode {}".format(mode))

with open(os.path.join(self.root, 'direction'), FMODE) as f:
with open(os.path.join(self.root, "direction"), FMODE) as f:
f.write(str(mode))
f.flush()

def set_active_low(self, active_low):
'''Set the polarity of pin
"""Set the polarity of pin
Args:
mode (bool): True = active low / False = active high
'''
"""
if not isinstance(active_low, bool):
raise ValueError("active_low must be True or False")

with open(os.path.join(self.root, 'active_low'), FMODE) as f:
f.write('1' if active_low else '0')
with open(os.path.join(self.root, "active_low"), FMODE) as f:
f.write("1" if active_low else "0")
f.flush()

def read(self):
'''Read pin value
"""Read pin value
Returns:
int: gpio.HIGH or gpio.LOW
'''
"""
self.value.seek(0)
value = self.value.read()
try:
Expand All @@ -147,20 +149,20 @@ def read(self):
return int(value)

def write(self, value):
'''Write pin value
"""Write pin value
Args:
value (bool): use either gpio.HIGH or gpio.LOW
'''
"""
# write as bytes, about 3x faster than string IO
self.value.write(b'1' if value else b'0')
self.value.write(b"1" if value else b"0")

def cleanup(self):
'''Clean up pin
"""Clean up pin
Unexports the pin and deletes it from the open list.
'''
"""
# Note: I have not put "cleanup" into the __del__ method since it's not
# always desirable to unexport pins at program exit.
# Additionally "open" can be deleted *before* the GPIOPin instance.
Expand Down Expand Up @@ -203,7 +205,7 @@ def cleanup(pin=None, assert_exists=False):

# TODO RPi.GPIO uses "pull_up_down", does rpio differ?
def setup(pins, mode, pullup=None, initial=LOW, active_low=None):
'''Setup pin with mode IN or OUT.
"""Setup pin with mode IN or OUT.
Args:
pin (int):
Expand All @@ -213,7 +215,7 @@ def setup(pins, mode, pullup=None, initial=LOW, active_low=None):
initial (bool, optional): Initial pin value. Default is LOW
active_low (bool, optional): Set the pin to active low. Default
is None which leaves things as configured in sysfs
'''
"""
if not isinstance(pins, Iterable):
pins = [pins]

Expand All @@ -231,33 +233,33 @@ def setup(pins, mode, pullup=None, initial=LOW, active_low=None):


def mode(pin):
'''get the pin mode
"""get the pin mode
Returns:
str: "in" or "out"
'''
"""
return GPIOPin.configured(pin).get_direction()


def read(pin):
'''read the pin value
"""read the pin value
Returns:
bool: either gpio.LOW or gpio.HIGH
'''
"""
# These function calls lose us a little speed
# but we're already > 2x faster so...
# If you want things to be faster use a GPIOPin instance directly.
return GPIOPin.configured(pin).read()


def write(pin, value):
'''set the pin value to LOW or HIGH
"""set the pin value to LOW or HIGH
Args:
pin (int): any configured pin
value (bool): use gpio.LOW or gpio.HIGH
'''
"""
# These function calls lose us a little speed
# but we're already > 2x faster so...
# If you want things to be faster use a GPIOPin instance directly.
Expand Down
3 changes: 2 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ def patch_open():
@pytest.fixture
def gpio():
import gpio

yield gpio
del sys.modules['gpio']
del sys.modules["gpio"]
88 changes: 43 additions & 45 deletions tests/test_gpio.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@
def test_setup_rpio(gpio, patch_open):
gpio.setup(10, gpio.OUT)

patch_open.assert_any_call('/sys/class/gpio/export', 'w+')
patch_open().__enter__().write.assert_any_call('10')
patch_open.assert_any_call("/sys/class/gpio/export", "w+")
patch_open().__enter__().write.assert_any_call("10")

patch_open.assert_any_call('/sys/class/gpio/gpio10/value', 'wb+', buffering=0)
patch_open.assert_any_call('/sys/class/gpio/gpio10/direction', 'w+')
patch_open.assert_any_call("/sys/class/gpio/gpio10/value", "wb+", buffering=0)
patch_open.assert_any_call("/sys/class/gpio/gpio10/direction", "w+")
patch_open().__enter__().write.assert_any_call(str(gpio.OUT))


def test_setup_class(gpio, patch_open):
_ = gpio.GPIOPin(10, gpio.OUT)

patch_open.assert_any_call('/sys/class/gpio/export', 'w+')
patch_open().__enter__().write.assert_any_call('10')
patch_open.assert_any_call("/sys/class/gpio/export", "w+")
patch_open().__enter__().write.assert_any_call("10")

patch_open.assert_any_call('/sys/class/gpio/gpio10/value', 'wb+', buffering=0)
patch_open.assert_any_call('/sys/class/gpio/gpio10/direction', 'w+')
patch_open.assert_any_call("/sys/class/gpio/gpio10/value", "wb+", buffering=0)
patch_open.assert_any_call("/sys/class/gpio/gpio10/direction", "w+")
patch_open().__enter__().write.assert_any_call(str(gpio.OUT))


Expand Down Expand Up @@ -99,8 +99,8 @@ def test_cleanup_class_unexports_pin(gpio, patch_open):
pin.root = "/dev/null" # Pass os.path.exists check
pin.cleanup()

patch_open.assert_any_call('/sys/class/gpio/unexport', 'w+')
patch_open().__enter__().write.assert_any_call('10')
patch_open.assert_any_call("/sys/class/gpio/unexport", "w+")
patch_open().__enter__().write.assert_any_call("10")


def test_setup_pin_is_not_int(gpio, patch_open):
Expand All @@ -123,46 +123,54 @@ def test_set_active_low(gpio, patch_open):

patch_open.reset_mock()
pin.set_active_low(False)
patch_open.assert_has_calls((
mock.call().__enter__().write('0'),
mock.call().__enter__().flush(),
))
patch_open.assert_has_calls(
(
mock.call().__enter__().write("0"),
mock.call().__enter__().flush(),
)
)

patch_open.reset_mock()
pin.set_active_low(True)
patch_open.assert_has_calls((
mock.call().__enter__().write('1'),
mock.call().__enter__().flush(),
))
patch_open.assert_has_calls(
(
mock.call().__enter__().write("1"),
mock.call().__enter__().flush(),
)
)

with pytest.raises(ValueError):
pin.set_active_low(None)


def test_setup_active_low(gpio, patch_open):
pin = gpio.GPIOPin(10, gpio.OUT, active_low=False)
patch_open.assert_has_calls((
mock.call().__enter__().write('0'),
mock.call().__enter__().flush(),
))
patch_open.assert_has_calls(
(
mock.call().__enter__().write("0"),
mock.call().__enter__().flush(),
)
)
pin.cleanup()

patch_open.reset_mock()
pin = gpio.GPIOPin(10, gpio.OUT, active_low=True)
patch_open.assert_has_calls((
mock.call().__enter__().write('1'),
mock.call().__enter__().flush(),
))
patch_open.assert_has_calls(
(
mock.call().__enter__().write("1"),
mock.call().__enter__().flush(),
)
)


def test_get_direction(gpio, patch_open):
pin = gpio.GPIOPin(10, gpio.IN)

patch_open().__enter__().read.return_value = 'in\n'
patch_open().__enter__().read.return_value = "in\n"
assert pin.get_direction() == gpio.IN
assert gpio.mode(10) == gpio.IN

patch_open().__enter__().read.return_value = 'out\n'
patch_open().__enter__().read.return_value = "out\n"
assert pin.get_direction() == gpio.OUT
assert gpio.mode(10) == gpio.OUT

Expand All @@ -173,9 +181,7 @@ def test_set_direction(gpio, patch_open):
for direction in (gpio.IN, gpio.OUT):
patch_open.reset_mock()
pin.set_direction(direction)
patch_open.assert_has_calls((
mock.call().__enter__().write(direction),
))
patch_open.assert_has_calls((mock.call().__enter__().write(direction),))

with pytest.raises(ValueError):
pin.set_direction(None)
Expand All @@ -191,36 +197,28 @@ def test_write(gpio, patch_open):

patch_open.reset_mock()
pin.write(False)
patch_open.assert_has_calls((
mock.call().write(b'0'),
))
patch_open.assert_has_calls((mock.call().write(b"0"),))

patch_open.reset_mock()
gpio.write(10, False)
patch_open.assert_has_calls((
mock.call().write(b'0'),
))
patch_open.assert_has_calls((mock.call().write(b"0"),))

patch_open.reset_mock()
pin.write(True)
patch_open.assert_has_calls((
mock.call().write(b'1'),
))
patch_open.assert_has_calls((mock.call().write(b"1"),))

patch_open.reset_mock()
gpio.write(10, True)
patch_open.assert_has_calls((
mock.call().write(b'1'),
))
patch_open.assert_has_calls((mock.call().write(b"1"),))


def test_read(gpio, patch_open):
pin = gpio.GPIOPin(10, gpio.IN)

patch_open().read.return_value = b'1\n'
patch_open().read.return_value = b"1\n"
assert pin.read() == gpio.HIGH
assert gpio.read(10) == gpio.HIGH

patch_open().read.return_value = b'0\n'
patch_open().read.return_value = b"0\n"
assert pin.read() == gpio.LOW
assert gpio.read(10) == gpio.LOW

0 comments on commit 19a917e

Please sign in to comment.