mirror of
https://github.com/KevinMidboe/python-gpiozero.git
synced 2025-10-29 17:50:37 +00:00
@@ -9,7 +9,7 @@ str = type('')
|
|||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
import weakref
|
import weakref
|
||||||
from functools import wraps
|
from functools import wraps, partial
|
||||||
from threading import Event
|
from threading import Event
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from time import time
|
from time import time
|
||||||
@@ -255,7 +255,16 @@ class EventsMixin(object):
|
|||||||
return None
|
return None
|
||||||
elif not callable(fn):
|
elif not callable(fn):
|
||||||
raise BadEventHandler('value must be None or a callable')
|
raise BadEventHandler('value must be None or a callable')
|
||||||
elif inspect.isbuiltin(fn):
|
# If fn is wrapped with partial (i.e. partial, partialmethod, or wraps
|
||||||
|
# has been used to produce it) we need to dig out the "real" function
|
||||||
|
# that's been wrapped along with all the mandatory positional args
|
||||||
|
# used in the wrapper so we can test the binding
|
||||||
|
args = ()
|
||||||
|
wrapped_fn = fn
|
||||||
|
while isinstance(wrapped_fn, partial):
|
||||||
|
args = wrapped_fn.args + args
|
||||||
|
wrapped_fn = wrapped_fn.func
|
||||||
|
if inspect.isbuiltin(wrapped_fn):
|
||||||
# We can't introspect the prototype of builtins. In this case we
|
# We can't introspect the prototype of builtins. In this case we
|
||||||
# assume that the builtin has no (mandatory) parameters; this is
|
# assume that the builtin has no (mandatory) parameters; this is
|
||||||
# the most reasonable assumption on the basis that pre-existing
|
# the most reasonable assumption on the basis that pre-existing
|
||||||
@@ -267,13 +276,13 @@ class EventsMixin(object):
|
|||||||
# If this works, assume the function is capable of accepting no
|
# If this works, assume the function is capable of accepting no
|
||||||
# parameters
|
# parameters
|
||||||
try:
|
try:
|
||||||
inspect.getcallargs(fn)
|
inspect.getcallargs(wrapped_fn, *args)
|
||||||
return fn
|
return fn
|
||||||
except TypeError:
|
except TypeError:
|
||||||
try:
|
try:
|
||||||
# If the above fails, try binding with a single parameter
|
# If the above fails, try binding with a single parameter
|
||||||
# (ourselves). If this works, wrap the specified callback
|
# (ourselves). If this works, wrap the specified callback
|
||||||
inspect.getcallargs(fn, self)
|
inspect.getcallargs(wrapped_fn, *(args + (self,)))
|
||||||
@wraps(fn)
|
@wraps(fn)
|
||||||
def wrapper():
|
def wrapper():
|
||||||
return fn(self)
|
return fn(self)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ str = type('')
|
|||||||
import sys
|
import sys
|
||||||
import pytest
|
import pytest
|
||||||
from threading import Event
|
from threading import Event
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
from gpiozero.pins.mock import (
|
from gpiozero.pins.mock import (
|
||||||
MockPin,
|
MockPin,
|
||||||
@@ -79,6 +80,20 @@ def test_input_event_deactivated():
|
|||||||
pin.drive_low()
|
pin.drive_low()
|
||||||
assert event.is_set()
|
assert event.is_set()
|
||||||
|
|
||||||
|
def test_input_partial_callback():
|
||||||
|
event = Event()
|
||||||
|
pin = MockPin(2)
|
||||||
|
def foo(a, b):
|
||||||
|
event.set()
|
||||||
|
return a + b
|
||||||
|
bar = partial(foo, 1)
|
||||||
|
baz = partial(bar, 2)
|
||||||
|
with DigitalInputDevice(pin) as device:
|
||||||
|
device.when_activated = baz
|
||||||
|
assert not event.is_set()
|
||||||
|
pin.drive_high()
|
||||||
|
assert event.is_set()
|
||||||
|
|
||||||
def test_input_wait_active():
|
def test_input_wait_active():
|
||||||
pin = MockPin(2)
|
pin = MockPin(2)
|
||||||
with DigitalInputDevice(pin) as device:
|
with DigitalInputDevice(pin) as device:
|
||||||
|
|||||||
Reference in New Issue
Block a user