Add {_get,_set,_has,_init}_by_field methods for faster field access
This commit is contained in:
@@ -225,7 +225,9 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp":
|
|||||||
cdef cppclass DynamicStruct:
|
cdef cppclass DynamicStruct:
|
||||||
cppclass Reader:
|
cppclass Reader:
|
||||||
DynamicValueForward.Reader get(char *) except +reraise_kj_exception
|
DynamicValueForward.Reader get(char *) except +reraise_kj_exception
|
||||||
|
DynamicValueForward.Reader getByField"get"(StructSchema.Field) except +reraise_kj_exception
|
||||||
bint has(char *) except +reraise_kj_exception
|
bint has(char *) except +reraise_kj_exception
|
||||||
|
bint hasByField"has"(StructSchema.Field) except +reraise_kj_exception
|
||||||
StructSchema getSchema()
|
StructSchema getSchema()
|
||||||
Maybe[StructSchema.Field] which()
|
Maybe[StructSchema.Field] which()
|
||||||
MessageSize totalSize()
|
MessageSize totalSize()
|
||||||
@@ -239,10 +241,15 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp":
|
|||||||
DynamicStruct_Builder()
|
DynamicStruct_Builder()
|
||||||
DynamicStruct_Builder(DynamicStruct_Builder &)
|
DynamicStruct_Builder(DynamicStruct_Builder &)
|
||||||
DynamicValueForward.Builder get(char *) except +reraise_kj_exception
|
DynamicValueForward.Builder get(char *) except +reraise_kj_exception
|
||||||
|
DynamicValueForward.Builder getByField"get"(StructSchema.Field) except +reraise_kj_exception
|
||||||
bint has(char *) except +reraise_kj_exception
|
bint has(char *) except +reraise_kj_exception
|
||||||
|
bint hasByField"has"(StructSchema.Field) except +reraise_kj_exception
|
||||||
void set(char *, DynamicValueForward.Reader) except +reraise_kj_exception
|
void set(char *, DynamicValueForward.Reader) except +reraise_kj_exception
|
||||||
|
void setByField"set"(StructSchema.Field, DynamicValueForward.Reader) except +reraise_kj_exception
|
||||||
DynamicValueForward.Builder init(char *, uint size) except +reraise_kj_exception
|
DynamicValueForward.Builder init(char *, uint size) except +reraise_kj_exception
|
||||||
DynamicValueForward.Builder init(char *) except +reraise_kj_exception
|
DynamicValueForward.Builder init(char *) except +reraise_kj_exception
|
||||||
|
DynamicValueForward.Builder initByField"init"(StructSchema.Field, uint size) except +reraise_kj_exception
|
||||||
|
DynamicValueForward.Builder initByField"init"(StructSchema.Field) except +reraise_kj_exception
|
||||||
StructSchema getSchema()
|
StructSchema getSchema()
|
||||||
Maybe[StructSchema.Field] which()
|
Maybe[StructSchema.Field] which()
|
||||||
void adopt(char *, DynamicOrphan) except +reraise_kj_exception
|
void adopt(char *, DynamicOrphan) except +reraise_kj_exception
|
||||||
|
|||||||
@@ -872,9 +872,15 @@ cdef class _DynamicStructReader:
|
|||||||
def __getattr__(self, field):
|
def __getattr__(self, field):
|
||||||
return to_python_reader(self.thisptr.get(field), self._parent)
|
return to_python_reader(self.thisptr.get(field), self._parent)
|
||||||
|
|
||||||
|
def _get_by_field(self, _StructSchemaField field):
|
||||||
|
return to_python_reader(self.thisptr.getByField(field.thisptr), self._parent)
|
||||||
|
|
||||||
def _has(self, field):
|
def _has(self, field):
|
||||||
return self.thisptr.has(field)
|
return self.thisptr.has(field)
|
||||||
|
|
||||||
|
def _has_by_field(self, _StructSchemaField field):
|
||||||
|
return self.thisptr.hasByField(field.thisptr)
|
||||||
|
|
||||||
cpdef _which(self):
|
cpdef _which(self):
|
||||||
"""Returns the enum corresponding to the union in this struct
|
"""Returns the enum corresponding to the union in this struct
|
||||||
|
|
||||||
@@ -1048,18 +1054,28 @@ cdef class _DynamicStructBuilder:
|
|||||||
|
|
||||||
return to_python_builder(value, self._parent)
|
return to_python_builder(value, self._parent)
|
||||||
|
|
||||||
|
def _get_by_field(self, _StructSchemaField field):
|
||||||
|
return to_python_builder(self.thisptr.getByField(field.thisptr), self._parent)
|
||||||
|
|
||||||
def __getattr__(self, field):
|
def __getattr__(self, field):
|
||||||
return self._get(field)
|
return self._get(field)
|
||||||
|
|
||||||
cdef _set(self, field, value):
|
cdef _set(self, field, value):
|
||||||
_setDynamicField(self.thisptr, field, value, self._parent)
|
_setDynamicField(self.thisptr, field, value, self._parent)
|
||||||
|
|
||||||
|
def _set_by_field(self, _StructSchemaField field, value):
|
||||||
|
# TODO: make this faster
|
||||||
|
_setDynamicField(self.thisptr, field.proto.name, value, self._parent)
|
||||||
|
|
||||||
def __setattr__(self, field, value):
|
def __setattr__(self, field, value):
|
||||||
self._set(field, value)
|
self._set(field, value)
|
||||||
|
|
||||||
def _has(self, field):
|
def _has(self, field):
|
||||||
return self.thisptr.has(field)
|
return self.thisptr.has(field)
|
||||||
|
|
||||||
|
def _has_by_field(self, _StructSchemaField field):
|
||||||
|
return self.thisptr.hasByField(field.thisptr)
|
||||||
|
|
||||||
cpdef init(self, field, size=None):
|
cpdef init(self, field, size=None):
|
||||||
"""Method for initializing fields that are of type union/struct/list
|
"""Method for initializing fields that are of type union/struct/list
|
||||||
|
|
||||||
@@ -1080,6 +1096,26 @@ cdef class _DynamicStructBuilder:
|
|||||||
else:
|
else:
|
||||||
return to_python_builder(self.thisptr.init(field, size), self._parent)
|
return to_python_builder(self.thisptr.init(field, size), self._parent)
|
||||||
|
|
||||||
|
def _init_by_field(self, _StructSchemaField field, size=None):
|
||||||
|
"""Method for initializing fields that are of type union/struct/list
|
||||||
|
|
||||||
|
Typically, you don't have to worry about initializing structs/unions, so this method is mainly for lists.
|
||||||
|
|
||||||
|
:type field: str
|
||||||
|
:param field: The field name to initialize
|
||||||
|
|
||||||
|
:type size: int
|
||||||
|
:param size: The size of the list to initiialize. This should be None for struct/union initialization.
|
||||||
|
|
||||||
|
:rtype: :class:`_DynamicStructBuilder` or :class:`_DynamicListBuilder`
|
||||||
|
|
||||||
|
:Raises: :exc:`exceptions.ValueError` if the field isn't in this struct
|
||||||
|
"""
|
||||||
|
if size is None:
|
||||||
|
return to_python_builder(self.thisptr.initByField(field.thisptr), self._parent)
|
||||||
|
else:
|
||||||
|
return to_python_builder(self.thisptr.initByField(field.thisptr, size), self._parent)
|
||||||
|
|
||||||
cpdef init_resizable_list(self, field):
|
cpdef init_resizable_list(self, field):
|
||||||
"""Method for initializing fields that are of type list (of structs)
|
"""Method for initializing fields that are of type list (of structs)
|
||||||
|
|
||||||
@@ -2129,12 +2165,13 @@ cdef class _Schema:
|
|||||||
|
|
||||||
cdef class _StructSchema:
|
cdef class _StructSchema:
|
||||||
cdef C_StructSchema thisptr
|
cdef C_StructSchema thisptr
|
||||||
cdef object __fieldnames, __union_fields, __non_union_fields
|
cdef object __fieldnames, __union_fields, __non_union_fields, __fields
|
||||||
cdef _init(self, C_StructSchema other):
|
cdef _init(self, C_StructSchema other):
|
||||||
self.thisptr = other
|
self.thisptr = other
|
||||||
self.__fieldnames = None
|
self.__fieldnames = None
|
||||||
self.__union_fields = None
|
self.__union_fields = None
|
||||||
self.__non_union_fields = None
|
self.__non_union_fields = None
|
||||||
|
self.__fields = None
|
||||||
return self
|
return self
|
||||||
|
|
||||||
property fieldnames:
|
property fieldnames:
|
||||||
@@ -2170,6 +2207,17 @@ cdef class _StructSchema:
|
|||||||
for i in xrange(nfields))
|
for i in xrange(nfields))
|
||||||
return self.__non_union_fields
|
return self.__non_union_fields
|
||||||
|
|
||||||
|
property fields:
|
||||||
|
"""A tuple of the field names in the struct."""
|
||||||
|
def __get__(self):
|
||||||
|
if self.__fields is not None:
|
||||||
|
return self.__fields
|
||||||
|
fieldlist = self.thisptr.getFields()
|
||||||
|
nfields = fieldlist.size()
|
||||||
|
self.__fields = {<char*>fieldlist[i].getProto().getName().cStr() : _StructSchemaField()._init(fieldlist[i], self)
|
||||||
|
for i in xrange(nfields)}
|
||||||
|
return self.__fields
|
||||||
|
|
||||||
property node:
|
property node:
|
||||||
"""The raw schema node"""
|
"""The raw schema node"""
|
||||||
def __get__(self):
|
def __get__(self):
|
||||||
@@ -2315,13 +2363,14 @@ class _StructModule(object):
|
|||||||
for field in schema.node.struct.fields:
|
for field in schema.node.struct.fields:
|
||||||
if field.which() == 'group':
|
if field.which() == 'group':
|
||||||
name = field.name.capitalize()
|
name = field.name.capitalize()
|
||||||
union_schema = schema.get_dependency(field.group.typeId).node.struct
|
raw_schema = schema.get_dependency(field.group.typeId)
|
||||||
|
union_schema = raw_schema.node.struct
|
||||||
|
|
||||||
if union_schema.discriminantCount == 0:
|
if union_schema.discriminantCount == 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
union_module = _StructModuleWhich()
|
union_module = _StructModuleWhich()
|
||||||
setattr(union_module, 'schema', union_schema)
|
setattr(union_module, 'schema', raw_schema.as_struct())
|
||||||
for union_field in union_schema.fields:
|
for union_field in union_schema.fields:
|
||||||
setattr(union_module, union_field.name, union_field.discriminantValue)
|
setattr(union_module, union_field.name, union_field.discriminantValue)
|
||||||
setattr(self, name, union_module)
|
setattr(self, name, union_module)
|
||||||
|
|||||||
@@ -192,6 +192,75 @@ def test_addressbook_resizable(addressbook):
|
|||||||
f = open('example', 'r')
|
f = open('example', 'r')
|
||||||
printAddressBook(f)
|
printAddressBook(f)
|
||||||
|
|
||||||
|
def test_addressbook_explicit_fields(addressbook):
|
||||||
|
def writeAddressBook(file):
|
||||||
|
addresses = addressbook.AddressBook.new_message()
|
||||||
|
address_fields = addressbook.AddressBook.schema.fields
|
||||||
|
person_fields = addressbook.Person.schema.fields
|
||||||
|
phone_fields = addressbook.Person.PhoneNumber.schema.fields
|
||||||
|
people = addresses._init_by_field(address_fields['people'], 2)
|
||||||
|
|
||||||
|
alice = people[0]
|
||||||
|
alice._set_by_field(person_fields['id'], 123)
|
||||||
|
alice._set_by_field(person_fields['name'], 'Alice')
|
||||||
|
alice._set_by_field(person_fields['email'], 'alice@example.com')
|
||||||
|
alicePhones = alice._init_by_field(person_fields['phones'], 1)
|
||||||
|
alicePhones[0]._set_by_field(phone_fields['number'], "555-1212")
|
||||||
|
alicePhones[0]._set_by_field(phone_fields['type'], 'mobile')
|
||||||
|
employment = alice._get_by_field(person_fields['employment'])
|
||||||
|
employment._set_by_field(addressbook.Person.Employment.schema.fields['school'], "MIT")
|
||||||
|
|
||||||
|
bob = people[1]
|
||||||
|
bob._set_by_field(person_fields['id'], 456)
|
||||||
|
bob._set_by_field(person_fields['name'], 'Bob')
|
||||||
|
bob._set_by_field(person_fields['email'], 'bob@example.com')
|
||||||
|
bobPhones = bob._init_by_field(person_fields['phones'], 2)
|
||||||
|
bobPhones[0]._set_by_field(phone_fields['number'], "555-4567")
|
||||||
|
bobPhones[0]._set_by_field(phone_fields['type'], 'home')
|
||||||
|
bobPhones[1]._set_by_field(phone_fields['number'], "555-7654")
|
||||||
|
bobPhones[1]._set_by_field(phone_fields['type'], 'work')
|
||||||
|
employment = bob._get_by_field(person_fields['employment'])
|
||||||
|
employment._set_by_field(addressbook.Person.Employment.schema.fields['unemployed'], None)
|
||||||
|
|
||||||
|
addresses.write(file)
|
||||||
|
|
||||||
|
|
||||||
|
def printAddressBook(file):
|
||||||
|
addresses = addressbook.AddressBook.read(file)
|
||||||
|
address_fields = addressbook.AddressBook.schema.fields
|
||||||
|
person_fields = addressbook.Person.schema.fields
|
||||||
|
phone_fields = addressbook.Person.PhoneNumber.schema.fields
|
||||||
|
|
||||||
|
people = addresses._get_by_field(address_fields['people'])
|
||||||
|
|
||||||
|
alice = people[0]
|
||||||
|
assert alice._get_by_field(person_fields['id']) == 123
|
||||||
|
assert alice._get_by_field(person_fields['name']) == 'Alice'
|
||||||
|
assert alice._get_by_field(person_fields['email']) == 'alice@example.com'
|
||||||
|
alicePhones = alice._get_by_field(person_fields['phones'])
|
||||||
|
assert alicePhones[0]._get_by_field(phone_fields['number']) == "555-1212"
|
||||||
|
assert alicePhones[0]._get_by_field(phone_fields['type']) == 'mobile'
|
||||||
|
employment = alice._get_by_field(person_fields['employment'])
|
||||||
|
employment._get_by_field(addressbook.Person.Employment.schema.fields['school']) == "MIT"
|
||||||
|
|
||||||
|
bob = people[1]
|
||||||
|
assert bob._get_by_field(person_fields['id']) == 456
|
||||||
|
assert bob._get_by_field(person_fields['name']) == 'Bob'
|
||||||
|
assert bob._get_by_field(person_fields['email']) == 'bob@example.com'
|
||||||
|
bobPhones = bob._get_by_field(person_fields['phones'])
|
||||||
|
assert bobPhones[0]._get_by_field(phone_fields['number']) == "555-4567"
|
||||||
|
assert bobPhones[0]._get_by_field(phone_fields['type']) == 'home'
|
||||||
|
assert bobPhones[1]._get_by_field(phone_fields['number']) == "555-7654"
|
||||||
|
assert bobPhones[1]._get_by_field(phone_fields['type']) == 'work'
|
||||||
|
employment = bob._get_by_field(person_fields['employment'])
|
||||||
|
employment._get_by_field(addressbook.Person.Employment.schema.fields['unemployed']) == None
|
||||||
|
|
||||||
|
|
||||||
|
f = open('example', 'w')
|
||||||
|
writeAddressBook(f)
|
||||||
|
|
||||||
|
f = open('example', 'r')
|
||||||
|
printAddressBook(f)
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def all_types():
|
def all_types():
|
||||||
|
|||||||
@@ -187,3 +187,12 @@ def test_to_dict_enum(addressbook):
|
|||||||
field = person.to_dict()['phones'][0]['type']
|
field = person.to_dict()['phones'][0]['type']
|
||||||
assert isstr(field)
|
assert isstr(field)
|
||||||
assert field == 'mobile'
|
assert field == 'mobile'
|
||||||
|
|
||||||
|
def test_explicit_field(addressbook):
|
||||||
|
person = addressbook.Person.new_message(**{'name': 'Test'})
|
||||||
|
|
||||||
|
name_field = addressbook.Person.schema.fields['name']
|
||||||
|
|
||||||
|
assert person.name == person._get_by_field(name_field)
|
||||||
|
assert person.name == person.as_reader()._get_by_field(name_field)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user