Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
class ObjectProperties:
"""
Class encapsulating the protobuf API, acting as adapter.
The idea is that the user should simply have to call
obj = ObjectProperties.getInstance(pb2_reference)
where pb2_reference is the generated python file by protobuf based on the users features.
The user then can simply use obj.set('attr', value) to set the value. __getitem__ accessor is with protobuf
extensions very complicated.
"""
def __init__(self, ref, instance):
"""
Parameters
----------
ref
reference to the protobuf type (class)
instance
Property instance
"""
object.__setattr__(self, 'pb2_ref', ref)
object.__setattr__(self, 'pb2_instance', instance)
@staticmethod
def get_instance(ref_pb2):
"""
Get an instance of a new empty object based on the given protobuf description.
Parameters
----------
ref_pb2
Reference to the type of protobuf object.
Returns
-------
The object properties to be filled.
"""
instance_constructor = getattr(ref_pb2.identification__pb2, 'Properties')
instance = instance_constructor()
return ObjectProperties(ref_pb2, instance)
@staticmethod
def add_to_objects(object_block_ref, obj_prop, id=None):
"""
Add the given id-object pair to the object block in the protobuf description. If id is None or not given, auto
assign an ID which is currently not taken in this object block.
Parameters
----------
object_block_ref
Reference to the object block for this subset.
obj_prop
The ObjectProperties object to be added.
id
ID to be set for the object. Can be for example the ID set in a labeled field.
"""
if id is None:
ids_in_use = [o.id for o in object_block_ref]
# pick first free id of object block
for cur_id in range(1, len(ids_in_use) + 2):
if cur_id not in ids_in_use:
id = cur_id
break
obj = object_block_ref.add()
obj.id = id
pb2_prop = obj_prop.as_pb2()
obj.properties.CopyFrom(pb2_prop)
def as_pb2(self):
return object.__getattribute__(self, 'pb2_instance')
@staticmethod
def remove_from_objects(object_block_ref, obj_instance):
"""
Parameters
----------
object_block_ref
Reference to the object block for this subset.
obj_instance
The object instance to be removed
Returns
-------
"""
# obj_instance = obj_instance.pb2_instance
for o in object_block_ref:
if o.properties == obj_instance.pb2_instance:
object_block_ref.remove(o)
return
raise ValueError("ObjectProperties to be removed not in given block.")
# TODO does this work with repeated fields? e.g. obj.foo[0].bar
def set(self, attr, value):
"""
Set an attribute of the object description.
Parameters
----------
attr : str
Name of attribute, e.g. 'foo' or if nested 'foo.bar'
value : the value
"""
attr_splits = attr.split('.')
if len(attr_splits) == 1:
self.pb2_instance.Extensions[getattr(self.pb2_ref, attr)] = value
else:
accessor = self.pb2_instance.Extensions[getattr(self.pb2_ref, attr_splits[0])]
for i in range(1, len(attr_splits) - 1):
accessor = getattr(accessor, attr_splits[i])
setattr(accessor, attr_splits[-1], value)
def get(self, attr):
"""
Getter for attributes in object description.
Parameters
----------
attr : str
Name of attribute.
Returns
-------
Value of attribute.
"""
attr_splits = attr.split('.')
if len(attr_splits) == 1:
return self.pb2_instance.Extensions[getattr(self.pb2_ref, attr)]
else:
accessor = self.pb2_instance.Extensions[getattr(self.pb2_ref, attr_splits[0])]
for i in range(1, len(attr_splits) - 1):
accessor = getattr(accessor, attr_splits[i])
return getattr(accessor, attr_splits[-1])