mirror of
				https://github.com/KevinMidboe/python-gpiozero.git
				synced 2025-10-29 17:50:37 +00:00 
			
		
		
		
	Permit replacement of pin_factory without closing old factory. However, continue closing devices associated with extant pin factory at script termination.
		
			
				
	
	
		
			198 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from __future__ import (
 | |
|     unicode_literals,
 | |
|     absolute_import,
 | |
|     print_function,
 | |
|     division,
 | |
|     )
 | |
| nstr = str
 | |
| str = type('')
 | |
| 
 | |
| 
 | |
| import sys
 | |
| import pytest
 | |
| from array import array
 | |
| from mock import patch
 | |
| from collections import namedtuple
 | |
| 
 | |
| from gpiozero.pins.native import NativeFactory
 | |
| from gpiozero.pins.local import (
 | |
|     LocalPiHardwareSPI,
 | |
|     LocalPiSoftwareSPI,
 | |
|     LocalPiHardwareSPIShared,
 | |
|     LocalPiSoftwareSPIShared,
 | |
|     )
 | |
| from gpiozero.pins.mock import MockSPIDevice
 | |
| from gpiozero import *
 | |
| 
 | |
| 
 | |
| def teardown_function(function):
 | |
|     Device.pin_factory.reset()
 | |
| 
 | |
| 
 | |
| def test_spi_hardware_params():
 | |
|     with patch('os.open'), patch('mmap.mmap') as mmap_mmap, patch('io.open') as io_open:
 | |
|         mmap_mmap.return_value = array(nstr('B'), (0,) * 4096)
 | |
|         io_open.return_value.__enter__.return_value = ['Revision: a21042']
 | |
|         with patch('gpiozero.devices.Device.pin_factory', NativeFactory()), \
 | |
|                 patch('gpiozero.pins.local.SpiDev'):
 | |
|             with Device.pin_factory.spi() as device:
 | |
|                 assert isinstance(device, LocalPiHardwareSPI)
 | |
|             with Device.pin_factory.spi(port=0, device=0) as device:
 | |
|                 assert isinstance(device, LocalPiHardwareSPI)
 | |
|             with Device.pin_factory.spi(port=0, device=1) as device:
 | |
|                 assert isinstance(device, LocalPiHardwareSPI)
 | |
|             with Device.pin_factory.spi(clock_pin=11) as device:
 | |
|                 assert isinstance(device, LocalPiHardwareSPI)
 | |
|             with Device.pin_factory.spi(clock_pin=11, mosi_pin=10, select_pin=8) as device:
 | |
|                 assert isinstance(device, LocalPiHardwareSPI)
 | |
|             with Device.pin_factory.spi(clock_pin=11, mosi_pin=10, select_pin=7) as device:
 | |
|                 assert isinstance(device, LocalPiHardwareSPI)
 | |
|             with Device.pin_factory.spi(shared=True) as device:
 | |
|                 assert isinstance(device, LocalPiHardwareSPIShared)
 | |
|             with pytest.raises(ValueError):
 | |
|                 Device.pin_factory.spi(port=1)
 | |
|             with pytest.raises(ValueError):
 | |
|                 Device.pin_factory.spi(device=2)
 | |
|             with pytest.raises(ValueError):
 | |
|                 Device.pin_factory.spi(port=0, clock_pin=12)
 | |
|             with pytest.raises(ValueError):
 | |
|                 Device.pin_factory.spi(foo='bar')
 | |
| 
 | |
| def test_spi_software_params():
 | |
|     with patch('os.open'), patch('mmap.mmap') as mmap_mmap, patch('io.open') as io_open:
 | |
|         mmap_mmap.return_value = array(nstr('B'), (0,) * 4096)
 | |
|         io_open.return_value.__enter__.return_value = ['Revision: a21042']
 | |
|         with patch('gpiozero.devices.Device.pin_factory', NativeFactory()), \
 | |
|                 patch('gpiozero.pins.local.SpiDev'):
 | |
|             with Device.pin_factory.spi(select_pin=6) as device:
 | |
|                 assert isinstance(device, LocalPiSoftwareSPI)
 | |
|             with Device.pin_factory.spi(clock_pin=11, mosi_pin=9, miso_pin=10) as device:
 | |
|                 assert isinstance(device, LocalPiSoftwareSPI)
 | |
|             with Device.pin_factory.spi(select_pin=6, shared=True) as device:
 | |
|                 assert isinstance(device, LocalPiSoftwareSPIShared)
 | |
|         with patch('gpiozero.devices.Device.pin_factory', NativeFactory()), \
 | |
|                 patch('gpiozero.pins.local.SpiDev', None):
 | |
|             # Clear out the old factory's pins cache (this is only necessary
 | |
|             # because we're being very naughty switching out pin factories)
 | |
|             Device.pin_factory.pins.clear()
 | |
|             # Ensure software fallback works when SpiDev isn't present
 | |
|             with Device.pin_factory.spi() as device:
 | |
|                 assert isinstance(device, LocalPiSoftwareSPI)
 | |
| 
 | |
| def test_spi_hardware_conflict():
 | |
|     with patch('gpiozero.pins.local.SpiDev') as spidev:
 | |
|         with LED(11) as led:
 | |
|             with pytest.raises(GPIOPinInUse):
 | |
|                 Device.pin_factory.spi(port=0, device=0)
 | |
|     with patch('gpiozero.pins.local.SpiDev') as spidev:
 | |
|         with Device.pin_factory.spi(port=0, device=0) as spi:
 | |
|             with pytest.raises(GPIOPinInUse):
 | |
|                 LED(11)
 | |
| 
 | |
| def test_spi_hardware_read():
 | |
|     with patch('gpiozero.pins.local.SpiDev') as spidev:
 | |
|         spidev.return_value.xfer2.side_effect = lambda data: list(range(10))[:len(data)]
 | |
|         with Device.pin_factory.spi() as device:
 | |
|             assert device.read(3) == [0, 1, 2]
 | |
|             assert device.read(6) == list(range(6))
 | |
| 
 | |
| def test_spi_hardware_write():
 | |
|     with patch('gpiozero.pins.local.SpiDev') as spidev:
 | |
|         spidev.return_value.xfer2.side_effect = lambda data: list(range(10))[:len(data)]
 | |
|         with Device.pin_factory.spi() as device:
 | |
|             assert device.write([0, 1, 2]) == 3
 | |
|             assert spidev.return_value.xfer2.called_with([0, 1, 2])
 | |
|             assert device.write(list(range(6))) == 6
 | |
|             assert spidev.return_value.xfer2.called_with(list(range(6)))
 | |
| 
 | |
| def test_spi_hardware_modes():
 | |
|     with patch('gpiozero.pins.local.SpiDev') as spidev:
 | |
|         spidev.return_value.mode = 0
 | |
|         spidev.return_value.lsbfirst = False
 | |
|         spidev.return_value.cshigh = True
 | |
|         spidev.return_value.bits_per_word = 8
 | |
|         with Device.pin_factory.spi() as device:
 | |
|             assert device.clock_mode == 0
 | |
|             assert not device.clock_polarity
 | |
|             assert not device.clock_phase
 | |
|             device.clock_polarity = False
 | |
|             assert device.clock_mode == 0
 | |
|             device.clock_polarity = True
 | |
|             assert device.clock_mode == 2
 | |
|             device.clock_phase = True
 | |
|             assert device.clock_mode == 3
 | |
|             assert not device.lsb_first
 | |
|             assert device.select_high
 | |
|             assert device.bits_per_word == 8
 | |
|             device.select_high = False
 | |
|             device.lsb_first = True
 | |
|             device.bits_per_word = 12
 | |
|             assert not spidev.return_value.cshigh
 | |
|             assert spidev.return_value.lsbfirst
 | |
|             assert spidev.return_value.bits_per_word == 12
 | |
| 
 | |
| def test_spi_software_read():
 | |
|     class SPISlave(MockSPIDevice):
 | |
|         def on_start(self):
 | |
|             super(SPISlave, self).on_start()
 | |
|             for i in range(10):
 | |
|                 self.tx_word(i)
 | |
|     with patch('gpiozero.pins.local.SpiDev', None), \
 | |
|             SPISlave(11, 10, 9, 8) as slave, \
 | |
|             Device.pin_factory.spi() as master:
 | |
|         assert master.read(3) == [0, 1, 2]
 | |
|         assert master.read(6) == [0, 1, 2, 3, 4, 5]
 | |
|         slave.clock_phase = True
 | |
|         master.clock_phase = True
 | |
|         assert master.read(3) == [0, 1, 2]
 | |
|         assert master.read(6) == [0, 1, 2, 3, 4, 5]
 | |
| 
 | |
| def test_spi_software_write():
 | |
|     with patch('gpiozero.pins.local.SpiDev', None), \
 | |
|             MockSPIDevice(11, 10, 9, 8) as test_device, \
 | |
|             Device.pin_factory.spi() as master:
 | |
|         master.write([0])
 | |
|         assert test_device.rx_word() == 0
 | |
|         master.write([2, 0])
 | |
|         assert test_device.rx_word() == 512
 | |
|         master.write([0, 1, 1])
 | |
|         assert test_device.rx_word() == 257
 | |
| 
 | |
| def test_spi_software_clock_mode():
 | |
|     with patch('gpiozero.pins.local.SpiDev', None), \
 | |
|             Device.pin_factory.spi() as master:
 | |
|         assert master.clock_mode == 0
 | |
|         assert not master.clock_polarity
 | |
|         assert not master.clock_phase
 | |
|         master.clock_polarity = False
 | |
|         assert master.clock_mode == 0
 | |
|         master.clock_polarity = True
 | |
|         assert master.clock_mode == 2
 | |
|         master.clock_phase = True
 | |
|         assert master.clock_mode == 3
 | |
|         master.clock_mode = 0
 | |
|         assert not master.clock_polarity
 | |
|         assert not master.clock_phase
 | |
|         with pytest.raises(ValueError):
 | |
|             master.clock_mode = 5
 | |
| 
 | |
| def test_spi_software_attr():
 | |
|     with patch('gpiozero.pins.local.SpiDev', None), \
 | |
|             Device.pin_factory.spi() as master:
 | |
|         assert not master.lsb_first
 | |
|         assert not master.select_high
 | |
|         assert master.bits_per_word == 8
 | |
|         master.bits_per_word = 12
 | |
|         assert master.bits_per_word == 12
 | |
|         master.lsb_first = True
 | |
|         assert master.lsb_first
 | |
|         master.select_high = True
 | |
|         assert master.select_high
 | |
|         with pytest.raises(ValueError):
 | |
|             master.bits_per_word = 0
 | |
| 
 | |
| 
 | |
| # XXX Test two simultaneous SPI devices sharing clock, MOSI, and MISO, with
 | |
| # separate select pins (including threaded tests which attempt simultaneous
 | |
| # reading/writing)
 |