mirror of
				https://github.com/KevinMidboe/python-gpiozero.git
				synced 2025-10-29 17:50:37 +00:00 
			
		
		
		
	Change CompositeDevice to reject invalid identifiers
Also updated StatusBoard and StatusZero to reject duplicate identifiers (namedtuple doesn't pick 'em up because they're passed in a dict and thus the dups are squashed prior to the call). Added tests for all the relevant stuff.
This commit is contained in:
		| @@ -12,7 +12,7 @@ except ImportError: | |||||||
| from time import sleep | from time import sleep | ||||||
| from itertools import repeat, cycle, chain | from itertools import repeat, cycle, chain | ||||||
| from threading import Lock | from threading import Lock | ||||||
| from collections import OrderedDict | from collections import OrderedDict, Counter | ||||||
|  |  | ||||||
| from .exc import ( | from .exc import ( | ||||||
|     DeviceClosed, |     DeviceClosed, | ||||||
| @@ -819,6 +819,8 @@ class StatusZero(LEDBoard): | |||||||
|  |  | ||||||
|     .. _STATUS Zero: https://thepihut.com/statuszero |     .. _STATUS Zero: https://thepihut.com/statuszero | ||||||
|     """ |     """ | ||||||
|  |     default_labels = ('one', 'two', 'three') | ||||||
|  |  | ||||||
|     def __init__(self, *labels, **kwargs): |     def __init__(self, *labels, **kwargs): | ||||||
|         pins = ( |         pins = ( | ||||||
|             (17, 4), |             (17, 4), | ||||||
| @@ -826,12 +828,14 @@ class StatusZero(LEDBoard): | |||||||
|             (9, 10), |             (9, 10), | ||||||
|         ) |         ) | ||||||
|         if len(labels) == 0: |         if len(labels) == 0: | ||||||
|             labels = ['one', 'two', 'three'] |             labels = self.default_labels | ||||||
|         elif len(labels) > len(pins): |         elif len(labels) > len(pins): | ||||||
|             raise ValueError |             raise ValueError("StatusZero doesn't support more than three labels") | ||||||
|  |         dup, count = Counter(labels).most_common(1)[0] | ||||||
|  |         if count > 1: | ||||||
|  |             raise ValueError("Duplicate label %s" % dup) | ||||||
|         strips = OrderedDict() |         strips = OrderedDict() | ||||||
|         for index, label in enumerate(labels): |         for (green, red), label in zip(pins, labels): | ||||||
|             green, red = pins[index] |  | ||||||
|             strips[label] = LEDBoard(red=red, green=green, |             strips[label] = LEDBoard(red=red, green=green, | ||||||
|                 _order=('red', 'green'), **kwargs) |                 _order=('red', 'green'), **kwargs) | ||||||
|         super(StatusZero, self).__init__(_order=strips.keys(), **strips) |         super(StatusZero, self).__init__(_order=strips.keys(), **strips) | ||||||
| @@ -861,6 +865,8 @@ class StatusBoard(CompositeOutputDevice): | |||||||
|  |  | ||||||
|     .. _STATUS: https://thepihut.com/status |     .. _STATUS: https://thepihut.com/status | ||||||
|     """ |     """ | ||||||
|  |     default_labels = ('one', 'two', 'three', 'four', 'five') | ||||||
|  |  | ||||||
|     def __init__(self, *labels, **kwargs): |     def __init__(self, *labels, **kwargs): | ||||||
|         pins = ( |         pins = ( | ||||||
|             (17, 4, 14), |             (17, 4, 14), | ||||||
| @@ -870,12 +876,14 @@ class StatusBoard(CompositeOutputDevice): | |||||||
|             (13, 6, 18), |             (13, 6, 18), | ||||||
|         ) |         ) | ||||||
|         if len(labels) == 0: |         if len(labels) == 0: | ||||||
|             labels = ['one', 'two', 'three', 'four', 'five'] |             labels = self.default_labels | ||||||
|         elif len(labels) > len(pins): |         elif len(labels) > len(pins): | ||||||
|             raise ValueError |             raise ValueError("StatusBoard doesn't support more than five labels") | ||||||
|  |         dup, count = Counter(labels).most_common(1)[0] | ||||||
|  |         if count > 1: | ||||||
|  |             raise ValueError("Duplicate label %s" % dup) | ||||||
|         strips = OrderedDict() |         strips = OrderedDict() | ||||||
|         for index, label in enumerate(labels): |         for (green, red, button), label in zip(pins, labels): | ||||||
|             green, red, button = pins[index] |  | ||||||
|             strips[label] = CompositeOutputDevice( |             strips[label] = CompositeOutputDevice( | ||||||
|                 button=Button(button), |                 button=Button(button), | ||||||
|                 lights=LEDBoard( |                 lights=LEDBoard( | ||||||
|   | |||||||
| @@ -330,8 +330,7 @@ class CompositeDevice(Device): | |||||||
|                 raise CompositeDeviceBadDevice("%s doesn't inherit from Device" % dev) |                 raise CompositeDeviceBadDevice("%s doesn't inherit from Device" % dev) | ||||||
|         self._named = frozendict(kwargs) |         self._named = frozendict(kwargs) | ||||||
|         self._namedtuple = namedtuple('%sValue' % self.__class__.__name__, chain( |         self._namedtuple = namedtuple('%sValue' % self.__class__.__name__, chain( | ||||||
|             (str(i) for i in range(len(args))), self._order), |             ('device_%d' % i for i in range(len(args))), self._order)) | ||||||
|             rename=True) |  | ||||||
|  |  | ||||||
|     def __getattr__(self, name): |     def __getattr__(self, name): | ||||||
|         # if _named doesn't exist yet, pretend it's an empty dict |         # if _named doesn't exist yet, pretend it's an empty dict | ||||||
|   | |||||||
| @@ -783,13 +783,21 @@ def test_energenie(): | |||||||
|  |  | ||||||
| def test_statuszero_init(): | def test_statuszero_init(): | ||||||
|     with StatusZero() as sz: |     with StatusZero() as sz: | ||||||
|         assert sz |         assert sz.namedtuple._fields == ('one', 'two', 'three') | ||||||
|     with StatusZero('a') as sz: |     with StatusZero('a') as sz: | ||||||
|         assert sz |         assert sz.namedtuple._fields == ('a',) | ||||||
|     with StatusZero('a', 'b') as sz: |     with StatusZero('a', 'b') as sz: | ||||||
|         assert sz |         assert sz.namedtuple._fields == ('a', 'b') | ||||||
|     with StatusZero('a', 'b', 'c') as sz: |     with StatusZero('a', 'b', 'c') as sz: | ||||||
|         assert sz |         assert sz.namedtuple._fields == ('a', 'b', 'c') | ||||||
|  |     with pytest.raises(ValueError): | ||||||
|  |         StatusZero('a', 'b', 'c', 'd') | ||||||
|  |     with pytest.raises(ValueError): | ||||||
|  |         StatusZero('0') | ||||||
|  |     with pytest.raises(ValueError): | ||||||
|  |         StatusZero('foo', 'hello world') | ||||||
|  |     with pytest.raises(ValueError): | ||||||
|  |         StatusZero('foo', 'foo') | ||||||
|  |  | ||||||
| def test_statuszero(): | def test_statuszero(): | ||||||
|     with StatusZero() as sz: |     with StatusZero() as sz: | ||||||
| @@ -824,13 +832,21 @@ def test_statuszero_named(): | |||||||
|  |  | ||||||
| def test_statusboard_init(): | def test_statusboard_init(): | ||||||
|     with StatusBoard() as sb: |     with StatusBoard() as sb: | ||||||
|         assert sb |         assert sb.namedtuple._fields == ('one', 'two', 'three', 'four', 'five') | ||||||
|     with StatusBoard('a') as sb: |     with StatusBoard('a') as sb: | ||||||
|         assert sb |         assert sb.namedtuple._fields == ('a',) | ||||||
|     with StatusBoard('a', 'b') as sb: |     with StatusBoard('a', 'b') as sb: | ||||||
|         assert sb |         assert sb.namedtuple._fields == ('a', 'b',) | ||||||
|     with StatusBoard('a', 'b', 'c', 'd', 'e') as sb: |     with StatusBoard('a', 'b', 'c', 'd', 'e') as sb: | ||||||
|         assert sb |         assert sb.namedtuple._fields == ('a', 'b', 'c', 'd', 'e') | ||||||
|  |     with pytest.raises(ValueError): | ||||||
|  |         StatusBoard('a', 'b', 'c', 'd', 'e', 'f') | ||||||
|  |     with pytest.raises(ValueError): | ||||||
|  |         StatusBoard('0') | ||||||
|  |     with pytest.raises(ValueError): | ||||||
|  |         StatusBoard('foo', 'hello world') | ||||||
|  |     with pytest.raises(ValueError): | ||||||
|  |         StatusBoard('foo', 'foo') | ||||||
|  |  | ||||||
| def test_statusboard(): | def test_statusboard(): | ||||||
|     with StatusBoard() as sb: |     with StatusBoard() as sb: | ||||||
|   | |||||||
| @@ -91,7 +91,7 @@ def test_composite_device_sequence(): | |||||||
|         assert len(device) == 2 |         assert len(device) == 2 | ||||||
|         assert device[0].pin.number == 4 |         assert device[0].pin.number == 4 | ||||||
|         assert device[1].pin.number == 5 |         assert device[1].pin.number == 5 | ||||||
|         assert device.namedtuple._fields == ('_0', '_1') |         assert device.namedtuple._fields == ('device_0', 'device_1') | ||||||
|  |  | ||||||
| def test_composite_device_values(): | def test_composite_device_values(): | ||||||
|     with CompositeDevice( |     with CompositeDevice( | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user