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,
|
GPIOPinInUse,
|
||||||
GPIODeviceClosed,
|
GPIODeviceClosed,
|
||||||
PinFactoryFallback,
|
PinFactoryFallback,
|
||||||
|
PinReservationsExist,
|
||||||
)
|
)
|
||||||
from .compat import frozendict
|
from .compat import frozendict
|
||||||
|
|
||||||
@@ -202,6 +203,20 @@ class Device(ValuesMixin, GPIOBase):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _set_pin_factory(cls, new_factory):
|
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:
|
if cls._pin_factory is not None:
|
||||||
cls._pin_factory.close()
|
cls._pin_factory.close()
|
||||||
cls._pin_factory = new_factory
|
cls._pin_factory = new_factory
|
||||||
|
|||||||
@@ -145,6 +145,9 @@ class PinNoPins(PinError, RuntimeError):
|
|||||||
class PinInvalidPin(PinError, ValueError):
|
class PinInvalidPin(PinError, ValueError):
|
||||||
"Error raised when an invalid pin specification is provided"
|
"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):
|
class GPIOZeroWarning(Warning):
|
||||||
"Base class for all warnings in GPIO Zero"
|
"Base class for all warnings in GPIO Zero"
|
||||||
|
|
||||||
|
|||||||
@@ -70,10 +70,13 @@ class SourceMixin(object):
|
|||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
try:
|
try:
|
||||||
super(SourceMixin, self).close()
|
|
||||||
self.source = None
|
self.source = None
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
try:
|
||||||
|
super(SourceMixin, self).close()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
def _copy_values(self, source):
|
def _copy_values(self, source):
|
||||||
for v in source:
|
for v in source:
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ str = type('')
|
|||||||
import io
|
import io
|
||||||
from threading import RLock
|
from threading import RLock
|
||||||
from types import MethodType
|
from types import MethodType
|
||||||
from weakref import ref, proxy
|
|
||||||
try:
|
try:
|
||||||
from weakref import WeakMethod
|
from weakref import ref, WeakMethod
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|
||||||
from ..compat import WeakMethod
|
from ..compat import WeakMethod
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
@@ -216,7 +216,7 @@ class PiPin(Pin):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, factory, number):
|
def __init__(self, factory, number):
|
||||||
super(PiPin, self).__init__()
|
super(PiPin, self).__init__()
|
||||||
self._factory = proxy(factory)
|
self._factory = factory
|
||||||
self._when_changed_lock = RLock()
|
self._when_changed_lock = RLock()
|
||||||
self._when_changed = None
|
self._when_changed = None
|
||||||
self._number = number
|
self._number = number
|
||||||
|
|||||||
Reference in New Issue
Block a user