mirror of
				https://github.com/KevinMidboe/python-gpiozero.git
				synced 2025-10-29 17:50:37 +00:00 
			
		
		
		
	Fix #279
Permit replacement of pin_factory without closing old factory. However, continue closing devices associated with extant pin factory at script termination.
This commit is contained in:
		| @@ -34,7 +34,6 @@ from .exc import ( | ||||
|     GPIOPinInUse, | ||||
|     GPIODeviceClosed, | ||||
|     PinFactoryFallback, | ||||
|     PinReservationsExist, | ||||
|     ) | ||||
| from .compat import frozendict | ||||
|  | ||||
| @@ -194,33 +193,13 @@ class Device(ValuesMixin, GPIOBase): | ||||
|     services applicable to all devices (specifically the :attr:`is_active` | ||||
|     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 __repr__(self): | ||||
|         return "<gpiozero.%s object>" % (self.__class__.__name__) | ||||
|  | ||||
|     @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 | ||||
|  | ||||
|     def _reserve_pins(self, *pins_or_addresses): | ||||
|         """ | ||||
|         Called to indicate that the device reserves the right to use the | ||||
| @@ -439,8 +418,8 @@ class GPIODevice(Device): | ||||
|             self._reserve_pins(pin) | ||||
|         else: | ||||
|             # Check you can reserve *before* constructing the pin | ||||
|             self._reserve_pins(Device._pin_factory.pin_address(pin)) | ||||
|             pin = Device._pin_factory.pin(pin) | ||||
|             self._reserve_pins(Device.pin_factory.pin_address(pin)) | ||||
|             pin = Device.pin_factory.pin(pin) | ||||
|         self._pin = pin | ||||
|         self._active_state = True | ||||
|         self._inactive_state = False | ||||
| @@ -524,11 +503,27 @@ def _default_pin_factory(name=os.getenv('GPIOZERO_PIN_FACTORY', None)): | ||||
|             return factory.load()() | ||||
|         raise BadPinFactory('Unable to find pin factory "%s"' % name) | ||||
|  | ||||
| Device._set_pin_factory(_default_pin_factory()) | ||||
|  | ||||
| def _devices_shutdown(): | ||||
|     if Device.pin_factory: | ||||
|         with Device._res_lock: | ||||
|             reserved_devices = { | ||||
|                 dev | ||||
|                 for ref_list in Device._reservations.values() | ||||
|                 for ref in ref_list | ||||
|                 for dev in (ref(),) | ||||
|                 if dev is not None | ||||
|             } | ||||
|         for dev in reserved_devices: | ||||
|             dev.close() | ||||
|         Device.pin_factory.close() | ||||
|         Device.pin_factory = None | ||||
|  | ||||
|  | ||||
| def _shutdown(): | ||||
|     _threads_shutdown() | ||||
|     Device._set_pin_factory(None) | ||||
|     _devices_shutdown() | ||||
|  | ||||
|  | ||||
| Device.pin_factory = _default_pin_factory() | ||||
| atexit.register(_shutdown) | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user