Skip to content

Commit

Permalink
Fix #115
Browse files Browse the repository at this point in the history
Adds when_held event hook to Button (via extension of the EventsMixin
class). Also fixes some minor notes and activates codecov coverage
tracking.
  • Loading branch information
waveform80 committed Apr 8, 2016
1 parent f746ecb commit 0838965
Show file tree
Hide file tree
Showing 12 changed files with 214 additions and 32 deletions.
6 changes: 6 additions & 0 deletions .travis.yml
Expand Up @@ -9,5 +9,11 @@ python:
- "pypy3"
install: "pip install -e .[test]"
script: make test
before_install:
# Coverage 4.0 no longer supports py3.2 and codecov depends on latest coverage
- if [[ $TRAVIS_PYTHON_VERSION == '3.2' ]]; then pip install "coverage<4.0dev"; fi
- pip install codecov
after_success:
- codecov
notifications:
slack: raspberrypifoundation:YoIHtVdg8Hd6gcA09QEmCYXN
8 changes: 4 additions & 4 deletions docs/api_exc.rst
Expand Up @@ -43,6 +43,10 @@ Errors

.. autoexception:: BadEventHandler

.. autoexception:: BadQueueLen

.. autoexception:: BadWaitTime

.. autoexception:: CompositeDeviceError

.. autoexception:: CompositeDeviceBadName
Expand All @@ -63,10 +67,6 @@ Errors

.. autoexception:: GPIOPinMissing

.. autoexception:: GPIOBadQueueLen

.. autoexception:: GPIOBadSampleWait

.. autoexception:: InputDeviceError

.. autoexception:: OutputDeviceError
Expand Down
6 changes: 6 additions & 0 deletions docs/api_generic.rst
Expand Up @@ -37,6 +37,9 @@ There are also several `mixin classes`_:
* :class:`EventsMixin` which adds activated/deactivated events to devices
along with the machinery to trigger those events

* :class:`HoldMixin` which derives from :class:`EventsMixin` and adds the
held event to devices along with the machinery to repeatedly trigger it

.. _mixin classes: https://en.wikipedia.org/wiki/Mixin

The current class hierarchies are displayed below. For brevity, the mixin
Expand Down Expand Up @@ -141,3 +144,6 @@ Mixin Classes
.. autoclass:: EventsMixin(...)
:members:

.. autoclass:: HoldMixin(...)
:members:

2 changes: 1 addition & 1 deletion docs/api_pins.rst
Expand Up @@ -72,7 +72,7 @@ to utilize pins that are part of IO extender chips. For example::

.. warning::

The astute and mischievious reader may note that it is possible to mix pin
The astute and mischievous reader may note that it is possible to mix pin
implementations, e.g. using ``RPiGPIOPin`` for one pin, and ``NativePin``
for another. This is unsupported, and if it results in your script
crashing, your components failing, or your Raspberry Pi turning into an
Expand Down
Binary file modified docs/images/reaction_game_bb.pdf
Binary file not shown.
Binary file modified docs/images/rgb_led_bb.pdf
Binary file not shown.
Binary file modified docs/images/rgb_led_bb.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/traffic_lights_bb.pdf
Binary file not shown.
5 changes: 3 additions & 2 deletions gpiozero/__init__.py
Expand Up @@ -17,6 +17,8 @@
GPIOZeroError,
DeviceClosed,
BadEventHandler,
BadWaitTime,
BadQueueLen,
CompositeDeviceError,
CompositeDeviceBadName,
CompositeDeviceBadOrder,
Expand All @@ -28,8 +30,6 @@
GPIODeviceClosed,
GPIOPinInUse,
GPIOPinMissing,
GPIOBadQueueLen,
GPIOBadSampleWait,
InputDeviceError,
OutputDeviceError,
OutputDeviceBadValue,
Expand Down Expand Up @@ -61,6 +61,7 @@
SourceMixin,
ValuesMixin,
EventsMixin,
HoldMixin,
)
from .input_devices import (
InputDevice,
Expand Down
15 changes: 6 additions & 9 deletions gpiozero/exc.py
Expand Up @@ -16,6 +16,12 @@ class DeviceClosed(GPIOZeroError):
class BadEventHandler(GPIOZeroError, ValueError):
"Error raised when an event handler with an incompatible prototype is specified"

class BadWaitTime(GPIOZeroError, ValueError):
"Error raised when an invalid wait time is specified"

class BadQueueLen(GPIOZeroError, ValueError):
"Error raised when non-positive queue length is specified"

class CompositeDeviceError(GPIOZeroError):
"Base class for errors specific to the CompositeDevice hierarchy"

Expand Down Expand Up @@ -49,15 +55,6 @@ class GPIOPinInUse(GPIODeviceError):
class GPIOPinMissing(GPIODeviceError, ValueError):
"Error raised when a pin number is not specified"

class GPIOBadQueueLen(GPIODeviceError, ValueError):
"Error raised when non-positive queue length is specified"

class GPIOBadSampleWait(GPIODeviceError, ValueError):
"Error raised when a negative sampling wait period is specified"

class GPIOBadSourceDelay(GPIODeviceError, ValueError):
"Error raised when a negative source delay is specified"

class InputDeviceError(GPIODeviceError):
"Base class for errors specific to the InputDevice hierarchy"

Expand Down
19 changes: 16 additions & 3 deletions gpiozero/input_devices.py
Expand Up @@ -12,7 +12,7 @@

from .exc import InputDeviceError, DeviceClosed
from .devices import GPIODevice
from .mixins import GPIOQueue, EventsMixin
from .mixins import GPIOQueue, EventsMixin, HoldMixin


class InputDevice(GPIODevice):
Expand Down Expand Up @@ -222,7 +222,7 @@ def is_active(self):
return self.value > self.threshold


class Button(DigitalInputDevice):
class Button(HoldMixin, DigitalInputDevice):
"""
Extends :class:`DigitalInputDevice` and represents a simple push button
or switch.
Expand Down Expand Up @@ -254,11 +254,24 @@ class Button(DigitalInputDevice):
If ``None`` (the default), no software bounce compensation will be
performed. Otherwise, this is the length in time (in seconds) that the
component will ignore changes in state after an initial change.
:param float hold_time:
The length of time (in seconds) to wait after the button is pushed,
until executing the :attr:`when_held` handler.
:param bool hold_repeat:
If ``True``, the :attr:`when_held` handler will be repeatedly executed
as long as the device remains active, every *hold_time* seconds.
"""
def __init__(self, pin=None, pull_up=True, bounce_time=None):
def __init__(
self, pin=None, pull_up=True, bounce_time=None,
hold_time=1, hold_repeat=False):
super(Button, self).__init__(pin, pull_up, bounce_time)
self.hold_time = hold_time
self.hold_repeat = hold_repeat

Button.is_pressed = Button.is_active
Button.pressed_time = Button.active_time
Button.when_pressed = Button.when_activated
Button.when_released = Button.when_deactivated
Button.wait_for_press = Button.wait_for_active
Expand Down

0 comments on commit 0838965

Please sign in to comment.