From 141800149252b1a9f47ad8364e66efbf778f3cd9 Mon Sep 17 00:00:00 2001 From: Mike Smith <157708531+m2es3h@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:02:57 -0700 Subject: [PATCH 1/2] add support to initialise NTEnum like NTScalar --- src/p4p/nt/enum.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/p4p/nt/enum.py b/src/p4p/nt/enum.py index 21f06fcb..3f9a2379 100644 --- a/src/p4p/nt/enum.py +++ b/src/p4p/nt/enum.py @@ -67,8 +67,12 @@ def wrap(self, value, choices=None, **kws): V['value.choices'] = choices if isinstance(value, dict): - # assume dict of index and choices list - V.value = value + if value.keys() == set(['index', 'choices']): + # assume dict for Value.value (index and choices list) + V.value = value + else: + # assume dict for Value + V = Value(self.type, value) self._choices = V['value.choices'] else: # index or string From 0303dc42396122d4513b17b28b32723017359c39 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Thu, 22 Aug 2024 10:58:05 -0700 Subject: [PATCH 2/2] make NTEnum.wrap() logic similar to NTScalar.wrap(), add tests --- src/p4p/nt/enum.py | 33 ++++++++++++++++++++------------- src/p4p/test/test_nt.py | 25 ++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/src/p4p/nt/enum.py b/src/p4p/nt/enum.py index 3f9a2379..bb45d4b5 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,23 +63,28 @@ 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): - if value.keys() == set(['index', 'choices']): - # assume dict for Value.value (index and choices list) - V.value = value - else: - # assume dict for Value - V = Value(self.type, 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): + value = self.Value(self.type, 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()