Rework when_changed attribute to use weakrefs

Some fairly major changes to ensure that the Pin.when_changed property
doesn't keep references to the objects owning the callbacks that are
assigned. This is vaguely tricky given that ordinary weakref's can't be
used with bound methods (which are ephemeral), so I've back-ported
weakref.WeakMethod from Py3.4.

This solves a whole pile of things like Button instances not
disappearing when they're deleted, and makes composite devices
containing Buttons much easier to construct as we don't need to worry
about partially constructed things not getting deleted.
This commit is contained in:
Dave Jones
2016-10-22 13:55:31 +01:00
parent 08076e8d0e
commit cab6cc8086
7 changed files with 193 additions and 80 deletions

View File

@@ -211,24 +211,20 @@ class LEDCollection(CompositeOutputDevice):
initial_value = kwargs.pop('initial_value', False)
order = kwargs.pop('_order', None)
LEDClass = PWMLED if pwm else LED
try:
super(LEDCollection, self).__init__(
*(
pin_or_collection
if isinstance(pin_or_collection, LEDCollection) else
LEDClass(pin_or_collection, active_high, initial_value)
for pin_or_collection in args
),
_order=order,
**{
name: pin_or_collection
if isinstance(pin_or_collection, LEDCollection) else
LEDClass(pin_or_collection, active_high, initial_value)
for name, pin_or_collection in kwargs.items()
})
except:
self.close()
raise
super(LEDCollection, self).__init__(
*(
pin_or_collection
if isinstance(pin_or_collection, LEDCollection) else
LEDClass(pin_or_collection, active_high, initial_value)
for pin_or_collection in args
),
_order=order,
**{
name: pin_or_collection
if isinstance(pin_or_collection, LEDCollection) else
LEDClass(pin_or_collection, active_high, initial_value)
for name, pin_or_collection in kwargs.items()
})
leds = []
for item in self:
if isinstance(item, LEDCollection):