diff --git a/src/p4p/nt/enum.py b/src/p4p/nt/enum.py index 21f06fcb..8a413f94 100644 --- a/src/p4p/nt/enum.py +++ b/src/p4p/nt/enum.py @@ -38,6 +38,8 @@ def __repr__(self): class NTEnum(NTBase): """Describes a string selected from among a list of possible choices. Stored internally as an integer """ + Value = Value + @staticmethod def buildType(extra=[], display=False, control=False, valueAlarm=False): F = [ @@ -61,19 +63,35 @@ def __init__(self, **kws): def wrap(self, value, choices=None, **kws): """Pack python value into Value + + Accepts dict to explicitly initialize fields by name. + Any other type is assigned to the 'value' field via + the self.assign() method. """ - V = self.type() - if choices is not None: - V['value.choices'] = choices - - if isinstance(value, dict): - # assume dict of index and choices list - V.value = value - self._choices = V['value.choices'] + if isinstance(value, Value): + pass + elif isinstance(value, ntwrappercommon): + kws.setdefault('timestamp', value.timestamp) + value = value.raw + elif isinstance(value, dict): + # if index, choices not in value.keys(), then + # use value dict to initalize fields by name + if {'index', 'choices'}.isdisjoint(value): + value = self.Value(self.type, value) + # if value = {'index': ..., 'choices': ...}, then + # assign these to value.index, value.choices + else: + value = self.Value(self.type, {'value': value}) else: # index or string + V = self.type() + if choices is not None: + V['value.choices'] = choices self.assign(V, value) - return self._annotate(V, **kws) + value = V + + self._choices = value['value.choices'] or self._choices + return self._annotate(value, **kws) def unwrap(self, value): """Unpack a Value into an augmented python type (selected from the 'value' field) diff --git a/src/p4p/test/test_nt.py b/src/p4p/test/test_nt.py index b5a75a10..b85ea1f8 100644 --- a/src/p4p/test/test_nt.py +++ b/src/p4p/test/test_nt.py @@ -267,18 +267,41 @@ def testSubStore(self): self.assertEqual(V.a.value.index, 1) self.assertEqual(V.b.value.index, 0) - def testWrap(self): + def testDictionaryOfValueWrap(self): W = nt.NTEnum() V = W.wrap({'index':1, 'choices':['X','Y']}) self.assertEqual(V.value.index, 1) self.assertEqual(V.value.choices, ['X','Y']) + def testDictionaryWrap(self): + W = nt.NTEnum() + V = W.wrap({'value.index': 0, + 'value.choices': ['X','Y'], + 'alarm.severity': 1}) + + self.assertEqual(V.value.index, 0) + self.assertEqual(V.value.choices, ['X','Y']) + self.assertEqual(V.alarm.severity, 1) + + def testWrap(self): W = nt.NTEnum() V = W.wrap(0) self.assertEqual(V.value.index, 0) self.assertEqual(V.value.choices, []) + self.assertTrue(V.changed('value')) + + V = W.wrap(1, choices=['X', 'Y']) + + self.assertEqual(V.value.index, 1) + self.assertEqual(V.value.choices, ['X', 'Y']) + self.assertTrue(V.changed('value')) + + V = W.wrap('X') + + self.assertEqual(V.value.index, 0) + self.assertTrue(V.changed('value.index')) def testAssign(self): W = nt.NTEnum()