From b5ee257fb478aa66ca1eecaff627bfecdac20294 Mon Sep 17 00:00:00 2001 From: Zhao Jiarong Date: Tue, 28 Nov 2017 15:17:07 +0800 Subject: [PATCH] Implement _fields and _asdict() for struct. --- capnpy/compiler/struct_.py | 7 +++++++ capnpy/struct_.py | 10 +++++++++ capnpy/testing/compiler/test_todict.py | 29 ++++++++++++++++++++++++++ docs/source/usage.rst | 3 +++ 4 files changed, 49 insertions(+) create mode 100644 capnpy/testing/compiler/test_todict.py diff --git a/capnpy/compiler/struct_.py b/capnpy/compiler/struct_.py index 98a59650..335f68d5 100644 --- a/capnpy/compiler/struct_.py +++ b/capnpy/compiler/struct_.py @@ -65,6 +65,7 @@ def emit_definition(self, m): __static_ptrs_size__ = {ptrs_size} """) + self._emit_fields(m, ns) for child in m.children[self.id]: child.emit_reference_as_child(m) m.w() @@ -97,6 +98,12 @@ def _get_enum_items(self, m): enum_items[field.discriminantValue] = m._field_name(field) return enum_items + def _emit_fields(self, m, ns): + fnames = [] + for f in self.struct.fields or []: + fnames.append(m._field_name(f)) + ns.w("_fields = {}".format(tuple(fnames))) + def _emit_union_tag_declaration(self, m): enum_items = self._get_enum_items(m) if not enum_items: diff --git a/capnpy/struct_.py b/capnpy/struct_.py index afe15547..6fc924d7 100644 --- a/capnpy/struct_.py +++ b/capnpy/struct_.py @@ -1,3 +1,5 @@ +from collections import OrderedDict + import capnpy from capnpy import ptr from capnpy.type import Types @@ -44,6 +46,8 @@ class Struct(Blob): __static_data_size__ = None __static_ptrs_size__ = None + _fields = None + def __init__(self, buf, offset, data_size, ptrs_size): self._init_from_buffer(buf, offset, data_size, ptrs_size) @@ -69,6 +73,12 @@ def __reduce__(self): self._data_size, self._ptrs_size) return (struct_from_buffer, args) + def _asdict(self): + o = OrderedDict() + for f in self._fields: + o[f] = getattr(self, f) + return o + @classmethod def from_buffer(cls, buf, offset, data_size, ptrs_size): return struct_from_buffer(cls, buf, offset, data_size, ptrs_size) diff --git a/capnpy/testing/compiler/test_todict.py b/capnpy/testing/compiler/test_todict.py new file mode 100644 index 00000000..cd1c0457 --- /dev/null +++ b/capnpy/testing/compiler/test_todict.py @@ -0,0 +1,29 @@ +from capnpy.testing.compiler.support import CompilerTest + + +class TestTodict(CompilerTest): + def test_fields(self): + schema = """ + @0xbf5147cbbecf40c1; + struct Point { + x @0 :Int64; + y @1 :Int64; + } + """ + mod = self.compile(schema) + assert mod.Point._fields == ('x', 'y') + + def test_todict(self): + schema = """ + @0xbf5147cbbecf40c1; + struct Point { + x @0 :Int64; + y @1 :Int64; + } + """ + mod = self.compile(schema) + p = mod.Point(1, 2) + d = p._asdict() + assert d == {'x': 1, 'y': 2} + assert list(d)[0] == 'x' + diff --git a/docs/source/usage.rst b/docs/source/usage.rst index 02678f8d..c555bb78 100644 --- a/docs/source/usage.rst +++ b/docs/source/usage.rst @@ -266,6 +266,9 @@ inspired by ``namedtuples``: value of a field, you can instantiate a new object, as you would do with namedtuples + - ``_fields`` and ``_asdict()`` are provided with the same semantics as + namedtuple + - objects can be made `comparable and hashable`__ by specifying the ``$Py.key`` annotation