From c1898ef73ff24b1f9f8bf7f1aa4e157590abf699 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Tue, 11 Jun 2019 22:31:02 +0100 Subject: [PATCH] Friendlier record accessors --- implementations/python/preserves/preserves.py | 11 +++++++++++ .../python/preserves/test_preserves.py | 15 +++++++++++++++ implementations/python/setup.py | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/implementations/python/preserves/preserves.py b/implementations/python/preserves/preserves.py index 78132b0..aa4332c 100644 --- a/implementations/python/preserves/preserves.py +++ b/implementations/python/preserves/preserves.py @@ -97,6 +97,17 @@ class Record(object): ctor.constructorInfo = RecordConstructorInfo(label, arity) ctor.isClassOf = lambda v: \ isinstance(v, Record) and v.key == label and len(v.fields) == arity + def ensureClassOf(v): + if not ctor.isClassOf(v): + raise TypeError("Record: expected %r/%d, got %r" % (label, arity, v)) + return v + ctor.ensureClassOf = ensureClassOf + for fieldIndex in range(len(fieldNames)): + fieldName = fieldNames[fieldIndex] + # Stupid python scoping bites again + def getter(fieldIndex): + return lambda v: ensureClassOf(v)[fieldIndex] + setattr(ctor, '_' + fieldName, getter(fieldIndex)) return ctor class RecordConstructorInfo(object): diff --git a/implementations/python/preserves/test_preserves.py b/implementations/python/preserves/test_preserves.py index 0131b4d..30f8453 100644 --- a/implementations/python/preserves/test_preserves.py +++ b/implementations/python/preserves/test_preserves.py @@ -204,3 +204,18 @@ class CodecTests(unittest.TestCase): self._roundtrip(SequenceStream([StringStream([b'abc']), StringStream([b'def'])]), _buf(0x2C, 0x25, 0x63, 'abc', 0x35, 0x25, 0x63, 'def', 0x35, 0x3C), back=(u'abc', u'def')) + +class RecordTests(unittest.TestCase): + def test_getters(self): + T = Record.makeConstructor('t', 'x y z') + T2 = Record.makeConstructor('t', 'x y z') + U = Record.makeConstructor('u', 'x y z') + t = T(1, 2, 3) + self.assertTrue(T.isClassOf(t)) + self.assertTrue(T2.isClassOf(t)) + self.assertFalse(U.isClassOf(t)) + self.assertEqual(T._x(t), 1) + self.assertEqual(T2._y(t), 2) + self.assertEqual(T._z(t), 3) + with self.assertRaises(TypeError): + U._x(t) diff --git a/implementations/python/setup.py b/implementations/python/setup.py index 5279f1c..124e032 100644 --- a/implementations/python/setup.py +++ b/implementations/python/setup.py @@ -5,7 +5,7 @@ except ImportError: setup( name="preserves", - version="0.0.4", + version="0.0.5", author="Tony Garnock-Jones", author_email="tonyg@leastfixedpoint.com", license="GNU General Public License v3 or later (GPLv3+)",