mirror of
				https://github.com/KevinMidboe/python-gpiozero.git
				synced 2025-10-29 17:50:37 +00:00 
			
		
		
		
	Fix real pin tests ... and some other bits
The real pin tests were broken by the new factory stuff. This commit fixes them up, and fixes up a few other bits besides (like why the pigpio PWM tests were failing, why RPi.GPIO sometimes segfaulted on PWM tests, etc.) It also causes the real pin tests to run against MockPin (thanks to @lurch for the suggestion!). This required some tweaks to MockPin to make it emulate physically pulled up pins itself (which in turn necessitated changing quite a few pin numbers in the main test suite because we were using 2 and 3 everywhere), and to allow one MockPin to drive another. Anyway, everything's working now including all the tests on a Pi (haven't tried RPIO yet, but only because I'm on a Pi3 - everything else works with overall coverage of 88% :).
This commit is contained in:
		| @@ -18,7 +18,13 @@ except ImportError: | |||||||
|  |  | ||||||
| import pkg_resources | import pkg_resources | ||||||
|  |  | ||||||
| from ..exc import PinPWMUnsupported, PinSetInput, PinFixedPull | from ..exc import ( | ||||||
|  |     PinPWMUnsupported, | ||||||
|  |     PinSetInput, | ||||||
|  |     PinFixedPull, | ||||||
|  |     PinInvalidFunction, | ||||||
|  |     PinInvalidPull, | ||||||
|  |     ) | ||||||
| from ..devices import Device | from ..devices import Device | ||||||
| from .pi import PiPin | from .pi import PiPin | ||||||
| from .local import LocalPiFactory | from .local import LocalPiFactory | ||||||
| @@ -34,8 +40,8 @@ class MockPin(PiPin): | |||||||
|     def __init__(self, factory, number): |     def __init__(self, factory, number): | ||||||
|         super(MockPin, self).__init__(factory, number) |         super(MockPin, self).__init__(factory, number) | ||||||
|         self._function = 'input' |         self._function = 'input' | ||||||
|         self._state = False |         self._pull = 'up' if factory.pi_info.pulled_up(self.address[-1]) else 'floating' | ||||||
|         self._pull = 'floating' |         self._state = self._pull == 'up' | ||||||
|         self._bounce = None |         self._bounce = None | ||||||
|         self._edges = 'both' |         self._edges = 'both' | ||||||
|         self._when_changed = None |         self._when_changed = None | ||||||
| @@ -49,7 +55,8 @@ class MockPin(PiPin): | |||||||
|         return self._function |         return self._function | ||||||
|  |  | ||||||
|     def _set_function(self, value): |     def _set_function(self, value): | ||||||
|         assert value in ('input', 'output') |         if value not in ('input', 'output'): | ||||||
|  |             raise PinInvalidFunction('function must be input or output') | ||||||
|         self._function = value |         self._function = value | ||||||
|         if value == 'input': |         if value == 'input': | ||||||
|             # Drive the input to the pull |             # Drive the input to the pull | ||||||
| @@ -85,8 +92,12 @@ class MockPin(PiPin): | |||||||
|         return self._pull |         return self._pull | ||||||
|  |  | ||||||
|     def _set_pull(self, value): |     def _set_pull(self, value): | ||||||
|         assert self._function == 'input' |         if self.function != 'input': | ||||||
|         assert value in ('floating', 'up', 'down') |             raise PinFixedPull('cannot set pull on non-input pin %r' % self) | ||||||
|  |         if value != 'up' and self.factory.pi_info.pulled_up(self.address[-1]): | ||||||
|  |             raise PinFixedPull('%r has a physical pull-up resistor' % self) | ||||||
|  |         if value not in ('floating', 'up', 'down'): | ||||||
|  |             raise PinInvalidPull('pull must be floating, up, or down') | ||||||
|         self._pull = value |         self._pull = value | ||||||
|         if value == 'up': |         if value == 'up': | ||||||
|             self.drive_high() |             self.drive_high() | ||||||
| @@ -132,7 +143,12 @@ class MockPin(PiPin): | |||||||
|     def assert_states(self, expected_states): |     def assert_states(self, expected_states): | ||||||
|         # Tests that the pin went through the expected states (a list of values) |         # Tests that the pin went through the expected states (a list of values) | ||||||
|         for actual, expected in zip(self.states, expected_states): |         for actual, expected in zip(self.states, expected_states): | ||||||
|             assert actual.state == expected |             try: | ||||||
|  |                 assert actual.state == expected | ||||||
|  |             except AssertionError: | ||||||
|  |                 print('Actual states', self.states) | ||||||
|  |                 print('Expected states', expected_states) | ||||||
|  |                 raise | ||||||
|  |  | ||||||
|     def assert_states_and_times(self, expected_states): |     def assert_states_and_times(self, expected_states): | ||||||
|         # Tests that the pin went through the expected states at the expected |         # Tests that the pin went through the expected states at the expected | ||||||
| @@ -140,8 +156,32 @@ class MockPin(PiPin): | |||||||
|         # that's about all we can reasonably expect in a non-realtime |         # that's about all we can reasonably expect in a non-realtime | ||||||
|         # environment on a Pi 1) |         # environment on a Pi 1) | ||||||
|         for actual, expected in zip(self.states, expected_states): |         for actual, expected in zip(self.states, expected_states): | ||||||
|             assert isclose(actual.timestamp, expected[0], rel_tol=0.05, abs_tol=0.05) |             try: | ||||||
|             assert isclose(actual.state, expected[1]) |                 assert isclose(actual.timestamp, expected[0], rel_tol=0.05, abs_tol=0.05) | ||||||
|  |                 assert isclose(actual.state, expected[1]) | ||||||
|  |             except AssertionError: | ||||||
|  |                 print('Actual states', self.states) | ||||||
|  |                 print('Expected states', expected_states) | ||||||
|  |                 raise | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class MockConnectedPin(MockPin): | ||||||
|  |     """ | ||||||
|  |     This derivative of :class:`MockPin` emulates a pin connected to another | ||||||
|  |     mock pin. This is used in the "real pins" portion of the test suite to | ||||||
|  |     check that one pin can influence another. | ||||||
|  |     """ | ||||||
|  |     def __init__(self, factory, number): | ||||||
|  |         super(MockConnectedPin, self).__init__(factory, number) | ||||||
|  |         self.input_pin = None | ||||||
|  |  | ||||||
|  |     def _change_state(self, value): | ||||||
|  |         if self.input_pin: | ||||||
|  |             if value: | ||||||
|  |                 self.input_pin.drive_high() | ||||||
|  |             else: | ||||||
|  |                 self.input_pin.drive_low() | ||||||
|  |         return super(MockConnectedPin, self)._change_state(value) | ||||||
|  |  | ||||||
|  |  | ||||||
| class MockPulledUpPin(MockPin): | class MockPulledUpPin(MockPin): | ||||||
|   | |||||||
| @@ -236,6 +236,12 @@ class PiGPIOPin(PiPin): | |||||||
|  |  | ||||||
|     def _set_frequency(self, value): |     def _set_frequency(self, value): | ||||||
|         if not self._pwm and value is not None: |         if not self._pwm and value is not None: | ||||||
|  |             if self.function != 'output': | ||||||
|  |                 raise PinPWMFixedValue('cannot start PWM on pin %r' % self) | ||||||
|  |             # NOTE: the pin's state *must* be set to zero; if it's currently | ||||||
|  |             # high, starting PWM and setting a 0 duty-cycle *doesn't* bring | ||||||
|  |             # the pin low; it stays high! | ||||||
|  |             self.factory.connection.write(self.number, 0) | ||||||
|             self.factory.connection.set_PWM_frequency(self.number, value) |             self.factory.connection.set_PWM_frequency(self.number, value) | ||||||
|             self.factory.connection.set_PWM_range(self.number, 10000) |             self.factory.connection.set_PWM_range(self.number, 10000) | ||||||
|             self.factory.connection.set_PWM_dutycycle(self.number, 0) |             self.factory.connection.set_PWM_dutycycle(self.number, 0) | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								setup.py
									
									
									
									
									
								
							| @@ -77,7 +77,6 @@ __entry_points__ = { | |||||||
|     'gpiozero_mock_pin_classes': [ |     'gpiozero_mock_pin_classes': [ | ||||||
|         'mockpin          = gpiozero.pins.mock:MockPin', |         'mockpin          = gpiozero.pins.mock:MockPin', | ||||||
|         'mockpwmpin       = gpiozero.pins.mock:MockPWMPin', |         'mockpwmpin       = gpiozero.pins.mock:MockPWMPin', | ||||||
|         'mockpulleduppin  = gpiozero.pins.mock:MockPulledUpPin', |  | ||||||
|         'mockchargingpin  = gpiozero.pins.mock:MockChargingPin', |         'mockchargingpin  = gpiozero.pins.mock:MockChargingPin', | ||||||
|         'mocktriggerpin   = gpiozero.pins.mock:MockTriggerPin', |         'mocktriggerpin   = gpiozero.pins.mock:MockTriggerPin', | ||||||
|     ], |     ], | ||||||
|   | |||||||
| @@ -246,10 +246,15 @@ def test_led_board_bad_blink(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_led_board_blink_background(): | def test_led_board_blink_background(): | ||||||
|     pin1 = Device._pin_factory.pin(2) |     pin1 = Device._pin_factory.pin(4) | ||||||
|     pin2 = Device._pin_factory.pin(3) |     pin2 = Device._pin_factory.pin(5) | ||||||
|     pin3 = Device._pin_factory.pin(4) |     pin3 = Device._pin_factory.pin(6) | ||||||
|     with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board: |     with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board: | ||||||
|  |         # Instantiation takes a long enough time that it throws off our timing | ||||||
|  |         # here! | ||||||
|  |         pin1.clear_states() | ||||||
|  |         pin2.clear_states() | ||||||
|  |         pin3.clear_states() | ||||||
|         board.blink(0.1, 0.1, n=2) |         board.blink(0.1, 0.1, n=2) | ||||||
|         board._blink_thread.join() # naughty, but ensures no arbitrary waits in the test |         board._blink_thread.join() # naughty, but ensures no arbitrary waits in the test | ||||||
|         test = [ |         test = [ | ||||||
| @@ -266,10 +271,13 @@ def test_led_board_blink_background(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_led_board_blink_foreground(): | def test_led_board_blink_foreground(): | ||||||
|     pin1 = Device._pin_factory.pin(2) |     pin1 = Device._pin_factory.pin(4) | ||||||
|     pin2 = Device._pin_factory.pin(3) |     pin2 = Device._pin_factory.pin(5) | ||||||
|     pin3 = Device._pin_factory.pin(4) |     pin3 = Device._pin_factory.pin(6) | ||||||
|     with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board: |     with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board: | ||||||
|  |         pin1.clear_states() | ||||||
|  |         pin2.clear_states() | ||||||
|  |         pin3.clear_states() | ||||||
|         board.blink(0.1, 0.1, n=2, background=False) |         board.blink(0.1, 0.1, n=2, background=False) | ||||||
|         test = [ |         test = [ | ||||||
|             (0.0, False), |             (0.0, False), | ||||||
| @@ -285,10 +293,13 @@ def test_led_board_blink_foreground(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_led_board_blink_control(): | def test_led_board_blink_control(): | ||||||
|     pin1 = Device._pin_factory.pin(2) |     pin1 = Device._pin_factory.pin(4) | ||||||
|     pin2 = Device._pin_factory.pin(3) |     pin2 = Device._pin_factory.pin(5) | ||||||
|     pin3 = Device._pin_factory.pin(4) |     pin3 = Device._pin_factory.pin(6) | ||||||
|     with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board: |     with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board: | ||||||
|  |         pin1.clear_states() | ||||||
|  |         pin2.clear_states() | ||||||
|  |         pin3.clear_states() | ||||||
|         board.blink(0.1, 0.1, n=2) |         board.blink(0.1, 0.1, n=2) | ||||||
|         # make sure the blink thread's started |         # make sure the blink thread's started | ||||||
|         while not board._blink_leds: |         while not board._blink_leds: | ||||||
| @@ -310,10 +321,13 @@ def test_led_board_blink_control(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_led_board_blink_take_over(): | def test_led_board_blink_take_over(): | ||||||
|     pin1 = Device._pin_factory.pin(2) |     pin1 = Device._pin_factory.pin(4) | ||||||
|     pin2 = Device._pin_factory.pin(3) |     pin2 = Device._pin_factory.pin(5) | ||||||
|     pin3 = Device._pin_factory.pin(4) |     pin3 = Device._pin_factory.pin(6) | ||||||
|     with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board: |     with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board: | ||||||
|  |         pin1.clear_states() | ||||||
|  |         pin2.clear_states() | ||||||
|  |         pin3.clear_states() | ||||||
|         board[1].blink(0.1, 0.1, n=2) |         board[1].blink(0.1, 0.1, n=2) | ||||||
|         board.blink(0.1, 0.1, n=2) # immediately take over blinking |         board.blink(0.1, 0.1, n=2) # immediately take over blinking | ||||||
|         board[1]._blink_thread.join() |         board[1]._blink_thread.join() | ||||||
| @@ -332,10 +346,13 @@ def test_led_board_blink_take_over(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_led_board_blink_control_all(): | def test_led_board_blink_control_all(): | ||||||
|     pin1 = Device._pin_factory.pin(2) |     pin1 = Device._pin_factory.pin(4) | ||||||
|     pin2 = Device._pin_factory.pin(3) |     pin2 = Device._pin_factory.pin(5) | ||||||
|     pin3 = Device._pin_factory.pin(4) |     pin3 = Device._pin_factory.pin(6) | ||||||
|     with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board: |     with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board: | ||||||
|  |         pin1.clear_states() | ||||||
|  |         pin2.clear_states() | ||||||
|  |         pin3.clear_states() | ||||||
|         board.blink(0.1, 0.1, n=2) |         board.blink(0.1, 0.1, n=2) | ||||||
|         # make sure the blink thread's started |         # make sure the blink thread's started | ||||||
|         while not board._blink_leds: |         while not board._blink_leds: | ||||||
| @@ -354,9 +371,9 @@ def test_led_board_blink_control_all(): | |||||||
|         pin3.assert_states_and_times(test) |         pin3.assert_states_and_times(test) | ||||||
|  |  | ||||||
| def test_led_board_blink_interrupt_on(): | def test_led_board_blink_interrupt_on(): | ||||||
|     pin1 = Device._pin_factory.pin(2) |     pin1 = Device._pin_factory.pin(4) | ||||||
|     pin2 = Device._pin_factory.pin(3) |     pin2 = Device._pin_factory.pin(5) | ||||||
|     pin3 = Device._pin_factory.pin(4) |     pin3 = Device._pin_factory.pin(6) | ||||||
|     with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board: |     with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board: | ||||||
|         board.blink(1, 0.1) |         board.blink(1, 0.1) | ||||||
|         sleep(0.2) |         sleep(0.2) | ||||||
| @@ -366,10 +383,13 @@ def test_led_board_blink_interrupt_on(): | |||||||
|         pin3.assert_states([False, True, False]) |         pin3.assert_states([False, True, False]) | ||||||
|  |  | ||||||
| def test_led_board_blink_interrupt_off(): | def test_led_board_blink_interrupt_off(): | ||||||
|     pin1 = Device._pin_factory.pin(2) |     pin1 = Device._pin_factory.pin(4) | ||||||
|     pin2 = Device._pin_factory.pin(3) |     pin2 = Device._pin_factory.pin(5) | ||||||
|     pin3 = Device._pin_factory.pin(4) |     pin3 = Device._pin_factory.pin(6) | ||||||
|     with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board: |     with LEDBoard(pin1, LEDBoard(pin2, pin3)) as board: | ||||||
|  |         pin1.clear_states() | ||||||
|  |         pin2.clear_states() | ||||||
|  |         pin3.clear_states() | ||||||
|         board.blink(0.1, 1) |         board.blink(0.1, 1) | ||||||
|         sleep(0.2) |         sleep(0.2) | ||||||
|         board.off() # should interrupt while off |         board.off() # should interrupt while off | ||||||
| @@ -380,10 +400,13 @@ def test_led_board_blink_interrupt_off(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_led_board_fade_background(): | def test_led_board_fade_background(): | ||||||
|     pin1 = Device._pin_factory.pin(2) |     pin1 = Device._pin_factory.pin(4) | ||||||
|     pin2 = Device._pin_factory.pin(3) |     pin2 = Device._pin_factory.pin(5) | ||||||
|     pin3 = Device._pin_factory.pin(4) |     pin3 = Device._pin_factory.pin(6) | ||||||
|     with LEDBoard(pin1, LEDBoard(pin2, pin3, pwm=True), pwm=True) as board: |     with LEDBoard(pin1, LEDBoard(pin2, pin3, pwm=True), pwm=True) as board: | ||||||
|  |         pin1.clear_states() | ||||||
|  |         pin2.clear_states() | ||||||
|  |         pin3.clear_states() | ||||||
|         board.blink(0, 0, 0.2, 0.2, n=2) |         board.blink(0, 0, 0.2, 0.2, n=2) | ||||||
|         board._blink_thread.join() |         board._blink_thread.join() | ||||||
|         test = [ |         test = [ | ||||||
|   | |||||||
| @@ -65,7 +65,7 @@ def test_device_reopen_same_pin(): | |||||||
|         assert device.pin is None |         assert device.pin is None | ||||||
|  |  | ||||||
| def test_device_repr(): | def test_device_repr(): | ||||||
|     with GPIODevice(2) as device: |     with GPIODevice(4) as device: | ||||||
|         assert repr(device) == '<gpiozero.GPIODevice object on pin %s, is_active=False>' % device.pin |         assert repr(device) == '<gpiozero.GPIODevice object on pin %s, is_active=False>' % device.pin | ||||||
|  |  | ||||||
| def test_device_repr_after_close(): | def test_device_repr_after_close(): | ||||||
| @@ -85,18 +85,18 @@ def test_device_context_manager(): | |||||||
|  |  | ||||||
| def test_composite_device_sequence(): | def test_composite_device_sequence(): | ||||||
|     with CompositeDevice( |     with CompositeDevice( | ||||||
|             InputDevice(2), |             InputDevice(4), | ||||||
|             InputDevice(3) |             InputDevice(5) | ||||||
|             ) as device: |             ) as device: | ||||||
|         assert len(device) == 2 |         assert len(device) == 2 | ||||||
|         assert device[0].pin.number == 2 |         assert device[0].pin.number == 4 | ||||||
|         assert device[1].pin.number == 3 |         assert device[1].pin.number == 5 | ||||||
|         assert device.namedtuple._fields == ('_0', '_1') |         assert device.namedtuple._fields == ('_0', '_1') | ||||||
|  |  | ||||||
| def test_composite_device_values(): | def test_composite_device_values(): | ||||||
|     with CompositeDevice( |     with CompositeDevice( | ||||||
|             InputDevice(2), |             InputDevice(4), | ||||||
|             InputDevice(3) |             InputDevice(5) | ||||||
|             ) as device: |             ) as device: | ||||||
|         assert device.value == (0, 0) |         assert device.value == (0, 0) | ||||||
|         assert not device.is_active |         assert not device.is_active | ||||||
| @@ -106,8 +106,8 @@ def test_composite_device_values(): | |||||||
|  |  | ||||||
| def test_composite_device_named(): | def test_composite_device_named(): | ||||||
|     with CompositeDevice( |     with CompositeDevice( | ||||||
|             foo=InputDevice(2), |             foo=InputDevice(4), | ||||||
|             bar=InputDevice(3), |             bar=InputDevice(5), | ||||||
|             _order=('foo', 'bar') |             _order=('foo', 'bar') | ||||||
|             ) as device: |             ) as device: | ||||||
|         assert device.namedtuple._fields == ('foo', 'bar') |         assert device.namedtuple._fields == ('foo', 'bar') | ||||||
| @@ -126,8 +126,8 @@ def test_composite_device_bad_init(): | |||||||
|  |  | ||||||
| def test_composite_device_read_only(): | def test_composite_device_read_only(): | ||||||
|     with CompositeDevice( |     with CompositeDevice( | ||||||
|         foo=InputDevice(2), |         foo=InputDevice(4), | ||||||
|         bar=InputDevice(3) |         bar=InputDevice(5) | ||||||
|         ) as device: |         ) as device: | ||||||
|         with pytest.raises(AttributeError): |         with pytest.raises(AttributeError): | ||||||
|             device.foo = 1 |             device.foo = 1 | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ import pytest | |||||||
| from threading import Event | from threading import Event | ||||||
| from functools import partial | from functools import partial | ||||||
|  |  | ||||||
| from gpiozero.pins.mock import MockPulledUpPin, MockChargingPin, MockTriggerPin | from gpiozero.pins.mock import MockChargingPin, MockTriggerPin | ||||||
| from gpiozero import * | from gpiozero import * | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -22,7 +22,7 @@ def teardown_function(function): | |||||||
|  |  | ||||||
|  |  | ||||||
| def test_input_initial_values(): | def test_input_initial_values(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     with InputDevice(pin, pull_up=True) as device: |     with InputDevice(pin, pull_up=True) as device: | ||||||
|         assert pin.function == 'input' |         assert pin.function == 'input' | ||||||
|         assert pin.pull == 'up' |         assert pin.pull == 'up' | ||||||
| @@ -42,23 +42,23 @@ def test_input_is_active_low(): | |||||||
|         assert repr(device) == '<gpiozero.InputDevice object on pin GPIO2, pull_up=True, is_active=True>' |         assert repr(device) == '<gpiozero.InputDevice object on pin GPIO2, pull_up=True, is_active=True>' | ||||||
|  |  | ||||||
| def test_input_is_active_high(): | def test_input_is_active_high(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     with InputDevice(pin, pull_up=False) as device: |     with InputDevice(pin, pull_up=False) as device: | ||||||
|         pin.drive_high() |         pin.drive_high() | ||||||
|         assert device.is_active |         assert device.is_active | ||||||
|         assert repr(device) == '<gpiozero.InputDevice object on pin GPIO2, pull_up=False, is_active=True>' |         assert repr(device) == '<gpiozero.InputDevice object on pin GPIO4, pull_up=False, is_active=True>' | ||||||
|         pin.drive_low() |         pin.drive_low() | ||||||
|         assert not device.is_active |         assert not device.is_active | ||||||
|         assert repr(device) == '<gpiozero.InputDevice object on pin GPIO2, pull_up=False, is_active=False>' |         assert repr(device) == '<gpiozero.InputDevice object on pin GPIO4, pull_up=False, is_active=False>' | ||||||
|  |  | ||||||
| def test_input_pulled_up(): | def test_input_pulled_up(): | ||||||
|     pin = Device._pin_factory.pin(2, pin_class=MockPulledUpPin) |     pin = Device._pin_factory.pin(2) | ||||||
|     with pytest.raises(PinFixedPull): |     with pytest.raises(PinFixedPull): | ||||||
|         InputDevice(pin, pull_up=False) |         InputDevice(pin, pull_up=False) | ||||||
|  |  | ||||||
| def test_input_event_activated(): | def test_input_event_activated(): | ||||||
|     event = Event() |     event = Event() | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     with DigitalInputDevice(pin) as device: |     with DigitalInputDevice(pin) as device: | ||||||
|         device.when_activated = lambda: event.set() |         device.when_activated = lambda: event.set() | ||||||
|         assert not event.is_set() |         assert not event.is_set() | ||||||
| @@ -67,7 +67,7 @@ def test_input_event_activated(): | |||||||
|  |  | ||||||
| def test_input_event_deactivated(): | def test_input_event_deactivated(): | ||||||
|     event = Event() |     event = Event() | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     with DigitalInputDevice(pin) as device: |     with DigitalInputDevice(pin) as device: | ||||||
|         device.when_deactivated = lambda: event.set() |         device.when_deactivated = lambda: event.set() | ||||||
|         assert not event.is_set() |         assert not event.is_set() | ||||||
| @@ -78,7 +78,7 @@ def test_input_event_deactivated(): | |||||||
|  |  | ||||||
| def test_input_partial_callback(): | def test_input_partial_callback(): | ||||||
|     event = Event() |     event = Event() | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     def foo(a, b): |     def foo(a, b): | ||||||
|         event.set() |         event.set() | ||||||
|         return a + b |         return a + b | ||||||
| @@ -91,22 +91,22 @@ def test_input_partial_callback(): | |||||||
|         assert event.is_set() |         assert event.is_set() | ||||||
|  |  | ||||||
| def test_input_wait_active(): | def test_input_wait_active(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     with DigitalInputDevice(pin) as device: |     with DigitalInputDevice(pin) as device: | ||||||
|         pin.drive_high() |         pin.drive_high() | ||||||
|         assert device.wait_for_active(1) |         assert device.wait_for_active(1) | ||||||
|         assert not device.wait_for_inactive(0) |         assert not device.wait_for_inactive(0) | ||||||
|  |  | ||||||
| def test_input_wait_inactive(): | def test_input_wait_inactive(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     with DigitalInputDevice(pin) as device: |     with DigitalInputDevice(pin) as device: | ||||||
|         assert device.wait_for_inactive(1) |         assert device.wait_for_inactive(1) | ||||||
|         assert not device.wait_for_active(0) |         assert not device.wait_for_active(0) | ||||||
|  |  | ||||||
| def test_input_smoothed_attrib(): | def test_input_smoothed_attrib(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     with SmoothedInputDevice(pin, threshold=0.5, queue_len=5, partial=False) as device: |     with SmoothedInputDevice(pin, threshold=0.5, queue_len=5, partial=False) as device: | ||||||
|         assert repr(device) == '<gpiozero.SmoothedInputDevice object on pin GPIO2, pull_up=False>' |         assert repr(device) == '<gpiozero.SmoothedInputDevice object on pin GPIO4, pull_up=False>' | ||||||
|         assert device.threshold == 0.5 |         assert device.threshold == 0.5 | ||||||
|         assert device.queue_len == 5 |         assert device.queue_len == 5 | ||||||
|         assert not device.partial |         assert not device.partial | ||||||
| @@ -116,7 +116,7 @@ def test_input_smoothed_attrib(): | |||||||
|             device.threshold = 1 |             device.threshold = 1 | ||||||
|  |  | ||||||
| def test_input_smoothed_values(): | def test_input_smoothed_values(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     with SmoothedInputDevice(pin) as device: |     with SmoothedInputDevice(pin) as device: | ||||||
|         device._queue.start() |         device._queue.start() | ||||||
|         assert not device.is_active |         assert not device.is_active | ||||||
| @@ -138,7 +138,7 @@ def test_input_button(): | |||||||
|         assert button.wait_for_release(1) |         assert button.wait_for_release(1) | ||||||
|  |  | ||||||
| def test_input_line_sensor(): | def test_input_line_sensor(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     with LineSensor(pin) as sensor: |     with LineSensor(pin) as sensor: | ||||||
|         pin.drive_low() # logic is inverted for line sensor |         pin.drive_low() # logic is inverted for line sensor | ||||||
|         assert sensor.wait_for_line(1) |         assert sensor.wait_for_line(1) | ||||||
| @@ -148,7 +148,7 @@ def test_input_line_sensor(): | |||||||
|         assert not sensor.line_detected |         assert not sensor.line_detected | ||||||
|  |  | ||||||
| def test_input_motion_sensor(): | def test_input_motion_sensor(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     with MotionSensor(pin) as sensor: |     with MotionSensor(pin) as sensor: | ||||||
|         pin.drive_high() |         pin.drive_high() | ||||||
|         assert sensor.wait_for_motion(1) |         assert sensor.wait_for_motion(1) | ||||||
| @@ -160,7 +160,7 @@ def test_input_motion_sensor(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_input_light_sensor(): | def test_input_light_sensor(): | ||||||
|     pin = Device._pin_factory.pin(2, pin_class=MockChargingPin) |     pin = Device._pin_factory.pin(4, pin_class=MockChargingPin) | ||||||
|     with LightSensor(pin) as sensor: |     with LightSensor(pin) as sensor: | ||||||
|         pin.charge_time = 0.1 |         pin.charge_time = 0.1 | ||||||
|         assert sensor.wait_for_dark(1) |         assert sensor.wait_for_dark(1) | ||||||
| @@ -170,8 +170,8 @@ def test_input_light_sensor(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_input_distance_sensor(): | def test_input_distance_sensor(): | ||||||
|     echo_pin = Device._pin_factory.pin(2) |     echo_pin = Device._pin_factory.pin(4) | ||||||
|     trig_pin = Device._pin_factory.pin(3, pin_class=MockTriggerPin) |     trig_pin = Device._pin_factory.pin(5, pin_class=MockTriggerPin) | ||||||
|     trig_pin.echo_pin = echo_pin |     trig_pin.echo_pin = echo_pin | ||||||
|     trig_pin.echo_time = 0.02 |     trig_pin.echo_time = 0.02 | ||||||
|     with pytest.raises(ValueError): |     with pytest.raises(ValueError): | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ def test_mock_pin_init(): | |||||||
|     assert Device._pin_factory.pin(2).number == 2 |     assert Device._pin_factory.pin(2).number == 2 | ||||||
|  |  | ||||||
| def test_mock_pin_defaults(): | def test_mock_pin_defaults(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     assert pin.bounce == None |     assert pin.bounce == None | ||||||
|     assert pin.edges == 'both' |     assert pin.edges == 'both' | ||||||
|     assert pin.frequency == None |     assert pin.frequency == None | ||||||
| @@ -36,6 +36,9 @@ def test_mock_pin_defaults(): | |||||||
|     assert pin.pull == 'floating' |     assert pin.pull == 'floating' | ||||||
|     assert pin.state == 0 |     assert pin.state == 0 | ||||||
|     assert pin.when_changed == None |     assert pin.when_changed == None | ||||||
|  |     pin.close() | ||||||
|  |     pin = Device._pin_factory.pin(2) | ||||||
|  |     assert pin.pull == 'up' | ||||||
|  |  | ||||||
| def test_mock_pin_open_close(): | def test_mock_pin_open_close(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(2) | ||||||
| @@ -54,7 +57,7 @@ def test_mock_pin_init_twice_different_pin(): | |||||||
|     assert pin2.number == pin1.number+1 |     assert pin2.number == pin1.number+1 | ||||||
|  |  | ||||||
| def test_mock_pwm_pin_defaults(): | def test_mock_pwm_pin_defaults(): | ||||||
|     pin = Device._pin_factory.pin(2, pin_class=MockPWMPin) |     pin = Device._pin_factory.pin(4, pin_class=MockPWMPin) | ||||||
|     assert pin.bounce == None |     assert pin.bounce == None | ||||||
|     assert pin.edges == 'both' |     assert pin.edges == 'both' | ||||||
|     assert pin.frequency == None |     assert pin.frequency == None | ||||||
| @@ -62,6 +65,9 @@ def test_mock_pwm_pin_defaults(): | |||||||
|     assert pin.pull == 'floating' |     assert pin.pull == 'floating' | ||||||
|     assert pin.state == 0 |     assert pin.state == 0 | ||||||
|     assert pin.when_changed == None |     assert pin.when_changed == None | ||||||
|  |     pin.close() | ||||||
|  |     pin = Device._pin_factory.pin(2, pin_class=MockPWMPin) | ||||||
|  |     assert pin.pull == 'up' | ||||||
|  |  | ||||||
| def test_mock_pwm_pin_open_close(): | def test_mock_pwm_pin_open_close(): | ||||||
|     pin = Device._pin_factory.pin(2, pin_class=MockPWMPin) |     pin = Device._pin_factory.pin(2, pin_class=MockPWMPin) | ||||||
| @@ -104,20 +110,25 @@ def test_mock_pin_frequency_supported(): | |||||||
|     assert not pin.state |     assert not pin.state | ||||||
|  |  | ||||||
| def test_mock_pin_pull(): | def test_mock_pin_pull(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     pin.function = 'input' |     pin.function = 'input' | ||||||
|     assert pin.pull == 'floating' |     assert pin.pull == 'floating' | ||||||
|     pin.pull = 'up' |     pin.pull = 'up' | ||||||
|     assert pin.state |     assert pin.state | ||||||
|     pin.pull = 'down' |     pin.pull = 'down' | ||||||
|     assert not pin.state |     assert not pin.state | ||||||
|  |     pin.close() | ||||||
|  |     pin = Device._pin_factory.pin(2) | ||||||
|  |     pin.function = 'input' | ||||||
|  |     assert pin.pull == 'up' | ||||||
|  |     with pytest.raises(PinFixedPull): | ||||||
|  |         pin.pull = 'floating' | ||||||
|  |  | ||||||
| def test_mock_pin_state(): | def test_mock_pin_state(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(2) | ||||||
|     with pytest.raises(PinSetInput): |     with pytest.raises(PinSetInput): | ||||||
|         pin.state = 1 |         pin.state = 1 | ||||||
|     pin.function = 'output' |     pin.function = 'output' | ||||||
|     assert pin.state == 0 |  | ||||||
|     pin.state = 1 |     pin.state = 1 | ||||||
|     assert pin.state == 1 |     assert pin.state == 1 | ||||||
|     pin.state = 0 |     pin.state = 0 | ||||||
| @@ -130,7 +141,6 @@ def test_mock_pwm_pin_state(): | |||||||
|     with pytest.raises(PinSetInput): |     with pytest.raises(PinSetInput): | ||||||
|         pin.state = 1 |         pin.state = 1 | ||||||
|     pin.function = 'output' |     pin.function = 'output' | ||||||
|     assert pin.state == 0 |  | ||||||
|     pin.state = 1 |     pin.state = 1 | ||||||
|     assert pin.state == 1 |     assert pin.state == 1 | ||||||
|     pin.state = 0 |     pin.state = 0 | ||||||
|   | |||||||
| @@ -95,7 +95,7 @@ def test_output_digital_toggle(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_output_blink_background(): | def test_output_blink_background(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     with DigitalOutputDevice(pin) as device: |     with DigitalOutputDevice(pin) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.blink(0.1, 0.1, n=2) |         device.blink(0.1, 0.1, n=2) | ||||||
| @@ -113,7 +113,7 @@ def test_output_blink_background(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_output_blink_foreground(): | def test_output_blink_foreground(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     with DigitalOutputDevice(pin) as device: |     with DigitalOutputDevice(pin) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.blink(0.1, 0.1, n=2, background=False) |         device.blink(0.1, 0.1, n=2, background=False) | ||||||
| @@ -127,7 +127,7 @@ def test_output_blink_foreground(): | |||||||
|             ]) |             ]) | ||||||
|  |  | ||||||
| def test_output_blink_interrupt_on(): | def test_output_blink_interrupt_on(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     with DigitalOutputDevice(pin) as device: |     with DigitalOutputDevice(pin) as device: | ||||||
|         device.blink(1, 0.1) |         device.blink(1, 0.1) | ||||||
|         sleep(0.2) |         sleep(0.2) | ||||||
| @@ -135,7 +135,7 @@ def test_output_blink_interrupt_on(): | |||||||
|         pin.assert_states([False, True, False]) |         pin.assert_states([False, True, False]) | ||||||
|  |  | ||||||
| def test_output_blink_interrupt_off(): | def test_output_blink_interrupt_off(): | ||||||
|     pin = Device._pin_factory.pin(2) |     pin = Device._pin_factory.pin(4) | ||||||
|     with DigitalOutputDevice(pin) as device: |     with DigitalOutputDevice(pin) as device: | ||||||
|         device.blink(0.1, 1) |         device.blink(0.1, 1) | ||||||
|         sleep(0.2) |         sleep(0.2) | ||||||
| @@ -151,7 +151,7 @@ def test_output_pwm_not_supported(): | |||||||
|         PWMOutputDevice(Device._pin_factory.pin(2)) |         PWMOutputDevice(Device._pin_factory.pin(2)) | ||||||
|  |  | ||||||
| def test_output_pwm_states(): | def test_output_pwm_states(): | ||||||
|     pin = Device._pin_factory.pin(2, pin_class=MockPWMPin) |     pin = Device._pin_factory.pin(4, pin_class=MockPWMPin) | ||||||
|     with PWMOutputDevice(pin) as device: |     with PWMOutputDevice(pin) as device: | ||||||
|         device.value = 0.1 |         device.value = 0.1 | ||||||
|         device.value = 0.2 |         device.value = 0.2 | ||||||
| @@ -172,14 +172,14 @@ def test_output_pwm_read(): | |||||||
|         assert device.frequency is None |         assert device.frequency is None | ||||||
|  |  | ||||||
| def test_output_pwm_write(): | def test_output_pwm_write(): | ||||||
|     pin = Device._pin_factory.pin(2, pin_class=MockPWMPin) |     pin = Device._pin_factory.pin(4, pin_class=MockPWMPin) | ||||||
|     with PWMOutputDevice(pin) as device: |     with PWMOutputDevice(pin) as device: | ||||||
|         device.on() |         device.on() | ||||||
|         device.off() |         device.off() | ||||||
|         pin.assert_states([False, True, False]) |         pin.assert_states([False, True, False]) | ||||||
|  |  | ||||||
| def test_output_pwm_toggle(): | def test_output_pwm_toggle(): | ||||||
|     pin = Device._pin_factory.pin(2, pin_class=MockPWMPin) |     pin = Device._pin_factory.pin(4, pin_class=MockPWMPin) | ||||||
|     with PWMOutputDevice(pin) as device: |     with PWMOutputDevice(pin) as device: | ||||||
|         device.toggle() |         device.toggle() | ||||||
|         device.value = 0.5 |         device.value = 0.5 | ||||||
| @@ -218,7 +218,7 @@ def test_output_pwm_write_silly(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_output_pwm_blink_background(): | def test_output_pwm_blink_background(): | ||||||
|     pin = Device._pin_factory.pin(2, pin_class=MockPWMPin) |     pin = Device._pin_factory.pin(4, pin_class=MockPWMPin) | ||||||
|     with PWMOutputDevice(pin) as device: |     with PWMOutputDevice(pin) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.blink(0.1, 0.1, n=2) |         device.blink(0.1, 0.1, n=2) | ||||||
| @@ -236,7 +236,7 @@ def test_output_pwm_blink_background(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_output_pwm_blink_foreground(): | def test_output_pwm_blink_foreground(): | ||||||
|     pin = Device._pin_factory.pin(2, pin_class=MockPWMPin) |     pin = Device._pin_factory.pin(4, pin_class=MockPWMPin) | ||||||
|     with PWMOutputDevice(pin) as device: |     with PWMOutputDevice(pin) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.blink(0.1, 0.1, n=2, background=False) |         device.blink(0.1, 0.1, n=2, background=False) | ||||||
| @@ -252,7 +252,7 @@ def test_output_pwm_blink_foreground(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_output_pwm_fade_background(): | def test_output_pwm_fade_background(): | ||||||
|     pin = Device._pin_factory.pin(2, pin_class=MockPWMPin) |     pin = Device._pin_factory.pin(4, pin_class=MockPWMPin) | ||||||
|     with PWMOutputDevice(pin) as device: |     with PWMOutputDevice(pin) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.blink(0, 0, 0.2, 0.2, n=2) |         device.blink(0, 0, 0.2, 0.2, n=2) | ||||||
| @@ -286,7 +286,7 @@ def test_output_pwm_fade_background(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_output_pwm_fade_foreground(): | def test_output_pwm_fade_foreground(): | ||||||
|     pin = Device._pin_factory.pin(2, pin_class=MockPWMPin) |     pin = Device._pin_factory.pin(4, pin_class=MockPWMPin) | ||||||
|     with PWMOutputDevice(pin) as device: |     with PWMOutputDevice(pin) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.blink(0, 0, 0.2, 0.2, n=2, background=False) |         device.blink(0, 0, 0.2, 0.2, n=2, background=False) | ||||||
| @@ -318,7 +318,7 @@ def test_output_pwm_fade_foreground(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_output_pwm_pulse_background(): | def test_output_pwm_pulse_background(): | ||||||
|     pin = Device._pin_factory.pin(2, pin_class=MockPWMPin) |     pin = Device._pin_factory.pin(4, pin_class=MockPWMPin) | ||||||
|     with PWMOutputDevice(pin) as device: |     with PWMOutputDevice(pin) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.pulse(0.2, 0.2, n=2) |         device.pulse(0.2, 0.2, n=2) | ||||||
| @@ -352,7 +352,7 @@ def test_output_pwm_pulse_background(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_output_pwm_pulse_foreground(): | def test_output_pwm_pulse_foreground(): | ||||||
|     pin = Device._pin_factory.pin(2, pin_class=MockPWMPin) |     pin = Device._pin_factory.pin(4, pin_class=MockPWMPin) | ||||||
|     with PWMOutputDevice(pin) as device: |     with PWMOutputDevice(pin) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.pulse(0.2, 0.2, n=2, background=False) |         device.pulse(0.2, 0.2, n=2, background=False) | ||||||
| @@ -382,7 +382,7 @@ def test_output_pwm_pulse_foreground(): | |||||||
|             ]) |             ]) | ||||||
|  |  | ||||||
| def test_output_pwm_blink_interrupt(): | def test_output_pwm_blink_interrupt(): | ||||||
|     pin = Device._pin_factory.pin(2, pin_class=MockPWMPin) |     pin = Device._pin_factory.pin(4, pin_class=MockPWMPin) | ||||||
|     with PWMOutputDevice(pin) as device: |     with PWMOutputDevice(pin) as device: | ||||||
|         device.blink(1, 0.1) |         device.blink(1, 0.1) | ||||||
|         sleep(0.2) |         sleep(0.2) | ||||||
| @@ -515,7 +515,7 @@ def test_rgbled_blink_nonpwm(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_rgbled_blink_background(): | def test_rgbled_blink_background(): | ||||||
|     r, g, b = (Device._pin_factory.pin(i, pin_class=MockPWMPin) for i in (1, 2, 3)) |     r, g, b = (Device._pin_factory.pin(i, pin_class=MockPWMPin) for i in (4, 5, 6)) | ||||||
|     with RGBLED(r, g, b) as device: |     with RGBLED(r, g, b) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.blink(0.1, 0.1, n=2) |         device.blink(0.1, 0.1, n=2) | ||||||
| @@ -536,7 +536,7 @@ def test_rgbled_blink_background(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_rgbled_blink_background_nonpwm(): | def test_rgbled_blink_background_nonpwm(): | ||||||
|     r, g, b = (Device._pin_factory.pin(i) for i in (1, 2, 3)) |     r, g, b = (Device._pin_factory.pin(i) for i in (4, 5, 6)) | ||||||
|     with RGBLED(r, g, b, pwm=False) as device: |     with RGBLED(r, g, b, pwm=False) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.blink(0.1, 0.1, n=2) |         device.blink(0.1, 0.1, n=2) | ||||||
| @@ -557,7 +557,7 @@ def test_rgbled_blink_background_nonpwm(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_rgbled_blink_foreground(): | def test_rgbled_blink_foreground(): | ||||||
|     r, g, b = (Device._pin_factory.pin(i, pin_class=MockPWMPin) for i in (1, 2, 3)) |     r, g, b = (Device._pin_factory.pin(i, pin_class=MockPWMPin) for i in (4, 5, 6)) | ||||||
|     with RGBLED(r, g, b) as device: |     with RGBLED(r, g, b) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.blink(0.1, 0.1, n=2, background=False) |         device.blink(0.1, 0.1, n=2, background=False) | ||||||
| @@ -576,7 +576,7 @@ def test_rgbled_blink_foreground(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_rgbled_blink_foreground_nonpwm(): | def test_rgbled_blink_foreground_nonpwm(): | ||||||
|     r, g, b = (Device._pin_factory.pin(i) for i in (1, 2, 3)) |     r, g, b = (Device._pin_factory.pin(i) for i in (4, 5, 6)) | ||||||
|     with RGBLED(r, g, b, pwm=False) as device: |     with RGBLED(r, g, b, pwm=False) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.blink(0.1, 0.1, n=2, background=False) |         device.blink(0.1, 0.1, n=2, background=False) | ||||||
| @@ -595,7 +595,7 @@ def test_rgbled_blink_foreground_nonpwm(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_rgbled_fade_background(): | def test_rgbled_fade_background(): | ||||||
|     r, g, b = (Device._pin_factory.pin(i, pin_class=MockPWMPin) for i in (1, 2, 3)) |     r, g, b = (Device._pin_factory.pin(i, pin_class=MockPWMPin) for i in (4, 5, 6)) | ||||||
|     with RGBLED(r, g, b) as device: |     with RGBLED(r, g, b) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.blink(0, 0, 0.2, 0.2, n=2) |         device.blink(0, 0, 0.2, 0.2, n=2) | ||||||
| @@ -638,7 +638,7 @@ def test_rgbled_fade_background_nonpwm(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_rgbled_fade_foreground(): | def test_rgbled_fade_foreground(): | ||||||
|     r, g, b = (Device._pin_factory.pin(i, pin_class=MockPWMPin) for i in (1, 2, 3)) |     r, g, b = (Device._pin_factory.pin(i, pin_class=MockPWMPin) for i in (4, 5, 6)) | ||||||
|     with RGBLED(r, g, b) as device: |     with RGBLED(r, g, b) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.blink(0, 0, 0.2, 0.2, n=2, background=False) |         device.blink(0, 0, 0.2, 0.2, n=2, background=False) | ||||||
| @@ -679,7 +679,7 @@ def test_rgbled_fade_foreground_nonpwm(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_rgbled_pulse_background(): | def test_rgbled_pulse_background(): | ||||||
|     r, g, b = (Device._pin_factory.pin(i, pin_class=MockPWMPin) for i in (1, 2, 3)) |     r, g, b = (Device._pin_factory.pin(i, pin_class=MockPWMPin) for i in (4, 5, 6)) | ||||||
|     with RGBLED(r, g, b) as device: |     with RGBLED(r, g, b) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.pulse(0.2, 0.2, n=2) |         device.pulse(0.2, 0.2, n=2) | ||||||
| @@ -722,7 +722,7 @@ def test_rgbled_pulse_background_nonpwm(): | |||||||
| @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | @pytest.mark.skipif(hasattr(sys, 'pypy_version_info'), | ||||||
|                     reason='timing is too random on pypy') |                     reason='timing is too random on pypy') | ||||||
| def test_rgbled_pulse_foreground(): | def test_rgbled_pulse_foreground(): | ||||||
|     r, g, b = (Device._pin_factory.pin(i, pin_class=MockPWMPin) for i in (1, 2, 3)) |     r, g, b = (Device._pin_factory.pin(i, pin_class=MockPWMPin) for i in (4, 5, 6)) | ||||||
|     with RGBLED(r, g, b) as device: |     with RGBLED(r, g, b) as device: | ||||||
|         start = time() |         start = time() | ||||||
|         device.pulse(0.2, 0.2, n=2, background=False) |         device.pulse(0.2, 0.2, n=2, background=False) | ||||||
| @@ -761,7 +761,7 @@ def test_rgbled_pulse_foreground_nonpwm(): | |||||||
|             device.pulse(0.2, 0.2, n=2, background=False) |             device.pulse(0.2, 0.2, n=2, background=False) | ||||||
|  |  | ||||||
| def test_rgbled_blink_interrupt(): | def test_rgbled_blink_interrupt(): | ||||||
|     r, g, b = (Device._pin_factory.pin(i, pin_class=MockPWMPin) for i in (1, 2, 3)) |     r, g, b = (Device._pin_factory.pin(i, pin_class=MockPWMPin) for i in (4, 5, 6)) | ||||||
|     with RGBLED(r, g, b) as device: |     with RGBLED(r, g, b) as device: | ||||||
|         device.blink(1, 0.1) |         device.blink(1, 0.1) | ||||||
|         sleep(0.2) |         sleep(0.2) | ||||||
| @@ -771,7 +771,7 @@ def test_rgbled_blink_interrupt(): | |||||||
|         b.assert_states([0, 1, 0]) |         b.assert_states([0, 1, 0]) | ||||||
|  |  | ||||||
| def test_rgbled_blink_interrupt_nonpwm(): | def test_rgbled_blink_interrupt_nonpwm(): | ||||||
|     r, g, b = (Device._pin_factory.pin(i) for i in (1, 2, 3)) |     r, g, b = (Device._pin_factory.pin(i) for i in (4, 5, 6)) | ||||||
|     with RGBLED(r, g, b, pwm=False) as device: |     with RGBLED(r, g, b, pwm=False) as device: | ||||||
|         device.blink(1, 0.1) |         device.blink(1, 0.1) | ||||||
|         sleep(0.2) |         sleep(0.2) | ||||||
|   | |||||||
| @@ -11,20 +11,33 @@ except NameError: | |||||||
|     pass |     pass | ||||||
|  |  | ||||||
| import io | import io | ||||||
|  | import os | ||||||
| import subprocess | import subprocess | ||||||
|  | from time import sleep | ||||||
|  |  | ||||||
| import pytest | import pytest | ||||||
|  | import pkg_resources | ||||||
|  |  | ||||||
| from gpiozero import PinFixedPull, PinInvalidPull, PinInvalidFunction | from gpiozero import ( | ||||||
|  |     PinFixedPull, | ||||||
|  |     PinInvalidPull, | ||||||
|  |     PinInvalidFunction, | ||||||
|  |     PinPWMUnsupported, | ||||||
|  |     Device, | ||||||
|  |     ) | ||||||
|  | from gpiozero.pins.mock import MockConnectedPin, MockFactory | ||||||
| try: | try: | ||||||
|     from math import isclose |     from math import isclose | ||||||
| except ImportError: | except ImportError: | ||||||
|     from gpiozero.compat import isclose |     from gpiozero.compat import isclose | ||||||
|  |  | ||||||
|  |  | ||||||
| # This module assumes you've wired the following GPIO pins together | # This module assumes you've wired the following GPIO pins together. The pins | ||||||
| TEST_PIN = 22 | # can be re-configured via the listed environment variables (useful for when | ||||||
| INPUT_PIN = 27 | # your testing rig requires different pins because the defaults interfere with | ||||||
|  | # attached hardware). | ||||||
|  | TEST_PIN = int(os.getenv('GPIOZERO_TEST_PIN', '22')) | ||||||
|  | INPUT_PIN = int(os.getenv('GPIOZERO_INPUT_PIN', '27')) | ||||||
|  |  | ||||||
|  |  | ||||||
| # Skip the entire module if we're not on a Pi | # Skip the entire module if we're not on a Pi | ||||||
| @@ -40,51 +53,48 @@ pytestmark = pytest.mark.skipif(not is_a_pi(), reason='tests cannot run on non-P | |||||||
| del is_a_pi | del is_a_pi | ||||||
|  |  | ||||||
|  |  | ||||||
| # Try and import as many pin libraries as possible | @pytest.fixture( | ||||||
| PIN_CLASSES = [] |     scope='module', | ||||||
| try: |     params=('rpigpio',)) | ||||||
|     from gpiozero.pins.rpigpio import RPiGPIOPin |     #params=pkg_resources.get_distribution('gpiozero').get_entry_map('gpiozero_pin_factories').keys()) | ||||||
|     PIN_CLASSES.append(RPiGPIOPin) | def pin_factory(request): | ||||||
| except ImportError: |     # Constructs each pin factory in turn with some extra logic to ensure | ||||||
|     RPiGPIOPin = None |     # the pigpiod daemon gets started and stopped around the pigpio factory | ||||||
| try: |     if request.param == 'pigpio': | ||||||
|     from gpiozero.pins.rpio import RPIOPin |         try: | ||||||
|     PIN_CLASSES.append(RPIOPin) |             subprocess.check_call(['sudo', 'systemctl', 'start', 'pigpiod']) | ||||||
| except ImportError: |         except subprocess.CalledProcessError: | ||||||
|     RPIOPin = None |             pytest.skip("skipped factory pigpio: failed to start pigpiod") | ||||||
| try: |     try: | ||||||
|     from gpiozero.pins.pigpiod import PiGPIOPin |         factory = pkg_resources.load_entry_point('gpiozero', 'gpiozero_pin_factories', request.param)() | ||||||
|     PIN_CLASSES.append(PiGPIOPin) |     except Exception as e: | ||||||
| except ImportError: |         if request.param == 'pigpio': | ||||||
|     PiGPIOPin = None |             subprocess.check_call(['sudo', 'systemctl', 'stop', 'pigpiod']) | ||||||
| try: |         pytest.skip("skipped factory %s: %s" % (request.param, str(e))) | ||||||
|     from gpiozero.pins.native import NativePin |     else: | ||||||
|     PIN_CLASSES.append(NativePin) |         Device._set_pin_factory(factory) | ||||||
| except ImportError: |         def fin(): | ||||||
|     NativePin = None |             Device._set_pin_factory(MockFactory()) | ||||||
|  |             if request.param == 'pigpio': | ||||||
|  |                 subprocess.check_call(['sudo', 'systemctl', 'stop', 'pigpiod']) | ||||||
|  |         request.addfinalizer(fin) | ||||||
|  |         return factory | ||||||
|  |  | ||||||
| @pytest.fixture(scope='module', params=PIN_CLASSES) |  | ||||||
| def pin_class(request): |  | ||||||
|     # pigpiod needs to be running for PiGPIOPin |  | ||||||
|     if request.param.__name__ == 'PiGPIOPin': |  | ||||||
|         subprocess.check_call(['sudo', 'pigpiod']) |  | ||||||
|         # Unfortunately, pigpiod provides no option for running in the |  | ||||||
|         # foreground, so we have to use the sledgehammer of killall to get shot |  | ||||||
|         # of it |  | ||||||
|         def kill_pigpiod(): |  | ||||||
|             subprocess.check_call(['sudo', 'killall', 'pigpiod']) |  | ||||||
|         request.addfinalizer(kill_pigpiod) |  | ||||||
|     return request.param |  | ||||||
|  |  | ||||||
| @pytest.fixture(scope='function') | @pytest.fixture(scope='function') | ||||||
| def pins(request, pin_class): | def pins(request, pin_factory): | ||||||
|     # Why return both pins in a single fixture? If we defined one fixture for |     # Why return both pins in a single fixture? If we defined one fixture for | ||||||
|     # each pin then pytest will (correctly) test RPiGPIOPin(22) against |     # each pin then pytest will (correctly) test RPiGPIOPin(22) against | ||||||
|     # NativePin(27) and so on. This isn't supported, so we don't test it |     # NativePin(27) and so on. This isn't supported, so we don't test it | ||||||
|     test_pin = pin_class(TEST_PIN) |     if pin_factory.__class__.__name__ == 'MockFactory': | ||||||
|     input_pin = pin_class(INPUT_PIN) |         test_pin = pin_factory.pin(TEST_PIN, pin_class=MockConnectedPin) | ||||||
|  |     else: | ||||||
|  |         test_pin = pin_factory.pin(TEST_PIN) | ||||||
|  |     input_pin = pin_factory.pin(INPUT_PIN) | ||||||
|     input_pin.function = 'input' |     input_pin.function = 'input' | ||||||
|     input_pin.pull = 'down' |     input_pin.pull = 'down' | ||||||
|  |     if pin_factory.__class__.__name__ == 'MockFactory': | ||||||
|  |         test_pin.input_pin = input_pin | ||||||
|     def fin(): |     def fin(): | ||||||
|         test_pin.close() |         test_pin.close() | ||||||
|         input_pin.close() |         input_pin.close() | ||||||
| @@ -134,17 +144,18 @@ def test_pull_bad(pins): | |||||||
|     with pytest.raises(PinInvalidPull): |     with pytest.raises(PinInvalidPull): | ||||||
|         test_pin.input_with_pull('foo') |         test_pin.input_with_pull('foo') | ||||||
|  |  | ||||||
| def test_pull_down_warning(pin_class): | def test_pull_down_warning(pin_factory): | ||||||
|     # XXX This assumes we're on a vaguely modern Pi and not a compute module |     if pin_factory.pi_info.pulled_up('GPIO2'): | ||||||
|     # Might want to refine this with the pi-info database |         pin = pin_factory.pin(2) | ||||||
|     pin = pin_class(2) |         try: | ||||||
|     try: |             with pytest.raises(PinFixedPull): | ||||||
|         with pytest.raises(PinFixedPull): |                 pin.pull = 'down' | ||||||
|             pin.pull = 'down' |             with pytest.raises(PinFixedPull): | ||||||
|         with pytest.raises(PinFixedPull): |                 pin.input_with_pull('down') | ||||||
|             pin.input_with_pull('down') |         finally: | ||||||
|     finally: |             pin.close() | ||||||
|         pin.close() |     else: | ||||||
|  |         pytest.skip("GPIO2 isn't pulled up on this pi") | ||||||
|  |  | ||||||
| def test_input_with_pull(pins): | def test_input_with_pull(pins): | ||||||
|     test_pin, input_pin = pins |     test_pin, input_pin = pins | ||||||
| @@ -153,25 +164,42 @@ def test_input_with_pull(pins): | |||||||
|     test_pin.input_with_pull('down') |     test_pin.input_with_pull('down') | ||||||
|     assert input_pin.state == 0 |     assert input_pin.state == 0 | ||||||
|  |  | ||||||
| @pytest.mark.skipif(True, reason='causes segfaults') |  | ||||||
| def test_bad_duty_cycle(pins): | def test_bad_duty_cycle(pins): | ||||||
|     test_pin, input_pin = pins |     test_pin, input_pin = pins | ||||||
|     if test_pin.__class__.__name__ == 'NativePin': |  | ||||||
|         pytest.skip("native pin doesn't support PWM") |  | ||||||
|     test_pin.function = 'output' |     test_pin.function = 'output' | ||||||
|     test_pin.frequency = 100 |     try: | ||||||
|     with pytest.raises(ValueError): |         # NOTE: There's some race in RPi.GPIO that causes a segfault if we | ||||||
|         test_pin.state = 1.1 |         # don't pause before starting PWM; only seems to happen when stopping | ||||||
|  |         # and restarting PWM very rapidly (i.e. between test cases). | ||||||
|  |         if Device._pin_factory.__class__.__name__ == 'RPiGPIOFactory': | ||||||
|  |             sleep(0.1) | ||||||
|  |         test_pin.frequency = 100 | ||||||
|  |     except PinPWMUnsupported: | ||||||
|  |         pytest.skip("%r doesn't support PWM" % test_pin.factory) | ||||||
|  |     else: | ||||||
|  |         try: | ||||||
|  |             with pytest.raises(ValueError): | ||||||
|  |                 test_pin.state = 1.1 | ||||||
|  |         finally: | ||||||
|  |             test_pin.frequency = None | ||||||
|  |  | ||||||
| def test_duty_cycles(pins): | def test_duty_cycles(pins): | ||||||
|     test_pin, input_pin = pins |     test_pin, input_pin = pins | ||||||
|     if test_pin.__class__.__name__ == 'NativePin': |  | ||||||
|         pytest.skip("native pin doesn't support PWM") |  | ||||||
|     test_pin.function = 'output' |     test_pin.function = 'output' | ||||||
|     test_pin.frequency = 100 |     try: | ||||||
|     for duty_cycle in (0.0, 0.1, 0.5, 1.0): |         # NOTE: see above | ||||||
|         test_pin.state = duty_cycle |         if Device._pin_factory.__class__.__name__ == 'RPiGPIOFactory': | ||||||
|         assert test_pin.state == duty_cycle |             sleep(0.1) | ||||||
|         total = sum(input_pin.state for i in range(20000)) |         test_pin.frequency = 100 | ||||||
|         assert isclose(total / 20000, duty_cycle, rel_tol=0.1, abs_tol=0.1) |     except PinPWMUnsupported: | ||||||
|  |         pytest.skip("%r doesn't support PWM" % test_pin.factory) | ||||||
|  |     else: | ||||||
|  |         try: | ||||||
|  |             for duty_cycle in (0.0, 0.1, 0.5, 1.0): | ||||||
|  |                 test_pin.state = duty_cycle | ||||||
|  |                 assert test_pin.state == duty_cycle | ||||||
|  |                 total = sum(input_pin.state for i in range(20000)) | ||||||
|  |                 assert isclose(total / 20000, duty_cycle, rel_tol=0.1, abs_tol=0.1) | ||||||
|  |         finally: | ||||||
|  |             test_pin.frequency = None | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user