Make tests work reliably on the Pi

While the tests work well on a PC or Travis, the Pi (where I ought to be
running them!) has some issues with the timing tests. Need to relax the
tolerance of the "assert_states_and_times" method to 0.05 seconds
otherwise it periodically fails even on something reasonably quick like
a Pi 2 (less failures on a Pi 3 but still occasionally).

Also reduced default fps to 25; if the default timing occasionally fails
on a Pi 2 it's evidently too fast for a Pi 1 and shouldn't be the
default; 25 also doesn't look any different to me on a pulsing LED.

There's also a bunch of miscellaneous fixes in here; last minute typos
and chart re-gens for the 1.2 release.
This commit is contained in:
Dave Jones
2016-04-08 11:10:59 +01:00
parent 44422bd6c9
commit c2a9392ea5
28 changed files with 846 additions and 842 deletions

View File

@@ -18,7 +18,7 @@ individually.
LED Board
=========
.. autoclass:: LEDBoard(\*pins, pwm=False, active_high=True, initial_value=False)
.. autoclass:: LEDBoard(\*pins, pwm=False, active_high=True, initial_value=False, \*\*named_pins)
:inherited-members:
:members:

View File

@@ -81,10 +81,10 @@ Base Classes
.. autoclass:: SPIDevice
:members:
.. autoclass:: InternalDevice
.. autoclass:: InternalDevice()
:members:
.. autoclass:: CompositeDevice
.. autoclass:: CompositeDevice(\*args, _order=None, \*\*kwargs)
:members:
Input Devices

View File

@@ -2,13 +2,20 @@
Source Tools
============
.. currentmodule:: gpiozero
.. currentmodule:: gpiozero.tools
GPIO Zero includes several utility routines which are intended to be used with
the :attr:`~SourceMixin.source` and :attr:`~ValuesMixin.values` attributes
common to most devices in the library. Given that ``source`` and ``values``
deal with infinite iterators, another excellent source of utilities is the
:mod:`itertools` module in the standard library.
the :attr:`~gpiozero.SourceMixin.source` and
:attr:`~gpiozero.ValuesMixin.values` attributes common to most devices in the
library. These utility routines are in the ``tools`` module of GPIO Zero and
are typically imported as follows::
from gpiozero.tools import scaled, negated, conjunction
Given that :attr:`~gpiozero.SourceMixin.source` and
:attr:`~gpiozero.ValuesMixin.values` deal with infinite iterators, another
excellent source of utilities is the :mod:`itertools` module in the standard
library.
Single source conversions
=========================

View File

@@ -12,6 +12,8 @@ Release 1.2.0 (2016-04-??)
* Added :class:`LineSensor` class for single line-sensors (`#109`_)
* Added :class:`DistanceSensor` class for HC-SR04 ultra-sonic sensors (`#114`_)
* Added :class:`SnowPi` class for the Ryanteck Snow-pi board (`#130`_)
* Added :attr:`~Button.when_held` (and related properties) to :class:`Button`
(`#115`_)
* Fixed issues with installing GPIO Zero for python 3 on Raspbian Wheezy
releases (`#140`_)
* Added support for lots of ADC chips (MCP3xxx family) (`#162`_) - many thanks
@@ -35,6 +37,7 @@ reports in this version - keep 'em coming!
.. _#69: https://github.com/RPi-Distro/python-gpiozero/issues/69
.. _#109: https://github.com/RPi-Distro/python-gpiozero/issues/109
.. _#114: https://github.com/RPi-Distro/python-gpiozero/issues/114
.. _#115: https://github.com/RPi-Distro/python-gpiozero/issues/115
.. _#130: https://github.com/RPi-Distro/python-gpiozero/issues/130
.. _#140: https://github.com/RPi-Distro/python-gpiozero/issues/140
.. _#162: https://github.com/RPi-Distro/python-gpiozero/issues/162

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -4,11 +4,11 @@
<!-- Generated by graphviz version 2.36.0 (20140111.2315)
-->
<!-- Title: classes Pages: 1 -->
<svg width="447pt" height="116pt"
viewBox="0.00 0.00 447.00 116.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg width="538pt" height="116pt"
viewBox="0.00 0.00 538.00 116.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 112)">
<title>classes</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-112 443,-112 443,4 -4,4"/>
<polygon fill="white" stroke="none" points="-4,4 -4,-112 534,-112 534,4 -4,4"/>
<!-- RGBLED -->
<g id="node1" class="node"><title>RGBLED</title>
<polygon fill="#298029" stroke="#298029" points="55.5,-108 0.5,-108 0.5,-72 55.5,-72 55.5,-108"/>
@@ -16,83 +16,98 @@
</g>
<!-- PWMLED -->
<g id="node2" class="node"><title>PWMLED</title>
<polygon fill="#298029" stroke="#298029" points="58.5,-36 1.5,-36 1.5,-0 58.5,-0 58.5,-36"/>
<text text-anchor="middle" x="30" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">PWMLED</text>
<polygon fill="#298029" stroke="#298029" points="143.5,-36 86.5,-36 86.5,-0 143.5,-0 143.5,-36"/>
<text text-anchor="middle" x="115" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">PWMLED</text>
</g>
<!-- RGBLED&#45;&gt;PWMLED -->
<g id="edge1" class="edge"><title>RGBLED&#45;&gt;PWMLED</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M28.4944,-71.6966C28.7148,-63.9827 28.9796,-54.7125 29.2254,-46.1124"/>
<polygon fill="none" stroke="black" points="32.7242,-46.2002 29.5113,-36.1043 25.727,-46.0003 32.7242,-46.2002"/>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M49.5056,-71.6966C60.4625,-62.8807 73.9459,-52.0321 85.8249,-42.4742"/>
<polygon fill="none" stroke="black" points="88.1446,-45.1001 93.7418,-36.1043 83.7565,-39.6462 88.1446,-45.1001"/>
</g>
<!-- LEDBoard -->
<g id="node3" class="node"><title>LEDBoard</title>
<polygon fill="#298029" stroke="#298029" points="138,-108 74,-108 74,-72 138,-72 138,-108"/>
<text text-anchor="middle" x="106" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">LEDBoard</text>
<polygon fill="#298029" stroke="#298029" points="238,-108 174,-108 174,-72 238,-72 238,-108"/>
<text text-anchor="middle" x="206" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">LEDBoard</text>
</g>
<!-- LEDBoard&#45;&gt;PWMLED -->
<g id="edge3" class="edge"><title>LEDBoard&#45;&gt;PWMLED</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M87.2135,-71.6966C77.826,-63.0503 66.3156,-52.4486 56.0865,-43.027"/>
<polygon fill="none" stroke="black" points="58.2971,-40.3047 48.5704,-36.1043 53.5547,-45.4535 58.2971,-40.3047"/>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M183.506,-71.6966C172.045,-62.8807 157.942,-52.0321 145.516,-42.4742"/>
<polygon fill="none" stroke="black" points="147.296,-39.4273 137.236,-36.1043 143.028,-44.9757 147.296,-39.4273"/>
</g>
<!-- LED -->
<g id="node4" class="node"><title>LED</title>
<polygon fill="#298029" stroke="#298029" points="133,-36 79,-36 79,-0 133,-0 133,-36"/>
<text text-anchor="middle" x="106" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">LED</text>
<polygon fill="#298029" stroke="#298029" points="224,-36 170,-36 170,-0 224,-0 224,-36"/>
<text text-anchor="middle" x="197" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">LED</text>
</g>
<!-- LEDBoard&#45;&gt;LED -->
<g id="edge2" class="edge"><title>LEDBoard&#45;&gt;LED</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M106,-71.6966C106,-63.9827 106,-54.7125 106,-46.1124"/>
<polygon fill="none" stroke="black" points="109.5,-46.1043 106,-36.1043 102.5,-46.1044 109.5,-46.1043"/>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M203.775,-71.6966C202.783,-63.9827 201.592,-54.7125 200.486,-46.1124"/>
<polygon fill="none" stroke="black" points="203.946,-45.5763 199.199,-36.1043 197.003,-46.469 203.946,-45.5763"/>
</g>
<!-- LEDBarGraph -->
<g id="node5" class="node"><title>LEDBarGraph</title>
<polygon fill="#298029" stroke="#298029" points="155.25,-108 74.75,-108 74.75,-72 155.25,-72 155.25,-108"/>
<text text-anchor="middle" x="115" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">LEDBarGraph</text>
</g>
<!-- LEDBarGraph&#45;&gt;PWMLED -->
<g id="edge5" class="edge"><title>LEDBarGraph&#45;&gt;PWMLED</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M115,-71.6966C115,-63.9827 115,-54.7125 115,-46.1124"/>
<polygon fill="none" stroke="black" points="118.5,-46.1043 115,-36.1043 111.5,-46.1044 118.5,-46.1043"/>
</g>
<!-- LEDBarGraph&#45;&gt;LED -->
<g id="edge4" class="edge"><title>LEDBarGraph&#45;&gt;LED</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M135.27,-71.6966C145.498,-62.9655 158.061,-52.2405 169.178,-42.7503"/>
<polygon fill="none" stroke="black" points="171.63,-45.259 176.963,-36.1043 167.085,-39.935 171.63,-45.259"/>
</g>
<!-- TrafficLightsBuzzer -->
<g id="node5" class="node"><title>TrafficLightsBuzzer</title>
<polygon fill="#298029" stroke="#298029" points="320.25,-108 215.75,-108 215.75,-72 320.25,-72 320.25,-108"/>
<text text-anchor="middle" x="268" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">TrafficLightsBuzzer</text>
<g id="node6" class="node"><title>TrafficLightsBuzzer</title>
<polygon fill="#298029" stroke="#298029" points="411.25,-108 306.75,-108 306.75,-72 411.25,-72 411.25,-108"/>
<text text-anchor="middle" x="359" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">TrafficLightsBuzzer</text>
</g>
<!-- TrafficLights -->
<g id="node6" class="node"><title>TrafficLights</title>
<polygon fill="#298029" stroke="#298029" points="223,-36 151,-36 151,-0 223,-0 223,-36"/>
<text text-anchor="middle" x="187" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">TrafficLights</text>
<g id="node7" class="node"><title>TrafficLights</title>
<polygon fill="#298029" stroke="#298029" points="314,-36 242,-36 242,-0 314,-0 314,-36"/>
<text text-anchor="middle" x="278" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">TrafficLights</text>
</g>
<!-- TrafficLightsBuzzer&#45;&gt;TrafficLights -->
<g id="edge4" class="edge"><title>TrafficLightsBuzzer&#45;&gt;TrafficLights</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M247.978,-71.6966C237.874,-62.9655 225.464,-52.2405 214.482,-42.7503"/>
<polygon fill="none" stroke="black" points="216.647,-39.9948 206.792,-36.1043 212.07,-45.2912 216.647,-39.9948"/>
<g id="edge6" class="edge"><title>TrafficLightsBuzzer&#45;&gt;TrafficLights</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M338.978,-71.6966C328.874,-62.9655 316.464,-52.2405 305.482,-42.7503"/>
<polygon fill="none" stroke="black" points="307.647,-39.9948 297.792,-36.1043 303.07,-45.2912 307.647,-39.9948"/>
</g>
<!-- Buzzer -->
<g id="node7" class="node"><title>Buzzer</title>
<polygon fill="#298029" stroke="#298029" points="295,-36 241,-36 241,-0 295,-0 295,-36"/>
<text text-anchor="middle" x="268" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">Buzzer</text>
<g id="node8" class="node"><title>Buzzer</title>
<polygon fill="#298029" stroke="#298029" points="386,-36 332,-36 332,-0 386,-0 386,-36"/>
<text text-anchor="middle" x="359" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">Buzzer</text>
</g>
<!-- TrafficLightsBuzzer&#45;&gt;Buzzer -->
<g id="edge5" class="edge"><title>TrafficLightsBuzzer&#45;&gt;Buzzer</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M268,-71.6966C268,-63.9827 268,-54.7125 268,-46.1124"/>
<polygon fill="none" stroke="black" points="271.5,-46.1043 268,-36.1043 264.5,-46.1044 271.5,-46.1043"/>
<g id="edge7" class="edge"><title>TrafficLightsBuzzer&#45;&gt;Buzzer</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M359,-71.6966C359,-63.9827 359,-54.7125 359,-46.1124"/>
<polygon fill="none" stroke="black" points="362.5,-46.1043 359,-36.1043 355.5,-46.1044 362.5,-46.1043"/>
</g>
<!-- Button -->
<g id="node8" class="node"><title>Button</title>
<polygon fill="#298029" stroke="#298029" points="367,-36 313,-36 313,-0 367,-0 367,-36"/>
<text text-anchor="middle" x="340" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">Button</text>
<g id="node9" class="node"><title>Button</title>
<polygon fill="#298029" stroke="#298029" points="458,-36 404,-36 404,-0 458,-0 458,-36"/>
<text text-anchor="middle" x="431" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">Button</text>
</g>
<!-- TrafficLightsBuzzer&#45;&gt;Button -->
<g id="edge6" class="edge"><title>TrafficLightsBuzzer&#45;&gt;Button</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M285.798,-71.6966C294.604,-63.135 305.382,-52.6562 315.001,-43.3045"/>
<polygon fill="none" stroke="black" points="317.677,-45.5846 322.407,-36.1043 312.797,-40.5657 317.677,-45.5846"/>
<g id="edge8" class="edge"><title>TrafficLightsBuzzer&#45;&gt;Button</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M376.798,-71.6966C385.604,-63.135 396.382,-52.6562 406.001,-43.3045"/>
<polygon fill="none" stroke="black" points="408.677,-45.5846 413.407,-36.1043 403.797,-40.5657 408.677,-45.5846"/>
</g>
<!-- Robot -->
<g id="node9" class="node"><title>Robot</title>
<polygon fill="#298029" stroke="#298029" points="439,-108 385,-108 385,-72 439,-72 439,-108"/>
<text text-anchor="middle" x="412" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">Robot</text>
<g id="node10" class="node"><title>Robot</title>
<polygon fill="#298029" stroke="#298029" points="530,-108 476,-108 476,-72 530,-72 530,-108"/>
<text text-anchor="middle" x="503" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">Robot</text>
</g>
<!-- Motor -->
<g id="node10" class="node"><title>Motor</title>
<polygon fill="#298029" stroke="#298029" points="439,-36 385,-36 385,-0 439,-0 439,-36"/>
<text text-anchor="middle" x="412" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">Motor</text>
<g id="node11" class="node"><title>Motor</title>
<polygon fill="#298029" stroke="#298029" points="530,-36 476,-36 476,-0 530,-0 530,-36"/>
<text text-anchor="middle" x="503" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">Motor</text>
</g>
<!-- Robot&#45;&gt;Motor -->
<g id="edge7" class="edge"><title>Robot&#45;&gt;Motor</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M412,-71.6966C412,-63.9827 412,-54.7125 412,-46.1124"/>
<polygon fill="none" stroke="black" points="415.5,-46.1043 412,-36.1043 408.5,-46.1044 415.5,-46.1043"/>
<g id="edge9" class="edge"><title>Robot&#45;&gt;Motor</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M503,-71.6966C503,-63.9827 503,-54.7125 503,-46.1124"/>
<polygon fill="none" stroke="black" points="506.5,-46.1043 503,-36.1043 499.5,-46.1044 506.5,-46.1043"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -32,6 +32,5 @@ digraph classes {
RyanteckRobot->Robot;
CamJamKitRobot->Robot;
RGBLED->CompositeDevice;
Motor->CompositeDevice;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -4,25 +4,25 @@
<!-- Generated by graphviz version 2.36.0 (20140111.2315)
-->
<!-- Title: classes Pages: 1 -->
<svg width="603pt" height="476pt"
viewBox="0.00 0.00 603.00 476.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg width="587pt" height="476pt"
viewBox="0.00 0.00 587.00 476.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 472)">
<title>classes</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-472 599,-472 599,4 -4,4"/>
<polygon fill="white" stroke="none" points="-4,4 -4,-472 583,-472 583,4 -4,4"/>
<!-- Device -->
<g id="node1" class="node"><title>Device</title>
<polygon fill="#9ec6e0" stroke="#9ec6e0" points="485,-468 431,-468 431,-432 485,-432 485,-468"/>
<text text-anchor="middle" x="458" y="-447.5" font-family="Sans" font-size="10.00" fill="#000000">Device</text>
<polygon fill="#9ec6e0" stroke="#9ec6e0" points="449,-468 395,-468 395,-432 449,-432 449,-468"/>
<text text-anchor="middle" x="422" y="-447.5" font-family="Sans" font-size="10.00" fill="#000000">Device</text>
</g>
<!-- CompositeDevice -->
<g id="node2" class="node"><title>CompositeDevice</title>
<polygon fill="#9ec6e0" stroke="#9ec6e0" points="508.5,-396 407.5,-396 407.5,-360 508.5,-360 508.5,-396"/>
<text text-anchor="middle" x="458" y="-375.5" font-family="Sans" font-size="10.00" fill="#000000">CompositeDevice</text>
<polygon fill="#9ec6e0" stroke="#9ec6e0" points="472.5,-396 371.5,-396 371.5,-360 472.5,-360 472.5,-396"/>
<text text-anchor="middle" x="422" y="-375.5" font-family="Sans" font-size="10.00" fill="#000000">CompositeDevice</text>
</g>
<!-- CompositeDevice&#45;&gt;Device -->
<g id="edge1" class="edge"><title>CompositeDevice&#45;&gt;Device</title>
<path fill="none" stroke="black" d="M458,-396.303C458,-404.017 458,-413.288 458,-421.888"/>
<polygon fill="black" stroke="black" points="454.5,-421.896 458,-431.896 461.5,-421.896 454.5,-421.896"/>
<path fill="none" stroke="black" d="M422,-396.303C422,-404.017 422,-413.288 422,-421.888"/>
<polygon fill="black" stroke="black" points="418.5,-421.896 422,-431.896 425.5,-421.896 418.5,-421.896"/>
</g>
<!-- CompositeOutputDevice -->
<g id="node3" class="node"><title>CompositeOutputDevice</title>
@@ -31,8 +31,8 @@
</g>
<!-- CompositeOutputDevice&#45;&gt;CompositeDevice -->
<g id="edge2" class="edge"><title>CompositeOutputDevice&#45;&gt;CompositeDevice</title>
<path fill="none" stroke="black" d="M344.694,-324.124C365.018,-333.608 390.471,-345.487 412.102,-355.581"/>
<polygon fill="black" stroke="black" points="410.883,-358.874 421.425,-359.932 413.843,-352.531 410.883,-358.874"/>
<path fill="none" stroke="black" d="M335.888,-324.124C350.793,-333.276 369.329,-344.658 385.382,-354.515"/>
<polygon fill="black" stroke="black" points="383.652,-357.56 394.005,-359.81 387.315,-351.595 383.652,-357.56"/>
</g>
<!-- LEDCollection -->
<g id="node4" class="node"><title>LEDCollection</title>
@@ -141,8 +141,8 @@
</g>
<!-- Robot&#45;&gt;CompositeDevice -->
<g id="edge13" class="edge"><title>Robot&#45;&gt;CompositeDevice</title>
<path fill="none" stroke="black" d="M430.899,-324.303C434.997,-332.272 439.949,-341.9 444.493,-350.736"/>
<polygon fill="black" stroke="black" points="441.517,-352.604 449.203,-359.896 447.742,-349.402 441.517,-352.604"/>
<path fill="none" stroke="black" d="M422,-324.303C422,-332.017 422,-341.288 422,-349.888"/>
<polygon fill="black" stroke="black" points="418.5,-349.896 422,-359.896 425.5,-349.896 418.5,-349.896"/>
</g>
<!-- RyanteckRobot -->
<g id="node15" class="node"><title>RyanteckRobot</title>
@@ -164,25 +164,15 @@
<path fill="none" stroke="black" d="M504.336,-252.124C490.216,-261.192 472.689,-272.448 457.439,-282.241"/>
<polygon fill="black" stroke="black" points="455.29,-279.462 448.767,-287.81 459.073,-285.352 455.29,-279.462"/>
</g>
<!-- RGBLED -->
<g id="node17" class="node"><title>RGBLED</title>
<polygon fill="#2980b9" stroke="#2980b9" points="523,-324 467,-324 467,-288 523,-288 523,-324"/>
<text text-anchor="middle" x="495" y="-303.5" font-family="Sans" font-size="10.00" fill="#ffffff">RGBLED</text>
</g>
<!-- RGBLED&#45;&gt;CompositeDevice -->
<g id="edge16" class="edge"><title>RGBLED&#45;&gt;CompositeDevice</title>
<path fill="none" stroke="black" d="M485.854,-324.303C481.597,-332.356 476.444,-342.106 471.734,-351.018"/>
<polygon fill="black" stroke="black" points="468.62,-349.419 467.041,-359.896 474.808,-352.69 468.62,-349.419"/>
</g>
<!-- Motor -->
<g id="node18" class="node"><title>Motor</title>
<polygon fill="#2980b9" stroke="#2980b9" points="595,-324 541,-324 541,-288 595,-288 595,-324"/>
<text text-anchor="middle" x="568" y="-303.5" font-family="Sans" font-size="10.00" fill="#ffffff">Motor</text>
<g id="node17" class="node"><title>Motor</title>
<polygon fill="#2980b9" stroke="#2980b9" points="521,-324 467,-324 467,-288 521,-288 521,-324"/>
<text text-anchor="middle" x="494" y="-303.5" font-family="Sans" font-size="10.00" fill="#ffffff">Motor</text>
</g>
<!-- Motor&#45;&gt;CompositeDevice -->
<g id="edge17" class="edge"><title>Motor&#45;&gt;CompositeDevice</title>
<path fill="none" stroke="black" d="M541.091,-324.124C526.842,-333.192 509.154,-344.448 493.764,-354.241"/>
<polygon fill="black" stroke="black" points="491.57,-351.489 485.012,-359.81 495.328,-357.394 491.57,-351.489"/>
<g id="edge16" class="edge"><title>Motor&#45;&gt;CompositeDevice</title>
<path fill="none" stroke="black" d="M476.202,-324.303C467.396,-332.865 456.618,-343.344 446.999,-352.696"/>
<polygon fill="black" stroke="black" points="444.323,-350.415 439.593,-359.896 449.203,-355.434 444.323,-350.415"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -30,5 +30,6 @@ digraph classes {
Buzzer->DigitalOutputDevice;
PWMOutputDevice->OutputDevice;
PWMLED->PWMOutputDevice;
RGBLED->Device;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -11,8 +11,8 @@
<polygon fill="white" stroke="none" points="-4,4 -4,-328 717,-328 717,4 -4,4"/>
<!-- Device -->
<g id="node1" class="node"><title>Device</title>
<polygon fill="#9ec6e0" stroke="#9ec6e0" points="499,-324 445,-324 445,-288 499,-288 499,-324"/>
<text text-anchor="middle" x="472" y="-303.5" font-family="Sans" font-size="10.00" fill="#000000">Device</text>
<polygon fill="#9ec6e0" stroke="#9ec6e0" points="540,-324 486,-324 486,-288 540,-288 540,-324"/>
<text text-anchor="middle" x="513" y="-303.5" font-family="Sans" font-size="10.00" fill="#000000">Device</text>
</g>
<!-- GPIODevice -->
<g id="node2" class="node"><title>GPIODevice</title>
@@ -21,8 +21,8 @@
</g>
<!-- GPIODevice&#45;&gt;Device -->
<g id="edge1" class="edge"><title>GPIODevice&#45;&gt;Device</title>
<path fill="none" stroke="black" d="M472,-252.303C472,-260.017 472,-269.288 472,-277.888"/>
<polygon fill="black" stroke="black" points="468.5,-277.896 472,-287.896 475.5,-277.896 468.5,-277.896"/>
<path fill="none" stroke="black" d="M482.135,-252.303C486.852,-260.356 492.562,-270.106 497.782,-279.018"/>
<polygon fill="black" stroke="black" points="494.908,-281.036 502.982,-287.896 500.948,-277.498 494.908,-281.036"/>
</g>
<!-- SmoothedInputDevice -->
<g id="node3" class="node"><title>SmoothedInputDevice</title>
@@ -164,5 +164,15 @@
<path fill="none" stroke="black" d="M661,-36.3034C661,-44.0173 661,-53.2875 661,-61.8876"/>
<polygon fill="black" stroke="black" points="657.5,-61.8956 661,-71.8957 664.5,-61.8957 657.5,-61.8956"/>
</g>
<!-- RGBLED -->
<g id="node17" class="node"><title>RGBLED</title>
<polygon fill="#2980b9" stroke="#2980b9" points="582,-252 526,-252 526,-216 582,-216 582,-252"/>
<text text-anchor="middle" x="554" y="-231.5" font-family="Sans" font-size="10.00" fill="#ffffff">RGBLED</text>
</g>
<!-- RGBLED&#45;&gt;Device -->
<g id="edge16" class="edge"><title>RGBLED&#45;&gt;Device</title>
<path fill="none" stroke="black" d="M543.865,-252.303C539.148,-260.356 533.438,-270.106 528.218,-279.018"/>
<polygon fill="black" stroke="black" points="525.052,-277.498 523.018,-287.896 531.092,-281.036 525.052,-277.498"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -14,7 +14,7 @@ Table of Contents
api_boards
api_other
api_generic
api_source_tools
api_tools
api_pins
api_exc
changelog

View File

@@ -121,19 +121,3 @@ from .other_devices import (
PingServer,
TimeOfDay,
)
from .source_tools import (
averaged,
clamped,
conjunction,
cos_values,
disjunction,
inverted,
negated,
post_delayed,
pre_delayed,
quantized,
queued,
random_values,
scaled,
sin_values,
)

View File

@@ -258,7 +258,7 @@ class LEDBoard(LEDCollection):
on_time, off_time, fade_in_time, fade_out_time, n, background
)
def _blink_device(self, on_time, off_time, fade_in_time, fade_out_time, n, fps=50):
def _blink_device(self, on_time, off_time, fade_in_time, fade_out_time, n, fps=25):
sequence = []
if fade_in_time > 0:
sequence += [

View File

@@ -107,7 +107,13 @@ class GPIOMeta(type):
try:
old_close()
finally:
del cls._INSTANCES[key]
try:
del cls._INSTANCES[key]
except KeyError:
# If the _refs go negative (too many closes)
# just ignore the resulting KeyError here -
# it's already gone
pass
self.close = close
cls._INSTANCES[key] = weakref.proxy(self)
else:

View File

@@ -374,7 +374,7 @@ class HoldMixin(EventsMixin):
@hold_time.setter
def hold_time(self, value):
if value < 0:
raise BadWaitTime('source_delay must be 0 or greater')
raise BadWaitTime('hold_time must be 0 or greater')
self._hold_time = float(value)
@property
@@ -403,8 +403,8 @@ class HoldMixin(EventsMixin):
The length of time (in seconds) that the device has been held for.
This is counted from the first execution of the :attr:`when_held` event
rather than when the device activated, in contrast to
:attr:`active_time`. If the device is not currently held, this is
``None``.
:attr:`~EventsMixin.active_time`. If the device is not currently held,
this is ``None``.
"""
if self._held_from is not None:
return time() - self._held_from

View File

@@ -19,8 +19,8 @@ class OutputDevice(SourceMixin, GPIODevice):
Represents a generic GPIO output device.
This class extends :class:`GPIODevice` to add facilities common to GPIO
output devices: an :meth:`on` method to switch the device on, and a
corresponding :meth:`off` method.
output devices: an :meth:`on` method to switch the device on, a
corresponding :meth:`off` method, and a :meth:`toggle` method.
:param int pin:
The GPIO pin (in BCM numbering) that the device is connected to. If
@@ -123,10 +123,9 @@ class DigitalOutputDevice(OutputDevice):
"""
Represents a generic output device with typical on/off behaviour.
This class extends :class:`OutputDevice` with a :meth:`toggle` method to
switch the device between its on and off states, and a :meth:`blink` method
which uses an optional background thread to handle toggling the device
state without further interaction.
This class extends :class:`OutputDevice` with a :meth:`blink` method which
uses an optional background thread to handle toggling the device state
without further interaction.
"""
def __init__(self, pin=None, active_high=True, initial_value=False):
self._blink_thread = None
@@ -458,7 +457,7 @@ class PWMOutputDevice(OutputDevice):
self._blink_thread = None
def _blink_device(
self, on_time, off_time, fade_in_time, fade_out_time, n, fps=50):
self, on_time, off_time, fade_in_time, fade_out_time, n, fps=25):
sequence = []
if fade_in_time > 0:
sequence += [
@@ -686,7 +685,7 @@ class RGBLED(SourceMixin, Device):
def _blink_device(
self, on_time, off_time, fade_in_time, fade_out_time, on_color,
off_color, n, fps=50):
off_color, n, fps=25):
# Define some simple lambdas to perform linear interpolation between
# off_color and on_color
lerp = lambda t, fade_in: tuple(

View File

@@ -159,7 +159,7 @@ class MockPin(Pin):
# that's about all we can reasonably expect in a non-realtime
# environment on a Pi 1)
for actual, expected in zip(self.states, expected_states):
assert isclose(actual.timestamp, expected[0], rel_tol=0.01, abs_tol=0.01)
assert isclose(actual.timestamp, expected[0], rel_tol=0.05, abs_tol=0.05)
assert isclose(actual.state, expected[1])

View File

@@ -31,84 +31,84 @@ def test_composite_output_on_off():
pin1 = MockPin(2)
pin2 = MockPin(3)
pin3 = MockPin(4)
device = CompositeOutputDevice(OutputDevice(pin1), OutputDevice(pin2), foo=OutputDevice(pin3))
device.on()
assert all((pin1.state, pin2.state, pin3.state))
device.off()
assert not any((pin1.state, pin2.state, pin3.state))
with CompositeOutputDevice(OutputDevice(pin1), OutputDevice(pin2), foo=OutputDevice(pin3)) as device:
device.on()
assert all((pin1.state, pin2.state, pin3.state))
device.off()
assert not any((pin1.state, pin2.state, pin3.state))
def test_composite_output_toggle():
pin1 = MockPin(2)
pin2 = MockPin(3)
pin3 = MockPin(4)
device = CompositeOutputDevice(OutputDevice(pin1), OutputDevice(pin2), foo=OutputDevice(pin3))
device.toggle()
assert all((pin1.state, pin2.state, pin3.state))
device[0].off()
device.toggle()
assert pin1.state
assert not pin2.state
assert not pin3.state
with CompositeOutputDevice(OutputDevice(pin1), OutputDevice(pin2), foo=OutputDevice(pin3)) as device:
device.toggle()
assert all((pin1.state, pin2.state, pin3.state))
device[0].off()
device.toggle()
assert pin1.state
assert not pin2.state
assert not pin3.state
def test_composite_output_value():
pin1 = MockPin(2)
pin2 = MockPin(3)
pin3 = MockPin(4)
device = CompositeOutputDevice(OutputDevice(pin1), OutputDevice(pin2), foo=OutputDevice(pin3))
assert device.value == (0, 0, 0)
device.toggle()
assert device.value == (1, 1, 1)
device.value = (1, 0, 1)
assert device[0].is_active
assert not device[1].is_active
assert device[2].is_active
with CompositeOutputDevice(OutputDevice(pin1), OutputDevice(pin2), foo=OutputDevice(pin3)) as device:
assert device.value == (0, 0, 0)
device.toggle()
assert device.value == (1, 1, 1)
device.value = (1, 0, 1)
assert device[0].is_active
assert not device[1].is_active
assert device[2].is_active
def test_led_board_on_off():
pin1 = MockPin(2)
pin2 = MockPin(3)
pin3 = MockPin(4)
board = LEDBoard(pin1, pin2, foo=pin3)
assert isinstance(board[0], LED)
assert isinstance(board[1], LED)
assert isinstance(board[2], LED)
board.on()
assert all((pin1.state, pin2.state, pin3.state))
board.off()
assert not any((pin1.state, pin2.state, pin3.state))
board[0].on()
assert board.value == (1, 0, 0)
assert pin1.state
assert not pin2.state
assert not pin3.state
board.toggle()
assert board.value == (0, 1, 1)
assert not pin1.state
assert pin2.state
assert pin3.state
with LEDBoard(pin1, pin2, foo=pin3) as board:
assert isinstance(board[0], LED)
assert isinstance(board[1], LED)
assert isinstance(board[2], LED)
board.on()
assert all((pin1.state, pin2.state, pin3.state))
board.off()
assert not any((pin1.state, pin2.state, pin3.state))
board[0].on()
assert board.value == (1, 0, 0)
assert pin1.state
assert not pin2.state
assert not pin3.state
board.toggle()
assert board.value == (0, 1, 1)
assert not pin1.state
assert pin2.state
assert pin3.state
def test_led_board_nested():
pin1 = MockPin(2)
pin2 = MockPin(3)
pin3 = MockPin(4)
board = LEDBoard(pin1, LEDBoard(pin2, pin3))
assert list(led.pin for led in board.leds) == [pin1, pin2, pin3]
assert board.value == (0, (0, 0))
board.value = (1, (0, 1))
assert pin1.state
assert not pin2.state
assert pin3.state
with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
assert list(led.pin for led in board.leds) == [pin1, pin2, pin3]
assert board.value == (0, (0, 0))
board.value = (1, (0, 1))
assert pin1.state
assert not pin2.state
assert pin3.state
def test_led_board_bad_blink():
pin1 = MockPin(2)
pin2 = MockPin(3)
pin3 = MockPin(4)
board = LEDBoard(pin1, LEDBoard(pin2, pin3))
with pytest.raises(ValueError):
board.blink(fade_in_time=1, fade_out_time=1)
with pytest.raises(ValueError):
board.blink(fade_out_time=1)
with pytest.raises(ValueError):
board.pulse()
with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
with pytest.raises(ValueError):
board.blink(fade_in_time=1, fade_out_time=1)
with pytest.raises(ValueError):
board.blink(fade_out_time=1)
with pytest.raises(ValueError):
board.pulse()
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
@@ -116,19 +116,19 @@ def test_led_board_blink_background():
pin1 = MockPin(2)
pin2 = MockPin(3)
pin3 = MockPin(4)
board = LEDBoard(pin1, LEDBoard(pin2, pin3))
board.blink(0.1, 0.1, n=2)
board._blink_thread.join() # naughty, but ensures no arbitrary waits in the test
test = [
(0.0, False),
(0.0, True),
(0.1, False),
(0.1, True),
(0.1, False)
]
pin1.assert_states_and_times(test)
pin2.assert_states_and_times(test)
pin3.assert_states_and_times(test)
with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
board.blink(0.1, 0.1, n=2)
board._blink_thread.join() # naughty, but ensures no arbitrary waits in the test
test = [
(0.0, False),
(0.0, True),
(0.1, False),
(0.1, True),
(0.1, False)
]
pin1.assert_states_and_times(test)
pin2.assert_states_and_times(test)
pin3.assert_states_and_times(test)
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
@@ -136,18 +136,18 @@ def test_led_board_blink_foreground():
pin1 = MockPin(2)
pin2 = MockPin(3)
pin3 = MockPin(4)
board = LEDBoard(pin1, LEDBoard(pin2, pin3))
board.blink(0.1, 0.1, n=2, background=False)
test = [
(0.0, False),
(0.0, True),
(0.1, False),
(0.1, True),
(0.1, False)
]
pin1.assert_states_and_times(test)
pin2.assert_states_and_times(test)
pin3.assert_states_and_times(test)
with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
board.blink(0.1, 0.1, n=2, background=False)
test = [
(0.0, False),
(0.0, True),
(0.1, False),
(0.1, True),
(0.1, False)
]
pin1.assert_states_and_times(test)
pin2.assert_states_and_times(test)
pin3.assert_states_and_times(test)
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
@@ -155,24 +155,24 @@ def test_led_board_blink_control():
pin1 = MockPin(2)
pin2 = MockPin(3)
pin3 = MockPin(4)
board = LEDBoard(pin1, LEDBoard(pin2, pin3))
board.blink(0.1, 0.1, n=2)
# make sure the blink thread's started
while not board._blink_leds:
sleep(0.00001)
board[1][0].off() # immediately take over the second LED
board._blink_thread.join() # naughty, but ensures no arbitrary waits in the test
test = [
(0.0, False),
(0.0, True),
(0.1, False),
(0.1, True),
(0.1, False)
]
pin1.assert_states_and_times(test)
pin3.assert_states_and_times(test)
print(pin2.states)
pin2.assert_states_and_times([(0.0, False), (0.0, True), (0.0, False)])
with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
board.blink(0.1, 0.1, n=2)
# make sure the blink thread's started
while not board._blink_leds:
sleep(0.00001)
board[1][0].off() # immediately take over the second LED
board._blink_thread.join() # naughty, but ensures no arbitrary waits in the test
test = [
(0.0, False),
(0.0, True),
(0.1, False),
(0.1, True),
(0.1, False)
]
pin1.assert_states_and_times(test)
pin3.assert_states_and_times(test)
print(pin2.states)
pin2.assert_states_and_times([(0.0, False), (0.0, True), (0.0, False)])
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
@@ -180,21 +180,21 @@ def test_led_board_blink_take_over():
pin1 = MockPin(2)
pin2 = MockPin(3)
pin3 = MockPin(4)
board = LEDBoard(pin1, LEDBoard(pin2, pin3))
board[1].blink(0.1, 0.1, n=2)
board.blink(0.1, 0.1, n=2) # immediately take over blinking
board[1]._blink_thread.join()
board._blink_thread.join()
test = [
(0.0, False),
(0.0, True),
(0.1, False),
(0.1, True),
(0.1, False)
]
pin1.assert_states_and_times(test)
pin2.assert_states_and_times(test)
pin3.assert_states_and_times(test)
with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
board[1].blink(0.1, 0.1, n=2)
board.blink(0.1, 0.1, n=2) # immediately take over blinking
board[1]._blink_thread.join()
board._blink_thread.join()
test = [
(0.0, False),
(0.0, True),
(0.1, False),
(0.1, True),
(0.1, False)
]
pin1.assert_states_and_times(test)
pin2.assert_states_and_times(test)
pin3.assert_states_and_times(test)
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
@@ -202,47 +202,47 @@ def test_led_board_blink_control_all():
pin1 = MockPin(2)
pin2 = MockPin(3)
pin3 = MockPin(4)
board = LEDBoard(pin1, LEDBoard(pin2, pin3))
board.blink(0.1, 0.1, n=2)
# make sure the blink thread's started
while not board._blink_leds:
sleep(0.00001)
board[0].off() # immediately take over all LEDs
board[1][0].off()
board[1][1].off()
board._blink_thread.join() # blink should terminate here anyway
test = [
(0.0, False),
(0.0, True),
(0.0, False),
]
pin1.assert_states_and_times(test)
pin2.assert_states_and_times(test)
pin3.assert_states_and_times(test)
with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
board.blink(0.1, 0.1, n=2)
# make sure the blink thread's started
while not board._blink_leds:
sleep(0.00001)
board[0].off() # immediately take over all LEDs
board[1][0].off()
board[1][1].off()
board._blink_thread.join() # blink should terminate here anyway
test = [
(0.0, False),
(0.0, True),
(0.0, False),
]
pin1.assert_states_and_times(test)
pin2.assert_states_and_times(test)
pin3.assert_states_and_times(test)
def test_led_board_blink_interrupt_on():
pin1 = MockPin(2)
pin2 = MockPin(3)
pin3 = MockPin(4)
board = LEDBoard(pin1, LEDBoard(pin2, pin3))
board.blink(1, 0.1)
sleep(0.2)
board.off() # should interrupt while on
pin1.assert_states([False, True, False])
pin2.assert_states([False, True, False])
pin3.assert_states([False, True, False])
with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
board.blink(1, 0.1)
sleep(0.2)
board.off() # should interrupt while on
pin1.assert_states([False, True, False])
pin2.assert_states([False, True, False])
pin3.assert_states([False, True, False])
def test_led_board_blink_interrupt_off():
pin1 = MockPin(2)
pin2 = MockPin(3)
pin3 = MockPin(4)
board = LEDBoard(pin1, LEDBoard(pin2, pin3))
board.blink(0.1, 1)
sleep(0.2)
board.off() # should interrupt while off
pin1.assert_states([False, True, False])
pin2.assert_states([False, True, False])
pin3.assert_states([False, True, False])
with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board:
board.blink(0.1, 1)
sleep(0.2)
board.off() # should interrupt while off
pin1.assert_states([False, True, False])
pin2.assert_states([False, True, False])
pin3.assert_states([False, True, False])
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
@@ -250,76 +250,76 @@ def test_led_board_fade_background():
pin1 = MockPWMPin(2)
pin2 = MockPWMPin(3)
pin3 = MockPWMPin(4)
board = LEDBoard(pin1, LEDBoard(pin2, pin3, pwm=True), pwm=True)
board.blink(0, 0, 0.1, 0.1, n=2)
board._blink_thread.join()
test = [
(0.0, 0),
(0.02, 0.2),
(0.02, 0.4),
(0.02, 0.6),
(0.02, 0.8),
(0.02, 1),
(0.02, 0.8),
(0.02, 0.6),
(0.02, 0.4),
(0.02, 0.2),
(0.02, 0),
(0.02, 0.2),
(0.02, 0.4),
(0.02, 0.6),
(0.02, 0.8),
(0.02, 1),
(0.02, 0.8),
(0.02, 0.6),
(0.02, 0.4),
(0.02, 0.2),
(0.02, 0),
]
pin1.assert_states_and_times(test)
pin2.assert_states_and_times(test)
pin3.assert_states_and_times(test)
with LEDBoard(pin1, LEDBoard(pin2, pin3, pwm=True), pwm=True) as board:
board.blink(0, 0, 0.2, 0.2, n=2)
board._blink_thread.join()
test = [
(0.0, 0),
(0.04, 0.2),
(0.04, 0.4),
(0.04, 0.6),
(0.04, 0.8),
(0.04, 1),
(0.04, 0.8),
(0.04, 0.6),
(0.04, 0.4),
(0.04, 0.2),
(0.04, 0),
(0.04, 0.2),
(0.04, 0.4),
(0.04, 0.6),
(0.04, 0.8),
(0.04, 1),
(0.04, 0.8),
(0.04, 0.6),
(0.04, 0.4),
(0.04, 0.2),
(0.04, 0),
]
pin1.assert_states_and_times(test)
pin2.assert_states_and_times(test)
pin3.assert_states_and_times(test)
def test_led_bar_graph_value():
pin1 = MockPin(2)
pin2 = MockPin(3)
pin3 = MockPin(4)
graph = LEDBarGraph(pin1, pin2, pin3)
graph.value = 0
assert not any((pin1.state, pin2.state, pin3.state))
graph.value = 1
assert all((pin1.state, pin2.state, pin3.state))
graph.value = 1/3
assert pin1.state and not (pin2.state or pin3.state)
graph.value = -1/3
assert pin3.state and not (pin1.state or pin2.state)
pin1.state = True
pin2.state = True
assert graph.value == 1
pin3.state = False
assert graph.value == 2/3
pin3.state = True
pin1.state = False
assert graph.value == -2/3
with LEDBarGraph(pin1, pin2, pin3) as graph:
graph.value = 0
assert not any((pin1.state, pin2.state, pin3.state))
graph.value = 1
assert all((pin1.state, pin2.state, pin3.state))
graph.value = 1/3
assert pin1.state and not (pin2.state or pin3.state)
graph.value = -1/3
assert pin3.state and not (pin1.state or pin2.state)
pin1.state = True
pin2.state = True
assert graph.value == 1
pin3.state = False
assert graph.value == 2/3
pin3.state = True
pin1.state = False
assert graph.value == -2/3
def test_led_bar_graph_pwm_value():
pin1 = MockPWMPin(2)
pin2 = MockPWMPin(3)
pin3 = MockPWMPin(4)
graph = LEDBarGraph(pin1, pin2, pin3, pwm=True)
graph.value = 0
assert not any((pin1.state, pin2.state, pin3.state))
graph.value = 1
assert all((pin1.state, pin2.state, pin3.state))
graph.value = 1/3
assert pin1.state and not (pin2.state or pin3.state)
graph.value = -1/3
assert pin3.state and not (pin1.state or pin2.state)
graph.value = 1/2
assert (pin1.state, pin2.state, pin3.state) == (1, 0.5, 0)
pin1.state = 0
pin3.state = 1
assert graph.value == -1/2
with LEDBarGraph(pin1, pin2, pin3, pwm=True) as graph:
graph.value = 0
assert not any((pin1.state, pin2.state, pin3.state))
graph.value = 1
assert all((pin1.state, pin2.state, pin3.state))
graph.value = 1/3
assert pin1.state and not (pin2.state or pin3.state)
graph.value = -1/3
assert pin3.state and not (pin1.state or pin2.state)
graph.value = 1/2
assert (pin1.state, pin2.state, pin3.state) == (1, 0.5, 0)
pin1.state = 0
pin3.state = 1
assert graph.value == -1/2
def test_led_bar_graph_bad_init():
pin1 = MockPin(2)
@@ -330,26 +330,26 @@ def test_led_bar_graph_bad_init():
def test_pi_liter():
pins = [MockPin(n) for n in (4, 17, 27, 18, 22, 23, 24, 25)]
board = PiLiter()
assert [device.pin for device in board] == pins
with PiLiter() as board:
assert [device.pin for device in board] == pins
def test_pi_liter_graph():
pins = [MockPin(n) for n in (4, 17, 27, 18, 22, 23, 24, 25)]
board = PiLiterBarGraph()
board.value = 0.5
assert [pin.state for pin in pins] == [1, 1, 1, 1, 0, 0, 0, 0]
pins[4].state = 1
assert board.value == 5/8
with PiLiterBarGraph() as board:
board.value = 0.5
assert [pin.state for pin in pins] == [1, 1, 1, 1, 0, 0, 0, 0]
pins[4].state = 1
assert board.value == 5/8
def test_traffic_lights():
red_pin = MockPin(2)
amber_pin = MockPin(3)
green_pin = MockPin(4)
board = TrafficLights(red_pin, amber_pin, green_pin)
board.red.on()
assert red_pin.state
assert not amber_pin.state
assert not green_pin.state
with TrafficLights(red_pin, amber_pin, green_pin) as board:
board.red.on()
assert red_pin.state
assert not amber_pin.state
assert not green_pin.state
def test_traffic_lights_bad_init():
with pytest.raises(ValueError):
@@ -357,13 +357,13 @@ def test_traffic_lights_bad_init():
def test_pi_traffic():
pins = [MockPin(n) for n in (9, 10, 11)]
board = PiTraffic()
assert [device.pin for device in board] == pins
with PiTraffic() as board:
assert [device.pin for device in board] == pins
def test_snow_pi():
pins = [MockPin(n) for n in (23, 24, 25, 17, 18, 22, 7, 8, 9)]
board = SnowPi()
assert [device.pin for device in board.leds] == pins
with SnowPi() as board:
assert [device.pin for device in board.leds] == pins
def test_traffic_lights_buzzer():
red_pin = MockPin(2)
@@ -371,59 +371,59 @@ def test_traffic_lights_buzzer():
green_pin = MockPin(4)
buzzer_pin = MockPin(5)
button_pin = MockPin(6)
board = TrafficLightsBuzzer(
with TrafficLightsBuzzer(
TrafficLights(red_pin, amber_pin, green_pin),
Buzzer(buzzer_pin),
Button(button_pin))
board.lights.red.on()
board.buzzer.on()
assert red_pin.state
assert not amber_pin.state
assert not green_pin.state
assert buzzer_pin.state
button_pin.drive_low()
assert board.button.is_active
Button(button_pin)) as board:
board.lights.red.on()
board.buzzer.on()
assert red_pin.state
assert not amber_pin.state
assert not green_pin.state
assert buzzer_pin.state
button_pin.drive_low()
assert board.button.is_active
def test_fish_dish():
pins = [MockPin(n) for n in (9, 22, 4, 8, 7)]
board = FishDish()
assert [led.pin for led in board.lights] + [board.buzzer.pin, board.button.pin] == pins
with FishDish() as board:
assert [led.pin for led in board.lights] + [board.buzzer.pin, board.button.pin] == pins
def test_traffic_hat():
pins = [MockPin(n) for n in (24, 23, 22, 5, 25)]
board = TrafficHat()
assert [led.pin for led in board.lights] + [board.buzzer.pin, board.button.pin] == pins
with TrafficHat() as board:
assert [led.pin for led in board.lights] + [board.buzzer.pin, board.button.pin] == pins
def test_robot():
pins = [MockPWMPin(n) for n in (2, 3, 4, 5)]
robot = Robot((2, 3), (4, 5))
assert (
[device.pin for device in robot.left_motor] +
[device.pin for device in robot.right_motor]) == pins
robot.forward()
assert [pin.state for pin in pins] == [1, 0, 1, 0]
robot.backward()
assert [pin.state for pin in pins] == [0, 1, 0, 1]
robot.forward(0.5)
assert [pin.state for pin in pins] == [0.5, 0, 0.5, 0]
robot.left()
assert [pin.state for pin in pins] == [0, 1, 1, 0]
robot.right()
assert [pin.state for pin in pins] == [1, 0, 0, 1]
robot.reverse()
assert [pin.state for pin in pins] == [0, 1, 1, 0]
robot.stop()
assert [pin.state for pin in pins] == [0, 0, 0, 0]
with Robot((2, 3), (4, 5)) as robot:
assert (
[device.pin for device in robot.left_motor] +
[device.pin for device in robot.right_motor]) == pins
robot.forward()
assert [pin.state for pin in pins] == [1, 0, 1, 0]
robot.backward()
assert [pin.state for pin in pins] == [0, 1, 0, 1]
robot.forward(0.5)
assert [pin.state for pin in pins] == [0.5, 0, 0.5, 0]
robot.left()
assert [pin.state for pin in pins] == [0, 1, 1, 0]
robot.right()
assert [pin.state for pin in pins] == [1, 0, 0, 1]
robot.reverse()
assert [pin.state for pin in pins] == [0, 1, 1, 0]
robot.stop()
assert [pin.state for pin in pins] == [0, 0, 0, 0]
def test_ryanteck_robot():
pins = [MockPWMPin(n) for n in (17, 18, 22, 23)]
board = RyanteckRobot()
assert [device.pin for motor in board for device in motor] == pins
with RyanteckRobot() as board:
assert [device.pin for motor in board for device in motor] == pins
def test_camjam_kit_robot():
pins = [MockPWMPin(n) for n in (9, 10, 7, 8)]
board = CamJamKitRobot()
assert [device.pin for motor in board for device in motor] == pins
with CamJamKitRobot() as board:
assert [device.pin for motor in board for device in motor] == pins
def test_energenie_bad_init():
with pytest.raises(ValueError):
@@ -433,26 +433,26 @@ def test_energenie_bad_init():
def test_energenie():
pins = [MockPin(n) for n in (17, 22, 23, 27, 24, 25)]
device1 = Energenie(1, initial_value=True)
device2 = Energenie(2, initial_value=False)
assert device1.value
assert not device2.value
[pin.clear_states() for pin in pins]
device1.on()
assert device1.value
pins[0].assert_states_and_times([(0.0, False), (0.0, True)])
pins[1].assert_states_and_times([(0.0, True), (0.0, True)])
pins[2].assert_states_and_times([(0.0, True), (0.0, True)])
pins[3].assert_states_and_times([(0.0, False), (0.0, True)])
pins[4].assert_states_and_times([(0.0, False)])
pins[5].assert_states_and_times([(0.0, False), (0.1, True), (0.25, False)])
[pin.clear_states() for pin in pins]
device2.on()
assert device2.value
pins[0].assert_states_and_times([(0.0, True), (0.0, False)])
pins[1].assert_states_and_times([(0.0, True), (0.0, True)])
pins[2].assert_states_and_times([(0.0, True), (0.0, True)])
pins[3].assert_states_and_times([(0.0, True), (0.0, True)])
pins[4].assert_states_and_times([(0.0, False)])
pins[5].assert_states_and_times([(0.0, False), (0.1, True), (0.25, False)])
with Energenie(1, initial_value=True) as device1, \
Energenie(2, initial_value=False) as device2:
assert device1.value
assert not device2.value
[pin.clear_states() for pin in pins]
device1.on()
assert device1.value
pins[0].assert_states_and_times([(0.0, False), (0.0, True)])
pins[1].assert_states_and_times([(0.0, True), (0.0, True)])
pins[2].assert_states_and_times([(0.0, True), (0.0, True)])
pins[3].assert_states_and_times([(0.0, False), (0.0, True)])
pins[4].assert_states_and_times([(0.0, False)])
pins[5].assert_states_and_times([(0.0, False), (0.1, True), (0.25, False)])
[pin.clear_states() for pin in pins]
device2.on()
assert device2.value
pins[0].assert_states_and_times([(0.0, True), (0.0, False)])
pins[1].assert_states_and_times([(0.0, True), (0.0, True)])
pins[2].assert_states_and_times([(0.0, True), (0.0, True)])
pins[3].assert_states_and_times([(0.0, True), (0.0, True)])
pins[4].assert_states_and_times([(0.0, False)])
pins[5].assert_states_and_times([(0.0, False), (0.1, True), (0.25, False)])

View File

@@ -24,21 +24,22 @@ def test_device_no_pin():
def test_device_init():
pin = MockPin(2)
device = GPIODevice(pin)
assert not device.closed
assert device.pin == pin
with GPIODevice(pin) as device:
assert not device.closed
assert device.pin == pin
def test_device_init_twice_same_pin():
pin = MockPin(2)
device = GPIODevice(pin)
with pytest.raises(GPIOPinInUse):
device2 = GPIODevice(pin)
with GPIODevice(pin) as device:
with pytest.raises(GPIOPinInUse):
device2 = GPIODevice(pin)
def test_device_init_twice_different_pin():
pin = MockPin(2)
device = GPIODevice(pin)
pin2 = MockPin(3)
device2 = GPIODevice(pin2)
with GPIODevice(pin) as device:
with GPIODevice(pin2) as device2:
pass
def test_device_close():
pin = MockPin(2)
@@ -56,11 +57,12 @@ def test_device_reopen_same_pin():
assert device2.pin == pin
assert device.closed
assert device.pin is None
device2.close()
def test_device_repr():
pin = MockPin(2)
device = GPIODevice(pin)
assert repr(device) == '<gpiozero.GPIODevice object on pin %s, is_active=False>' % pin
with GPIODevice(pin) as device:
assert repr(device) == '<gpiozero.GPIODevice object on pin %s, is_active=False>' % pin
def test_device_repr_after_close():
pin = MockPin(2)
@@ -70,9 +72,9 @@ def test_device_repr_after_close():
def test_device_unknown_attr():
pin = MockPin(2)
device = GPIODevice(pin)
with pytest.raises(AttributeError):
device.foo = 1
with GPIODevice(pin) as device:
with pytest.raises(AttributeError):
device.foo = 1
def test_device_context_manager():
pin = MockPin(2)
@@ -81,35 +83,35 @@ def test_device_context_manager():
assert device.closed
def test_composite_device_sequence():
device = CompositeDevice(
InputDevice(MockPin(2)),
InputDevice(MockPin(3))
)
assert len(device) == 2
assert device[0].pin.number == 2
assert device[1].pin.number == 3
assert device.tuple._fields == ('_0', '_1')
with CompositeDevice(
InputDevice(MockPin(2)),
InputDevice(MockPin(3))
) as device:
assert len(device) == 2
assert device[0].pin.number == 2
assert device[1].pin.number == 3
assert device.tuple._fields == ('_0', '_1')
def test_composite_device_values():
device = CompositeDevice(
InputDevice(MockPin(2)),
InputDevice(MockPin(3))
)
assert device.value == (0, 0)
assert not device.is_active
device[0].pin.drive_high()
assert device.value == (1, 0)
assert device.is_active
with CompositeDevice(
InputDevice(MockPin(2)),
InputDevice(MockPin(3))
) as device:
assert device.value == (0, 0)
assert not device.is_active
device[0].pin.drive_high()
assert device.value == (1, 0)
assert device.is_active
def test_composite_device_named():
device = CompositeDevice(
foo=InputDevice(MockPin(2)),
bar=InputDevice(MockPin(3)),
_order=('foo', 'bar')
)
assert device.tuple._fields == ('foo', 'bar')
assert device.value == (0, 0)
assert not device.is_active
with CompositeDevice(
foo=InputDevice(MockPin(2)),
bar=InputDevice(MockPin(3)),
_order=('foo', 'bar')
) as device:
assert device.tuple._fields == ('foo', 'bar')
assert device.value == (0, 0)
assert not device.is_active
def test_composite_device_bad_init():
with pytest.raises(ValueError):

View File

@@ -25,131 +25,121 @@ def teardown_function(function):
def test_input_initial_values():
pin = MockPin(2)
device = InputDevice(pin, pull_up=True)
assert pin.function == 'input'
assert pin.pull == 'up'
assert device.pull_up
device.close()
device = InputDevice(pin, pull_up=False)
assert pin.pull == 'down'
assert not device.pull_up
device.close()
with InputDevice(pin, pull_up=True) as device:
assert pin.function == 'input'
assert pin.pull == 'up'
assert device.pull_up
device.close()
device = InputDevice(pin, pull_up=False)
assert pin.pull == 'down'
assert not device.pull_up
def test_input_is_active():
pin = MockPin(2)
device = InputDevice(pin, pull_up=True)
pin.drive_high()
assert not device.is_active
pin.drive_low()
assert device.is_active
with InputDevice(pin, pull_up=True) as device:
pin.drive_high()
assert not device.is_active
pin.drive_low()
assert device.is_active
def test_input_pulled_up():
pin = MockPulledUpPin(2)
with pytest.raises(PinFixedPull):
device = InputDevice(pin, pull_up=False)
InputDevice(pin, pull_up=False)
def test_input_event_activated():
event = Event()
pin = MockPin(2)
device = DigitalInputDevice(pin)
device.when_activated = lambda: event.set()
assert not event.wait(0)
pin.drive_high()
assert event.wait(0)
with DigitalInputDevice(pin) as device:
device.when_activated = lambda: event.set()
assert not event.wait(0)
pin.drive_high()
assert event.wait(0)
def test_input_event_deactivated():
event = Event()
pin = MockPin(2)
device = DigitalInputDevice(pin)
device.when_deactivated = lambda: event.set()
assert not event.wait(0)
pin.drive_high()
assert not event.wait(0)
pin.drive_low()
assert event.wait(0)
with DigitalInputDevice(pin) as device:
device.when_deactivated = lambda: event.set()
assert not event.wait(0)
pin.drive_high()
assert not event.wait(0)
pin.drive_low()
assert event.wait(0)
def test_input_wait_active():
pin = MockPin(2)
device = DigitalInputDevice(pin)
pin.drive_high()
assert device.wait_for_active(1)
assert not device.wait_for_inactive(0)
with DigitalInputDevice(pin) as device:
pin.drive_high()
assert device.wait_for_active(1)
assert not device.wait_for_inactive(0)
def test_input_wait_inactive():
pin = MockPin(2)
device = DigitalInputDevice(pin)
assert device.wait_for_inactive(1)
assert not device.wait_for_active(0)
with DigitalInputDevice(pin) as device:
assert device.wait_for_inactive(1)
assert not device.wait_for_active(0)
def test_input_smoothed_attrib():
pin = MockPin(2)
device = SmoothedInputDevice(pin, threshold=0.5, queue_len=5, partial=False)
assert device.threshold == 0.5
assert device.queue_len == 5
assert not device.partial
device._queue.start()
assert not device.is_active
def test_input_smoothed_silly():
pin = MockPin(2)
with pytest.raises(InputDeviceError):
device = SmoothedInputDevice(pin, threshold=-1)
device = SmoothedInputDevice(pin)
del device._queue.stopping
with pytest.raises(AttributeError):
device.close()
with SmoothedInputDevice(pin, threshold=0.5, queue_len=5, partial=False) as device:
assert device.threshold == 0.5
assert device.queue_len == 5
assert not device.partial
device._queue.start()
assert not device.is_active
def test_input_smoothed_values():
pin = MockPin(2)
device = SmoothedInputDevice(pin)
device._queue.start()
assert not device.is_active
pin.drive_high()
assert device.wait_for_active(1)
pin.drive_low()
assert device.wait_for_inactive(1)
with SmoothedInputDevice(pin) as device:
device._queue.start()
assert not device.is_active
pin.drive_high()
assert device.wait_for_active(1)
pin.drive_low()
assert device.wait_for_inactive(1)
def test_input_button():
pin = MockPin(2)
button = Button(pin)
assert pin.pull == 'up'
assert not button.is_pressed
pin.drive_low()
assert button.is_pressed
assert button.wait_for_press(1)
pin.drive_high()
assert not button.is_pressed
assert button.wait_for_release(1)
with Button(pin) as button:
assert pin.pull == 'up'
assert not button.is_pressed
pin.drive_low()
assert button.is_pressed
assert button.wait_for_press(1)
pin.drive_high()
assert not button.is_pressed
assert button.wait_for_release(1)
def test_input_line_sensor():
pin = MockPin(2)
sensor = LineSensor(pin)
pin.drive_low() # logic is inverted for line sensor
assert sensor.wait_for_line(1)
assert sensor.line_detected
pin.drive_high()
assert sensor.wait_for_no_line(1)
assert not sensor.line_detected
with LineSensor(pin) as sensor:
pin.drive_low() # logic is inverted for line sensor
assert sensor.wait_for_line(1)
assert sensor.line_detected
pin.drive_high()
assert sensor.wait_for_no_line(1)
assert not sensor.line_detected
def test_input_motion_sensor():
pin = MockPin(2)
sensor = MotionSensor(pin)
pin.drive_high()
assert sensor.wait_for_motion(1)
assert sensor.motion_detected
pin.drive_low()
assert sensor.wait_for_no_motion(1)
assert not sensor.motion_detected
with MotionSensor(pin) as sensor:
pin.drive_high()
assert sensor.wait_for_motion(1)
assert sensor.motion_detected
pin.drive_low()
assert sensor.wait_for_no_motion(1)
assert not sensor.motion_detected
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
def test_input_light_sensor():
pin = MockChargingPin(2)
sensor = LightSensor(pin)
pin.charge_time = 0.1
assert sensor.wait_for_dark(1)
pin.charge_time = 0.0
assert sensor.wait_for_light(1)
with LightSensor(pin) as sensor:
pin.charge_time = 0.1
assert sensor.wait_for_dark(1)
pin.charge_time = 0.0
assert sensor.wait_for_light(1)
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
@@ -162,22 +152,22 @@ def test_input_distance_sensor():
DistanceSensor(echo_pin, trig_pin, max_distance=-1)
# normal queue len is large (because the sensor is *really* jittery) but
# we want quick tests and we've got precisely controlled pins :)
sensor = DistanceSensor(echo_pin, trig_pin, queue_len=5, max_distance=1)
assert sensor.max_distance == 1
assert sensor.trigger is trig_pin
assert sensor.echo is echo_pin
assert sensor.wait_for_out_of_range(1)
assert not sensor.in_range
assert sensor.distance == 1.0 # should be waay before max-distance so this should work
trig_pin.echo_time = 0.0
assert sensor.wait_for_in_range(1)
assert sensor.in_range
assert sensor.distance < sensor.threshold_distance # depending on speed of machine, may not reach 0 here
sensor.threshold_distance = 0.1
assert sensor.threshold_distance == 0.1
with pytest.raises(ValueError):
sensor.max_distance = -1
sensor.max_distance = 20
assert sensor.max_distance == 20
assert sensor.threshold_distance == 0.1
with DistanceSensor(echo_pin, trig_pin, queue_len=5, max_distance=1) as sensor:
assert sensor.max_distance == 1
assert sensor.trigger is trig_pin
assert sensor.echo is echo_pin
assert sensor.wait_for_out_of_range(1)
assert not sensor.in_range
assert sensor.distance == 1.0 # should be waay before max-distance so this should work
trig_pin.echo_time = 0.0
assert sensor.wait_for_in_range(1)
assert sensor.in_range
assert sensor.distance < sensor.threshold_distance # depending on speed of machine, may not reach 0 here
sensor.threshold_distance = 0.1
assert sensor.threshold_distance == 0.1
with pytest.raises(ValueError):
sensor.max_distance = -1
sensor.max_distance = 20
assert sensor.max_distance == 20
assert sensor.threshold_distance == 0.1

View File

@@ -25,114 +25,112 @@ def teardown_function(function):
def test_output_initial_values():
pin = MockPin(2)
device = OutputDevice(pin, initial_value=False)
assert pin.function == 'output'
assert not pin.state
device.close()
device = OutputDevice(pin, initial_value=True)
assert pin.state
device.close()
state = pin.state
device = OutputDevice(pin, initial_value=None)
assert state == pin.state
with OutputDevice(pin, initial_value=False) as device:
assert pin.function == 'output'
assert not pin.state
with OutputDevice(pin, initial_value=True) as device:
assert pin.state
state = pin.state
with OutputDevice(pin, initial_value=None) as device:
assert state == pin.state
def test_output_write_active_high():
pin = MockPin(2)
device = OutputDevice(pin)
device.on()
assert pin.state
device.off()
assert not pin.state
with OutputDevice(pin) as device:
device.on()
assert pin.state
device.off()
assert not pin.state
def test_output_write_active_low():
pin = MockPin(2)
device = OutputDevice(pin, active_high=False)
device.on()
assert not pin.state
device.off()
assert pin.state
with OutputDevice(pin, active_high=False) as device:
device.on()
assert not pin.state
device.off()
assert pin.state
def test_output_write_closed():
device = OutputDevice(MockPin(2))
device.close()
with pytest.raises(GPIODeviceClosed):
device.on()
with OutputDevice(MockPin(2)) as device:
device.close()
with pytest.raises(GPIODeviceClosed):
device.on()
def test_output_write_silly():
pin = MockPin(2)
device = OutputDevice(pin)
pin.function = 'input'
with pytest.raises(AttributeError):
device.on()
with OutputDevice(pin) as device:
pin.function = 'input'
with pytest.raises(AttributeError):
device.on()
def test_output_value():
pin = MockPin(2)
device = OutputDevice(pin)
assert not device.value
assert not pin.state
device.on()
assert device.value
assert pin.state
device.value = False
assert not device.value
assert not pin.state
with OutputDevice(pin) as device:
assert not device.value
assert not pin.state
device.on()
assert device.value
assert pin.state
device.value = False
assert not device.value
assert not pin.state
def test_output_digital_toggle():
pin = MockPin(2)
device = DigitalOutputDevice(pin)
assert not device.value
assert not pin.state
device.toggle()
assert device.value
assert pin.state
device.toggle()
assert not device.value
assert not pin.state
with DigitalOutputDevice(pin) as device:
assert not device.value
assert not pin.state
device.toggle()
assert device.value
assert pin.state
device.toggle()
assert not device.value
assert not pin.state
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
def test_output_blink_background():
pin = MockPin(2)
device = DigitalOutputDevice(pin)
device.blink(0.1, 0.1, n=2)
device._blink_thread.join() # naughty, but ensures no arbitrary waits in the test
pin.assert_states_and_times([
(0.0, False),
(0.0, True),
(0.1, False),
(0.1, True),
(0.1, False)
])
with DigitalOutputDevice(pin) as device:
device.blink(0.1, 0.1, n=2)
device._blink_thread.join() # naughty, but ensures no arbitrary waits in the test
pin.assert_states_and_times([
(0.0, False),
(0.0, True),
(0.1, False),
(0.1, True),
(0.1, False)
])
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
def test_output_blink_foreground():
pin = MockPin(2)
device = DigitalOutputDevice(pin)
device.blink(0.1, 0.1, n=2, background=False)
pin.assert_states_and_times([
(0.0, False),
(0.0, True),
(0.1, False),
(0.1, True),
(0.1, False)
])
with DigitalOutputDevice(pin) as device:
device.blink(0.1, 0.1, n=2, background=False)
pin.assert_states_and_times([
(0.0, False),
(0.0, True),
(0.1, False),
(0.1, True),
(0.1, False)
])
def test_output_blink_interrupt_on():
pin = MockPin(2)
device = DigitalOutputDevice(pin)
device.blink(1, 0.1)
sleep(0.2)
device.off() # should interrupt while on
pin.assert_states([False, True, False])
with DigitalOutputDevice(pin) as device:
device.blink(1, 0.1)
sleep(0.2)
device.off() # should interrupt while on
pin.assert_states([False, True, False])
def test_output_blink_interrupt_off():
pin = MockPin(2)
device = DigitalOutputDevice(pin)
device.blink(0.1, 1)
sleep(0.2)
device.off() # should interrupt while off
pin.assert_states([False, True, False])
with DigitalOutputDevice(pin) as device:
device.blink(0.1, 1)
sleep(0.2)
device.off() # should interrupt while off
pin.assert_states([False, True, False])
def test_output_pwm_bad_initial_value():
with pytest.raises(ValueError):
@@ -144,50 +142,50 @@ def test_output_pwm_not_supported():
def test_output_pwm_states():
pin = MockPWMPin(2)
device = PWMOutputDevice(pin)
device.value = 0.1
device.value = 0.2
device.value = 0.0
pin.assert_states([0.0, 0.1, 0.2, 0.0])
with PWMOutputDevice(pin) as device:
device.value = 0.1
device.value = 0.2
device.value = 0.0
pin.assert_states([0.0, 0.1, 0.2, 0.0])
def test_output_pwm_read():
pin = MockPWMPin(2)
device = PWMOutputDevice(pin, frequency=100)
assert device.frequency == 100
device.value = 0.1
assert isclose(device.value, 0.1)
assert isclose(pin.state, 0.1)
assert device.is_active
device.frequency = None
assert not device.value
assert not device.is_active
assert device.frequency is None
with PWMOutputDevice(pin, frequency=100) as device:
assert device.frequency == 100
device.value = 0.1
assert isclose(device.value, 0.1)
assert isclose(pin.state, 0.1)
assert device.is_active
device.frequency = None
assert not device.value
assert not device.is_active
assert device.frequency is None
def test_output_pwm_write():
pin = MockPWMPin(2)
device = PWMOutputDevice(pin)
device.on()
device.off()
pin.assert_states([False, True, False])
with PWMOutputDevice(pin) as device:
device.on()
device.off()
pin.assert_states([False, True, False])
def test_output_pwm_toggle():
pin = MockPWMPin(2)
device = PWMOutputDevice(pin)
device.toggle()
device.value = 0.5
device.value = 0.1
device.toggle()
device.off()
pin.assert_states([False, True, 0.5, 0.1, 0.9, False])
with PWMOutputDevice(pin) as device:
device.toggle()
device.value = 0.5
device.value = 0.1
device.toggle()
device.off()
pin.assert_states([False, True, 0.5, 0.1, 0.9, False])
def test_output_pwm_active_high_read():
pin = MockPWMPin(2)
device = PWMOutputDevice(pin, active_high=False)
device.value = 0.1
assert isclose(device.value, 0.1)
assert isclose(pin.state, 0.9)
device.frequency = None
assert device.value
with PWMOutputDevice(pin, active_high=False) as device:
device.value = 0.1
assert isclose(device.value, 0.1)
assert isclose(pin.state, 0.9)
device.frequency = None
assert device.value
def test_output_pwm_bad_value():
with pytest.raises(ValueError):
@@ -201,108 +199,108 @@ def test_output_pwm_write_closed():
def test_output_pwm_write_silly():
pin = MockPWMPin(2)
device = PWMOutputDevice(pin)
pin.function = 'input'
with pytest.raises(AttributeError):
device.off()
with PWMOutputDevice(pin) as device:
pin.function = 'input'
with pytest.raises(AttributeError):
device.off()
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
def test_output_pwm_blink_background():
pin = MockPWMPin(2)
device = PWMOutputDevice(pin)
device.blink(0.1, 0.1, n=2)
device._blink_thread.join()
pin.assert_states_and_times([
(0.0, 0),
(0.0, 1),
(0.1, 0),
(0.1, 1),
(0.1, 0)
])
with PWMOutputDevice(pin) as device:
device.blink(0.1, 0.1, n=2)
device._blink_thread.join()
pin.assert_states_and_times([
(0.0, 0),
(0.0, 1),
(0.1, 0),
(0.1, 1),
(0.1, 0)
])
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
def test_output_pwm_blink_foreground():
pin = MockPWMPin(2)
device = PWMOutputDevice(pin)
device.blink(0.1, 0.1, n=2, background=False)
pin.assert_states_and_times([
(0.0, 0),
(0.0, 1),
(0.1, 0),
(0.1, 1),
(0.1, 0)
])
with PWMOutputDevice(pin) as device:
device.blink(0.1, 0.1, n=2, background=False)
pin.assert_states_and_times([
(0.0, 0),
(0.0, 1),
(0.1, 0),
(0.1, 1),
(0.1, 0)
])
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
def test_output_pwm_fade_background():
pin = MockPWMPin(2)
device = PWMOutputDevice(pin)
device.blink(0, 0, 0.1, 0.1, n=2)
device._blink_thread.join()
pin.assert_states_and_times([
(0.0, 0),
(0.02, 0.2),
(0.02, 0.4),
(0.02, 0.6),
(0.02, 0.8),
(0.02, 1),
(0.02, 0.8),
(0.02, 0.6),
(0.02, 0.4),
(0.02, 0.2),
(0.02, 0),
(0.02, 0.2),
(0.02, 0.4),
(0.02, 0.6),
(0.02, 0.8),
(0.02, 1),
(0.02, 0.8),
(0.02, 0.6),
(0.02, 0.4),
(0.02, 0.2),
(0.02, 0),
])
with PWMOutputDevice(pin) as device:
device.blink(0, 0, 0.2, 0.2, n=2)
device._blink_thread.join()
pin.assert_states_and_times([
(0.0, 0),
(0.04, 0.2),
(0.04, 0.4),
(0.04, 0.6),
(0.04, 0.8),
(0.04, 1),
(0.04, 0.8),
(0.04, 0.6),
(0.04, 0.4),
(0.04, 0.2),
(0.04, 0),
(0.04, 0.2),
(0.04, 0.4),
(0.04, 0.6),
(0.04, 0.8),
(0.04, 1),
(0.04, 0.8),
(0.04, 0.6),
(0.04, 0.4),
(0.04, 0.2),
(0.04, 0),
])
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
def test_output_pwm_fade_foreground():
pin = MockPWMPin(2)
device = PWMOutputDevice(pin)
device.blink(0, 0, 0.1, 0.1, n=2, background=False)
pin.assert_states_and_times([
(0.0, 0),
(0.02, 0.2),
(0.02, 0.4),
(0.02, 0.6),
(0.02, 0.8),
(0.02, 1),
(0.02, 0.8),
(0.02, 0.6),
(0.02, 0.4),
(0.02, 0.2),
(0.02, 0),
(0.02, 0.2),
(0.02, 0.4),
(0.02, 0.6),
(0.02, 0.8),
(0.02, 1),
(0.02, 0.8),
(0.02, 0.6),
(0.02, 0.4),
(0.02, 0.2),
(0.02, 0),
])
with PWMOutputDevice(pin) as device:
device.blink(0, 0, 0.2, 0.2, n=2, background=False)
pin.assert_states_and_times([
(0.0, 0),
(0.04, 0.2),
(0.04, 0.4),
(0.04, 0.6),
(0.04, 0.8),
(0.04, 1),
(0.04, 0.8),
(0.04, 0.6),
(0.04, 0.4),
(0.04, 0.2),
(0.04, 0),
(0.04, 0.2),
(0.04, 0.4),
(0.04, 0.6),
(0.04, 0.8),
(0.04, 1),
(0.04, 0.8),
(0.04, 0.6),
(0.04, 0.4),
(0.04, 0.2),
(0.04, 0),
])
def test_output_pwm_blink_interrupt():
pin = MockPWMPin(2)
device = PWMOutputDevice(pin)
device.blink(1, 0.1)
sleep(0.2)
device.off() # should interrupt while on
pin.assert_states([0, 1, 0])
with PWMOutputDevice(pin) as device:
device.blink(1, 0.1)
sleep(0.2)
device.off() # should interrupt while on
pin.assert_states([0, 1, 0])
def test_rgbled_missing_pins():
with pytest.raises(ValueError):
@@ -310,116 +308,116 @@ def test_rgbled_missing_pins():
def test_rgbled_initial_value():
r, g, b = (MockPWMPin(i) for i in (1, 2, 3))
device = RGBLED(r, g, b, initial_value=(0.1, 0.2, 0))
assert r.frequency
assert g.frequency
assert b.frequency
assert isclose(r.state, 0.1)
assert isclose(g.state, 0.2)
assert isclose(b.state, 0.0)
with RGBLED(r, g, b, initial_value=(0.1, 0.2, 0)) as device:
assert r.frequency
assert g.frequency
assert b.frequency
assert isclose(r.state, 0.1)
assert isclose(g.state, 0.2)
assert isclose(b.state, 0.0)
def test_rgbled_value():
r, g, b = (MockPWMPin(i) for i in (1, 2, 3))
device = RGBLED(r, g, b)
assert not device.is_active
assert device.value == (0, 0, 0)
device.on()
assert device.is_active
assert device.value == (1, 1, 1)
device.off()
assert not device.is_active
assert device.value == (0, 0, 0)
with RGBLED(r, g, b) as device:
assert not device.is_active
assert device.value == (0, 0, 0)
device.on()
assert device.is_active
assert device.value == (1, 1, 1)
device.off()
assert not device.is_active
assert device.value == (0, 0, 0)
def test_rgbled_toggle():
r, g, b = (MockPWMPin(i) for i in (1, 2, 3))
device = RGBLED(r, g, b)
assert not device.is_active
assert device.value == (0, 0, 0)
device.toggle()
assert device.is_active
assert device.value == (1, 1, 1)
device.toggle()
assert not device.is_active
assert device.value == (0, 0, 0)
with RGBLED(r, g, b) as device:
assert not device.is_active
assert device.value == (0, 0, 0)
device.toggle()
assert device.is_active
assert device.value == (1, 1, 1)
device.toggle()
assert not device.is_active
assert device.value == (0, 0, 0)
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
def test_rgbled_blink_background():
r, g, b = (MockPWMPin(i) for i in (1, 2, 3))
device = RGBLED(r, g, b)
device.blink(0.1, 0.1, n=2)
device._blink_thread.join()
expected = [
(0.0, 0),
(0.0, 1),
(0.1, 0),
(0.1, 1),
(0.1, 0)
]
r.assert_states_and_times(expected)
g.assert_states_and_times(expected)
b.assert_states_and_times(expected)
with RGBLED(r, g, b) as device:
device.blink(0.1, 0.1, n=2)
device._blink_thread.join()
expected = [
(0.0, 0),
(0.0, 1),
(0.1, 0),
(0.1, 1),
(0.1, 0)
]
r.assert_states_and_times(expected)
g.assert_states_and_times(expected)
b.assert_states_and_times(expected)
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
def test_rgbled_blink_foreground():
r, g, b = (MockPWMPin(i) for i in (1, 2, 3))
device = RGBLED(r, g, b)
device.blink(0.1, 0.1, n=2, background=False)
expected = [
(0.0, 0),
(0.0, 1),
(0.1, 0),
(0.1, 1),
(0.1, 0)
]
r.assert_states_and_times(expected)
g.assert_states_and_times(expected)
b.assert_states_and_times(expected)
with RGBLED(r, g, b) as device:
device.blink(0.1, 0.1, n=2, background=False)
expected = [
(0.0, 0),
(0.0, 1),
(0.1, 0),
(0.1, 1),
(0.1, 0)
]
r.assert_states_and_times(expected)
g.assert_states_and_times(expected)
b.assert_states_and_times(expected)
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
def test_rgbled_fade_background():
r, g, b = (MockPWMPin(i) for i in (1, 2, 3))
device = RGBLED(r, g, b)
device.blink(0, 0, 0.1, 0.1, n=2)
device._blink_thread.join()
expected = [
(0.0, 0),
(0.02, 0.2),
(0.02, 0.4),
(0.02, 0.6),
(0.02, 0.8),
(0.02, 1),
(0.02, 0.8),
(0.02, 0.6),
(0.02, 0.4),
(0.02, 0.2),
(0.02, 0),
(0.02, 0.2),
(0.02, 0.4),
(0.02, 0.6),
(0.02, 0.8),
(0.02, 1),
(0.02, 0.8),
(0.02, 0.6),
(0.02, 0.4),
(0.02, 0.2),
(0.02, 0),
]
r.assert_states_and_times(expected)
g.assert_states_and_times(expected)
b.assert_states_and_times(expected)
with RGBLED(r, g, b) as device:
device.blink(0, 0, 0.2, 0.2, n=2)
device._blink_thread.join()
expected = [
(0.0, 0),
(0.04, 0.2),
(0.04, 0.4),
(0.04, 0.6),
(0.04, 0.8),
(0.04, 1),
(0.04, 0.8),
(0.04, 0.6),
(0.04, 0.4),
(0.04, 0.2),
(0.04, 0),
(0.04, 0.2),
(0.04, 0.4),
(0.04, 0.6),
(0.04, 0.8),
(0.04, 1),
(0.04, 0.8),
(0.04, 0.6),
(0.04, 0.4),
(0.04, 0.2),
(0.04, 0),
]
r.assert_states_and_times(expected)
g.assert_states_and_times(expected)
b.assert_states_and_times(expected)
def test_output_rgbled_blink_interrupt():
r, g, b = (MockPWMPin(i) for i in (1, 2, 3))
device = RGBLED(r, g, b)
device.blink(1, 0.1)
sleep(0.2)
device.off() # should interrupt while on
r.assert_states([0, 1, 0])
g.assert_states([0, 1, 0])
b.assert_states([0, 1, 0])
with RGBLED(r, g, b) as device:
device.blink(1, 0.1)
sleep(0.2)
device.off() # should interrupt while on
r.assert_states([0, 1, 0])
g.assert_states([0, 1, 0])
b.assert_states([0, 1, 0])
def test_motor_missing_pins():
with pytest.raises(ValueError):
@@ -428,55 +426,55 @@ def test_motor_missing_pins():
def test_motor_pins():
f = MockPWMPin(1)
b = MockPWMPin(2)
device = Motor(f, b)
assert device.forward_device.pin is f
assert device.backward_device.pin is b
with Motor(f, b) as device:
assert device.forward_device.pin is f
assert device.backward_device.pin is b
def test_motor_close():
f = MockPWMPin(1)
b = MockPWMPin(2)
device = Motor(f, b)
device.close()
assert device.closed
assert device.forward_device.pin is None
assert device.backward_device.pin is None
with Motor(f, b) as device:
device.close()
assert device.closed
assert device.forward_device.pin is None
assert device.backward_device.pin is None
def test_motor_value():
f = MockPWMPin(1)
b = MockPWMPin(2)
device = Motor(f, b)
device.value = -1
assert device.is_active
assert device.value == -1
assert b.state == 1 and f.state == 0
device.value = 1
assert device.is_active
assert device.value == 1
assert b.state == 0 and f.state == 1
device.value = 0.5
assert device.is_active
assert device.value == 0.5
assert b.state == 0 and f.state == 0.5
device.value = 0
assert not device.is_active
assert not device.value
assert b.state == 0 and f.state == 0
with Motor(f, b) as device:
device.value = -1
assert device.is_active
assert device.value == -1
assert b.state == 1 and f.state == 0
device.value = 1
assert device.is_active
assert device.value == 1
assert b.state == 0 and f.state == 1
device.value = 0.5
assert device.is_active
assert device.value == 0.5
assert b.state == 0 and f.state == 0.5
device.value = 0
assert not device.is_active
assert not device.value
assert b.state == 0 and f.state == 0
def test_motor_bad_value():
f = MockPWMPin(1)
b = MockPWMPin(2)
device = Motor(f, b)
with pytest.raises(ValueError):
device.value = 2
with Motor(f, b) as device:
with pytest.raises(ValueError):
device.value = 2
def test_motor_reverse():
f = MockPWMPin(1)
b = MockPWMPin(2)
device = Motor(f, b)
device.forward()
assert device.value == 1
assert b.state == 0 and f.state == 1
device.reverse()
assert device.value == -1
assert b.state == 1 and f.state == 0
with Motor(f, b) as device:
device.forward()
assert device.value == 1
assert b.state == 0 and f.state == 1
device.reverse()
assert device.value == -1
assert b.state == 1 and f.state == 0

View File

@@ -11,7 +11,7 @@ import pytest
from math import sin, cos, radians
from time import time
from gpiozero import *
from gpiozero.tools import *
try:
from math import isclose
except ImportError: