mirror of
				https://github.com/KevinMidboe/python-gpiozero.git
				synced 2025-10-29 17:50:37 +00:00 
			
		
		
		
	Fix #553
Ensure SourceMixin descendents shut down the source prior to closing. Furthermore, make sure devices are closed before pin factory shuts down, and that pins have a strong reference to their owning factory (to prevent losing the factory before the pins).
This commit is contained in:
		@@ -34,6 +34,7 @@ from .exc import (
 | 
			
		||||
    GPIOPinInUse,
 | 
			
		||||
    GPIODeviceClosed,
 | 
			
		||||
    PinFactoryFallback,
 | 
			
		||||
    PinReservationsExist,
 | 
			
		||||
    )
 | 
			
		||||
from .compat import frozendict
 | 
			
		||||
 | 
			
		||||
@@ -202,6 +203,20 @@ class Device(ValuesMixin, GPIOBase):
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def _set_pin_factory(cls, new_factory):
 | 
			
		||||
        reserved_devices = {
 | 
			
		||||
            dev
 | 
			
		||||
            for ref_list in cls._reservations.values()
 | 
			
		||||
            for ref in ref_list
 | 
			
		||||
            for dev in (ref(),)
 | 
			
		||||
            if dev is not None
 | 
			
		||||
        }
 | 
			
		||||
        if new_factory is None:
 | 
			
		||||
            for dev in reserved_devices:
 | 
			
		||||
                dev.close()
 | 
			
		||||
        elif reserved_devices:
 | 
			
		||||
            raise PinReservationsExist(
 | 
			
		||||
                "can't change factory while devices still hold pin "
 | 
			
		||||
                "reservations (%r)" % dev)
 | 
			
		||||
        if cls._pin_factory is not None:
 | 
			
		||||
            cls._pin_factory.close()
 | 
			
		||||
        cls._pin_factory = new_factory
 | 
			
		||||
 
 | 
			
		||||
@@ -145,6 +145,9 @@ class PinNoPins(PinError, RuntimeError):
 | 
			
		||||
class PinInvalidPin(PinError, ValueError):
 | 
			
		||||
    "Error raised when an invalid pin specification is provided"
 | 
			
		||||
 | 
			
		||||
class PinReservationsExist(PinError, RuntimeError):
 | 
			
		||||
    "Error raised when pin factory is changed while reservations still exist"
 | 
			
		||||
 | 
			
		||||
class GPIOZeroWarning(Warning):
 | 
			
		||||
    "Base class for all warnings in GPIO Zero"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -70,10 +70,13 @@ class SourceMixin(object):
 | 
			
		||||
 | 
			
		||||
    def close(self):
 | 
			
		||||
        try:
 | 
			
		||||
            super(SourceMixin, self).close()
 | 
			
		||||
            self.source = None
 | 
			
		||||
        except AttributeError:
 | 
			
		||||
            pass
 | 
			
		||||
        try:
 | 
			
		||||
            super(SourceMixin, self).close()
 | 
			
		||||
        except AttributeError:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    def _copy_values(self, source):
 | 
			
		||||
        for v in source:
 | 
			
		||||
 
 | 
			
		||||
@@ -9,10 +9,10 @@ str = type('')
 | 
			
		||||
import io
 | 
			
		||||
from threading import RLock
 | 
			
		||||
from types import MethodType
 | 
			
		||||
from weakref import ref, proxy
 | 
			
		||||
try:
 | 
			
		||||
    from weakref import WeakMethod
 | 
			
		||||
    from weakref import ref, WeakMethod
 | 
			
		||||
except ImportError:
 | 
			
		||||
 | 
			
		||||
    from ..compat import WeakMethod
 | 
			
		||||
import warnings
 | 
			
		||||
 | 
			
		||||
@@ -216,7 +216,7 @@ class PiPin(Pin):
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, factory, number):
 | 
			
		||||
        super(PiPin, self).__init__()
 | 
			
		||||
        self._factory = proxy(factory)
 | 
			
		||||
        self._factory = factory
 | 
			
		||||
        self._when_changed_lock = RLock()
 | 
			
		||||
        self._when_changed = None
 | 
			
		||||
        self._number = number
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user