mirror of
				https://github.com/KevinMidboe/python-gpiozero.git
				synced 2025-10-29 17:50:37 +00:00 
			
		
		
		
	Fix #279 once and for all (ha! ;)
This implements the proposal discussed in the re-opened #279 to add a pin_factory argument at the device level and remove the ability to specify a pin instance to device constructors (they now only accept a pin specification). Note: there's still a couple of bits to tidy up (tests on "real" Pis, and pin_factory.release_all needs refinement) but the test suite is now at least capable of passing on a PC.
This commit is contained in:
		@@ -11,7 +11,7 @@ import os
 | 
				
			|||||||
import atexit
 | 
					import atexit
 | 
				
			||||||
import weakref
 | 
					import weakref
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
from collections import namedtuple, defaultdict
 | 
					from collections import namedtuple
 | 
				
			||||||
from itertools import chain
 | 
					from itertools import chain
 | 
				
			||||||
from types import FunctionType
 | 
					from types import FunctionType
 | 
				
			||||||
from threading import Lock
 | 
					from threading import Lock
 | 
				
			||||||
@@ -194,77 +194,21 @@ class Device(ValuesMixin, GPIOBase):
 | 
				
			|||||||
    property, the :attr:`value` property, and the :meth:`close` method).
 | 
					    property, the :attr:`value` property, and the :meth:`close` method).
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    pin_factory = None # instance of a Factory sub-class
 | 
					    pin_factory = None # instance of a Factory sub-class
 | 
				
			||||||
    _reservations = defaultdict(list) # maps pin addresses to lists of devices
 | 
					
 | 
				
			||||||
    _res_lock = Lock()
 | 
					    def __init__(self, **kwargs):
 | 
				
			||||||
 | 
					        # Force pin_factory to be keyword-only, even in Python 2
 | 
				
			||||||
 | 
					        self.pin_factory = kwargs.pop('pin_factory', Device.pin_factory)
 | 
				
			||||||
 | 
					        if kwargs:
 | 
				
			||||||
 | 
					            raise TypeError("Device.__init__() got unexpected keyword "
 | 
				
			||||||
 | 
					                            "argument '%s'" % kwargs.popitem()[0])
 | 
				
			||||||
 | 
					        super(Device, self).__init__()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __repr__(self):
 | 
					    def __repr__(self):
 | 
				
			||||||
        return "<gpiozero.%s object>" % (self.__class__.__name__)
 | 
					        return "<gpiozero.%s object>" % (self.__class__.__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _reserve_pins(self, *pins_or_addresses):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Called to indicate that the device reserves the right to use the
 | 
					 | 
				
			||||||
        specified *pins_or_addresses*. This should be done during device
 | 
					 | 
				
			||||||
        construction.  If pins are reserved, you must ensure that the
 | 
					 | 
				
			||||||
        reservation is released by eventually called :meth:`_release_pins`.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        The *pins_or_addresses* can be actual :class:`Pin` instances or the
 | 
					 | 
				
			||||||
        addresses of pin instances (each address is a tuple of strings). The
 | 
					 | 
				
			||||||
        latter form is permitted to ensure that devices do not have to
 | 
					 | 
				
			||||||
        construct :class:`Pin` objects to reserve pins. This is important as
 | 
					 | 
				
			||||||
        constructing a pin often configures it (e.g. as an input) which
 | 
					 | 
				
			||||||
        conflicts with alternate pin functions like SPI.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        addresses = (
 | 
					 | 
				
			||||||
            p.address if isinstance(p, Pin) else p
 | 
					 | 
				
			||||||
            for p in pins_or_addresses
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        with Device._res_lock:
 | 
					 | 
				
			||||||
            for address in addresses:
 | 
					 | 
				
			||||||
                for device_ref in Device._reservations[address]:
 | 
					 | 
				
			||||||
                    device = device_ref()
 | 
					 | 
				
			||||||
                    if device is not None and self._conflicts_with(device):
 | 
					 | 
				
			||||||
                        raise GPIOPinInUse(
 | 
					 | 
				
			||||||
                            'pin %s is already in use by %r' % (
 | 
					 | 
				
			||||||
                                '/'.join(address), device)
 | 
					 | 
				
			||||||
                        )
 | 
					 | 
				
			||||||
                Device._reservations[address].append(weakref.ref(self))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _release_pins(self, *pins_or_addresses):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Releases the reservation of this device against *pins_or_addresses*.
 | 
					 | 
				
			||||||
        This is typically called during :meth:`close` to clean up reservations
 | 
					 | 
				
			||||||
        taken during construction. Releasing a reservation that is not
 | 
					 | 
				
			||||||
        currently held will be silently ignored (to permit clean-up after
 | 
					 | 
				
			||||||
        failed / partial construction).
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        addresses = (
 | 
					 | 
				
			||||||
            p.address if isinstance(p, Pin) else p
 | 
					 | 
				
			||||||
            for p in pins_or_addresses
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        with Device._res_lock:
 | 
					 | 
				
			||||||
            for address in addresses:
 | 
					 | 
				
			||||||
                Device._reservations[address] = [
 | 
					 | 
				
			||||||
                    ref for ref in Device._reservations[address]
 | 
					 | 
				
			||||||
                    if ref() not in (self, None) # may as well clean up dead refs
 | 
					 | 
				
			||||||
                    ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _release_all(self):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Releases all pin reservations taken out by this device. See
 | 
					 | 
				
			||||||
        :meth:`_release_pins` for further information).
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        with Device._res_lock:
 | 
					 | 
				
			||||||
            Device._reservations = defaultdict(list, {
 | 
					 | 
				
			||||||
                address: [
 | 
					 | 
				
			||||||
                    ref for ref in conflictors
 | 
					 | 
				
			||||||
                    if ref() not in (self, None)
 | 
					 | 
				
			||||||
                    ]
 | 
					 | 
				
			||||||
                for address, conflictors in Device._reservations.items()
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _conflicts_with(self, other):
 | 
					    def _conflicts_with(self, other):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Called by :meth:`_reserve_pin` to test whether the *other*
 | 
					        Called by :meth:`Factory.reserve_pins` to test whether the *other*
 | 
				
			||||||
        :class:`Device` using a common pin conflicts with this device's intent
 | 
					        :class:`Device` using a common pin conflicts with this device's intent
 | 
				
			||||||
        to use it. The default is ``True`` indicating that all devices conflict
 | 
					        to use it. The default is ``True`` indicating that all devices conflict
 | 
				
			||||||
        with common pins.  Sub-classes may override this to permit more nuanced
 | 
					        with common pins.  Sub-classes may override this to permit more nuanced
 | 
				
			||||||
@@ -315,6 +259,7 @@ class CompositeDevice(Device):
 | 
				
			|||||||
        self._named = frozendict({})
 | 
					        self._named = frozendict({})
 | 
				
			||||||
        self._namedtuple = None
 | 
					        self._namedtuple = None
 | 
				
			||||||
        self._order = kwargs.pop('_order', None)
 | 
					        self._order = kwargs.pop('_order', None)
 | 
				
			||||||
 | 
					        pin_factory = kwargs.pop('pin_factory', None)
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            if self._order is None:
 | 
					            if self._order is None:
 | 
				
			||||||
                self._order = sorted(kwargs.keys())
 | 
					                self._order = sorted(kwargs.keys())
 | 
				
			||||||
@@ -336,7 +281,8 @@ class CompositeDevice(Device):
 | 
				
			|||||||
                    dev.close()
 | 
					                    dev.close()
 | 
				
			||||||
            raise
 | 
					            raise
 | 
				
			||||||
        self._all = args + tuple(kwargs[v] for v in self._order)
 | 
					        self._all = args + tuple(kwargs[v] for v in self._order)
 | 
				
			||||||
        super(CompositeDevice, self).__init__()
 | 
					        kwargs = {'pin_factory': pin_factory} if pin_factory is not None else {}
 | 
				
			||||||
 | 
					        super(CompositeDevice, self).__init__(**kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __getattr__(self, name):
 | 
					    def __getattr__(self, name):
 | 
				
			||||||
        # if _named doesn't exist yet, pretend it's an empty dict
 | 
					        # if _named doesn't exist yet, pretend it's an empty dict
 | 
				
			||||||
@@ -412,20 +358,17 @@ class GPIODevice(Device):
 | 
				
			|||||||
        this is ``None``, :exc:`GPIOPinMissing` will be raised. If the pin is
 | 
					        this is ``None``, :exc:`GPIOPinMissing` will be raised. If the pin is
 | 
				
			||||||
        already in use by another device, :exc:`GPIOPinInUse` will be raised.
 | 
					        already in use by another device, :exc:`GPIOPinInUse` will be raised.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    def __init__(self, pin=None):
 | 
					    def __init__(self, pin=None, **kwargs):
 | 
				
			||||||
        super(GPIODevice, self).__init__()
 | 
					        super(GPIODevice, self).__init__(**kwargs)
 | 
				
			||||||
        # self._pin must be set before any possible exceptions can be raised
 | 
					        # self._pin must be set before any possible exceptions can be raised
 | 
				
			||||||
        # because it's accessed in __del__. However, it mustn't be given the
 | 
					        # because it's accessed in __del__. However, it mustn't be given the
 | 
				
			||||||
        # value of pin until we've verified that it isn't already allocated
 | 
					        # value of pin until we've verified that it isn't already allocated
 | 
				
			||||||
        self._pin = None
 | 
					        self._pin = None
 | 
				
			||||||
        if pin is None:
 | 
					        if pin is None:
 | 
				
			||||||
            raise GPIOPinMissing('No pin given')
 | 
					            raise GPIOPinMissing('No pin given')
 | 
				
			||||||
        if isinstance(pin, Pin):
 | 
					        # Check you can reserve *before* constructing the pin
 | 
				
			||||||
            self._reserve_pins(pin)
 | 
					        self.pin_factory.reserve_pins(self, pin)
 | 
				
			||||||
        else:
 | 
					        pin = self.pin_factory.pin(pin)
 | 
				
			||||||
            # Check you can reserve *before* constructing the pin
 | 
					 | 
				
			||||||
            self._reserve_pins(Device.pin_factory.pin_address(pin))
 | 
					 | 
				
			||||||
            pin = Device.pin_factory.pin(pin)
 | 
					 | 
				
			||||||
        self._pin = pin
 | 
					        self._pin = pin
 | 
				
			||||||
        self._active_state = True
 | 
					        self._active_state = True
 | 
				
			||||||
        self._inactive_state = False
 | 
					        self._inactive_state = False
 | 
				
			||||||
@@ -443,7 +386,7 @@ class GPIODevice(Device):
 | 
				
			|||||||
    def close(self):
 | 
					    def close(self):
 | 
				
			||||||
        super(GPIODevice, self).close()
 | 
					        super(GPIODevice, self).close()
 | 
				
			||||||
        if self._pin is not None:
 | 
					        if self._pin is not None:
 | 
				
			||||||
            self._release_pins(self._pin)
 | 
					            self.pin_factory.release_pins(self, self._pin.number)
 | 
				
			||||||
            self._pin.close()
 | 
					            self._pin.close()
 | 
				
			||||||
            self._pin = None
 | 
					            self._pin = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -512,10 +455,10 @@ def _default_pin_factory(name=os.getenv('GPIOZERO_PIN_FACTORY', None)):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def _devices_shutdown():
 | 
					def _devices_shutdown():
 | 
				
			||||||
    if Device.pin_factory:
 | 
					    if Device.pin_factory:
 | 
				
			||||||
        with Device._res_lock:
 | 
					        with Device.pin_factory._res_lock:
 | 
				
			||||||
            reserved_devices = {
 | 
					            reserved_devices = {
 | 
				
			||||||
                dev
 | 
					                dev
 | 
				
			||||||
                for ref_list in Device._reservations.values()
 | 
					                for ref_list in Device.pin_factory._reservations.values()
 | 
				
			||||||
                for ref in ref_list
 | 
					                for ref in ref_list
 | 
				
			||||||
                for dev in (ref(),)
 | 
					                for dev in (ref(),)
 | 
				
			||||||
                if dev is not None
 | 
					                if dev is not None
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,10 @@ from __future__ import (
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
str = type('')
 | 
					str = type('')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from weakref import ref
 | 
				
			||||||
 | 
					from collections import defaultdict
 | 
				
			||||||
 | 
					from threading import Lock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ..exc import (
 | 
					from ..exc import (
 | 
				
			||||||
    PinInvalidFunction,
 | 
					    PinInvalidFunction,
 | 
				
			||||||
    PinSetInput,
 | 
					    PinSetInput,
 | 
				
			||||||
@@ -20,6 +24,7 @@ from ..exc import (
 | 
				
			|||||||
    SPIFixedBitOrder,
 | 
					    SPIFixedBitOrder,
 | 
				
			||||||
    SPIFixedSelect,
 | 
					    SPIFixedSelect,
 | 
				
			||||||
    SPIFixedWordSize,
 | 
					    SPIFixedWordSize,
 | 
				
			||||||
 | 
					    GPIOPinInUse,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -36,10 +41,61 @@ class Factory(object):
 | 
				
			|||||||
    applicable:
 | 
					    applicable:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    * :meth:`close`
 | 
					    * :meth:`close`
 | 
				
			||||||
 | 
					    * :meth:`reserve_pins`
 | 
				
			||||||
 | 
					    * :meth:`release_pins`
 | 
				
			||||||
 | 
					    * :meth:`release_all`
 | 
				
			||||||
    * :meth:`pin`
 | 
					    * :meth:`pin`
 | 
				
			||||||
    * :meth:`spi`
 | 
					    * :meth:`spi`
 | 
				
			||||||
    * :meth:`_get_pi_info`
 | 
					    * :meth:`_get_pi_info`
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					    def __init__(self):
 | 
				
			||||||
 | 
					        self._reservations = defaultdict(list)
 | 
				
			||||||
 | 
					        self._res_lock = Lock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def reserve_pins(self, requester, *pins):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Called to indicate that the device reserves the right to use the
 | 
				
			||||||
 | 
					        specified *pins*. This should be done during device construction.  If
 | 
				
			||||||
 | 
					        pins are reserved, you must ensure that the reservation is released by
 | 
				
			||||||
 | 
					        eventually called :meth:`release_pins`.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        with self._res_lock:
 | 
				
			||||||
 | 
					            for pin in pins:
 | 
				
			||||||
 | 
					                for reserver_ref in self._reservations[pin]:
 | 
				
			||||||
 | 
					                    reserver = reserver_ref()
 | 
				
			||||||
 | 
					                    if reserver is not None and requester._conflicts_with(reserver):
 | 
				
			||||||
 | 
					                        raise GPIOPinInUse('pin %s is already in use by %r' %
 | 
				
			||||||
 | 
					                                           (pin, reserver))
 | 
				
			||||||
 | 
					                self._reservations[pin].append(ref(requester))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def release_pins(self, reserver, *pins):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Releases the reservation of *reserver* against *pins*.  This is
 | 
				
			||||||
 | 
					        typically called during :meth:`Device.close` to clean up reservations
 | 
				
			||||||
 | 
					        taken during construction. Releasing a reservation that is not currently
 | 
				
			||||||
 | 
					        held will be silently ignored (to permit clean-up after failed / partial
 | 
				
			||||||
 | 
					        construction).
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        with self._res_lock:
 | 
				
			||||||
 | 
					            for pin in pins:
 | 
				
			||||||
 | 
					                self._reservations[pin] = [
 | 
				
			||||||
 | 
					                    ref for ref in self._reservations[pin]
 | 
				
			||||||
 | 
					                    if ref() not in (reserver, None) # may as well clean up dead refs
 | 
				
			||||||
 | 
					                    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def release_all(self, reserver):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Releases all pin reservations taken out by *reserver*. See
 | 
				
			||||||
 | 
					        :meth:`release_pins` for further information).
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        with self._res_lock:
 | 
				
			||||||
 | 
					            self._reservations = defaultdict(list, {
 | 
				
			||||||
 | 
					                pin: [
 | 
				
			||||||
 | 
					                    ref for ref in conflictors
 | 
				
			||||||
 | 
					                    if ref() not in (reserver, None)
 | 
				
			||||||
 | 
					                    ]
 | 
				
			||||||
 | 
					                for pin, conflictors in self._reservations.items()
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def close(self):
 | 
					    def close(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@@ -63,19 +119,6 @@ class Factory(object):
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        raise PinUnsupported("Individual pins are not supported by this pin factory")
 | 
					        raise PinUnsupported("Individual pins are not supported by this pin factory")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def pin_address(self, spec):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Returns the address that a pin *would* have if constructed from the
 | 
					 | 
				
			||||||
        given *spec*.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        This unusual method is used by the pin reservation system to check
 | 
					 | 
				
			||||||
        for conflicts *prior* to pin construction; with most implementations,
 | 
					 | 
				
			||||||
        pin construction implicitly alters the state of the pin (e.g. setting
 | 
					 | 
				
			||||||
        it to an input). This allows pin reservation to take place without
 | 
					 | 
				
			||||||
        affecting the state of other components.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        raise NotImplementedError
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def spi(self, **spi_args):
 | 
					    def spi(self, **spi_args):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Returns an instance of an :class:`SPI` interface, for the specified SPI
 | 
					        Returns an instance of an :class:`SPI` interface, for the specified SPI
 | 
				
			||||||
@@ -89,21 +132,6 @@ class Factory(object):
 | 
				
			|||||||
    def _get_address(self):
 | 
					    def _get_address(self):
 | 
				
			||||||
        raise NotImplementedError
 | 
					        raise NotImplementedError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    address = property(
 | 
					 | 
				
			||||||
        lambda self: self._get_address(),
 | 
					 | 
				
			||||||
        doc="""\
 | 
					 | 
				
			||||||
        Returns a tuple of strings representing the address of the factory.
 | 
					 | 
				
			||||||
        For the Pi itself this is a tuple of one string representing the Pi's
 | 
					 | 
				
			||||||
        address (e.g. "localhost"). Expander chips can return a tuple appending
 | 
					 | 
				
			||||||
        whatever string they require to uniquely identify the expander chip
 | 
					 | 
				
			||||||
        amongst all factories in the system.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        .. note::
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            This property *must* return an immutable object capable of being
 | 
					 | 
				
			||||||
            used as a dictionary key.
 | 
					 | 
				
			||||||
        """)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _get_pi_info(self):
 | 
					    def _get_pi_info(self):
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -128,7 +156,6 @@ class Pin(object):
 | 
				
			|||||||
    represent the capabilities of pins. Descendents *must* override the
 | 
					    represent the capabilities of pins. Descendents *must* override the
 | 
				
			||||||
    following methods:
 | 
					    following methods:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    * :meth:`_get_address`
 | 
					 | 
				
			||||||
    * :meth:`_get_function`
 | 
					    * :meth:`_get_function`
 | 
				
			||||||
    * :meth:`_set_function`
 | 
					    * :meth:`_set_function`
 | 
				
			||||||
    * :meth:`_get_state`
 | 
					    * :meth:`_get_state`
 | 
				
			||||||
@@ -153,7 +180,7 @@ class Pin(object):
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __repr__(self):
 | 
					    def __repr__(self):
 | 
				
			||||||
        return self.address[-1]
 | 
					        return "<Pin>"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def close(self):
 | 
					    def close(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@@ -195,18 +222,6 @@ class Pin(object):
 | 
				
			|||||||
        self.function = 'input'
 | 
					        self.function = 'input'
 | 
				
			||||||
        self.pull = pull
 | 
					        self.pull = pull
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _get_address(self):
 | 
					 | 
				
			||||||
        raise NotImplementedError
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    address = property(
 | 
					 | 
				
			||||||
        lambda self: self._get_address(),
 | 
					 | 
				
			||||||
        doc="""\
 | 
					 | 
				
			||||||
        The address of the pin. This property is a tuple of strings constructed
 | 
					 | 
				
			||||||
        from the owning factory's address with the unique address of the pin
 | 
					 | 
				
			||||||
        appended to it. The tuple as a whole uniquely identifies the pin
 | 
					 | 
				
			||||||
        amongst all pins attached to the system.
 | 
					 | 
				
			||||||
        """)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _get_function(self):
 | 
					    def _get_function(self):
 | 
				
			||||||
        return "input"
 | 
					        return "input"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,8 @@ str = type('')
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import io
 | 
					import io
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
 | 
					from collections import defaultdict
 | 
				
			||||||
 | 
					from threading import Lock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
try:
 | 
					try:
 | 
				
			||||||
    from spidev import SpiDev
 | 
					    from spidev import SpiDev
 | 
				
			||||||
@@ -31,6 +33,8 @@ class LocalPiFactory(PiFactory):
 | 
				
			|||||||
    :class:`~gpiozero.pins.native.NativePin`).
 | 
					    :class:`~gpiozero.pins.native.NativePin`).
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    pins = {}
 | 
					    pins = {}
 | 
				
			||||||
 | 
					    _reservations = defaultdict(list)
 | 
				
			||||||
 | 
					    _res_lock = Lock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
        super(LocalPiFactory, self).__init__()
 | 
					        super(LocalPiFactory, self).__init__()
 | 
				
			||||||
@@ -40,14 +44,13 @@ class LocalPiFactory(PiFactory):
 | 
				
			|||||||
            ('software', 'exclusive'): LocalPiSoftwareSPI,
 | 
					            ('software', 'exclusive'): LocalPiSoftwareSPI,
 | 
				
			||||||
            ('software', 'shared'):    LocalPiSoftwareSPIShared,
 | 
					            ('software', 'shared'):    LocalPiSoftwareSPIShared,
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        # Override the pins dict to be this class' pins dict. This is a bit of
 | 
					        # Override the reservations and pins dict to be this class' attributes.
 | 
				
			||||||
        # a dirty hack, but ensures that anyone evil enough to mix pin
 | 
					        # This is a bit of a dirty hack, but ensures that anyone evil enough to
 | 
				
			||||||
        # implementations doesn't try and control the same pin with different
 | 
					        # mix pin implementations doesn't try and control the same pin with
 | 
				
			||||||
        # backends
 | 
					        # different backends
 | 
				
			||||||
        self.pins = LocalPiFactory.pins
 | 
					        self.pins = LocalPiFactory.pins
 | 
				
			||||||
 | 
					        self._reservations = LocalPiFactory._reservations
 | 
				
			||||||
    def _get_address(self):
 | 
					        self._res_lock = LocalPiFactory._res_lock
 | 
				
			||||||
        return ('localhost',)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _get_revision(self):
 | 
					    def _get_revision(self):
 | 
				
			||||||
        # Cache the result as we can reasonably assume it won't change during
 | 
					        # Cache the result as we can reasonably assume it won't change during
 | 
				
			||||||
@@ -74,19 +77,19 @@ class LocalPiPin(PiPin):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class LocalPiHardwareSPI(SPI, Device):
 | 
					class LocalPiHardwareSPI(SPI, Device):
 | 
				
			||||||
    def __init__(self, factory, port, device):
 | 
					    def __init__(self, factory, port, device):
 | 
				
			||||||
        if SpiDev is None:
 | 
					 | 
				
			||||||
            raise ImportError('failed to import spidev')
 | 
					 | 
				
			||||||
        self._port = port
 | 
					        self._port = port
 | 
				
			||||||
        self._device = device
 | 
					        self._device = device
 | 
				
			||||||
        self._interface = None
 | 
					        self._interface = None
 | 
				
			||||||
        self._address = factory.address + ('SPI(port=%d, device=%d)' % (port, device),)
 | 
					        if SpiDev is None:
 | 
				
			||||||
 | 
					            raise ImportError('failed to import spidev')
 | 
				
			||||||
        super(LocalPiHardwareSPI, self).__init__()
 | 
					        super(LocalPiHardwareSPI, self).__init__()
 | 
				
			||||||
        pins = SPI_HARDWARE_PINS[port]
 | 
					        pins = SPI_HARDWARE_PINS[port]
 | 
				
			||||||
        self._reserve_pins(
 | 
					        self.pin_factory.reserve_pins(
 | 
				
			||||||
            factory.pin_address(pins['clock']),
 | 
					            self,
 | 
				
			||||||
            factory.pin_address(pins['mosi']),
 | 
					            pins['clock'],
 | 
				
			||||||
            factory.pin_address(pins['miso']),
 | 
					            pins['mosi'],
 | 
				
			||||||
            factory.pin_address(pins['select'][device])
 | 
					            pins['miso'],
 | 
				
			||||||
 | 
					            pins['select'][device]
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        self._interface = SpiDev()
 | 
					        self._interface = SpiDev()
 | 
				
			||||||
        self._interface.open(port, device)
 | 
					        self._interface.open(port, device)
 | 
				
			||||||
@@ -98,7 +101,7 @@ class LocalPiHardwareSPI(SPI, Device):
 | 
				
			|||||||
                self._interface.close()
 | 
					                self._interface.close()
 | 
				
			||||||
            finally:
 | 
					            finally:
 | 
				
			||||||
                self._interface = None
 | 
					                self._interface = None
 | 
				
			||||||
        self._release_all()
 | 
					        self.pin_factory.release_all(self)
 | 
				
			||||||
        super(LocalPiHardwareSPI, self).close()
 | 
					        super(LocalPiHardwareSPI, self).close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
@@ -148,10 +151,6 @@ class LocalPiHardwareSPI(SPI, Device):
 | 
				
			|||||||
class LocalPiSoftwareSPI(SPI, OutputDevice):
 | 
					class LocalPiSoftwareSPI(SPI, OutputDevice):
 | 
				
			||||||
    def __init__(self, factory, clock_pin, mosi_pin, miso_pin, select_pin):
 | 
					    def __init__(self, factory, clock_pin, mosi_pin, miso_pin, select_pin):
 | 
				
			||||||
        self._bus = None
 | 
					        self._bus = None
 | 
				
			||||||
        self._address = factory.address + (
 | 
					 | 
				
			||||||
            'SPI(clock_pin=%d, mosi_pin=%d, miso_pin=%d, select_pin=%d)' % (
 | 
					 | 
				
			||||||
            clock_pin, mosi_pin, miso_pin, select_pin),
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        super(LocalPiSoftwareSPI, self).__init__(select_pin, active_high=False)
 | 
					        super(LocalPiSoftwareSPI, self).__init__(select_pin, active_high=False)
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            self._clock_phase = False
 | 
					            self._clock_phase = False
 | 
				
			||||||
@@ -163,6 +162,7 @@ class LocalPiSoftwareSPI(SPI, OutputDevice):
 | 
				
			|||||||
            raise
 | 
					            raise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _conflicts_with(self, other):
 | 
					    def _conflicts_with(self, other):
 | 
				
			||||||
 | 
					        # XXX Need to refine this
 | 
				
			||||||
        return not (
 | 
					        return not (
 | 
				
			||||||
            isinstance(other, LocalPiSoftwareSPI) and
 | 
					            isinstance(other, LocalPiSoftwareSPI) and
 | 
				
			||||||
            (self.pin.number != other.pin.number)
 | 
					            (self.pin.number != other.pin.number)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,7 +40,7 @@ class MockPin(PiPin):
 | 
				
			|||||||
    def __init__(self, factory, number):
 | 
					    def __init__(self, factory, number):
 | 
				
			||||||
        super(MockPin, self).__init__(factory, number)
 | 
					        super(MockPin, self).__init__(factory, number)
 | 
				
			||||||
        self._function = 'input'
 | 
					        self._function = 'input'
 | 
				
			||||||
        self._pull = 'up' if factory.pi_info.pulled_up(self.address[-1]) else 'floating'
 | 
					        self._pull = 'up' if factory.pi_info.pulled_up(repr(self)) else 'floating'
 | 
				
			||||||
        self._state = self._pull == 'up'
 | 
					        self._state = self._pull == 'up'
 | 
				
			||||||
        self._bounce = None
 | 
					        self._bounce = None
 | 
				
			||||||
        self._edges = 'both'
 | 
					        self._edges = 'both'
 | 
				
			||||||
@@ -94,7 +94,7 @@ class MockPin(PiPin):
 | 
				
			|||||||
    def _set_pull(self, value):
 | 
					    def _set_pull(self, value):
 | 
				
			||||||
        if self.function != 'input':
 | 
					        if self.function != 'input':
 | 
				
			||||||
            raise PinFixedPull('cannot set pull on non-input pin %r' % self)
 | 
					            raise PinFixedPull('cannot set pull on non-input pin %r' % self)
 | 
				
			||||||
        if value != 'up' and self.factory.pi_info.pulled_up(self.address[-1]):
 | 
					        if value != 'up' and self.factory.pi_info.pulled_up(repr(self)):
 | 
				
			||||||
            raise PinFixedPull('%r has a physical pull-up resistor' % self)
 | 
					            raise PinFixedPull('%r has a physical pull-up resistor' % self)
 | 
				
			||||||
        if value not in ('floating', 'up', 'down'):
 | 
					        if value not in ('floating', 'up', 'down'):
 | 
				
			||||||
            raise PinInvalidPull('pull must be floating, up, or down')
 | 
					            raise PinInvalidPull('pull must be floating, up, or down')
 | 
				
			||||||
@@ -423,14 +423,12 @@ class MockFactory(LocalPiFactory):
 | 
				
			|||||||
            pin_class = pkg_resources.load_entry_point(dist, group, pin_class.lower())
 | 
					            pin_class = pkg_resources.load_entry_point(dist, group, pin_class.lower())
 | 
				
			||||||
        self.pin_class = pin_class
 | 
					        self.pin_class = pin_class
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _get_address(self):
 | 
					 | 
				
			||||||
        return ('mock',)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _get_revision(self):
 | 
					    def _get_revision(self):
 | 
				
			||||||
        return self._revision
 | 
					        return self._revision
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def reset(self):
 | 
					    def reset(self):
 | 
				
			||||||
        self.pins.clear()
 | 
					        self.pins.clear()
 | 
				
			||||||
 | 
					        self._reservations.clear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def pin(self, spec, pin_class=None, **kwargs):
 | 
					    def pin(self, spec, pin_class=None, **kwargs):
 | 
				
			||||||
        if pin_class is None:
 | 
					        if pin_class is None:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -228,7 +228,7 @@ class NativePin(LocalPiPin):
 | 
				
			|||||||
        self._change_thread = None
 | 
					        self._change_thread = None
 | 
				
			||||||
        self._change_event = Event()
 | 
					        self._change_event = Event()
 | 
				
			||||||
        self.function = 'input'
 | 
					        self.function = 'input'
 | 
				
			||||||
        self.pull = 'up' if factory.pi_info.pulled_up(self.address[-1]) else 'floating'
 | 
					        self.pull = 'up' if self.factory.pi_info.pulled_up(repr(self)) else 'floating'
 | 
				
			||||||
        self.bounce = None
 | 
					        self.bounce = None
 | 
				
			||||||
        self.edges = 'both'
 | 
					        self.edges = 'both'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -236,7 +236,7 @@ class NativePin(LocalPiPin):
 | 
				
			|||||||
        self.frequency = None
 | 
					        self.frequency = None
 | 
				
			||||||
        self.when_changed = None
 | 
					        self.when_changed = None
 | 
				
			||||||
        self.function = 'input'
 | 
					        self.function = 'input'
 | 
				
			||||||
        self.pull = 'up' if self.factory.pi_info.pulled_up(self.address[-1]) else 'floating'
 | 
					        self.pull = 'up' if self.factory.pi_info.pulled_up(repr(self)) else 'floating'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _get_function(self):
 | 
					    def _get_function(self):
 | 
				
			||||||
        return self.GPIO_FUNCTION_NAMES[(self.factory.mem[self._func_offset] >> self._func_shift) & 7]
 | 
					        return self.GPIO_FUNCTION_NAMES[(self.factory.mem[self._func_offset] >> self._func_shift) & 7]
 | 
				
			||||||
@@ -269,7 +269,7 @@ class NativePin(LocalPiPin):
 | 
				
			|||||||
    def _set_pull(self, value):
 | 
					    def _set_pull(self, value):
 | 
				
			||||||
        if self.function != 'input':
 | 
					        if self.function != 'input':
 | 
				
			||||||
            raise PinFixedPull('cannot set pull on non-input pin %r' % self)
 | 
					            raise PinFixedPull('cannot set pull on non-input pin %r' % self)
 | 
				
			||||||
        if value != 'up' and self.factory.pi_info.pulled_up(self.address[-1]):
 | 
					        if value != 'up' and self.factory.pi_info.pulled_up(repr(self)):
 | 
				
			||||||
            raise PinFixedPull('%r has a physical pull-up resistor' % self)
 | 
					            raise PinFixedPull('%r has a physical pull-up resistor' % self)
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            value = self.GPIO_PULL_UPS[value]
 | 
					            value = self.GPIO_PULL_UPS[value]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,8 +7,9 @@ from __future__ import (
 | 
				
			|||||||
str = type('')
 | 
					str = type('')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import io
 | 
					import io
 | 
				
			||||||
from threading import RLock
 | 
					from threading import RLock, Lock
 | 
				
			||||||
from types import MethodType
 | 
					from types import MethodType
 | 
				
			||||||
 | 
					from collections import defaultdict
 | 
				
			||||||
try:
 | 
					try:
 | 
				
			||||||
    from weakref import ref, WeakMethod
 | 
					    from weakref import ref, WeakMethod
 | 
				
			||||||
except ImportError:
 | 
					except ImportError:
 | 
				
			||||||
@@ -48,6 +49,7 @@ class PiFactory(Factory):
 | 
				
			|||||||
    forms the base of :class:`~gpiozero.pins.local.LocalPiFactory`.
 | 
					    forms the base of :class:`~gpiozero.pins.local.LocalPiFactory`.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
 | 
					        super(PiFactory, self).__init__()
 | 
				
			||||||
        self._info = None
 | 
					        self._info = None
 | 
				
			||||||
        self.pins = {}
 | 
					        self.pins = {}
 | 
				
			||||||
        self.pin_class = None
 | 
					        self.pin_class = None
 | 
				
			||||||
@@ -72,10 +74,6 @@ class PiFactory(Factory):
 | 
				
			|||||||
            self.pins[n] = pin
 | 
					            self.pins[n] = pin
 | 
				
			||||||
        return pin
 | 
					        return pin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def pin_address(self, spec):
 | 
					 | 
				
			||||||
        n = self._to_gpio(spec)
 | 
					 | 
				
			||||||
        return self.address + ('GPIO%d' % n,)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _to_gpio(self, spec):
 | 
					    def _to_gpio(self, spec):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Converts the pin *spec* to a GPIO port number.
 | 
					        Converts the pin *spec* to a GPIO port number.
 | 
				
			||||||
@@ -240,23 +238,23 @@ class PiPin(Pin):
 | 
				
			|||||||
        self._when_changed = None
 | 
					        self._when_changed = None
 | 
				
			||||||
        self._number = number
 | 
					        self._number = number
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            factory.pi_info.physical_pin(self.address[-1])
 | 
					            factory.pi_info.physical_pin('GPIO%d' % self.number)
 | 
				
			||||||
        except PinNoPins:
 | 
					        except PinNoPins:
 | 
				
			||||||
            warnings.warn(
 | 
					            warnings.warn(
 | 
				
			||||||
                PinNonPhysical(
 | 
					                PinNonPhysical(
 | 
				
			||||||
                    'no physical pins exist for %s' % self.address[-1]))
 | 
					                    'no physical pins exist for GPIO%d' % self.number))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def number(self):
 | 
					    def number(self):
 | 
				
			||||||
        return self._number
 | 
					        return self._number
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __repr__(self):
 | 
				
			||||||
 | 
					        return 'GPIO%d' % self._number
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def factory(self):
 | 
					    def factory(self):
 | 
				
			||||||
        return self._factory
 | 
					        return self._factory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _get_address(self):
 | 
					 | 
				
			||||||
        return self.factory.address + ('GPIO%d' % self.number,)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _call_when_changed(self):
 | 
					    def _call_when_changed(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Called to fire the :attr:`when_changed` event handler; override this
 | 
					        Called to fire the :attr:`when_changed` event handler; override this
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,6 @@ from __future__ import (
 | 
				
			|||||||
str = type('')
 | 
					str = type('')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
from weakref import proxy
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pigpio
 | 
					import pigpio
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -126,9 +125,6 @@ class PiGPIOFactory(PiFactory):
 | 
				
			|||||||
    def _get_revision(self):
 | 
					    def _get_revision(self):
 | 
				
			||||||
        return self.connection.get_hardware_revision()
 | 
					        return self.connection.get_hardware_revision()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _get_address(self):
 | 
					 | 
				
			||||||
        return ("%s:%d" % (self.host, self.port),)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def spi(self, **spi_args):
 | 
					    def spi(self, **spi_args):
 | 
				
			||||||
        intf = super(PiGPIOFactory, self).spi(**spi_args)
 | 
					        intf = super(PiGPIOFactory, self).spi(**spi_args)
 | 
				
			||||||
        self._spis.append(intf)
 | 
					        self._spis.append(intf)
 | 
				
			||||||
@@ -166,7 +162,7 @@ class PiGPIOPin(PiPin):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def __init__(self, factory, number):
 | 
					    def __init__(self, factory, number):
 | 
				
			||||||
        super(PiGPIOPin, self).__init__(factory, number)
 | 
					        super(PiGPIOPin, self).__init__(factory, number)
 | 
				
			||||||
        self._pull = 'up' if factory.pi_info.pulled_up(self.address[-1]) else 'floating'
 | 
					        self._pull = 'up' if factory.pi_info.pulled_up(repr(self)) else 'floating'
 | 
				
			||||||
        self._pwm = False
 | 
					        self._pwm = False
 | 
				
			||||||
        self._bounce = None
 | 
					        self._bounce = None
 | 
				
			||||||
        self._callback = None
 | 
					        self._callback = None
 | 
				
			||||||
@@ -183,7 +179,7 @@ class PiGPIOPin(PiPin):
 | 
				
			|||||||
            self.frequency = None
 | 
					            self.frequency = None
 | 
				
			||||||
            self.when_changed = None
 | 
					            self.when_changed = None
 | 
				
			||||||
            self.function = 'input'
 | 
					            self.function = 'input'
 | 
				
			||||||
            self.pull = 'up' if self.factory.pi_info.pulled_up(self.address[-1]) else 'floating'
 | 
					            self.pull = 'up' if self.factory.pi_info.pulled_up(repr(self)) else 'floating'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _get_function(self):
 | 
					    def _get_function(self):
 | 
				
			||||||
        return self.GPIO_FUNCTION_NAMES[self.factory.connection.get_mode(self.number)]
 | 
					        return self.GPIO_FUNCTION_NAMES[self.factory.connection.get_mode(self.number)]
 | 
				
			||||||
@@ -225,7 +221,7 @@ class PiGPIOPin(PiPin):
 | 
				
			|||||||
    def _set_pull(self, value):
 | 
					    def _set_pull(self, value):
 | 
				
			||||||
        if self.function != 'input':
 | 
					        if self.function != 'input':
 | 
				
			||||||
            raise PinFixedPull('cannot set pull on non-input pin %r' % self)
 | 
					            raise PinFixedPull('cannot set pull on non-input pin %r' % self)
 | 
				
			||||||
        if value != 'up' and self.factory.pi_info.pulled_up(self.address[-1]):
 | 
					        if value != 'up' and self.factory.pi_info.pulled_up(repr(self)):
 | 
				
			||||||
            raise PinFixedPull('%r has a physical pull-up resistor' % self)
 | 
					            raise PinFixedPull('%r has a physical pull-up resistor' % self)
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            self.factory.connection.set_pull_up_down(self.number, self.GPIO_PULL_UPS[value])
 | 
					            self.factory.connection.set_pull_up_down(self.number, self.GPIO_PULL_UPS[value])
 | 
				
			||||||
@@ -296,19 +292,17 @@ class PiGPIOHardwareSPI(SPI, Device):
 | 
				
			|||||||
    def __init__(self, factory, port, device):
 | 
					    def __init__(self, factory, port, device):
 | 
				
			||||||
        self._port = port
 | 
					        self._port = port
 | 
				
			||||||
        self._device = device
 | 
					        self._device = device
 | 
				
			||||||
        self._factory = proxy(factory)
 | 
					        self._factory = factory
 | 
				
			||||||
        self._handle = None
 | 
					        self._handle = None
 | 
				
			||||||
        super(PiGPIOHardwareSPI, self).__init__()
 | 
					        super(PiGPIOHardwareSPI, self).__init__()
 | 
				
			||||||
        pins = SPI_HARDWARE_PINS[port]
 | 
					        pins = SPI_HARDWARE_PINS[port]
 | 
				
			||||||
        self._reserve_pins(*(
 | 
					        self._factory.reserve_pins(
 | 
				
			||||||
            factory.address + ('GPIO%d' % pin,)
 | 
					            self,
 | 
				
			||||||
            for pin in (
 | 
					            pins['clock'],
 | 
				
			||||||
                pins['clock'],
 | 
					            pins['mosi'],
 | 
				
			||||||
                pins['mosi'],
 | 
					            pins['miso'],
 | 
				
			||||||
                pins['miso'],
 | 
					            pins['select'][device]
 | 
				
			||||||
                pins['select'][device]
 | 
					        )
 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        ))
 | 
					 | 
				
			||||||
        self._spi_flags = 8 << 16
 | 
					        self._spi_flags = 8 << 16
 | 
				
			||||||
        self._baud = 500000
 | 
					        self._baud = 500000
 | 
				
			||||||
        self._handle = self._factory.connection.spi_open(
 | 
					        self._handle = self._factory.connection.spi_open(
 | 
				
			||||||
@@ -330,7 +324,7 @@ class PiGPIOHardwareSPI(SPI, Device):
 | 
				
			|||||||
        if not self.closed:
 | 
					        if not self.closed:
 | 
				
			||||||
            self._factory.connection.spi_close(self._handle)
 | 
					            self._factory.connection.spi_close(self._handle)
 | 
				
			||||||
        self._handle = None
 | 
					        self._handle = None
 | 
				
			||||||
        self._release_all()
 | 
					        self._factory.release_all(self)
 | 
				
			||||||
        super(PiGPIOHardwareSPI, self).close()
 | 
					        super(PiGPIOHardwareSPI, self).close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
@@ -397,13 +391,14 @@ class PiGPIOSoftwareSPI(SPI, Device):
 | 
				
			|||||||
        self._clock_pin = clock_pin
 | 
					        self._clock_pin = clock_pin
 | 
				
			||||||
        self._mosi_pin = mosi_pin
 | 
					        self._mosi_pin = mosi_pin
 | 
				
			||||||
        self._miso_pin = miso_pin
 | 
					        self._miso_pin = miso_pin
 | 
				
			||||||
        self._factory = proxy(factory)
 | 
					        self._factory = factory
 | 
				
			||||||
        super(PiGPIOSoftwareSPI, self).__init__()
 | 
					        super(PiGPIOSoftwareSPI, self).__init__()
 | 
				
			||||||
        self._reserve_pins(
 | 
					        self._factory.reserve_pins(
 | 
				
			||||||
            factory.pin_address(clock_pin),
 | 
					            self,
 | 
				
			||||||
            factory.pin_address(mosi_pin),
 | 
					            clock_pin,
 | 
				
			||||||
            factory.pin_address(miso_pin),
 | 
					            mosi_pin,
 | 
				
			||||||
            factory.pin_address(select_pin),
 | 
					            miso_pin,
 | 
				
			||||||
 | 
					            select_pin,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        self._spi_flags = 0
 | 
					        self._spi_flags = 0
 | 
				
			||||||
        self._baud = 100000
 | 
					        self._baud = 100000
 | 
				
			||||||
@@ -434,7 +429,7 @@ class PiGPIOSoftwareSPI(SPI, Device):
 | 
				
			|||||||
        if not self.closed:
 | 
					        if not self.closed:
 | 
				
			||||||
            self._closed = True
 | 
					            self._closed = True
 | 
				
			||||||
            self._factory.connection.bb_spi_close(self._select_pin)
 | 
					            self._factory.connection.bb_spi_close(self._select_pin)
 | 
				
			||||||
        self._release_all()
 | 
					        self.factory.release_all(self)
 | 
				
			||||||
        super(PiGPIOSoftwareSPI, self).close()
 | 
					        super(PiGPIOSoftwareSPI, self).close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,7 +85,7 @@ class RPiGPIOPin(LocalPiPin):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def __init__(self, factory, number):
 | 
					    def __init__(self, factory, number):
 | 
				
			||||||
        super(RPiGPIOPin, self).__init__(factory, number)
 | 
					        super(RPiGPIOPin, self).__init__(factory, number)
 | 
				
			||||||
        self._pull = 'up' if factory.pi_info.pulled_up(self.address[-1]) else 'floating'
 | 
					        self._pull = 'up' if self.factory.pi_info.pulled_up(self.address[-1]) else 'floating'
 | 
				
			||||||
        self._pwm = None
 | 
					        self._pwm = None
 | 
				
			||||||
        self._frequency = None
 | 
					        self._frequency = None
 | 
				
			||||||
        self._duty_cycle = None
 | 
					        self._duty_cycle = None
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -80,7 +80,7 @@ class RPIOPin(LocalPiPin):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def __init__(self, factory, number):
 | 
					    def __init__(self, factory, number):
 | 
				
			||||||
        super(RPIOPin, self).__init__(factory, number)
 | 
					        super(RPIOPin, self).__init__(factory, number)
 | 
				
			||||||
        self._pull = 'up' if factory.pi_info.pulled_up(self.address[-1]) else 'floating'
 | 
					        self._pull = 'up' if self.factory.pi_info.pulled_up(self.address[-1]) else 'floating'
 | 
				
			||||||
        self._pwm = False
 | 
					        self._pwm = False
 | 
				
			||||||
        self._duty_cycle = None
 | 
					        self._duty_cycle = None
 | 
				
			||||||
        self._bounce = None
 | 
					        self._bounce = None
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,7 +36,6 @@ def setup_function(function):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def teardown_function(function):
 | 
					def teardown_function(function):
 | 
				
			||||||
    Device.pin_factory.reset()
 | 
					    Device.pin_factory.reset()
 | 
				
			||||||
    Device._reservations.clear()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def teardown_module(module):
 | 
					def teardown_module(module):
 | 
				
			||||||
    # make sure we reset the default
 | 
					    # make sure we reset the default
 | 
				
			||||||
@@ -47,7 +46,7 @@ def test_composite_output_on_off():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with CompositeOutputDevice(OutputDevice(pin1), OutputDevice(pin2), foo=OutputDevice(pin3)) as device:
 | 
					    with CompositeOutputDevice(OutputDevice(2), OutputDevice(3), foo=OutputDevice(4)) as device:
 | 
				
			||||||
        device.on()
 | 
					        device.on()
 | 
				
			||||||
        assert all((pin1.state, pin2.state, pin3.state))
 | 
					        assert all((pin1.state, pin2.state, pin3.state))
 | 
				
			||||||
        device.off()
 | 
					        device.off()
 | 
				
			||||||
@@ -57,7 +56,7 @@ def test_composite_output_toggle():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with CompositeOutputDevice(OutputDevice(pin1), OutputDevice(pin2), foo=OutputDevice(pin3)) as device:
 | 
					    with CompositeOutputDevice(OutputDevice(2), OutputDevice(3), foo=OutputDevice(4)) as device:
 | 
				
			||||||
        device.toggle()
 | 
					        device.toggle()
 | 
				
			||||||
        assert all((pin1.state, pin2.state, pin3.state))
 | 
					        assert all((pin1.state, pin2.state, pin3.state))
 | 
				
			||||||
        device[0].off()
 | 
					        device[0].off()
 | 
				
			||||||
@@ -70,7 +69,7 @@ def test_composite_output_value():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with CompositeOutputDevice(OutputDevice(pin1), OutputDevice(pin2), foo=OutputDevice(pin3)) as device:
 | 
					    with CompositeOutputDevice(OutputDevice(2), OutputDevice(3), foo=OutputDevice(4)) as device:
 | 
				
			||||||
        assert device.value == (0, 0, 0)
 | 
					        assert device.value == (0, 0, 0)
 | 
				
			||||||
        device.toggle()
 | 
					        device.toggle()
 | 
				
			||||||
        assert device.value == (1, 1, 1)
 | 
					        assert device.value == (1, 1, 1)
 | 
				
			||||||
@@ -83,7 +82,7 @@ def test_led_board_on_off():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LEDBoard(pin1, pin2, foo=pin3) as board:
 | 
					    with LEDBoard(2, 3, foo=4) as board:
 | 
				
			||||||
        assert isinstance(board[0], LED)
 | 
					        assert isinstance(board[0], LED)
 | 
				
			||||||
        assert isinstance(board[1], LED)
 | 
					        assert isinstance(board[1], LED)
 | 
				
			||||||
        assert isinstance(board[2], LED)
 | 
					        assert isinstance(board[2], LED)
 | 
				
			||||||
@@ -140,7 +139,7 @@ def test_led_board_active_low():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LEDBoard(pin1, pin2, foo=pin3, active_high=False) as board:
 | 
					    with LEDBoard(2, 3, foo=4, active_high=False) as board:
 | 
				
			||||||
        assert not board.active_high
 | 
					        assert not board.active_high
 | 
				
			||||||
        assert not board[0].active_high
 | 
					        assert not board[0].active_high
 | 
				
			||||||
        assert not board[1].active_high
 | 
					        assert not board[1].active_high
 | 
				
			||||||
@@ -164,7 +163,7 @@ def test_led_board_value():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LEDBoard(pin1, pin2, foo=pin3) as board:
 | 
					    with LEDBoard(2, 3, foo=4) as board:
 | 
				
			||||||
        assert board.value == (0, 0, 0)
 | 
					        assert board.value == (0, 0, 0)
 | 
				
			||||||
        board.value = (0, 1, 0)
 | 
					        board.value = (0, 1, 0)
 | 
				
			||||||
        assert board.value == (0, 1, 0)
 | 
					        assert board.value == (0, 1, 0)
 | 
				
			||||||
@@ -175,7 +174,7 @@ def test_led_board_pwm_value():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LEDBoard(pin1, pin2, foo=pin3, pwm=True) as board:
 | 
					    with LEDBoard(2, 3, foo=4, pwm=True) as board:
 | 
				
			||||||
        assert board.value == (0, 0, 0)
 | 
					        assert board.value == (0, 0, 0)
 | 
				
			||||||
        board.value = (0, 1, 0)
 | 
					        board.value = (0, 1, 0)
 | 
				
			||||||
        assert board.value == (0, 1, 0)
 | 
					        assert board.value == (0, 1, 0)
 | 
				
			||||||
@@ -186,7 +185,7 @@ def test_led_board_pwm_bad_value():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LEDBoard(pin1, pin2, foo=pin3, pwm=True) as board:
 | 
					    with LEDBoard(2, 3, foo=4, pwm=True) as board:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            board.value = (-1, 0, 0)
 | 
					            board.value = (-1, 0, 0)
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
@@ -196,20 +195,20 @@ def test_led_board_initial_value():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LEDBoard(pin1, pin2, foo=pin3, initial_value=0) as board:
 | 
					    with LEDBoard(2, 3, foo=4, initial_value=0) as board:
 | 
				
			||||||
        assert board.value == (0, 0, 0)
 | 
					        assert board.value == (0, 0, 0)
 | 
				
			||||||
    with LEDBoard(pin1, pin2, foo=pin3, initial_value=1) as board:
 | 
					    with LEDBoard(2, 3, foo=4, initial_value=1) as board:
 | 
				
			||||||
        assert board.value == (1, 1, 1)
 | 
					        assert board.value == (1, 1, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_led_board_pwm_initial_value():
 | 
					def test_led_board_pwm_initial_value():
 | 
				
			||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LEDBoard(pin1, pin2, foo=pin3, pwm=True, initial_value=0) as board:
 | 
					    with LEDBoard(2, 3, foo=4, pwm=True, initial_value=0) as board:
 | 
				
			||||||
        assert board.value == (0, 0, 0)
 | 
					        assert board.value == (0, 0, 0)
 | 
				
			||||||
    with LEDBoard(pin1, pin2, foo=pin3, pwm=True, initial_value=1) as board:
 | 
					    with LEDBoard(2, 3, foo=4, pwm=True, initial_value=1) as board:
 | 
				
			||||||
        assert board.value == (1, 1, 1)
 | 
					        assert board.value == (1, 1, 1)
 | 
				
			||||||
    with LEDBoard(pin1, pin2, foo=pin3, pwm=True, initial_value=0.5) as board:
 | 
					    with LEDBoard(2, 3, foo=4, pwm=True, initial_value=0.5) as board:
 | 
				
			||||||
        assert board.value == (0.5, 0.5, 0.5)
 | 
					        assert board.value == (0.5, 0.5, 0.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_led_board_pwm_bad_initial_value():
 | 
					def test_led_board_pwm_bad_initial_value():
 | 
				
			||||||
@@ -217,15 +216,15 @@ def test_led_board_pwm_bad_initial_value():
 | 
				
			|||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        LEDBoard(pin1, pin2, foo=pin3, pwm=True, initial_value=-1)
 | 
					        LEDBoard(2, 3, foo=4, pwm=True, initial_value=-1)
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        LEDBoard(pin1, pin2, foo=pin3, pwm=True, initial_value=2)
 | 
					        LEDBoard(2, 3, foo=4, pwm=True, initial_value=2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_led_board_nested():
 | 
					def test_led_board_nested():
 | 
				
			||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
 | 
					    with LEDBoard(2, LEDBoard(3, 4)) as board:
 | 
				
			||||||
        assert list(led.pin for led in board.leds) == [pin1, pin2, pin3]
 | 
					        assert list(led.pin for led in board.leds) == [pin1, pin2, pin3]
 | 
				
			||||||
        assert board.value == (0, (0, 0))
 | 
					        assert board.value == (0, (0, 0))
 | 
				
			||||||
        board.value = (1, (0, 1))
 | 
					        board.value = (1, (0, 1))
 | 
				
			||||||
@@ -237,7 +236,7 @@ def test_led_board_bad_blink():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
 | 
					    with LEDBoard(2, LEDBoard(3, 4)) as board:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            board.blink(fade_in_time=1, fade_out_time=1)
 | 
					            board.blink(fade_in_time=1, fade_out_time=1)
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
@@ -251,7 +250,7 @@ def test_led_board_blink_background():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(4)
 | 
					    pin1 = Device.pin_factory.pin(4)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(5)
 | 
					    pin2 = Device.pin_factory.pin(5)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(6)
 | 
					    pin3 = Device.pin_factory.pin(6)
 | 
				
			||||||
    with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
 | 
					    with LEDBoard(4, LEDBoard(5, 6)) as board:
 | 
				
			||||||
        # Instantiation takes a long enough time that it throws off our timing
 | 
					        # Instantiation takes a long enough time that it throws off our timing
 | 
				
			||||||
        # here!
 | 
					        # here!
 | 
				
			||||||
        pin1.clear_states()
 | 
					        pin1.clear_states()
 | 
				
			||||||
@@ -276,7 +275,7 @@ def test_led_board_blink_foreground():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(4)
 | 
					    pin1 = Device.pin_factory.pin(4)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(5)
 | 
					    pin2 = Device.pin_factory.pin(5)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(6)
 | 
					    pin3 = Device.pin_factory.pin(6)
 | 
				
			||||||
    with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
 | 
					    with LEDBoard(4, LEDBoard(5, 6)) as board:
 | 
				
			||||||
        pin1.clear_states()
 | 
					        pin1.clear_states()
 | 
				
			||||||
        pin2.clear_states()
 | 
					        pin2.clear_states()
 | 
				
			||||||
        pin3.clear_states()
 | 
					        pin3.clear_states()
 | 
				
			||||||
@@ -298,7 +297,7 @@ def test_led_board_blink_control():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(4)
 | 
					    pin1 = Device.pin_factory.pin(4)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(5)
 | 
					    pin2 = Device.pin_factory.pin(5)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(6)
 | 
					    pin3 = Device.pin_factory.pin(6)
 | 
				
			||||||
    with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
 | 
					    with LEDBoard(4, LEDBoard(5, 6)) as board:
 | 
				
			||||||
        pin1.clear_states()
 | 
					        pin1.clear_states()
 | 
				
			||||||
        pin2.clear_states()
 | 
					        pin2.clear_states()
 | 
				
			||||||
        pin3.clear_states()
 | 
					        pin3.clear_states()
 | 
				
			||||||
@@ -326,7 +325,7 @@ def test_led_board_blink_take_over():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(4)
 | 
					    pin1 = Device.pin_factory.pin(4)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(5)
 | 
					    pin2 = Device.pin_factory.pin(5)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(6)
 | 
					    pin3 = Device.pin_factory.pin(6)
 | 
				
			||||||
    with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
 | 
					    with LEDBoard(4, LEDBoard(5, 6)) as board:
 | 
				
			||||||
        pin1.clear_states()
 | 
					        pin1.clear_states()
 | 
				
			||||||
        pin2.clear_states()
 | 
					        pin2.clear_states()
 | 
				
			||||||
        pin3.clear_states()
 | 
					        pin3.clear_states()
 | 
				
			||||||
@@ -351,7 +350,7 @@ def test_led_board_blink_control_all():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(4)
 | 
					    pin1 = Device.pin_factory.pin(4)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(5)
 | 
					    pin2 = Device.pin_factory.pin(5)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(6)
 | 
					    pin3 = Device.pin_factory.pin(6)
 | 
				
			||||||
    with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
 | 
					    with LEDBoard(4, LEDBoard(5, 6)) as board:
 | 
				
			||||||
        pin1.clear_states()
 | 
					        pin1.clear_states()
 | 
				
			||||||
        pin2.clear_states()
 | 
					        pin2.clear_states()
 | 
				
			||||||
        pin3.clear_states()
 | 
					        pin3.clear_states()
 | 
				
			||||||
@@ -376,7 +375,7 @@ def test_led_board_blink_interrupt_on():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(4)
 | 
					    pin1 = Device.pin_factory.pin(4)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(5)
 | 
					    pin2 = Device.pin_factory.pin(5)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(6)
 | 
					    pin3 = Device.pin_factory.pin(6)
 | 
				
			||||||
    with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
 | 
					    with LEDBoard(4, LEDBoard(5, 6)) as board:
 | 
				
			||||||
        board.blink(1, 0.1)
 | 
					        board.blink(1, 0.1)
 | 
				
			||||||
        sleep(0.2)
 | 
					        sleep(0.2)
 | 
				
			||||||
        board.off() # should interrupt while on
 | 
					        board.off() # should interrupt while on
 | 
				
			||||||
@@ -388,7 +387,7 @@ def test_led_board_blink_interrupt_off():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(4)
 | 
					    pin1 = Device.pin_factory.pin(4)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(5)
 | 
					    pin2 = Device.pin_factory.pin(5)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(6)
 | 
					    pin3 = Device.pin_factory.pin(6)
 | 
				
			||||||
    with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
 | 
					    with LEDBoard(4, LEDBoard(5, 6)) as board:
 | 
				
			||||||
        pin1.clear_states()
 | 
					        pin1.clear_states()
 | 
				
			||||||
        pin2.clear_states()
 | 
					        pin2.clear_states()
 | 
				
			||||||
        pin3.clear_states()
 | 
					        pin3.clear_states()
 | 
				
			||||||
@@ -405,7 +404,7 @@ def test_led_board_fade_background():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(4)
 | 
					    pin1 = Device.pin_factory.pin(4)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(5)
 | 
					    pin2 = Device.pin_factory.pin(5)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(6)
 | 
					    pin3 = Device.pin_factory.pin(6)
 | 
				
			||||||
    with LEDBoard(pin1, LEDBoard(pin2, pin3, pwm=True), pwm=True) as board:
 | 
					    with LEDBoard(4, LEDBoard(5, 6, pwm=True), pwm=True) as board:
 | 
				
			||||||
        pin1.clear_states()
 | 
					        pin1.clear_states()
 | 
				
			||||||
        pin2.clear_states()
 | 
					        pin2.clear_states()
 | 
				
			||||||
        pin3.clear_states()
 | 
					        pin3.clear_states()
 | 
				
			||||||
@@ -442,7 +441,7 @@ def test_led_bar_graph_value():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LEDBarGraph(pin1, pin2, pin3) as graph:
 | 
					    with LEDBarGraph(2, 3, 4) as graph:
 | 
				
			||||||
        assert isinstance(graph[0], LED)
 | 
					        assert isinstance(graph[0], LED)
 | 
				
			||||||
        assert isinstance(graph[1], LED)
 | 
					        assert isinstance(graph[1], LED)
 | 
				
			||||||
        assert isinstance(graph[2], LED)
 | 
					        assert isinstance(graph[2], LED)
 | 
				
			||||||
@@ -475,7 +474,7 @@ def test_led_bar_graph_active_low():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LEDBarGraph(pin1, pin2, pin3, active_high=False) as graph:
 | 
					    with LEDBarGraph(2, 3, 4, active_high=False) as graph:
 | 
				
			||||||
        assert not graph.active_high
 | 
					        assert not graph.active_high
 | 
				
			||||||
        assert not graph[0].active_high
 | 
					        assert not graph[0].active_high
 | 
				
			||||||
        assert not graph[1].active_high
 | 
					        assert not graph[1].active_high
 | 
				
			||||||
@@ -497,7 +496,7 @@ def test_led_bar_graph_pwm_value():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LEDBarGraph(pin1, pin2, pin3, pwm=True) as graph:
 | 
					    with LEDBarGraph(2, 3, 4, pwm=True) as graph:
 | 
				
			||||||
        assert isinstance(graph[0], PWMLED)
 | 
					        assert isinstance(graph[0], PWMLED)
 | 
				
			||||||
        assert isinstance(graph[1], PWMLED)
 | 
					        assert isinstance(graph[1], PWMLED)
 | 
				
			||||||
        assert isinstance(graph[2], PWMLED)
 | 
					        assert isinstance(graph[2], PWMLED)
 | 
				
			||||||
@@ -524,7 +523,7 @@ def test_led_bar_graph_bad_value():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LEDBarGraph(pin1, pin2, pin3) as graph:
 | 
					    with LEDBarGraph(2, 3, 4) as graph:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            graph.value = -2
 | 
					            graph.value = -2
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
@@ -535,20 +534,20 @@ def test_led_bar_graph_bad_init():
 | 
				
			|||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with pytest.raises(TypeError):
 | 
					    with pytest.raises(TypeError):
 | 
				
			||||||
        LEDBarGraph(pin1, pin2, foo=pin3)
 | 
					        LEDBarGraph(2, 3, foo=4)
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        LEDBarGraph(pin1, pin2, pin3, initial_value=-2)
 | 
					        LEDBarGraph(2, 3, 4, initial_value=-2)
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        LEDBarGraph(pin1, pin2, pin3, initial_value=2)
 | 
					        LEDBarGraph(2, 3, 4, initial_value=2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_led_bar_graph_initial_value():
 | 
					def test_led_bar_graph_initial_value():
 | 
				
			||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LEDBarGraph(pin1, pin2, pin3, initial_value=1/3) as graph:
 | 
					    with LEDBarGraph(2, 3, 4, initial_value=1/3) as graph:
 | 
				
			||||||
        assert graph.value == 1/3
 | 
					        assert graph.value == 1/3
 | 
				
			||||||
        assert pin1.state and not (pin2.state or pin3.state)
 | 
					        assert pin1.state and not (pin2.state or pin3.state)
 | 
				
			||||||
    with LEDBarGraph(pin1, pin2, pin3, initial_value=-1/3) as graph:
 | 
					    with LEDBarGraph(2, 3, 4, initial_value=-1/3) as graph:
 | 
				
			||||||
        assert graph.value == -1/3
 | 
					        assert graph.value == -1/3
 | 
				
			||||||
        assert pin3.state and not (pin1.state or pin2.state)
 | 
					        assert pin3.state and not (pin1.state or pin2.state)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -556,10 +555,10 @@ def test_led_bar_graph_pwm_initial_value():
 | 
				
			|||||||
    pin1 = Device.pin_factory.pin(2)
 | 
					    pin1 = Device.pin_factory.pin(2)
 | 
				
			||||||
    pin2 = Device.pin_factory.pin(3)
 | 
					    pin2 = Device.pin_factory.pin(3)
 | 
				
			||||||
    pin3 = Device.pin_factory.pin(4)
 | 
					    pin3 = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LEDBarGraph(pin1, pin2, pin3, pwm=True, initial_value=0.5) as graph:
 | 
					    with LEDBarGraph(2, 3, 4, pwm=True, initial_value=0.5) as graph:
 | 
				
			||||||
        assert graph.value == 0.5
 | 
					        assert graph.value == 0.5
 | 
				
			||||||
        assert (pin1.state, pin2.state, pin3.state) == (1, 0.5, 0)
 | 
					        assert (pin1.state, pin2.state, pin3.state) == (1, 0.5, 0)
 | 
				
			||||||
    with LEDBarGraph(pin1, pin2, pin3, pwm=True, initial_value=-0.5) as graph:
 | 
					    with LEDBarGraph(2, 3, 4, pwm=True, initial_value=-0.5) as graph:
 | 
				
			||||||
        assert graph.value == -0.5
 | 
					        assert graph.value == -0.5
 | 
				
			||||||
        assert (pin1.state, pin2.state, pin3.state) == (0, 0.5, 1)
 | 
					        assert (pin1.state, pin2.state, pin3.state) == (0, 0.5, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -585,7 +584,7 @@ def test_traffic_lights():
 | 
				
			|||||||
    red_pin = Device.pin_factory.pin(2)
 | 
					    red_pin = Device.pin_factory.pin(2)
 | 
				
			||||||
    amber_pin = Device.pin_factory.pin(3)
 | 
					    amber_pin = Device.pin_factory.pin(3)
 | 
				
			||||||
    green_pin = Device.pin_factory.pin(4)
 | 
					    green_pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with TrafficLights(red_pin, amber_pin, green_pin) as board:
 | 
					    with TrafficLights(2, 3, 4) as board:
 | 
				
			||||||
        board.red.on()
 | 
					        board.red.on()
 | 
				
			||||||
        assert board.red.value
 | 
					        assert board.red.value
 | 
				
			||||||
        assert not board.amber.value
 | 
					        assert not board.amber.value
 | 
				
			||||||
@@ -598,7 +597,7 @@ def test_traffic_lights():
 | 
				
			|||||||
        assert amber_pin.state
 | 
					        assert amber_pin.state
 | 
				
			||||||
        board.yellow.off()
 | 
					        board.yellow.off()
 | 
				
			||||||
        assert not amber_pin.state
 | 
					        assert not amber_pin.state
 | 
				
			||||||
    with TrafficLights(red=red_pin, yellow=amber_pin, green=green_pin) as board:
 | 
					    with TrafficLights(red=2, yellow=3, green=4) as board:
 | 
				
			||||||
        board.yellow.on()
 | 
					        board.yellow.on()
 | 
				
			||||||
        assert not board.red.value
 | 
					        assert not board.red.value
 | 
				
			||||||
        assert board.amber.value
 | 
					        assert board.amber.value
 | 
				
			||||||
@@ -618,7 +617,7 @@ def test_traffic_lights_bad_init():
 | 
				
			|||||||
    green_pin = Device.pin_factory.pin(4)
 | 
					    green_pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    yellow_pin = Device.pin_factory.pin(5)
 | 
					    yellow_pin = Device.pin_factory.pin(5)
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        TrafficLights(red=red_pin, amber=amber_pin, yellow=yellow_pin, green=green_pin)
 | 
					        TrafficLights(red=2, amber=3, yellow=5, green=4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pi_traffic():
 | 
					def test_pi_traffic():
 | 
				
			||||||
    pins = [Device.pin_factory.pin(n) for n in (9, 10, 11)]
 | 
					    pins = [Device.pin_factory.pin(n) for n in (9, 10, 11)]
 | 
				
			||||||
@@ -677,9 +676,9 @@ def test_traffic_lights_buzzer():
 | 
				
			|||||||
    buzzer_pin = Device.pin_factory.pin(5)
 | 
					    buzzer_pin = Device.pin_factory.pin(5)
 | 
				
			||||||
    button_pin = Device.pin_factory.pin(6)
 | 
					    button_pin = Device.pin_factory.pin(6)
 | 
				
			||||||
    with TrafficLightsBuzzer(
 | 
					    with TrafficLightsBuzzer(
 | 
				
			||||||
            TrafficLights(red_pin, amber_pin, green_pin),
 | 
					            TrafficLights(2, 3, 4),
 | 
				
			||||||
            Buzzer(buzzer_pin),
 | 
					            Buzzer(5),
 | 
				
			||||||
            Button(button_pin)) as board:
 | 
					            Button(6)) as board:
 | 
				
			||||||
        board.lights.red.on()
 | 
					        board.lights.red.on()
 | 
				
			||||||
        board.buzzer.on()
 | 
					        board.buzzer.on()
 | 
				
			||||||
        assert red_pin.state
 | 
					        assert red_pin.state
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,7 +33,7 @@ def test_device_non_physical():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_device_init():
 | 
					def test_device_init():
 | 
				
			||||||
    pin = Device.pin_factory.pin(2)
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
    with GPIODevice(pin) as device:
 | 
					    with GPIODevice(2) as device:
 | 
				
			||||||
        assert not device.closed
 | 
					        assert not device.closed
 | 
				
			||||||
        assert device.pin == pin
 | 
					        assert device.pin == pin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -56,9 +56,9 @@ def test_device_close():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_device_reopen_same_pin():
 | 
					def test_device_reopen_same_pin():
 | 
				
			||||||
    pin = Device.pin_factory.pin(2)
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
    with GPIODevice(pin) as device:
 | 
					    with GPIODevice(2) as device:
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
    with GPIODevice(pin) as device2:
 | 
					    with GPIODevice(2) as device2:
 | 
				
			||||||
        assert not device2.closed
 | 
					        assert not device2.closed
 | 
				
			||||||
        assert device2.pin is pin
 | 
					        assert device2.pin is pin
 | 
				
			||||||
        assert device.closed
 | 
					        assert device.closed
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,22 +18,21 @@ from gpiozero import *
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def teardown_function(function):
 | 
					def teardown_function(function):
 | 
				
			||||||
    Device.pin_factory.reset()
 | 
					    Device.pin_factory.reset()
 | 
				
			||||||
    Device._reservations.clear()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_input_initial_values():
 | 
					def test_input_initial_values():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with InputDevice(pin, pull_up=True) as device:
 | 
					    with InputDevice(4, pull_up=True) as device:
 | 
				
			||||||
        assert pin.function == 'input'
 | 
					        assert pin.function == 'input'
 | 
				
			||||||
        assert pin.pull == 'up'
 | 
					        assert pin.pull == 'up'
 | 
				
			||||||
        assert device.pull_up
 | 
					        assert device.pull_up
 | 
				
			||||||
    with InputDevice(pin, pull_up=False) as device:
 | 
					    with InputDevice(4, pull_up=False) as device:
 | 
				
			||||||
        assert pin.pull == 'down'
 | 
					        assert pin.pull == 'down'
 | 
				
			||||||
        assert not device.pull_up
 | 
					        assert not device.pull_up
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_input_is_active_low():
 | 
					def test_input_is_active_low():
 | 
				
			||||||
    pin = Device.pin_factory.pin(2)
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
    with InputDevice(pin, pull_up=True) as device:
 | 
					    with InputDevice(2, pull_up=True) as device:
 | 
				
			||||||
        pin.drive_high()
 | 
					        pin.drive_high()
 | 
				
			||||||
        assert not device.is_active
 | 
					        assert not device.is_active
 | 
				
			||||||
        assert repr(device) == '<gpiozero.InputDevice object on pin GPIO2, pull_up=True, is_active=False>'
 | 
					        assert repr(device) == '<gpiozero.InputDevice object on pin GPIO2, pull_up=True, is_active=False>'
 | 
				
			||||||
@@ -43,7 +42,7 @@ def test_input_is_active_low():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_input_is_active_high():
 | 
					def test_input_is_active_high():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with InputDevice(pin, pull_up=False) as device:
 | 
					    with InputDevice(4, pull_up=False) as device:
 | 
				
			||||||
        pin.drive_high()
 | 
					        pin.drive_high()
 | 
				
			||||||
        assert device.is_active
 | 
					        assert device.is_active
 | 
				
			||||||
        assert repr(device) == '<gpiozero.InputDevice object on pin GPIO4, pull_up=False, is_active=True>'
 | 
					        assert repr(device) == '<gpiozero.InputDevice object on pin GPIO4, pull_up=False, is_active=True>'
 | 
				
			||||||
@@ -54,12 +53,12 @@ def test_input_is_active_high():
 | 
				
			|||||||
def test_input_pulled_up():
 | 
					def test_input_pulled_up():
 | 
				
			||||||
    pin = Device.pin_factory.pin(2)
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
    with pytest.raises(PinFixedPull):
 | 
					    with pytest.raises(PinFixedPull):
 | 
				
			||||||
        InputDevice(pin, pull_up=False)
 | 
					        InputDevice(2, pull_up=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_input_event_activated():
 | 
					def test_input_event_activated():
 | 
				
			||||||
    event = Event()
 | 
					    event = Event()
 | 
				
			||||||
    pin = Device.pin_factory.pin(4)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with DigitalInputDevice(pin) as device:
 | 
					    with DigitalInputDevice(4) as device:
 | 
				
			||||||
        device.when_activated = lambda: event.set()
 | 
					        device.when_activated = lambda: event.set()
 | 
				
			||||||
        assert not event.is_set()
 | 
					        assert not event.is_set()
 | 
				
			||||||
        pin.drive_high()
 | 
					        pin.drive_high()
 | 
				
			||||||
@@ -68,7 +67,7 @@ def test_input_event_activated():
 | 
				
			|||||||
def test_input_event_deactivated():
 | 
					def test_input_event_deactivated():
 | 
				
			||||||
    event = Event()
 | 
					    event = Event()
 | 
				
			||||||
    pin = Device.pin_factory.pin(4)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with DigitalInputDevice(pin) as device:
 | 
					    with DigitalInputDevice(4) as device:
 | 
				
			||||||
        device.when_deactivated = lambda: event.set()
 | 
					        device.when_deactivated = lambda: event.set()
 | 
				
			||||||
        assert not event.is_set()
 | 
					        assert not event.is_set()
 | 
				
			||||||
        pin.drive_high()
 | 
					        pin.drive_high()
 | 
				
			||||||
@@ -84,7 +83,7 @@ def test_input_partial_callback():
 | 
				
			|||||||
        return a + b
 | 
					        return a + b
 | 
				
			||||||
    bar = partial(foo, 1)
 | 
					    bar = partial(foo, 1)
 | 
				
			||||||
    baz = partial(bar, 2)
 | 
					    baz = partial(bar, 2)
 | 
				
			||||||
    with DigitalInputDevice(pin) as device:
 | 
					    with DigitalInputDevice(4) as device:
 | 
				
			||||||
        device.when_activated = baz
 | 
					        device.when_activated = baz
 | 
				
			||||||
        assert not event.is_set()
 | 
					        assert not event.is_set()
 | 
				
			||||||
        pin.drive_high()
 | 
					        pin.drive_high()
 | 
				
			||||||
@@ -92,20 +91,20 @@ def test_input_partial_callback():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_input_wait_active():
 | 
					def test_input_wait_active():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with DigitalInputDevice(pin) as device:
 | 
					    with DigitalInputDevice(4) as device:
 | 
				
			||||||
        pin.drive_high()
 | 
					        pin.drive_high()
 | 
				
			||||||
        assert device.wait_for_active(1)
 | 
					        assert device.wait_for_active(1)
 | 
				
			||||||
        assert not device.wait_for_inactive(0)
 | 
					        assert not device.wait_for_inactive(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_input_wait_inactive():
 | 
					def test_input_wait_inactive():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with DigitalInputDevice(pin) as device:
 | 
					    with DigitalInputDevice(4) as device:
 | 
				
			||||||
        assert device.wait_for_inactive(1)
 | 
					        assert device.wait_for_inactive(1)
 | 
				
			||||||
        assert not device.wait_for_active(0)
 | 
					        assert not device.wait_for_active(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_input_smoothed_attrib():
 | 
					def test_input_smoothed_attrib():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with SmoothedInputDevice(pin, threshold=0.5, queue_len=5, partial=False) as device:
 | 
					    with SmoothedInputDevice(4, threshold=0.5, queue_len=5, partial=False) as device:
 | 
				
			||||||
        assert repr(device) == '<gpiozero.SmoothedInputDevice object on pin GPIO4, pull_up=False>'
 | 
					        assert repr(device) == '<gpiozero.SmoothedInputDevice object on pin GPIO4, pull_up=False>'
 | 
				
			||||||
        assert device.threshold == 0.5
 | 
					        assert device.threshold == 0.5
 | 
				
			||||||
        assert device.queue_len == 5
 | 
					        assert device.queue_len == 5
 | 
				
			||||||
@@ -117,7 +116,7 @@ def test_input_smoothed_attrib():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_input_smoothed_values():
 | 
					def test_input_smoothed_values():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with SmoothedInputDevice(pin) as device:
 | 
					    with SmoothedInputDevice(4) as device:
 | 
				
			||||||
        device._queue.start()
 | 
					        device._queue.start()
 | 
				
			||||||
        assert not device.is_active
 | 
					        assert not device.is_active
 | 
				
			||||||
        pin.drive_high()
 | 
					        pin.drive_high()
 | 
				
			||||||
@@ -127,7 +126,7 @@ def test_input_smoothed_values():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_input_button():
 | 
					def test_input_button():
 | 
				
			||||||
    pin = Device.pin_factory.pin(2)
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
    with Button(pin) as button:
 | 
					    with Button(2) as button:
 | 
				
			||||||
        assert pin.pull == 'up'
 | 
					        assert pin.pull == 'up'
 | 
				
			||||||
        assert not button.is_pressed
 | 
					        assert not button.is_pressed
 | 
				
			||||||
        pin.drive_low()
 | 
					        pin.drive_low()
 | 
				
			||||||
@@ -139,7 +138,7 @@ def test_input_button():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_input_line_sensor():
 | 
					def test_input_line_sensor():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with LineSensor(pin) as sensor:
 | 
					    with LineSensor(4) as sensor:
 | 
				
			||||||
        pin.drive_low() # logic is inverted for line sensor
 | 
					        pin.drive_low() # logic is inverted for line sensor
 | 
				
			||||||
        assert sensor.wait_for_line(1)
 | 
					        assert sensor.wait_for_line(1)
 | 
				
			||||||
        assert sensor.line_detected
 | 
					        assert sensor.line_detected
 | 
				
			||||||
@@ -149,7 +148,7 @@ def test_input_line_sensor():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_input_motion_sensor():
 | 
					def test_input_motion_sensor():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with MotionSensor(pin) as sensor:
 | 
					    with MotionSensor(4) as sensor:
 | 
				
			||||||
        pin.drive_high()
 | 
					        pin.drive_high()
 | 
				
			||||||
        assert sensor.wait_for_motion(1)
 | 
					        assert sensor.wait_for_motion(1)
 | 
				
			||||||
        assert sensor.motion_detected
 | 
					        assert sensor.motion_detected
 | 
				
			||||||
@@ -161,7 +160,7 @@ def test_input_motion_sensor():
 | 
				
			|||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_input_light_sensor():
 | 
					def test_input_light_sensor():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4, pin_class=MockChargingPin)
 | 
					    pin = Device.pin_factory.pin(4, pin_class=MockChargingPin)
 | 
				
			||||||
    with LightSensor(pin) as sensor:
 | 
					    with LightSensor(4) as sensor:
 | 
				
			||||||
        pin.charge_time = 0.1
 | 
					        pin.charge_time = 0.1
 | 
				
			||||||
        assert sensor.wait_for_dark(1)
 | 
					        assert sensor.wait_for_dark(1)
 | 
				
			||||||
        pin.charge_time = 0.0
 | 
					        pin.charge_time = 0.0
 | 
				
			||||||
@@ -173,10 +172,10 @@ def test_input_distance_sensor():
 | 
				
			|||||||
    echo_pin = Device.pin_factory.pin(4)
 | 
					    echo_pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    trig_pin = Device.pin_factory.pin(5, pin_class=MockTriggerPin, echo_pin=echo_pin, echo_time=0.02)
 | 
					    trig_pin = Device.pin_factory.pin(5, pin_class=MockTriggerPin, echo_pin=echo_pin, echo_time=0.02)
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        DistanceSensor(echo_pin, trig_pin, max_distance=-1)
 | 
					        DistanceSensor(4, 5, max_distance=-1)
 | 
				
			||||||
    # normal queue len is large (because the sensor is *really* jittery) but
 | 
					    # normal queue len is large (because the sensor is *really* jittery) but
 | 
				
			||||||
    # we want quick tests and we've got precisely controlled pins :)
 | 
					    # we want quick tests and we've got precisely controlled pins :)
 | 
				
			||||||
    with DistanceSensor(echo_pin, trig_pin, queue_len=5, max_distance=1) as sensor:
 | 
					    with DistanceSensor(4, 5, queue_len=5, max_distance=1) as sensor:
 | 
				
			||||||
        assert sensor.max_distance == 1
 | 
					        assert sensor.max_distance == 1
 | 
				
			||||||
        assert sensor.trigger is trig_pin
 | 
					        assert sensor.trigger is trig_pin
 | 
				
			||||||
        assert sensor.echo is echo_pin
 | 
					        assert sensor.echo is echo_pin
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,29 +16,73 @@ except ImportError:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from gpiozero.pins.mock import MockPWMPin
 | 
					from gpiozero.pins.mock import MockPin, MockPWMPin
 | 
				
			||||||
from gpiozero import *
 | 
					from gpiozero import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def setup_function(function):
 | 
				
			||||||
 | 
					    # dirty, but it does the job
 | 
				
			||||||
 | 
					    Device.pin_factory.pin_class = MockPWMPin if function.__name__ in (
 | 
				
			||||||
 | 
					        'test_output_pwm_states',
 | 
				
			||||||
 | 
					        'test_output_pwm_read',
 | 
				
			||||||
 | 
					        'test_output_pwm_write',
 | 
				
			||||||
 | 
					        'test_output_pwm_toggle',
 | 
				
			||||||
 | 
					        'test_output_pwm_active_high_read',
 | 
				
			||||||
 | 
					        'test_output_pwm_bad_value',
 | 
				
			||||||
 | 
					        'test_output_pwm_write_closed',
 | 
				
			||||||
 | 
					        'test_output_pwm_write_silly',
 | 
				
			||||||
 | 
					        'test_output_pwm_blink_background',
 | 
				
			||||||
 | 
					        'test_output_pwm_blink_foreground',
 | 
				
			||||||
 | 
					        'test_output_pwm_fade_background',
 | 
				
			||||||
 | 
					        'test_output_pwm_fade_foreground',
 | 
				
			||||||
 | 
					        'test_output_pwm_pulse_background',
 | 
				
			||||||
 | 
					        'test_output_pwm_pulse_foreground',
 | 
				
			||||||
 | 
					        'test_output_pwm_blink_interrupt',
 | 
				
			||||||
 | 
					        'test_rgbled_initial_value',
 | 
				
			||||||
 | 
					        'test_rgbled_initial_bad_value',
 | 
				
			||||||
 | 
					        'test_rgbled_value',
 | 
				
			||||||
 | 
					        'test_rgbled_bad_value',
 | 
				
			||||||
 | 
					        'test_rgbled_toggle',
 | 
				
			||||||
 | 
					        'test_rgbled_blink_background',
 | 
				
			||||||
 | 
					        'test_rgbled_blink_foreground',
 | 
				
			||||||
 | 
					        'test_rgbled_fade_background',
 | 
				
			||||||
 | 
					        'test_rgbled_fade_foreground',
 | 
				
			||||||
 | 
					        'test_rgbled_pulse_background',
 | 
				
			||||||
 | 
					        'test_rgbled_pulse_foreground',
 | 
				
			||||||
 | 
					        'test_rgbled_blink_interrupt',
 | 
				
			||||||
 | 
					        'test_rgbled_close',
 | 
				
			||||||
 | 
					        'test_motor_pins',
 | 
				
			||||||
 | 
					        'test_motor_close',
 | 
				
			||||||
 | 
					        'test_motor_value',
 | 
				
			||||||
 | 
					        'test_motor_bad_value',
 | 
				
			||||||
 | 
					        'test_motor_reverse',
 | 
				
			||||||
 | 
					        'test_servo_pins',
 | 
				
			||||||
 | 
					        'test_servo_bad_value',
 | 
				
			||||||
 | 
					        'test_servo_close',
 | 
				
			||||||
 | 
					        'test_servo_pulse_width',
 | 
				
			||||||
 | 
					        'test_servo_values',
 | 
				
			||||||
 | 
					        'test_angular_servo_range',
 | 
				
			||||||
 | 
					        'test_angular_servo_angles',
 | 
				
			||||||
 | 
					        ) else MockPin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def teardown_function(function):
 | 
					def teardown_function(function):
 | 
				
			||||||
    Device.pin_factory.reset()
 | 
					    Device.pin_factory.reset()
 | 
				
			||||||
    Device._reservations.clear()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_output_initial_values():
 | 
					def test_output_initial_values():
 | 
				
			||||||
    pin = Device.pin_factory.pin(2)
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
    with OutputDevice(pin, initial_value=False) as device:
 | 
					    with OutputDevice(2, initial_value=False) as device:
 | 
				
			||||||
        assert pin.function == 'output'
 | 
					        assert pin.function == 'output'
 | 
				
			||||||
        assert not pin.state
 | 
					        assert not pin.state
 | 
				
			||||||
    with OutputDevice(pin, initial_value=True) as device:
 | 
					    with OutputDevice(2, initial_value=True) as device:
 | 
				
			||||||
        assert pin.state
 | 
					        assert pin.state
 | 
				
			||||||
        state = pin.state
 | 
					        state = pin.state
 | 
				
			||||||
    with OutputDevice(pin, initial_value=None) as device:
 | 
					    with OutputDevice(2, initial_value=None) as device:
 | 
				
			||||||
        assert state == pin.state
 | 
					        assert state == pin.state
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_output_write_active_high():
 | 
					def test_output_write_active_high():
 | 
				
			||||||
    pin = Device.pin_factory.pin(2)
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
    with OutputDevice(pin) as device:
 | 
					    with OutputDevice(2) as device:
 | 
				
			||||||
        device.on()
 | 
					        device.on()
 | 
				
			||||||
        assert pin.state
 | 
					        assert pin.state
 | 
				
			||||||
        device.off()
 | 
					        device.off()
 | 
				
			||||||
@@ -46,14 +90,14 @@ def test_output_write_active_high():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_output_write_active_low():
 | 
					def test_output_write_active_low():
 | 
				
			||||||
    pin = Device.pin_factory.pin(2)
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
    with OutputDevice(pin, active_high=False) as device:
 | 
					    with OutputDevice(2, active_high=False) as device:
 | 
				
			||||||
        device.on()
 | 
					        device.on()
 | 
				
			||||||
        assert not pin.state
 | 
					        assert not pin.state
 | 
				
			||||||
        device.off()
 | 
					        device.off()
 | 
				
			||||||
        assert pin.state
 | 
					        assert pin.state
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_output_write_closed():
 | 
					def test_output_write_closed():
 | 
				
			||||||
    with OutputDevice(Device.pin_factory.pin(2)) as device:
 | 
					    with OutputDevice(2) as device:
 | 
				
			||||||
        device.close()
 | 
					        device.close()
 | 
				
			||||||
        assert device.closed
 | 
					        assert device.closed
 | 
				
			||||||
        device.close()
 | 
					        device.close()
 | 
				
			||||||
@@ -63,14 +107,14 @@ def test_output_write_closed():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_output_write_silly():
 | 
					def test_output_write_silly():
 | 
				
			||||||
    pin = Device.pin_factory.pin(2)
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
    with OutputDevice(pin) as device:
 | 
					    with OutputDevice(2) as device:
 | 
				
			||||||
        pin.function = 'input'
 | 
					        pin.function = 'input'
 | 
				
			||||||
        with pytest.raises(AttributeError):
 | 
					        with pytest.raises(AttributeError):
 | 
				
			||||||
            device.on()
 | 
					            device.on()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_output_value():
 | 
					def test_output_value():
 | 
				
			||||||
    pin = Device.pin_factory.pin(2)
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
    with OutputDevice(pin) as device:
 | 
					    with OutputDevice(2) as device:
 | 
				
			||||||
        assert not device.value
 | 
					        assert not device.value
 | 
				
			||||||
        assert not pin.state
 | 
					        assert not pin.state
 | 
				
			||||||
        device.on()
 | 
					        device.on()
 | 
				
			||||||
@@ -82,7 +126,7 @@ def test_output_value():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_output_digital_toggle():
 | 
					def test_output_digital_toggle():
 | 
				
			||||||
    pin = Device.pin_factory.pin(2)
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
    with DigitalOutputDevice(pin) as device:
 | 
					    with DigitalOutputDevice(2) as device:
 | 
				
			||||||
        assert not device.value
 | 
					        assert not device.value
 | 
				
			||||||
        assert not pin.state
 | 
					        assert not pin.state
 | 
				
			||||||
        device.toggle()
 | 
					        device.toggle()
 | 
				
			||||||
@@ -96,7 +140,7 @@ def test_output_digital_toggle():
 | 
				
			|||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_output_blink_background():
 | 
					def test_output_blink_background():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with DigitalOutputDevice(pin) as device:
 | 
					    with DigitalOutputDevice(4) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.blink(0.1, 0.1, n=2)
 | 
					        device.blink(0.1, 0.1, n=2)
 | 
				
			||||||
        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
				
			||||||
@@ -114,7 +158,7 @@ def test_output_blink_background():
 | 
				
			|||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_output_blink_foreground():
 | 
					def test_output_blink_foreground():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with DigitalOutputDevice(pin) as device:
 | 
					    with DigitalOutputDevice(4) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.blink(0.1, 0.1, n=2, background=False)
 | 
					        device.blink(0.1, 0.1, n=2, background=False)
 | 
				
			||||||
        assert isclose(time() - start, 0.4, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0.4, abs_tol=0.05)
 | 
				
			||||||
@@ -128,7 +172,7 @@ def test_output_blink_foreground():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_output_blink_interrupt_on():
 | 
					def test_output_blink_interrupt_on():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with DigitalOutputDevice(pin) as device:
 | 
					    with DigitalOutputDevice(4) as device:
 | 
				
			||||||
        device.blink(1, 0.1)
 | 
					        device.blink(1, 0.1)
 | 
				
			||||||
        sleep(0.2)
 | 
					        sleep(0.2)
 | 
				
			||||||
        device.off() # should interrupt while on
 | 
					        device.off() # should interrupt while on
 | 
				
			||||||
@@ -136,7 +180,7 @@ def test_output_blink_interrupt_on():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_output_blink_interrupt_off():
 | 
					def test_output_blink_interrupt_off():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with DigitalOutputDevice(pin) as device:
 | 
					    with DigitalOutputDevice(4) as device:
 | 
				
			||||||
        device.blink(0.1, 1)
 | 
					        device.blink(0.1, 1)
 | 
				
			||||||
        sleep(0.2)
 | 
					        sleep(0.2)
 | 
				
			||||||
        device.off() # should interrupt while off
 | 
					        device.off() # should interrupt while off
 | 
				
			||||||
@@ -144,23 +188,23 @@ def test_output_blink_interrupt_off():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_output_pwm_bad_initial_value():
 | 
					def test_output_pwm_bad_initial_value():
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        PWMOutputDevice(Device.pin_factory.pin(2), initial_value=2)
 | 
					        PWMOutputDevice(2, initial_value=2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_output_pwm_not_supported():
 | 
					def test_output_pwm_not_supported():
 | 
				
			||||||
    with pytest.raises(AttributeError):
 | 
					    with pytest.raises(AttributeError):
 | 
				
			||||||
        PWMOutputDevice(Device.pin_factory.pin(2))
 | 
					        PWMOutputDevice(2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_output_pwm_states():
 | 
					def test_output_pwm_states():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4, pin_class=MockPWMPin)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with PWMOutputDevice(pin) as device:
 | 
					    with PWMOutputDevice(4) as device:
 | 
				
			||||||
        device.value = 0.1
 | 
					        device.value = 0.1
 | 
				
			||||||
        device.value = 0.2
 | 
					        device.value = 0.2
 | 
				
			||||||
        device.value = 0.0
 | 
					        device.value = 0.0
 | 
				
			||||||
        pin.assert_states([0.0, 0.1, 0.2, 0.0])
 | 
					        pin.assert_states([0.0, 0.1, 0.2, 0.0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_output_pwm_read():
 | 
					def test_output_pwm_read():
 | 
				
			||||||
    pin = Device.pin_factory.pin(2, pin_class=MockPWMPin)
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
    with PWMOutputDevice(pin, frequency=100) as device:
 | 
					    with PWMOutputDevice(2, frequency=100) as device:
 | 
				
			||||||
        assert device.frequency == 100
 | 
					        assert device.frequency == 100
 | 
				
			||||||
        device.value = 0.1
 | 
					        device.value = 0.1
 | 
				
			||||||
        assert isclose(device.value, 0.1)
 | 
					        assert isclose(device.value, 0.1)
 | 
				
			||||||
@@ -172,15 +216,15 @@ def test_output_pwm_read():
 | 
				
			|||||||
        assert device.frequency is None
 | 
					        assert device.frequency is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_output_pwm_write():
 | 
					def test_output_pwm_write():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4, pin_class=MockPWMPin)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with PWMOutputDevice(pin) as device:
 | 
					    with PWMOutputDevice(4) as device:
 | 
				
			||||||
        device.on()
 | 
					        device.on()
 | 
				
			||||||
        device.off()
 | 
					        device.off()
 | 
				
			||||||
        pin.assert_states([False, True, False])
 | 
					        pin.assert_states([False, True, False])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_output_pwm_toggle():
 | 
					def test_output_pwm_toggle():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4, pin_class=MockPWMPin)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with PWMOutputDevice(pin) as device:
 | 
					    with PWMOutputDevice(4) as device:
 | 
				
			||||||
        device.toggle()
 | 
					        device.toggle()
 | 
				
			||||||
        device.value = 0.5
 | 
					        device.value = 0.5
 | 
				
			||||||
        device.value = 0.1
 | 
					        device.value = 0.1
 | 
				
			||||||
@@ -189,8 +233,8 @@ def test_output_pwm_toggle():
 | 
				
			|||||||
        pin.assert_states([False, True, 0.5, 0.1, 0.9, False])
 | 
					        pin.assert_states([False, True, 0.5, 0.1, 0.9, False])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_output_pwm_active_high_read():
 | 
					def test_output_pwm_active_high_read():
 | 
				
			||||||
    pin = Device.pin_factory.pin(2, pin_class=MockPWMPin)
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
    with PWMOutputDevice(pin, active_high=False) as device:
 | 
					    with PWMOutputDevice(2, active_high=False) as device:
 | 
				
			||||||
        device.value = 0.1
 | 
					        device.value = 0.1
 | 
				
			||||||
        assert isclose(device.value, 0.1)
 | 
					        assert isclose(device.value, 0.1)
 | 
				
			||||||
        assert isclose(pin.state, 0.9)
 | 
					        assert isclose(pin.state, 0.9)
 | 
				
			||||||
@@ -198,19 +242,21 @@ def test_output_pwm_active_high_read():
 | 
				
			|||||||
        assert device.value
 | 
					        assert device.value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_output_pwm_bad_value():
 | 
					def test_output_pwm_bad_value():
 | 
				
			||||||
    with PWMOutputDevice(Device.pin_factory.pin(2, pin_class=MockPWMPin)) as device:
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
 | 
					    with PWMOutputDevice(2) as device:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            device.value = 2
 | 
					            device.value = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_output_pwm_write_closed():
 | 
					def test_output_pwm_write_closed():
 | 
				
			||||||
    with PWMOutputDevice(Device.pin_factory.pin(2, pin_class=MockPWMPin)) as device:
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
 | 
					    with PWMOutputDevice(2) as device:
 | 
				
			||||||
        device.close()
 | 
					        device.close()
 | 
				
			||||||
        with pytest.raises(GPIODeviceClosed):
 | 
					        with pytest.raises(GPIODeviceClosed):
 | 
				
			||||||
            device.on()
 | 
					            device.on()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_output_pwm_write_silly():
 | 
					def test_output_pwm_write_silly():
 | 
				
			||||||
    pin = Device.pin_factory.pin(2, pin_class=MockPWMPin)
 | 
					    pin = Device.pin_factory.pin(2)
 | 
				
			||||||
    with PWMOutputDevice(pin) as device:
 | 
					    with PWMOutputDevice(2) as device:
 | 
				
			||||||
        pin.function = 'input'
 | 
					        pin.function = 'input'
 | 
				
			||||||
        with pytest.raises(AttributeError):
 | 
					        with pytest.raises(AttributeError):
 | 
				
			||||||
            device.off()
 | 
					            device.off()
 | 
				
			||||||
@@ -218,8 +264,8 @@ def test_output_pwm_write_silly():
 | 
				
			|||||||
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
					@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
				
			||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_output_pwm_blink_background():
 | 
					def test_output_pwm_blink_background():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4, pin_class=MockPWMPin)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with PWMOutputDevice(pin) as device:
 | 
					    with PWMOutputDevice(4) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.blink(0.1, 0.1, n=2)
 | 
					        device.blink(0.1, 0.1, n=2)
 | 
				
			||||||
        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
				
			||||||
@@ -236,8 +282,8 @@ def test_output_pwm_blink_background():
 | 
				
			|||||||
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
					@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
				
			||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_output_pwm_blink_foreground():
 | 
					def test_output_pwm_blink_foreground():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4, pin_class=MockPWMPin)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with PWMOutputDevice(pin) as device:
 | 
					    with PWMOutputDevice(4) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.blink(0.1, 0.1, n=2, background=False)
 | 
					        device.blink(0.1, 0.1, n=2, background=False)
 | 
				
			||||||
        assert isclose(time() - start, 0.4, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0.4, abs_tol=0.05)
 | 
				
			||||||
@@ -252,8 +298,8 @@ def test_output_pwm_blink_foreground():
 | 
				
			|||||||
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
					@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
				
			||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_output_pwm_fade_background():
 | 
					def test_output_pwm_fade_background():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4, pin_class=MockPWMPin)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with PWMOutputDevice(pin) as device:
 | 
					    with PWMOutputDevice(4) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.blink(0, 0, 0.2, 0.2, n=2)
 | 
					        device.blink(0, 0, 0.2, 0.2, n=2)
 | 
				
			||||||
        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
				
			||||||
@@ -286,8 +332,8 @@ def test_output_pwm_fade_background():
 | 
				
			|||||||
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
					@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
				
			||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_output_pwm_fade_foreground():
 | 
					def test_output_pwm_fade_foreground():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4, pin_class=MockPWMPin)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with PWMOutputDevice(pin) as device:
 | 
					    with PWMOutputDevice(4) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.blink(0, 0, 0.2, 0.2, n=2, background=False)
 | 
					        device.blink(0, 0, 0.2, 0.2, n=2, background=False)
 | 
				
			||||||
        assert isclose(time() - start, 0.8, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0.8, abs_tol=0.05)
 | 
				
			||||||
@@ -318,8 +364,8 @@ def test_output_pwm_fade_foreground():
 | 
				
			|||||||
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
					@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
				
			||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_output_pwm_pulse_background():
 | 
					def test_output_pwm_pulse_background():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4, pin_class=MockPWMPin)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with PWMOutputDevice(pin) as device:
 | 
					    with PWMOutputDevice(4) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.pulse(0.2, 0.2, n=2)
 | 
					        device.pulse(0.2, 0.2, n=2)
 | 
				
			||||||
        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
				
			||||||
@@ -352,8 +398,8 @@ def test_output_pwm_pulse_background():
 | 
				
			|||||||
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
					@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
				
			||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_output_pwm_pulse_foreground():
 | 
					def test_output_pwm_pulse_foreground():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4, pin_class=MockPWMPin)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with PWMOutputDevice(pin) as device:
 | 
					    with PWMOutputDevice(4) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.pulse(0.2, 0.2, n=2, background=False)
 | 
					        device.pulse(0.2, 0.2, n=2, background=False)
 | 
				
			||||||
        assert isclose(time() - start, 0.8, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0.8, abs_tol=0.05)
 | 
				
			||||||
@@ -382,8 +428,8 @@ def test_output_pwm_pulse_foreground():
 | 
				
			|||||||
            ])
 | 
					            ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_output_pwm_blink_interrupt():
 | 
					def test_output_pwm_blink_interrupt():
 | 
				
			||||||
    pin = Device.pin_factory.pin(4, pin_class=MockPWMPin)
 | 
					    pin = Device.pin_factory.pin(4)
 | 
				
			||||||
    with PWMOutputDevice(pin) as device:
 | 
					    with PWMOutputDevice(4) as device:
 | 
				
			||||||
        device.blink(1, 0.1)
 | 
					        device.blink(1, 0.1)
 | 
				
			||||||
        sleep(0.2)
 | 
					        sleep(0.2)
 | 
				
			||||||
        device.off() # should interrupt while on
 | 
					        device.off() # should interrupt while on
 | 
				
			||||||
@@ -394,8 +440,8 @@ def test_rgbled_missing_pins():
 | 
				
			|||||||
        RGBLED()
 | 
					        RGBLED()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgbled_initial_value():
 | 
					def test_rgbled_initial_value():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i, pin_class=MockPWMPin) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with RGBLED(r, g, b, initial_value=(0.1, 0.2, 0)) as device:
 | 
					    with RGBLED(1, 2, 3, initial_value=(0.1, 0.2, 0)) as device:
 | 
				
			||||||
        assert r.frequency
 | 
					        assert r.frequency
 | 
				
			||||||
        assert g.frequency
 | 
					        assert g.frequency
 | 
				
			||||||
        assert b.frequency
 | 
					        assert b.frequency
 | 
				
			||||||
@@ -405,24 +451,24 @@ def test_rgbled_initial_value():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_rgbled_initial_value_nonpwm():
 | 
					def test_rgbled_initial_value_nonpwm():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False, initial_value=(0, 1, 1)) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False, initial_value=(0, 1, 1)) as device:
 | 
				
			||||||
        assert r.state == 0
 | 
					        assert r.state == 0
 | 
				
			||||||
        assert g.state == 1
 | 
					        assert g.state == 1
 | 
				
			||||||
        assert b.state == 1
 | 
					        assert b.state == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgbled_initial_bad_value():
 | 
					def test_rgbled_initial_bad_value():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i, pin_class=MockPWMPin) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        RGBLED(r, g, b, initial_value=(0.1, 0.2, 1.2))
 | 
					        RGBLED(1, 2, 3, initial_value=(0.1, 0.2, 1.2))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgbled_initial_bad_value_nonpwm():
 | 
					def test_rgbled_initial_bad_value_nonpwm():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        RGBLED(r, g, b, pwm=False, initial_value=(0.1, 0.2, 0))
 | 
					        RGBLED(1, 2, 3, pwm=False, initial_value=(0.1, 0.2, 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgbled_value():
 | 
					def test_rgbled_value():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i, pin_class=MockPWMPin) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with RGBLED(r, g, b) as device:
 | 
					    with RGBLED(1, 2, 3) as device:
 | 
				
			||||||
        assert isinstance(device._leds[0], PWMLED)
 | 
					        assert isinstance(device._leds[0], PWMLED)
 | 
				
			||||||
        assert isinstance(device._leds[1], PWMLED)
 | 
					        assert isinstance(device._leds[1], PWMLED)
 | 
				
			||||||
        assert isinstance(device._leds[2], PWMLED)
 | 
					        assert isinstance(device._leds[2], PWMLED)
 | 
				
			||||||
@@ -440,7 +486,7 @@ def test_rgbled_value():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_rgbled_value_nonpwm():
 | 
					def test_rgbled_value_nonpwm():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        assert isinstance(device._leds[0], LED)
 | 
					        assert isinstance(device._leds[0], LED)
 | 
				
			||||||
        assert isinstance(device._leds[1], LED)
 | 
					        assert isinstance(device._leds[1], LED)
 | 
				
			||||||
        assert isinstance(device._leds[2], LED)
 | 
					        assert isinstance(device._leds[2], LED)
 | 
				
			||||||
@@ -454,35 +500,35 @@ def test_rgbled_value_nonpwm():
 | 
				
			|||||||
        assert device.value == (0, 0, 0)
 | 
					        assert device.value == (0, 0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgbled_bad_value():
 | 
					def test_rgbled_bad_value():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i, pin_class=MockPWMPin) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with RGBLED(r, g, b) as device:
 | 
					    with RGBLED(1, 2, 3) as device:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            device.value = (2, 0, 0)
 | 
					            device.value = (2, 0, 0)
 | 
				
			||||||
    with RGBLED(r, g, b) as device:
 | 
					    with RGBLED(1, 2, 3) as device:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            device.value = (0, -1, 0)
 | 
					            device.value = (0, -1, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgbled_bad_value_nonpwm():
 | 
					def test_rgbled_bad_value_nonpwm():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            device.value = (2, 0, 0)
 | 
					            device.value = (2, 0, 0)
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            device.value = (0, -1, 0)
 | 
					            device.value = (0, -1, 0)
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            device.value = (0.5, 0, 0)
 | 
					            device.value = (0.5, 0, 0)
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            device.value = (0, 0.5, 0)
 | 
					            device.value = (0, 0.5, 0)
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            device.value = (0, 0, 0.5)
 | 
					            device.value = (0, 0, 0.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgbled_toggle():
 | 
					def test_rgbled_toggle():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i, pin_class=MockPWMPin) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with RGBLED(r, g, b) as device:
 | 
					    with RGBLED(1, 2, 3) as device:
 | 
				
			||||||
        assert not device.is_active
 | 
					        assert not device.is_active
 | 
				
			||||||
        assert device.value == (0, 0, 0)
 | 
					        assert device.value == (0, 0, 0)
 | 
				
			||||||
        device.toggle()
 | 
					        device.toggle()
 | 
				
			||||||
@@ -494,7 +540,7 @@ def test_rgbled_toggle():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_rgbled_toggle_nonpwm():
 | 
					def test_rgbled_toggle_nonpwm():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        assert not device.is_active
 | 
					        assert not device.is_active
 | 
				
			||||||
        assert device.value == (0, 0, 0)
 | 
					        assert device.value == (0, 0, 0)
 | 
				
			||||||
        device.toggle()
 | 
					        device.toggle()
 | 
				
			||||||
@@ -506,7 +552,7 @@ def test_rgbled_toggle_nonpwm():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_rgbled_blink_nonpwm():
 | 
					def test_rgbled_blink_nonpwm():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            device.blink(fade_in_time=1)
 | 
					            device.blink(fade_in_time=1)
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
@@ -515,8 +561,8 @@ def test_rgbled_blink_nonpwm():
 | 
				
			|||||||
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
					@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
				
			||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_rgbled_blink_background():
 | 
					def test_rgbled_blink_background():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i, pin_class=MockPWMPin) for i in (4, 5, 6))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (4, 5, 6))
 | 
				
			||||||
    with RGBLED(r, g, b) as device:
 | 
					    with RGBLED(1, 2, 3) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.blink(0.1, 0.1, n=2)
 | 
					        device.blink(0.1, 0.1, n=2)
 | 
				
			||||||
        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
				
			||||||
@@ -537,7 +583,7 @@ def test_rgbled_blink_background():
 | 
				
			|||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_rgbled_blink_background_nonpwm():
 | 
					def test_rgbled_blink_background_nonpwm():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i) for i in (4, 5, 6))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (4, 5, 6))
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.blink(0.1, 0.1, n=2)
 | 
					        device.blink(0.1, 0.1, n=2)
 | 
				
			||||||
        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
				
			||||||
@@ -557,8 +603,8 @@ def test_rgbled_blink_background_nonpwm():
 | 
				
			|||||||
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
					@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
				
			||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_rgbled_blink_foreground():
 | 
					def test_rgbled_blink_foreground():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i, pin_class=MockPWMPin) for i in (4, 5, 6))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (4, 5, 6))
 | 
				
			||||||
    with RGBLED(r, g, b) as device:
 | 
					    with RGBLED(1, 2, 3) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.blink(0.1, 0.1, n=2, background=False)
 | 
					        device.blink(0.1, 0.1, n=2, background=False)
 | 
				
			||||||
        assert isclose(time() - start, 0.4, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0.4, abs_tol=0.05)
 | 
				
			||||||
@@ -577,7 +623,7 @@ def test_rgbled_blink_foreground():
 | 
				
			|||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_rgbled_blink_foreground_nonpwm():
 | 
					def test_rgbled_blink_foreground_nonpwm():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i) for i in (4, 5, 6))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (4, 5, 6))
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.blink(0.1, 0.1, n=2, background=False)
 | 
					        device.blink(0.1, 0.1, n=2, background=False)
 | 
				
			||||||
        assert isclose(time() - start, 0.4, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0.4, abs_tol=0.05)
 | 
				
			||||||
@@ -595,8 +641,8 @@ def test_rgbled_blink_foreground_nonpwm():
 | 
				
			|||||||
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
					@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
				
			||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_rgbled_fade_background():
 | 
					def test_rgbled_fade_background():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i, pin_class=MockPWMPin) for i in (4, 5, 6))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (4, 5, 6))
 | 
				
			||||||
    with RGBLED(r, g, b) as device:
 | 
					    with RGBLED(1, 2, 3) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.blink(0, 0, 0.2, 0.2, n=2)
 | 
					        device.blink(0, 0, 0.2, 0.2, n=2)
 | 
				
			||||||
        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
				
			||||||
@@ -631,15 +677,15 @@ def test_rgbled_fade_background():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_rgbled_fade_background_nonpwm():
 | 
					def test_rgbled_fade_background_nonpwm():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            device.blink(0, 0, 0.2, 0.2, n=2)
 | 
					            device.blink(0, 0, 0.2, 0.2, n=2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
					@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
				
			||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_rgbled_fade_foreground():
 | 
					def test_rgbled_fade_foreground():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i, pin_class=MockPWMPin) for i in (4, 5, 6))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (4, 5, 6))
 | 
				
			||||||
    with RGBLED(r, g, b) as device:
 | 
					    with RGBLED(1, 2, 3) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.blink(0, 0, 0.2, 0.2, n=2, background=False)
 | 
					        device.blink(0, 0, 0.2, 0.2, n=2, background=False)
 | 
				
			||||||
        assert isclose(time() - start, 0.8, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0.8, abs_tol=0.05)
 | 
				
			||||||
@@ -672,15 +718,15 @@ def test_rgbled_fade_foreground():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_rgbled_fade_foreground_nonpwm():
 | 
					def test_rgbled_fade_foreground_nonpwm():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            device.blink(0, 0, 0.2, 0.2, n=2, background=False)
 | 
					            device.blink(0, 0, 0.2, 0.2, n=2, background=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
					@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
				
			||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_rgbled_pulse_background():
 | 
					def test_rgbled_pulse_background():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i, pin_class=MockPWMPin) for i in (4, 5, 6))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (4, 5, 6))
 | 
				
			||||||
    with RGBLED(r, g, b) as device:
 | 
					    with RGBLED(1, 2, 3) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.pulse(0.2, 0.2, n=2)
 | 
					        device.pulse(0.2, 0.2, n=2)
 | 
				
			||||||
        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0, abs_tol=0.05)
 | 
				
			||||||
@@ -715,15 +761,15 @@ def test_rgbled_pulse_background():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_rgbled_pulse_background_nonpwm():
 | 
					def test_rgbled_pulse_background_nonpwm():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            device.pulse(0.2, 0.2, n=2)
 | 
					            device.pulse(0.2, 0.2, n=2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
					@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
 | 
				
			||||||
                    reason='timing is too random on pypy')
 | 
					                    reason='timing is too random on pypy')
 | 
				
			||||||
def test_rgbled_pulse_foreground():
 | 
					def test_rgbled_pulse_foreground():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i, pin_class=MockPWMPin) for i in (4, 5, 6))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (4, 5, 6))
 | 
				
			||||||
    with RGBLED(r, g, b) as device:
 | 
					    with RGBLED(1, 2, 3) as device:
 | 
				
			||||||
        start = time()
 | 
					        start = time()
 | 
				
			||||||
        device.pulse(0.2, 0.2, n=2, background=False)
 | 
					        device.pulse(0.2, 0.2, n=2, background=False)
 | 
				
			||||||
        assert isclose(time() - start, 0.8, abs_tol=0.05)
 | 
					        assert isclose(time() - start, 0.8, abs_tol=0.05)
 | 
				
			||||||
@@ -756,13 +802,13 @@ def test_rgbled_pulse_foreground():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_rgbled_pulse_foreground_nonpwm():
 | 
					def test_rgbled_pulse_foreground_nonpwm():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            device.pulse(0.2, 0.2, n=2, background=False)
 | 
					            device.pulse(0.2, 0.2, n=2, background=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgbled_blink_interrupt():
 | 
					def test_rgbled_blink_interrupt():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i, pin_class=MockPWMPin) for i in (4, 5, 6))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (4, 5, 6))
 | 
				
			||||||
    with RGBLED(r, g, b) as device:
 | 
					    with RGBLED(1, 2, 3) as device:
 | 
				
			||||||
        device.blink(1, 0.1)
 | 
					        device.blink(1, 0.1)
 | 
				
			||||||
        sleep(0.2)
 | 
					        sleep(0.2)
 | 
				
			||||||
        device.off() # should interrupt while on
 | 
					        device.off() # should interrupt while on
 | 
				
			||||||
@@ -772,7 +818,7 @@ def test_rgbled_blink_interrupt():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_rgbled_blink_interrupt_nonpwm():
 | 
					def test_rgbled_blink_interrupt_nonpwm():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i) for i in (4, 5, 6))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (4, 5, 6))
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        device.blink(1, 0.1)
 | 
					        device.blink(1, 0.1)
 | 
				
			||||||
        sleep(0.2)
 | 
					        sleep(0.2)
 | 
				
			||||||
        device.off() # should interrupt while on
 | 
					        device.off() # should interrupt while on
 | 
				
			||||||
@@ -781,8 +827,8 @@ def test_rgbled_blink_interrupt_nonpwm():
 | 
				
			|||||||
        b.assert_states([0, 1, 0])
 | 
					        b.assert_states([0, 1, 0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgbled_close():
 | 
					def test_rgbled_close():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i, pin_class=MockPWMPin) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with RGBLED(r, g, b) as device:
 | 
					    with RGBLED(1, 2, 3) as device:
 | 
				
			||||||
        assert not device.closed
 | 
					        assert not device.closed
 | 
				
			||||||
        device.close()
 | 
					        device.close()
 | 
				
			||||||
        assert device.closed
 | 
					        assert device.closed
 | 
				
			||||||
@@ -791,7 +837,7 @@ def test_rgbled_close():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_rgbled_close_nonpwm():
 | 
					def test_rgbled_close_nonpwm():
 | 
				
			||||||
    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
					    r, g, b = (Device.pin_factory.pin(i) for i in (1, 2, 3))
 | 
				
			||||||
    with RGBLED(r, g, b, pwm=False) as device:
 | 
					    with RGBLED(1, 2, 3, pwm=False) as device:
 | 
				
			||||||
        assert not device.closed
 | 
					        assert not device.closed
 | 
				
			||||||
        device.close()
 | 
					        device.close()
 | 
				
			||||||
        assert device.closed
 | 
					        assert device.closed
 | 
				
			||||||
@@ -803,9 +849,9 @@ def test_motor_missing_pins():
 | 
				
			|||||||
        Motor()
 | 
					        Motor()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_motor_pins():
 | 
					def test_motor_pins():
 | 
				
			||||||
    f = Device.pin_factory.pin(1, pin_class=MockPWMPin)
 | 
					    f = Device.pin_factory.pin(1)
 | 
				
			||||||
    b = Device.pin_factory.pin(2, pin_class=MockPWMPin)
 | 
					    b = Device.pin_factory.pin(2)
 | 
				
			||||||
    with Motor(f, b) as device:
 | 
					    with Motor(1, 2) as device:
 | 
				
			||||||
        assert device.forward_device.pin is f
 | 
					        assert device.forward_device.pin is f
 | 
				
			||||||
        assert isinstance(device.forward_device, PWMOutputDevice)
 | 
					        assert isinstance(device.forward_device, PWMOutputDevice)
 | 
				
			||||||
        assert device.backward_device.pin is b
 | 
					        assert device.backward_device.pin is b
 | 
				
			||||||
@@ -814,16 +860,16 @@ def test_motor_pins():
 | 
				
			|||||||
def test_motor_pins_nonpwm():
 | 
					def test_motor_pins_nonpwm():
 | 
				
			||||||
    f = Device.pin_factory.pin(1)
 | 
					    f = Device.pin_factory.pin(1)
 | 
				
			||||||
    b = Device.pin_factory.pin(2)
 | 
					    b = Device.pin_factory.pin(2)
 | 
				
			||||||
    with Motor(f, b, pwm=False) as device:
 | 
					    with Motor(1, 2, pwm=False) as device:
 | 
				
			||||||
        assert device.forward_device.pin is f
 | 
					        assert device.forward_device.pin is f
 | 
				
			||||||
        assert isinstance(device.forward_device, DigitalOutputDevice)
 | 
					        assert isinstance(device.forward_device, DigitalOutputDevice)
 | 
				
			||||||
        assert device.backward_device.pin is b
 | 
					        assert device.backward_device.pin is b
 | 
				
			||||||
        assert isinstance(device.backward_device, DigitalOutputDevice)
 | 
					        assert isinstance(device.backward_device, DigitalOutputDevice)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_motor_close():
 | 
					def test_motor_close():
 | 
				
			||||||
    f = Device.pin_factory.pin(1, pin_class=MockPWMPin)
 | 
					    f = Device.pin_factory.pin(1)
 | 
				
			||||||
    b = Device.pin_factory.pin(2, pin_class=MockPWMPin)
 | 
					    b = Device.pin_factory.pin(2)
 | 
				
			||||||
    with Motor(f, b) as device:
 | 
					    with Motor(1, 2) as device:
 | 
				
			||||||
        device.close()
 | 
					        device.close()
 | 
				
			||||||
        assert device.closed
 | 
					        assert device.closed
 | 
				
			||||||
        assert device.forward_device.pin is None
 | 
					        assert device.forward_device.pin is None
 | 
				
			||||||
@@ -834,16 +880,16 @@ def test_motor_close():
 | 
				
			|||||||
def test_motor_close_nonpwm():
 | 
					def test_motor_close_nonpwm():
 | 
				
			||||||
    f = Device.pin_factory.pin(1)
 | 
					    f = Device.pin_factory.pin(1)
 | 
				
			||||||
    b = Device.pin_factory.pin(2)
 | 
					    b = Device.pin_factory.pin(2)
 | 
				
			||||||
    with Motor(f, b, pwm=False) as device:
 | 
					    with Motor(1, 2, pwm=False) as device:
 | 
				
			||||||
        device.close()
 | 
					        device.close()
 | 
				
			||||||
        assert device.closed
 | 
					        assert device.closed
 | 
				
			||||||
        assert device.forward_device.pin is None
 | 
					        assert device.forward_device.pin is None
 | 
				
			||||||
        assert device.backward_device.pin is None
 | 
					        assert device.backward_device.pin is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_motor_value():
 | 
					def test_motor_value():
 | 
				
			||||||
    f = Device.pin_factory.pin(1, pin_class=MockPWMPin)
 | 
					    f = Device.pin_factory.pin(1)
 | 
				
			||||||
    b = Device.pin_factory.pin(2, pin_class=MockPWMPin)
 | 
					    b = Device.pin_factory.pin(2)
 | 
				
			||||||
    with Motor(f, b) as device:
 | 
					    with Motor(1, 2) as device:
 | 
				
			||||||
        device.value = -1
 | 
					        device.value = -1
 | 
				
			||||||
        assert device.is_active
 | 
					        assert device.is_active
 | 
				
			||||||
        assert device.value == -1
 | 
					        assert device.value == -1
 | 
				
			||||||
@@ -868,7 +914,7 @@ def test_motor_value():
 | 
				
			|||||||
def test_motor_value_nonpwm():
 | 
					def test_motor_value_nonpwm():
 | 
				
			||||||
    f = Device.pin_factory.pin(1)
 | 
					    f = Device.pin_factory.pin(1)
 | 
				
			||||||
    b = Device.pin_factory.pin(2)
 | 
					    b = Device.pin_factory.pin(2)
 | 
				
			||||||
    with Motor(f, b, pwm=False) as device:
 | 
					    with Motor(1, 2, pwm=False) as device:
 | 
				
			||||||
        device.value = -1
 | 
					        device.value = -1
 | 
				
			||||||
        assert device.is_active
 | 
					        assert device.is_active
 | 
				
			||||||
        assert device.value == -1
 | 
					        assert device.value == -1
 | 
				
			||||||
@@ -883,9 +929,9 @@ def test_motor_value_nonpwm():
 | 
				
			|||||||
        assert b.state == 0 and f.state == 0
 | 
					        assert b.state == 0 and f.state == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_motor_bad_value():
 | 
					def test_motor_bad_value():
 | 
				
			||||||
    f = Device.pin_factory.pin(1, pin_class=MockPWMPin)
 | 
					    f = Device.pin_factory.pin(1)
 | 
				
			||||||
    b = Device.pin_factory.pin(2, pin_class=MockPWMPin)
 | 
					    b = Device.pin_factory.pin(2)
 | 
				
			||||||
    with Motor(f, b) as device:
 | 
					    with Motor(1, 2) as device:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            device.value = -2
 | 
					            device.value = -2
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
@@ -898,7 +944,7 @@ def test_motor_bad_value():
 | 
				
			|||||||
def test_motor_bad_value_nonpwm():
 | 
					def test_motor_bad_value_nonpwm():
 | 
				
			||||||
    f = Device.pin_factory.pin(1)
 | 
					    f = Device.pin_factory.pin(1)
 | 
				
			||||||
    b = Device.pin_factory.pin(2)
 | 
					    b = Device.pin_factory.pin(2)
 | 
				
			||||||
    with Motor(f, b, pwm=False) as device:
 | 
					    with Motor(1, 2, pwm=False) as device:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            device.value = -2
 | 
					            device.value = -2
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
@@ -909,9 +955,9 @@ def test_motor_bad_value_nonpwm():
 | 
				
			|||||||
            device.value = -0.5
 | 
					            device.value = -0.5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_motor_reverse():
 | 
					def test_motor_reverse():
 | 
				
			||||||
    f = Device.pin_factory.pin(1, pin_class=MockPWMPin)
 | 
					    f = Device.pin_factory.pin(1)
 | 
				
			||||||
    b = Device.pin_factory.pin(2, pin_class=MockPWMPin)
 | 
					    b = Device.pin_factory.pin(2)
 | 
				
			||||||
    with Motor(f, b) as device:
 | 
					    with Motor(1, 2) as device:
 | 
				
			||||||
        device.forward()
 | 
					        device.forward()
 | 
				
			||||||
        assert device.value == 1
 | 
					        assert device.value == 1
 | 
				
			||||||
        assert b.state == 0 and f.state == 1
 | 
					        assert b.state == 0 and f.state == 1
 | 
				
			||||||
@@ -928,7 +974,7 @@ def test_motor_reverse():
 | 
				
			|||||||
def test_motor_reverse_nonpwm():
 | 
					def test_motor_reverse_nonpwm():
 | 
				
			||||||
    f = Device.pin_factory.pin(1)
 | 
					    f = Device.pin_factory.pin(1)
 | 
				
			||||||
    b = Device.pin_factory.pin(2)
 | 
					    b = Device.pin_factory.pin(2)
 | 
				
			||||||
    with Motor(f, b, pwm=False) as device:
 | 
					    with Motor(1, 2, pwm=False) as device:
 | 
				
			||||||
        device.forward()
 | 
					        device.forward()
 | 
				
			||||||
        assert device.value == 1
 | 
					        assert device.value == 1
 | 
				
			||||||
        assert b.state == 0 and f.state == 1
 | 
					        assert b.state == 0 and f.state == 1
 | 
				
			||||||
@@ -937,28 +983,28 @@ def test_motor_reverse_nonpwm():
 | 
				
			|||||||
        assert b.state == 1 and f.state == 0
 | 
					        assert b.state == 1 and f.state == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_servo_pins():
 | 
					def test_servo_pins():
 | 
				
			||||||
    p = Device.pin_factory.pin(1, pin_class=MockPWMPin)
 | 
					    p = Device.pin_factory.pin(1)
 | 
				
			||||||
    with Servo(p) as device:
 | 
					    with Servo(1) as device:
 | 
				
			||||||
        assert device.pwm_device.pin is p
 | 
					        assert device.pwm_device.pin is p
 | 
				
			||||||
        assert isinstance(device.pwm_device, PWMOutputDevice)
 | 
					        assert isinstance(device.pwm_device, PWMOutputDevice)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_servo_bad_value():
 | 
					def test_servo_bad_value():
 | 
				
			||||||
    p = Device.pin_factory.pin(1, pin_class=MockPWMPin)
 | 
					    p = Device.pin_factory.pin(1)
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        Servo(p, initial_value=2)
 | 
					        Servo(1, initial_value=2)
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        Servo(p, min_pulse_width=30/1000)
 | 
					        Servo(1, min_pulse_width=30/1000)
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        Servo(p, max_pulse_width=30/1000)
 | 
					        Servo(1, max_pulse_width=30/1000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_servo_pins_nonpwm():
 | 
					def test_servo_pins_nonpwm():
 | 
				
			||||||
    p = Device.pin_factory.pin(2)
 | 
					    p = Device.pin_factory.pin(2)
 | 
				
			||||||
    with pytest.raises(PinPWMUnsupported):
 | 
					    with pytest.raises(PinPWMUnsupported):
 | 
				
			||||||
        Servo(p)
 | 
					        Servo(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_servo_close():
 | 
					def test_servo_close():
 | 
				
			||||||
    p = Device.pin_factory.pin(2, pin_class=MockPWMPin)
 | 
					    p = Device.pin_factory.pin(2)
 | 
				
			||||||
    with Servo(p) as device:
 | 
					    with Servo(1) as device:
 | 
				
			||||||
        device.close()
 | 
					        device.close()
 | 
				
			||||||
        assert device.closed
 | 
					        assert device.closed
 | 
				
			||||||
        assert device.pwm_device.pin is None
 | 
					        assert device.pwm_device.pin is None
 | 
				
			||||||
@@ -966,8 +1012,8 @@ def test_servo_close():
 | 
				
			|||||||
        assert device.closed
 | 
					        assert device.closed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_servo_pulse_width():
 | 
					def test_servo_pulse_width():
 | 
				
			||||||
    p = Device.pin_factory.pin(2, pin_class=MockPWMPin)
 | 
					    p = Device.pin_factory.pin(2)
 | 
				
			||||||
    with Servo(p, min_pulse_width=5/10000, max_pulse_width=25/10000) as device:
 | 
					    with Servo(1, min_pulse_width=5/10000, max_pulse_width=25/10000) as device:
 | 
				
			||||||
        assert isclose(device.min_pulse_width, 5/10000)
 | 
					        assert isclose(device.min_pulse_width, 5/10000)
 | 
				
			||||||
        assert isclose(device.max_pulse_width, 25/10000)
 | 
					        assert isclose(device.max_pulse_width, 25/10000)
 | 
				
			||||||
        assert isclose(device.frame_width, 20/1000)
 | 
					        assert isclose(device.frame_width, 20/1000)
 | 
				
			||||||
@@ -980,8 +1026,8 @@ def test_servo_pulse_width():
 | 
				
			|||||||
        assert device.pulse_width is None
 | 
					        assert device.pulse_width is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_servo_values():
 | 
					def test_servo_values():
 | 
				
			||||||
    p = Device.pin_factory.pin(1, pin_class=MockPWMPin)
 | 
					    p = Device.pin_factory.pin(1)
 | 
				
			||||||
    with Servo(p) as device:
 | 
					    with Servo(1) as device:
 | 
				
			||||||
        device.min()
 | 
					        device.min()
 | 
				
			||||||
        assert device.is_active
 | 
					        assert device.is_active
 | 
				
			||||||
        assert device.value == -1
 | 
					        assert device.value == -1
 | 
				
			||||||
@@ -1007,14 +1053,14 @@ def test_servo_values():
 | 
				
			|||||||
        assert device.value is None
 | 
					        assert device.value is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_angular_servo_range():
 | 
					def test_angular_servo_range():
 | 
				
			||||||
    p = Device.pin_factory.pin(1, pin_class=MockPWMPin)
 | 
					    p = Device.pin_factory.pin(1)
 | 
				
			||||||
    with AngularServo(p, initial_angle=15, min_angle=0, max_angle=90) as device:
 | 
					    with AngularServo(1, initial_angle=15, min_angle=0, max_angle=90) as device:
 | 
				
			||||||
        assert device.min_angle == 0
 | 
					        assert device.min_angle == 0
 | 
				
			||||||
        assert device.max_angle == 90
 | 
					        assert device.max_angle == 90
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_angular_servo_angles():
 | 
					def test_angular_servo_angles():
 | 
				
			||||||
    p = Device.pin_factory.pin(1, pin_class=MockPWMPin)
 | 
					    p = Device.pin_factory.pin(1)
 | 
				
			||||||
    with AngularServo(p) as device:
 | 
					    with AngularServo(1) as device:
 | 
				
			||||||
        device.angle = 0
 | 
					        device.angle = 0
 | 
				
			||||||
        assert device.angle == 0
 | 
					        assert device.angle == 0
 | 
				
			||||||
        assert isclose(device.value, 0)
 | 
					        assert isclose(device.value, 0)
 | 
				
			||||||
@@ -1026,7 +1072,7 @@ def test_angular_servo_angles():
 | 
				
			|||||||
        assert isclose(device.value, -1)
 | 
					        assert isclose(device.value, -1)
 | 
				
			||||||
        device.detach()
 | 
					        device.detach()
 | 
				
			||||||
        assert device.angle is None
 | 
					        assert device.angle is None
 | 
				
			||||||
    with AngularServo(p, initial_angle=15, min_angle=0, max_angle=90) as device:
 | 
					    with AngularServo(1, initial_angle=15, min_angle=0, max_angle=90) as device:
 | 
				
			||||||
        assert device.angle == 15
 | 
					        assert device.angle == 15
 | 
				
			||||||
        assert isclose(device.value, -2/3)
 | 
					        assert isclose(device.value, -2/3)
 | 
				
			||||||
        device.angle = 0
 | 
					        device.angle = 0
 | 
				
			||||||
@@ -1037,7 +1083,7 @@ def test_angular_servo_angles():
 | 
				
			|||||||
        assert isclose(device.value, 1)
 | 
					        assert isclose(device.value, 1)
 | 
				
			||||||
        device.angle = None
 | 
					        device.angle = None
 | 
				
			||||||
        assert device.angle is None
 | 
					        assert device.angle is None
 | 
				
			||||||
    with AngularServo(p, min_angle=45, max_angle=-45) as device:
 | 
					    with AngularServo(1, min_angle=45, max_angle=-45) as device:
 | 
				
			||||||
        assert device.angle == 0
 | 
					        assert device.angle == 0
 | 
				
			||||||
        assert isclose(device.value, 0)
 | 
					        assert isclose(device.value, 0)
 | 
				
			||||||
        device.angle = -45
 | 
					        device.angle = -45
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,50 +33,50 @@ def test_spi_hardware_params():
 | 
				
			|||||||
    with patch('os.open'), patch('mmap.mmap') as mmap_mmap, patch('io.open') as io_open:
 | 
					    with patch('os.open'), patch('mmap.mmap') as mmap_mmap, patch('io.open') as io_open:
 | 
				
			||||||
        mmap_mmap.return_value = array(nstr('B'), (0,) * 4096)
 | 
					        mmap_mmap.return_value = array(nstr('B'), (0,) * 4096)
 | 
				
			||||||
        io_open.return_value.__enter__.return_value = ['Revision: a21042']
 | 
					        io_open.return_value.__enter__.return_value = ['Revision: a21042']
 | 
				
			||||||
        with patch('gpiozero.devices.Device.pin_factory', NativeFactory()), \
 | 
					        factory = NativeFactory()
 | 
				
			||||||
                patch('gpiozero.pins.local.SpiDev'):
 | 
					        with patch('gpiozero.pins.local.SpiDev'):
 | 
				
			||||||
            with Device.pin_factory.spi() as device:
 | 
					            with factory.spi() as device:
 | 
				
			||||||
                assert isinstance(device, LocalPiHardwareSPI)
 | 
					                assert isinstance(device, LocalPiHardwareSPI)
 | 
				
			||||||
            with Device.pin_factory.spi(port=0, device=0) as device:
 | 
					            with factory.spi(port=0, device=0) as device:
 | 
				
			||||||
                assert isinstance(device, LocalPiHardwareSPI)
 | 
					                assert isinstance(device, LocalPiHardwareSPI)
 | 
				
			||||||
            with Device.pin_factory.spi(port=0, device=1) as device:
 | 
					            with factory.spi(port=0, device=1) as device:
 | 
				
			||||||
                assert isinstance(device, LocalPiHardwareSPI)
 | 
					                assert isinstance(device, LocalPiHardwareSPI)
 | 
				
			||||||
            with Device.pin_factory.spi(clock_pin=11) as device:
 | 
					            with factory.spi(clock_pin=11) as device:
 | 
				
			||||||
                assert isinstance(device, LocalPiHardwareSPI)
 | 
					                assert isinstance(device, LocalPiHardwareSPI)
 | 
				
			||||||
            with Device.pin_factory.spi(clock_pin=11, mosi_pin=10, select_pin=8) as device:
 | 
					            with factory.spi(clock_pin=11, mosi_pin=10, select_pin=8) as device:
 | 
				
			||||||
                assert isinstance(device, LocalPiHardwareSPI)
 | 
					                assert isinstance(device, LocalPiHardwareSPI)
 | 
				
			||||||
            with Device.pin_factory.spi(clock_pin=11, mosi_pin=10, select_pin=7) as device:
 | 
					            with factory.spi(clock_pin=11, mosi_pin=10, select_pin=7) as device:
 | 
				
			||||||
                assert isinstance(device, LocalPiHardwareSPI)
 | 
					                assert isinstance(device, LocalPiHardwareSPI)
 | 
				
			||||||
            with Device.pin_factory.spi(shared=True) as device:
 | 
					            with factory.spi(shared=True) as device:
 | 
				
			||||||
                assert isinstance(device, LocalPiHardwareSPIShared)
 | 
					                assert isinstance(device, LocalPiHardwareSPIShared)
 | 
				
			||||||
            with pytest.raises(ValueError):
 | 
					            with pytest.raises(ValueError):
 | 
				
			||||||
                Device.pin_factory.spi(port=1)
 | 
					                factory.spi(port=1)
 | 
				
			||||||
            with pytest.raises(ValueError):
 | 
					            with pytest.raises(ValueError):
 | 
				
			||||||
                Device.pin_factory.spi(device=2)
 | 
					                factory.spi(device=2)
 | 
				
			||||||
            with pytest.raises(ValueError):
 | 
					            with pytest.raises(ValueError):
 | 
				
			||||||
                Device.pin_factory.spi(port=0, clock_pin=12)
 | 
					                factory.spi(port=0, clock_pin=12)
 | 
				
			||||||
            with pytest.raises(ValueError):
 | 
					            with pytest.raises(ValueError):
 | 
				
			||||||
                Device.pin_factory.spi(foo='bar')
 | 
					                factory.spi(foo='bar')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_spi_software_params():
 | 
					def test_spi_software_params():
 | 
				
			||||||
    with patch('os.open'), patch('mmap.mmap') as mmap_mmap, patch('io.open') as io_open:
 | 
					    with patch('os.open'), patch('mmap.mmap') as mmap_mmap, patch('io.open') as io_open:
 | 
				
			||||||
        mmap_mmap.return_value = array(nstr('B'), (0,) * 4096)
 | 
					        mmap_mmap.return_value = array(nstr('B'), (0,) * 4096)
 | 
				
			||||||
        io_open.return_value.__enter__.return_value = ['Revision: a21042']
 | 
					        io_open.return_value.__enter__.return_value = ['Revision: a21042']
 | 
				
			||||||
        with patch('gpiozero.devices.Device.pin_factory', NativeFactory()), \
 | 
					        factory = NativeFactory()
 | 
				
			||||||
                patch('gpiozero.pins.local.SpiDev'):
 | 
					        with patch('gpiozero.pins.local.SpiDev'):
 | 
				
			||||||
            with Device.pin_factory.spi(select_pin=6) as device:
 | 
					            with factory.spi(select_pin=6) as device:
 | 
				
			||||||
                assert isinstance(device, LocalPiSoftwareSPI)
 | 
					                assert isinstance(device, LocalPiSoftwareSPI)
 | 
				
			||||||
            with Device.pin_factory.spi(clock_pin=11, mosi_pin=9, miso_pin=10) as device:
 | 
					            with factory.spi(clock_pin=11, mosi_pin=9, miso_pin=10) as device:
 | 
				
			||||||
                assert isinstance(device, LocalPiSoftwareSPI)
 | 
					                assert isinstance(device, LocalPiSoftwareSPI)
 | 
				
			||||||
            with Device.pin_factory.spi(select_pin=6, shared=True) as device:
 | 
					            with factory.spi(select_pin=6, shared=True) as device:
 | 
				
			||||||
                assert isinstance(device, LocalPiSoftwareSPIShared)
 | 
					                assert isinstance(device, LocalPiSoftwareSPIShared)
 | 
				
			||||||
        with patch('gpiozero.devices.Device.pin_factory', NativeFactory()), \
 | 
					        with patch('gpiozero.pins.local.SpiDev', None):
 | 
				
			||||||
                patch('gpiozero.pins.local.SpiDev', None):
 | 
					            # Clear out the old factory's caches (this is only necessary because
 | 
				
			||||||
            # Clear out the old factory's pins cache (this is only necessary
 | 
					            # we're being naughty switching out patches)
 | 
				
			||||||
            # because we're being very naughty switching out pin factories)
 | 
					            factory.pins.clear()
 | 
				
			||||||
            Device.pin_factory.pins.clear()
 | 
					            factory._reservations.clear()
 | 
				
			||||||
            # Ensure software fallback works when SpiDev isn't present
 | 
					            # Ensure software fallback works when SpiDev isn't present
 | 
				
			||||||
            with Device.pin_factory.spi() as device:
 | 
					            with factory.spi() as device:
 | 
				
			||||||
                assert isinstance(device, LocalPiSoftwareSPI)
 | 
					                assert isinstance(device, LocalPiSoftwareSPI)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_spi_hardware_conflict():
 | 
					def test_spi_hardware_conflict():
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user