20
import xml.parsers.expat
24
def __init__(self, key, value):
32
def __init__(self, name, signature):
34
self.signature = signature
41
def __init__(self, name, h_type_implies_unix_fd=True):
43
self.h_type_implies_unix_fd = h_type_implies_unix_fd
49
self.deprecated = False
54
def __init__(self, name):
60
self.deprecated = False
64
def __init__(self, name, signature, access):
66
self.signature = signature
69
self.arg = Arg("value", self.signature)
70
self.arg.annotations = self.annotations
73
if self.access == "readwrite":
76
elif self.access == "read":
78
elif self.access == "write":
81
raise ValueError('Invalid access type "{}"'.format(self.access))
84
self.deprecated = False
85
self.emits_changed_signal = True
89
def __init__(self, name):
96
self.doc_string_brief = ""
98
self.deprecated = False
104
STATE_INTERFACE = "interface"
105
STATE_METHOD = "method"
106
STATE_SIGNAL = "signal"
107
STATE_PROPERTY = "property"
109
STATE_ANNOTATION = "annotation"
110
STATE_IGNORED = "ignored"
112
def __init__(self, xml_data, h_type_implies_unix_fd=True):
113
self._parser = xml.parsers.expat.ParserCreate()
114
self._parser.CommentHandler = self.handle_comment
115
self._parser.CharacterDataHandler = self.handle_char_data
116
self._parser.StartElementHandler = self.handle_start_element
117
self._parser.EndElementHandler = self.handle_end_element
119
self.parsed_interfaces = []
120
self._cur_object = None
122
self.state = DBusXMLParser.STATE_TOP
123
self.state_stack = []
124
self._cur_object = None
125
self._cur_object_stack = []
127
self.doc_comment_last_symbol = ""
129
self._h_type_implies_unix_fd = h_type_implies_unix_fd
131
self._parser.Parse(xml_data)
133
COMMENT_STATE_BEGIN = "begin"
134
COMMENT_STATE_PARAMS = "params"
135
COMMENT_STATE_BODY = "body"
136
COMMENT_STATE_SKIP = "skip"
138
def handle_comment(self, data):
139
comment_state = DBusXMLParser.COMMENT_STATE_BEGIN
140
lines = data.split("\n")
148
if comment_state == DBusXMLParser.COMMENT_STATE_BEGIN:
150
colon_index = line.find(": ")
151
if colon_index == -1:
152
if line.endswith(":"):
153
symbol = line[0 : len(line) - 1]
154
comment_state = DBusXMLParser.COMMENT_STATE_PARAMS
156
comment_state = DBusXMLParser.COMMENT_STATE_SKIP
158
symbol = line[0:colon_index]
159
rest_of_line = line[colon_index + 2 :].strip()
160
if len(rest_of_line) > 0:
161
body += rest_of_line + "\n"
162
comment_state = DBusXMLParser.COMMENT_STATE_PARAMS
163
elif comment_state == DBusXMLParser.COMMENT_STATE_PARAMS:
164
if line.startswith("@"):
165
colon_index = line.find(": ")
166
if colon_index == -1:
167
comment_state = DBusXMLParser.COMMENT_STATE_BODY
170
body += orig_line + "\n"
172
param = line[1:colon_index]
173
docs = line[colon_index + 2 :]
176
comment_state = DBusXMLParser.COMMENT_STATE_BODY
180
body += orig_line + "\n"
181
elif comment_state == DBusXMLParser.COMMENT_STATE_BODY:
185
body += orig_line + "\n"
194
self.doc_comment_last_symbol = symbol
195
self.doc_comment_params = params
196
self.doc_comment_body = body
198
def handle_char_data(self, data):
202
def handle_start_element(self, name, attrs):
203
old_state = self.state
204
old_cur_object = self._cur_object
205
if self.state == DBusXMLParser.STATE_IGNORED:
206
self.state = DBusXMLParser.STATE_IGNORED
207
elif self.state == DBusXMLParser.STATE_TOP:
208
if name == DBusXMLParser.STATE_NODE:
209
self.state = DBusXMLParser.STATE_NODE
211
self.state = DBusXMLParser.STATE_IGNORED
212
elif self.state == DBusXMLParser.STATE_NODE:
213
if name == DBusXMLParser.STATE_INTERFACE:
214
self.state = DBusXMLParser.STATE_INTERFACE
215
iface = Interface(attrs["name"])
216
self._cur_object = iface
217
self.parsed_interfaces.append(iface)
218
elif name == DBusXMLParser.STATE_ANNOTATION:
219
self.state = DBusXMLParser.STATE_ANNOTATION
220
anno = Annotation(attrs["name"], attrs["value"])
221
self._cur_object.annotations.append(anno)
222
self._cur_object = anno
224
self.state = DBusXMLParser.STATE_IGNORED
227
if "name" in attrs and self.doc_comment_last_symbol == attrs["name"]:
228
self._cur_object.doc_string = self.doc_comment_body
229
if "short_description" in self.doc_comment_params:
230
short_description = self.doc_comment_params["short_description"]
231
self._cur_object.doc_string_brief = short_description
232
if "since" in self.doc_comment_params:
233
self._cur_object.since = self.doc_comment_params["since"].strip()
235
elif self.state == DBusXMLParser.STATE_INTERFACE:
236
if name == DBusXMLParser.STATE_METHOD:
237
self.state = DBusXMLParser.STATE_METHOD
239
attrs["name"], h_type_implies_unix_fd=self._h_type_implies_unix_fd
241
self._cur_object.methods.append(method)
242
self._cur_object = method
243
elif name == DBusXMLParser.STATE_SIGNAL:
244
self.state = DBusXMLParser.STATE_SIGNAL
245
signal = Signal(attrs["name"])
246
self._cur_object.signals.append(signal)
247
self._cur_object = signal
248
elif name == DBusXMLParser.STATE_PROPERTY:
249
self.state = DBusXMLParser.STATE_PROPERTY
250
prop = Property(attrs["name"], attrs["type"], attrs["access"])
251
self._cur_object.properties.append(prop)
252
self._cur_object = prop
253
elif name == DBusXMLParser.STATE_ANNOTATION:
254
self.state = DBusXMLParser.STATE_ANNOTATION
255
anno = Annotation(attrs["name"], attrs["value"])
256
self._cur_object.annotations.append(anno)
257
self._cur_object = anno
259
self.state = DBusXMLParser.STATE_IGNORED
262
if "name" in attrs and self.doc_comment_last_symbol == attrs["name"]:
263
self._cur_object.doc_string = self.doc_comment_body
264
if "since" in self.doc_comment_params:
265
self._cur_object.since = self.doc_comment_params["since"].strip()
267
elif self.state == DBusXMLParser.STATE_METHOD:
268
if name == DBusXMLParser.STATE_ARG:
269
self.state = DBusXMLParser.STATE_ARG
272
arg_name = attrs["name"]
273
arg = Arg(arg_name, attrs["type"])
274
direction = attrs.get("direction", "in")
275
if direction == "in":
276
self._cur_object.in_args.append(arg)
277
elif direction == "out":
278
self._cur_object.out_args.append(arg)
280
raise ValueError('Invalid direction "{}"'.format(direction))
281
self._cur_object = arg
282
elif name == DBusXMLParser.STATE_ANNOTATION:
283
self.state = DBusXMLParser.STATE_ANNOTATION
284
anno = Annotation(attrs["name"], attrs["value"])
285
self._cur_object.annotations.append(anno)
286
self._cur_object = anno
288
self.state = DBusXMLParser.STATE_IGNORED
291
if self.doc_comment_last_symbol == old_cur_object.name:
292
if "name" in attrs and attrs["name"] in self.doc_comment_params:
293
doc_string = self.doc_comment_params[attrs["name"]]
294
if doc_string is not None:
295
self._cur_object.doc_string = doc_string
296
if "since" in self.doc_comment_params:
297
self._cur_object.since = self.doc_comment_params[
301
elif self.state == DBusXMLParser.STATE_SIGNAL:
302
if name == DBusXMLParser.STATE_ARG:
303
self.state = DBusXMLParser.STATE_ARG
306
arg_name = attrs["name"]
307
arg = Arg(arg_name, attrs["type"])
308
self._cur_object.args.append(arg)
309
self._cur_object = arg
310
elif name == DBusXMLParser.STATE_ANNOTATION:
311
self.state = DBusXMLParser.STATE_ANNOTATION
312
anno = Annotation(attrs["name"], attrs["value"])
313
self._cur_object.annotations.append(anno)
314
self._cur_object = anno
316
self.state = DBusXMLParser.STATE_IGNORED
319
if self.doc_comment_last_symbol == old_cur_object.name:
320
if "name" in attrs and attrs["name"] in self.doc_comment_params:
321
doc_string = self.doc_comment_params[attrs["name"]]
322
if doc_string is not None:
323
self._cur_object.doc_string = doc_string
324
if "since" in self.doc_comment_params:
325
self._cur_object.since = self.doc_comment_params[
329
elif self.state == DBusXMLParser.STATE_PROPERTY:
330
if name == DBusXMLParser.STATE_ANNOTATION:
331
self.state = DBusXMLParser.STATE_ANNOTATION
332
anno = Annotation(attrs["name"], attrs["value"])
333
self._cur_object.annotations.append(anno)
334
self._cur_object = anno
336
self.state = DBusXMLParser.STATE_IGNORED
338
elif self.state == DBusXMLParser.STATE_ARG:
339
if name == DBusXMLParser.STATE_ANNOTATION:
340
self.state = DBusXMLParser.STATE_ANNOTATION
341
anno = Annotation(attrs["name"], attrs["value"])
342
self._cur_object.annotations.append(anno)
343
self._cur_object = anno
345
self.state = DBusXMLParser.STATE_IGNORED
347
elif self.state == DBusXMLParser.STATE_ANNOTATION:
348
if name == DBusXMLParser.STATE_ANNOTATION:
349
self.state = DBusXMLParser.STATE_ANNOTATION
350
anno = Annotation(attrs["name"], attrs["value"])
351
self._cur_object.annotations.append(anno)
352
self._cur_object = anno
354
self.state = DBusXMLParser.STATE_IGNORED
358
'Unhandled state "{}" while entering element with name "{}"'.format(
363
self.state_stack.append(old_state)
364
self._cur_object_stack.append(old_cur_object)
366
def handle_end_element(self, name):
367
self.state = self.state_stack.pop()
368
self._cur_object = self._cur_object_stack.pop()
371
def parse_dbus_xml(xml_data):
372
parser = DBusXMLParser(xml_data, True)
373
return parser.parsed_interfaces