Overhauled the schema system to make more sense. Implemented a dump_structure utility.
[~jspiros/python-ebml.git] / ebml / utils / dump_structure.py
1 from ..schema import EBMLDocument, UnknownElement, CONTAINER, BINARY
2
3
4 def dump_element(element, indent=0):
5         if isinstance(element, UnknownElement):
6                 print(('\t' * indent) + ('<Unknown id=\'%s\' bytes=\'%i\' />' % (hex(element.id), element.encoding[0])))
7         else:
8                 sargs = {
9                         'name': element.name,
10                         'bytes': element.body_size,
11                         'value': element.value
12                 }
13                 def print_indented(foo):
14                         print(('\t' * indent) + foo)
15                 if element.type == CONTAINER:
16                         print_indented('<%(name)s>' % sargs)
17                         for sub_el in element.value:
18                                 dump_element(sub_el, indent + 1)
19                         print_indented('</%(name)s>' % sargs)
20                 elif element.type == BINARY:
21                         print_indented('<%(name)s bytes=\'%(bytes)i\' />' % sargs)
22                 else:
23                         print_indented('<%(name)s>%(value)s</%(name)s>' % sargs)
24
25
26 def dump_document(document):
27         for el in document.roots:
28                 dump_element(el)
29
30
31 if __name__ == '__main__':
32         import sys
33         from optparse import OptionParser
34         
35         parser = OptionParser(usage='Usage: %prog [OPTION] FILE')
36         parser.add_option('--document-class', dest='document_class', help='the document class to use', metavar='CLASS')
37         options, args = parser.parse_args()
38         
39         if options.document_class is None:
40                 class doc_cls(EBMLDocument):
41                         type = None
42                         version = None
43         else:
44                 mod_name, _, cls_name = options.document_class.rpartition('.')
45                 try:
46                         doc_mod = __import__(mod_name, fromlist=[cls_name])
47                         doc_cls = getattr(doc_mod, cls_name)
48                 except ImportError:
49                         parser.error('unable to import module %s' % mod_name)
50                 except AttributeError:
51                         parser.error('unable to import class %s from %s' % (cls_name, mod_name))
52         
53         if not args:
54                 parser.error('no file provided')
55         elif len(args) > 1:
56                 parser.error('more than one file provided')
57         
58         with open(args[0], 'rb') as stream:
59                 doc = doc_cls(stream)
60                 dump_document(doc)