added binary support in dictionaries via base64 encoding
This commit is contained in:
committed by
Jacob Alexander
parent
3a3adfb5f1
commit
ed461ed2f5
@@ -27,6 +27,7 @@ import array
|
|||||||
import asyncio
|
import asyncio
|
||||||
import collections as _collections
|
import collections as _collections
|
||||||
import contextlib
|
import contextlib
|
||||||
|
import base64
|
||||||
import enum as _enum
|
import enum as _enum
|
||||||
import inspect as _inspect
|
import inspect as _inspect
|
||||||
import os as _os
|
import os as _os
|
||||||
@@ -969,17 +970,17 @@ cdef _DynamicStructBuilder temp_msg_b
|
|||||||
cdef _DynamicStructReader temp_msg_r
|
cdef _DynamicStructReader temp_msg_r
|
||||||
|
|
||||||
|
|
||||||
cdef _to_dict(msg, bint verbose, bint ordered):
|
cdef _to_dict(msg, bint verbose, bint ordered, bint encode_bytes_as_base64=False):
|
||||||
msg_type = type(msg)
|
msg_type = type(msg)
|
||||||
if msg_type is _DynamicListBuilder:
|
if msg_type is _DynamicListBuilder:
|
||||||
temp_list_b = msg
|
temp_list_b = msg
|
||||||
return [_to_dict(temp_list_b._get(i), verbose, ordered) for i in range(len(msg))]
|
return [_to_dict(temp_list_b._get(i), verbose, ordered, encode_bytes_as_base64) for i in range(len(msg))]
|
||||||
elif msg_type is _DynamicListReader:
|
elif msg_type is _DynamicListReader:
|
||||||
temp_list_r = msg
|
temp_list_r = msg
|
||||||
return [_to_dict(temp_list_r._get(i), verbose, ordered) for i in range(len(msg))]
|
return [_to_dict(temp_list_r._get(i), verbose, ordered, encode_bytes_as_base64) for i in range(len(msg))]
|
||||||
elif msg_type is _DynamicResizableListBuilder:
|
elif msg_type is _DynamicResizableListBuilder:
|
||||||
temp_list_rb = msg
|
temp_list_rb = msg
|
||||||
return [_to_dict(temp_list_rb._get(i), verbose, ordered) for i in range(len(msg))]
|
return [_to_dict(temp_list_rb._get(i), verbose, ordered, encode_bytes_as_base64) for i in range(len(msg))]
|
||||||
|
|
||||||
if msg_type is _DynamicStructBuilder or isinstance(msg, _Request):
|
if msg_type is _DynamicStructBuilder or isinstance(msg, _Request):
|
||||||
temp_msg_b = msg
|
temp_msg_b = msg
|
||||||
@@ -989,13 +990,13 @@ cdef _to_dict(msg, bint verbose, bint ordered):
|
|||||||
ret = {}
|
ret = {}
|
||||||
try:
|
try:
|
||||||
which = temp_msg_b.which()
|
which = temp_msg_b.which()
|
||||||
ret[which] = _to_dict(temp_msg_b._get(which), verbose, ordered)
|
ret[which] = _to_dict(temp_msg_b._get(which), verbose, ordered, encode_bytes_as_base64)
|
||||||
except KjException:
|
except KjException:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
for field in temp_msg_b.schema.non_union_fields:
|
for field in temp_msg_b.schema.non_union_fields:
|
||||||
if verbose or temp_msg_b._has(field):
|
if verbose or temp_msg_b._has(field):
|
||||||
ret[field] = _to_dict(temp_msg_b._get(field), verbose, ordered)
|
ret[field] = _to_dict(temp_msg_b._get(field), verbose, ordered, encode_bytes_as_base64)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
elif msg_type is _DynamicStructReader or isinstance(msg, _Response):
|
elif msg_type is _DynamicStructReader or isinstance(msg, _Response):
|
||||||
@@ -1006,13 +1007,13 @@ cdef _to_dict(msg, bint verbose, bint ordered):
|
|||||||
ret = {}
|
ret = {}
|
||||||
try:
|
try:
|
||||||
which = temp_msg_r.which()
|
which = temp_msg_r.which()
|
||||||
ret[which] = _to_dict(temp_msg_r._get(which), verbose, ordered)
|
ret[which] = _to_dict(temp_msg_r._get(which), verbose, ordered, encode_bytes_as_base64)
|
||||||
except KjException:
|
except KjException:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
for field in temp_msg_r.schema.non_union_fields:
|
for field in temp_msg_r.schema.non_union_fields:
|
||||||
if verbose or temp_msg_r._has(field):
|
if verbose or temp_msg_r._has(field):
|
||||||
ret[field] = _to_dict(temp_msg_r._get(field), verbose, ordered)
|
ret[field] = _to_dict(temp_msg_r._get(field), verbose, ordered, encode_bytes_as_base64)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@@ -1022,6 +1023,10 @@ cdef _to_dict(msg, bint verbose, bint ordered):
|
|||||||
if msg_type is _DynamicEnum:
|
if msg_type is _DynamicEnum:
|
||||||
return str(msg)
|
return str(msg)
|
||||||
|
|
||||||
|
if encode_bytes_as_base64 and msg_type is bytes:
|
||||||
|
# encode the message as base64 and return utf-8 string
|
||||||
|
return base64.b64encode(msg).decode('utf-8')
|
||||||
|
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
@@ -1234,8 +1239,8 @@ cdef class _DynamicStructReader:
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s reader %s>' % (self.schema.node.displayName, <char*>strStructReader(self.thisptr).cStr())
|
return '<%s reader %s>' % (self.schema.node.displayName, <char*>strStructReader(self.thisptr).cStr())
|
||||||
|
|
||||||
def to_dict(self, verbose=False, ordered=False):
|
def to_dict(self, verbose=False, ordered=False, encode_bytes_as_base64=False):
|
||||||
return _to_dict(self, verbose, ordered)
|
return _to_dict(self, verbose, ordered, encode_bytes_as_base64)
|
||||||
|
|
||||||
cpdef as_builder(self, num_first_segment_words=None):
|
cpdef as_builder(self, num_first_segment_words=None):
|
||||||
"""A method for casting this Reader to a Builder
|
"""A method for casting this Reader to a Builder
|
||||||
@@ -1618,12 +1623,18 @@ cdef class _DynamicStructBuilder:
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s builder %s>' % (self.schema.node.displayName, <char*>strStructBuilder(self.thisptr).cStr())
|
return '<%s builder %s>' % (self.schema.node.displayName, <char*>strStructBuilder(self.thisptr).cStr())
|
||||||
|
|
||||||
def to_dict(self, verbose=False, ordered=False):
|
def to_dict(self, verbose=False, ordered=False, encode_bytes_as_base64=False):
|
||||||
return _to_dict(self, verbose, ordered)
|
return _to_dict(self, verbose, ordered, encode_bytes_as_base64)
|
||||||
|
|
||||||
def from_dict(self, dict d):
|
def from_dict(self, dict d):
|
||||||
for key, val in d.iteritems():
|
for key, val in d.iteritems():
|
||||||
if key != 'which':
|
if key != 'which':
|
||||||
|
field = self.schema.fields.get(key)
|
||||||
|
if isinstance(val, str):
|
||||||
|
dtype = field.proto.slot.type.which()
|
||||||
|
if dtype == "data":
|
||||||
|
# decode bytes from utf-8 base64 encoding
|
||||||
|
val = base64.b64decode(val)
|
||||||
try:
|
try:
|
||||||
self._set(key, val)
|
self._set(key, val)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -1703,8 +1714,8 @@ cdef class _DynamicStructPipeline:
|
|||||||
# def __repr__(self):
|
# def __repr__(self):
|
||||||
# return '<%s reader %s>' % (self.schema.node.displayName, strStructReader(self.thisptr).cStr())
|
# return '<%s reader %s>' % (self.schema.node.displayName, strStructReader(self.thisptr).cStr())
|
||||||
|
|
||||||
def to_dict(self, verbose=False, ordered=False):
|
def to_dict(self, verbose=False, ordered=False, encode_bytes_as_base64=False):
|
||||||
return _to_dict(self, verbose, ordered)
|
return _to_dict(self, verbose, ordered, encode_bytes_as_base64)
|
||||||
|
|
||||||
|
|
||||||
cdef class _DynamicOrphan:
|
cdef class _DynamicOrphan:
|
||||||
@@ -2086,8 +2097,8 @@ cdef class _RemotePromise:
|
|||||||
def __dir__(self):
|
def __dir__(self):
|
||||||
return list(set(self.schema.fieldnames + tuple(dir(self.__class__))))
|
return list(set(self.schema.fieldnames + tuple(dir(self.__class__))))
|
||||||
|
|
||||||
def to_dict(self, verbose=False, ordered=False):
|
def to_dict(self, verbose=False, ordered=False, encode_bytes_as_base64=False):
|
||||||
return _to_dict(self, verbose, ordered)
|
return _to_dict(self, verbose, ordered, encode_bytes_as_base64)
|
||||||
|
|
||||||
cpdef cancel(self):
|
cpdef cancel(self):
|
||||||
self.thisptr = Own[RemotePromise]()
|
self.thisptr = Own[RemotePromise]()
|
||||||
|
|||||||
21
test/test_blob_to_dict_base64.py
Normal file
21
test/test_blob_to_dict_base64.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import os
|
||||||
|
import capnp
|
||||||
|
import base64
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
this_dir = os.path.dirname(__file__)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def blob_schema():
|
||||||
|
return capnp.load(os.path.join(this_dir, "blob_test.capnp"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_blob_to_dict(blob_schema):
|
||||||
|
blob_value = b"hello world"
|
||||||
|
blob = blob_schema.BlobTest(blob=blob_value)
|
||||||
|
blob_dict = blob.to_dict(encode_bytes_as_base64=True)
|
||||||
|
assert base64.b64decode(blob_dict["blob"]) == blob_value
|
||||||
|
msg = blob_schema.BlobTest.new_message()
|
||||||
|
msg.from_dict(blob_dict)
|
||||||
|
assert blob.blob == blob_value
|
||||||
Reference in New Issue
Block a user