swrast: simplify assertion to silence warning
[mesa.git] / src / gallium / tests / python / retrace / interpreter.py
1 #!/usr/bin/env python
2 ##########################################################################
3 #
4 # Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
5 # All Rights Reserved.
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining a
8 # copy of this software and associated documentation files (the
9 # "Software"), to deal in the Software without restriction, including
10 # without limitation the rights to use, copy, modify, merge, publish,
11 # distribute, sub license, and/or sell copies of the Software, and to
12 # permit persons to whom the Software is furnished to do so, subject to
13 # the following conditions:
14 #
15 # The above copyright notice and this permission notice (including the
16 # next paragraph) shall be included in all copies or substantial portions
17 # of the Software.
18 #
19 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 # IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23 # ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #
27 ##########################################################################
28
29
30 import sys
31 import struct
32
33 import gallium
34 import model
35 import parse as parser
36
37
38 try:
39 from struct import unpack_from
40 except ImportError:
41 def unpack_from(fmt, buf, offset=0):
42 size = struct.calcsize(fmt)
43 return struct.unpack(fmt, buf[offset:offset + size])
44
45
46 def make_image(ctx, surface, x=None, y=None, w=None, h=None):
47 if x is None:
48 x = 0
49 if y is None:
50 y = 0
51 if w is None:
52 w = surface.width - x
53 if h is None:
54 h = surface.height - y
55 data = ctx.surface_read_rgba8(surface, x, y, surface.width, surface.height)
56
57 import Image
58 outimage = Image.fromstring('RGBA', (w, h), data, "raw", 'RGBA', 0, 1)
59 return outimage
60
61 def save_image(ctx, filename, surface, x=None, y=None, w=None, h=None):
62 outimage = make_image(ctx, surface, x, y, w, h)
63 outimage.save(filename, "PNG")
64
65 def show_image(ctx, surface, title, x=None, y=None, w=None, h=None):
66 outimage = make_image(ctx, surface, x, y, w, h)
67
68 import Tkinter as tk
69 from PIL import Image, ImageTk
70 root = tk.Tk()
71
72 root.title(title)
73
74 image1 = ImageTk.PhotoImage(outimage)
75 w = image1.width()
76 h = image1.height()
77 x = 100
78 y = 100
79 root.geometry("%dx%d+%d+%d" % (w, h, x, y))
80 panel1 = tk.Label(root, image=image1)
81 panel1.pack(side='top', fill='both', expand='yes')
82 panel1.image = image1
83 root.mainloop()
84
85
86 class Struct:
87 """C-like struct"""
88
89 # A basic Python class can pass as a C-like structure
90 pass
91
92
93 struct_factories = {
94 "pipe_blend_color": gallium.BlendColor,
95 "pipe_blend_state": gallium.Blend,
96 #"pipe_clip_state": gallium.Clip,
97 #"pipe_buffer": gallium.Buffer,
98 "pipe_depth_state": gallium.Depth,
99 "pipe_stencil_state": gallium.Stencil,
100 "pipe_alpha_state": gallium.Alpha,
101 "pipe_depth_stencil_alpha_state": gallium.DepthStencilAlpha,
102 #"pipe_framebuffer_state": gallium.Framebuffer,
103 "pipe_poly_stipple": gallium.PolyStipple,
104 "pipe_rasterizer_state": gallium.Rasterizer,
105 "pipe_sampler_state": gallium.Sampler,
106 "pipe_scissor_state": gallium.Scissor,
107 #"pipe_shader_state": gallium.Shader,
108 #"pipe_vertex_buffer": gallium.VertexBuffer,
109 "pipe_vertex_element": gallium.VertexElement,
110 "pipe_viewport_state": gallium.Viewport,
111 #"pipe_texture": gallium.Texture,
112 'pipe_subresource': gallium.pipe_subresource,
113 'pipe_box': gallium.pipe_box,
114 'pipe_draw_info': gallium.pipe_draw_info,
115 }
116
117
118 member_array_factories = {
119 #"pipe_rasterizer_state": {"sprite_coord_mode": gallium.ByteArray},
120 "pipe_poly_stipple": {"stipple": gallium.UnsignedArray},
121 "pipe_viewport_state": {"scale": gallium.FloatArray, "translate": gallium.FloatArray},
122 #"pipe_clip_state": {"ucp": gallium.FloatArray},
123 "pipe_depth_stencil_alpha_state": {"stencil": gallium.StencilArray},
124 "pipe_blend_color": {"color": gallium.FloatArray},
125 "pipe_sampler_state": {"border_color": gallium.FloatArray},
126 }
127
128
129 class Translator(model.Visitor):
130 """Translate model arguments into regular Python objects"""
131
132 def __init__(self, interpreter):
133 self.interpreter = interpreter
134 self.result = None
135
136 def visit(self, node):
137 self.result = None
138 node.visit(self)
139 return self.result
140
141 def visit_literal(self, node):
142 self.result = node.value
143
144 def visit_named_constant(self, node):
145 # lookup the named constant in the gallium module
146 self.result = getattr(gallium, node.name)
147
148 def visit_array(self, node):
149 array = []
150 for element in node.elements:
151 array.append(self.visit(element))
152 self.result = array
153
154 def visit_struct(self, node):
155 struct_factory = struct_factories.get(node.name, Struct)
156 struct = struct_factory()
157 for member_name, member_node in node.members:
158 member_value = self.visit(member_node)
159 try:
160 array_factory = member_array_factories[node.name][member_name]
161 except KeyError:
162 pass
163 else:
164 assert isinstance(member_value, list)
165 array = array_factory(len(member_value))
166 for i in range(len(member_value)):
167 array[i] = member_value[i]
168 member_value = array
169 #print node.name, member_name, member_value
170 assert isinstance(struct, Struct) or hasattr(struct, member_name)
171 setattr(struct, member_name, member_value)
172 self.result = struct
173
174 def visit_pointer(self, node):
175 self.result = self.interpreter.lookup_object(node.address)
176
177
178 class Object:
179
180 def __init__(self, interpreter, real):
181 self.interpreter = interpreter
182 self.real = real
183
184
185 class Global(Object):
186
187 def __init__(self, interpreter, real):
188 self.interpreter = interpreter
189 self.real = real
190
191 def pipe_screen_create(self):
192 real = gallium.Device()
193 return Screen(self.interpreter, real)
194
195 def pipe_context_create(self, screen):
196 context = screen.real.context_create()
197 return Context(self.interpreter, context)
198
199
200 class Transfer:
201
202 def __init__(self, resource, usage, subresource, box):
203 self.resource = resource
204 self.usage = usage
205 self.subresource = subresource
206 self.box = box
207
208
209 class Screen(Object):
210
211 def __init__(self, interpreter, real):
212 Object.__init__(self, interpreter, real)
213 self.context = self.real.context_create()
214
215 def destroy(self):
216 pass
217
218 def get_name(self):
219 pass
220
221 def get_vendor(self):
222 pass
223
224 def get_param(self, param):
225 pass
226
227 def get_paramf(self, param):
228 pass
229
230 def context_create(self):
231 context = self.real.context_create()
232 return Context(self.interpreter, context)
233
234 def is_format_supported(self, format, target, sample_count, bind, geom_flags):
235 return self.real.is_format_supported(format, target, sample_count, bind, geom_flags)
236
237 def resource_create(self, templat):
238 return self.real.resource_create(
239 format = templat.format,
240 width = templat.width,
241 height = templat.height,
242 depth = templat.depth,
243 last_level = templat.last_level,
244 target = templat.target,
245 bind = templat.bind,
246 )
247
248 def texture_destroy(self, texture):
249 self.interpreter.unregister_object(texture)
250
251 def texture_release(self, surface):
252 pass
253
254 def tex_surface_release(self, surface):
255 pass
256
257 def user_buffer_create(self, data, size, usage):
258 bind = usage
259 # We don't really care to distinguish between user and regular buffers
260 buffer = self.real.buffer_create(size, bind)
261 assert size == len(data)
262 self.context.buffer_write(buffer, data)
263 return buffer
264
265 def buffer_create(self, alignment, usage, size):
266 return self.real.buffer_create(size, alignment, usage)
267
268 def buffer_destroy(self, buffer):
269 pass
270
271 def fence_finish(self, fence, flags):
272 pass
273
274 def fence_reference(self, dst, src):
275 pass
276
277 def flush_frontbuffer(self, resource):
278 pass
279
280
281 class Context(Object):
282
283 def __init__(self, interpreter, real):
284 Object.__init__(self, interpreter, real)
285 self.cbufs = []
286 self.zsbuf = None
287 self.vbufs = []
288 self.velems = []
289 self.dirty = False
290
291 def destroy(self):
292 pass
293
294 def create_blend_state(self, state):
295 if isinstance(state, str):
296 state = gallium.Blend(state)
297 sys.stdout.write('\t%s\n' % state)
298 return state
299
300 def bind_blend_state(self, state):
301 if state is not None:
302 self.real.set_blend(state)
303
304 def delete_blend_state(self, state):
305 pass
306
307 def create_sampler_state(self, state):
308 return state
309
310 def delete_sampler_state(self, state):
311 pass
312
313 def bind_vertex_sampler_states(self, num_states, states):
314 for i in range(num_states):
315 self.real.set_vertex_sampler(i, states[i])
316
317 def bind_fragment_sampler_states(self, num_states, states):
318 for i in range(num_states):
319 self.real.set_fragment_sampler(i, states[i])
320
321 def create_rasterizer_state(self, state):
322 return state
323
324 def bind_rasterizer_state(self, state):
325 if state is not None:
326 self.real.set_rasterizer(state)
327
328 def delete_rasterizer_state(self, state):
329 pass
330
331 def create_depth_stencil_alpha_state(self, state):
332 return state
333
334 def bind_depth_stencil_alpha_state(self, state):
335 if state is not None:
336 self.real.set_depth_stencil_alpha(state)
337
338 def delete_depth_stencil_alpha_state(self, state):
339 pass
340
341 def create_fs_state(self, state):
342 tokens = str(state.tokens)
343 shader = gallium.Shader(tokens)
344 return shader
345
346 create_vs_state = create_fs_state
347
348 def bind_fs_state(self, state):
349 self.real.set_fragment_shader(state)
350
351 def bind_vs_state(self, state):
352 self.real.set_vertex_shader(state)
353
354 def delete_fs_state(self, state):
355 pass
356
357 delete_vs_state = delete_fs_state
358
359 def set_blend_color(self, state):
360 self.real.set_blend_color(state)
361
362 def set_stencil_ref(self, state):
363 self.real.set_stencil_ref(state)
364
365 def set_clip_state(self, state):
366 _state = gallium.Clip()
367 _state.nr = state.nr
368 if state.nr:
369 # FIXME
370 ucp = gallium.FloatArray(gallium.PIPE_MAX_CLIP_PLANES*4)
371 for i in range(len(state.ucp)):
372 for j in range(len(state.ucp[i])):
373 ucp[i*4 + j] = state.ucp[i][j]
374 _state.ucp = ucp
375 self.real.set_clip(_state)
376
377 def dump_constant_buffer(self, buffer):
378 if not self.interpreter.verbosity(2):
379 return
380
381 data = self.real.buffer_read(buffer)
382 format = '4f'
383 index = 0
384 for offset in range(0, len(data), struct.calcsize(format)):
385 x, y, z, w = unpack_from(format, data, offset)
386 sys.stdout.write('\tCONST[%2u] = {%10.4f, %10.4f, %10.4f, %10.4f}\n' % (index, x, y, z, w))
387 index += 1
388 sys.stdout.flush()
389
390 def set_constant_buffer(self, shader, index, buffer):
391 if buffer is not None:
392 self.real.set_constant_buffer(shader, index, buffer)
393
394 self.dump_constant_buffer(buffer)
395
396 def set_framebuffer_state(self, state):
397 _state = gallium.Framebuffer()
398 _state.width = state.width
399 _state.height = state.height
400 _state.nr_cbufs = state.nr_cbufs
401 for i in range(len(state.cbufs)):
402 _state.set_cbuf(i, state.cbufs[i])
403 _state.set_zsbuf(state.zsbuf)
404 self.real.set_framebuffer(_state)
405
406 self.cbufs = state.cbufs
407 self.zsbuf = state.zsbuf
408
409 def set_polygon_stipple(self, state):
410 self.real.set_polygon_stipple(state)
411
412 def set_scissor_state(self, state):
413 self.real.set_scissor(state)
414
415 def set_viewport_state(self, state):
416 self.real.set_viewport(state)
417
418 def create_sampler_view(self, texture, templ):
419 return self.real.create_sampler_view(texture,
420 format = templ.format,
421 first_level = templ.first_level,
422 last_level = templ.last_level,
423 swizzle_r = templ.swizzle_r,
424 swizzle_g = templ.swizzle_r,
425 swizzle_b = templ.swizzle_g,
426 swizzle_a = templ.swizzle_a)
427
428 def sampler_view_destroy(self, view):
429 pass
430
431 def set_fragment_sampler_views(self, num, views):
432 for i in range(num):
433 self.real.set_fragment_sampler_view(i, views[i])
434
435 def set_vertex_sampler_views(self, num, views):
436 for i in range(num):
437 self.real.set_vertex_sampler_view(i, views[i])
438
439 def set_vertex_buffers(self, num_buffers, buffers):
440 self.vbufs = buffers[0:num_buffers]
441 for i in range(num_buffers):
442 vbuf = buffers[i]
443 self.real.set_vertex_buffer(
444 i,
445 stride = vbuf.stride,
446 max_index = vbuf.max_index,
447 buffer_offset = vbuf.buffer_offset,
448 buffer = vbuf.buffer,
449 )
450
451 def create_vertex_elements_state(self, num_elements, elements):
452 return elements[0:num_elements]
453
454 def bind_vertex_elements_state(self, state):
455 if state is None:
456 self.real.set_vertex_elements(0)
457 return
458
459 elements = state
460 num_elements = len(elements)
461 self.velems = elements
462 for i in range(num_elements):
463 self.real.set_vertex_element(i, elements[i])
464 self.real.set_vertex_elements(num_elements)
465
466 def delete_vertex_elements_state(self, state):
467 pass
468
469 def dump_vertices(self, start, count):
470 if not self.interpreter.verbosity(2):
471 return
472
473 for index in range(start, start + count):
474 if index >= start + 16:
475 sys.stdout.write('\t...\n')
476 break
477 sys.stdout.write('\t{\n')
478 for velem in self.velems:
479 vbuf = self.vbufs[velem.vertex_buffer_index]
480
481 offset = vbuf.buffer_offset + velem.src_offset + vbuf.stride*index
482 format = {
483 gallium.PIPE_FORMAT_R32_FLOAT: 'f',
484 gallium.PIPE_FORMAT_R32G32_FLOAT: '2f',
485 gallium.PIPE_FORMAT_R32G32B32_FLOAT: '3f',
486 gallium.PIPE_FORMAT_R32G32B32A32_FLOAT: '4f',
487 gallium.PIPE_FORMAT_A8R8G8B8_UNORM: '4B',
488 gallium.PIPE_FORMAT_R8G8B8A8_UNORM: '4B',
489 gallium.PIPE_FORMAT_B8G8R8A8_UNORM: '4B',
490 gallium.PIPE_FORMAT_R16G16B16_SNORM: '3h',
491 }[velem.src_format]
492
493 data = self.real.buffer_read(vbuf.buffer)
494 values = unpack_from(format, data, offset)
495 sys.stdout.write('\t\t{' + ', '.join(map(str, values)) + '},\n')
496 sys.stdout.write('\t},\n')
497 sys.stdout.flush()
498
499 def dump_indices(self, ibuf, isize, ibias, start, count):
500 if not self.interpreter.verbosity(2):
501 return
502
503 format = {
504 1: 'B',
505 2: 'H',
506 4: 'I',
507 }[isize]
508
509 assert struct.calcsize(format) == isize
510
511 data = self.real.buffer_read(ibuf)
512 maxindex, minindex = 0, 0xffffffff
513
514 sys.stdout.write('\t{\n')
515 for i in range(start, start + count):
516 if i >= start + 16 and not self.interpreter.verbosity(3):
517 sys.stdout.write('\t...\n')
518 break
519 offset = i*isize
520 index, = unpack_from(format, data, offset)
521 sys.stdout.write('\t\t%u,\n' % index)
522 minindex = min(minindex, index)
523 maxindex = max(maxindex, index)
524 sys.stdout.write('\t},\n')
525 sys.stdout.flush()
526
527 return minindex + ibias, maxindex + ibias
528
529 def set_index_buffer(self, ib):
530 if ib:
531 self.real.set_index_buffer(ib.index_size, ib.offset, ib.buffer)
532 else:
533 self.real.set_index_buffer(0, 0, None)
534
535 def draw_vbo(self, info):
536 if self.interpreter.verbosity(2):
537 if 0:
538 minindex, maxindex = self.dump_indices(indexBuffer, indexSize, indexBias, start, count)
539
540 self.dump_vertices(info.minindex, info.maxindex + 1 - info.minindex)
541
542 self.real.draw_vbo(info)
543 self._set_dirty()
544
545 def resource_copy_region(self, dst, subdst, dstx, dsty, dstz, src, subsrc, srcx, srcy, srcz, width, height):
546 if dst is not None and src is not None:
547 if self.interpreter.options.all:
548 self.interpreter.present(self.real, src, 'resource_copy_src', srcx, srcy, width, height)
549 self.real.resource_copy_region(dst, subdst, dstx, dsty, dstx, src, subsrc, srcx, srcy, srcz, width, height)
550 flags = 0
551 self.flush(flags)
552 if self.interpreter.options.all:
553 self.interpreter.present(self.real, dst, 'resource_copy_dst', dstx, dsty, width, height)
554
555 def is_resource_referenced(self, texture, face, level):
556 #return self.real.is_resource_referenced(format, texture, face, level)
557 pass
558
559 def buffer_write(self, buffer, data, size, offset=0):
560 assert size == len(data)
561 self.buffer_write(buffer, data)
562
563 def surface_write(self, surface, data, stride, size):
564 if surface is None:
565 return
566 # assert surface.nblocksy * stride == size
567 surface.put_tile_raw(0, 0, surface.width, surface.height, data, stride)
568
569 def get_transfer(self, texture, sr, usage, box):
570 if texture is None:
571 return None
572 transfer = Transfer(texture, sr, usage, box)
573 if transfer and usage & gallium.PIPE_TRANSFER_READ:
574 if self.interpreter.options.all:
575 surface = texture.get_surface(sr.face, sr.level, box.z)
576 self.interpreter.present(self.real, transfer.surface, 'transf_read', box.x, box.y, box.width, box.height)
577 return transfer
578
579 def tex_transfer_destroy(self, transfer):
580 self.interpreter.unregister_object(transfer)
581
582 def transfer_inline_write(self, resource, sr, usage, box, stride, slice_stride, data):
583 self.real.transfer_inline_write(resource, sr, usage, box, data, stride, slice_stride)
584 if self.interpreter.options.all:
585 for z in range(box.z, box.z + box.depth):
586 surface = resource.get_surface(sr.face, sr.level, box.z)
587 self.interpreter.present(self.real, surface, 'transf_inline_write%u' % z, box.x, box.y, box.width, box.height)
588
589 def _set_dirty(self):
590 if self.interpreter.options.step:
591 self._present()
592 else:
593 self.dirty = True
594
595 def flush(self, flags):
596 self.real.flush(flags)
597 if self.dirty:
598 if flags & gallium.PIPE_FLUSH_FRAME:
599 self._present()
600 self.dirty = False
601 return None
602
603 def clear(self, buffers, rgba, depth, stencil):
604 _rgba = gallium.FloatArray(4)
605 for i in range(4):
606 _rgba[i] = rgba[i]
607 self.real.clear(buffers, _rgba, depth, stencil)
608
609 def clear_render_target(self, dst, rgba, dstx, dsty, width, height):
610 _rgba = gallium.FloatArray(4)
611 for i in range(4):
612 _rgba[i] = rgba[i]
613 self.real.clear_render_target(dst, _rgba, dstx, dsty, width, height)
614
615 def clear_depth_stencil(self, dst, clear_flags, depth, stencil, dstx, dsty, width, height):
616 self.real.clear_depth_stencil(dst, clear_flags, depth, stencil, dstx, dsty, width, height)
617
618 def _present(self):
619 self.real.flush()
620
621 if self.cbufs and self.cbufs[0]:
622 self.interpreter.present(self.real, self.cbufs[0], "cbuf")
623 if self.zsbuf:
624 if self.interpreter.options.all:
625 self.interpreter.present(self.real, self.zsbuf, "zsbuf")
626 def create_surface(self, texture, level, layer, usage):
627 if texture is None:
628 return None
629 return texture.get_surface(level, layer)
630
631 def surface_destroy(self, surface):
632 self.interpreter.unregister_object(surface)
633
634 class Interpreter(parser.TraceDumper):
635
636 ignore_calls = set((
637 ('pipe_screen', 'is_format_supported'),
638 ('pipe_screen', 'get_param'),
639 ('pipe_screen', 'get_paramf'),
640 ))
641
642 def __init__(self, stream, options):
643 parser.TraceDumper.__init__(self, stream)
644 self.options = options
645 self.objects = {}
646 self.result = None
647 self.globl = Global(self, None)
648 self.call_no = None
649
650 def register_object(self, address, object):
651 self.objects[address] = object
652
653 def unregister_object(self, object):
654 # FIXME:
655 pass
656
657 def lookup_object(self, address):
658 return self.objects[address]
659
660 def interpret(self, trace):
661 for call in trace.calls:
662 self.interpret_call(call)
663
664 def handle_call(self, call):
665 if self.options.stop and call.no > self.options.stop:
666 sys.exit(0)
667
668 if (call.klass, call.method) in self.ignore_calls:
669 return
670
671 self.call_no = call.no
672
673 if self.verbosity(1):
674 parser.TraceDumper.handle_call(self, call)
675 sys.stdout.flush()
676
677 args = [(str(name), self.interpret_arg(arg)) for name, arg in call.args]
678
679 if call.klass:
680 name, obj = args[0]
681 args = args[1:]
682 else:
683 obj = self.globl
684
685 method = getattr(obj, call.method)
686 ret = method(**dict(args))
687
688 if call.ret and isinstance(call.ret, model.Pointer):
689 if ret is None:
690 sys.stderr.write('warning: NULL returned\n')
691 self.register_object(call.ret.address, ret)
692
693 self.call_no = None
694
695 def interpret_arg(self, node):
696 translator = Translator(self)
697 return translator.visit(node)
698
699 def verbosity(self, level):
700 return self.options.verbosity >= level
701
702 def present(self, ctx, surface, description, x=None, y=None, w=None, h=None):
703 if self.call_no < self.options.start:
704 return
705
706 if self.options.images:
707 filename = '%04u_%s.png' % (self.call_no, description)
708 save_image(ctx, filename, surface, x, y, w, h)
709 else:
710 title = '%u. %s' % (self.call_no, description)
711 show_image(ctx, surface, title, x, y, w, h)
712
713
714 class Main(parser.Main):
715
716 def get_optparser(self):
717 optparser = parser.Main.get_optparser(self)
718 optparser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbosity", help="no messages")
719 optparser.add_option("-v", "--verbose", action="count", dest="verbosity", default=1, help="increase verbosity level")
720 optparser.add_option("-i", "--images", action="store_true", dest="images", default=False, help="save images instead of showing them")
721 optparser.add_option("-a", "--all", action="store_true", dest="all", default=False, help="show depth, stencil, and transfers")
722 optparser.add_option("-s", "--step", action="store_true", dest="step", default=False, help="step trhough every draw")
723 optparser.add_option("-f", "--from", action="store", type="int", dest="start", default=0, help="from call no")
724 optparser.add_option("-t", "--to", action="store", type="int", dest="stop", default=0, help="until call no")
725 return optparser
726
727 def process_arg(self, stream, options):
728 parser = Interpreter(stream, options)
729 parser.parse()
730
731
732 if __name__ == '__main__':
733 Main().main()