Added gst-plugins-base-subtitles0.10-0.10.34 for Meego Harmattan 1.2
[mafwsubrenderer] / gst-plugins-base-subtitles0.10 / common / scangobj-merge.py
1 #!/usr/bin/python
2 # -*- Mode: Python -*-
3 # vi:si:et:sw=4:sts=4:ts=4
4
5 """
6 parse, update and write .signals and .args files
7 """
8
9 import sys
10 import os
11
12 def debug(*args):
13     pass
14
15 # OrderedDict class based on
16 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747
17 # Licensed under the Python License
18 class OrderedDict(dict):
19     def __init__(self, dict = None):
20         self._keys = []
21         dict.__init__(self, dict)
22
23     def __delitem__(self, key):
24         dict.__delitem__(self, key)
25         self._keys.remove(key)
26
27     def __setitem__(self, key, item):
28         dict.__setitem__(self, key, item)
29         if key not in self._keys: self._keys.append(key)
30
31     def clear(self):
32         dict.clear(self)
33         self._keys = []
34
35     def copy(self):
36         dict = dict.copy(self)
37         dict._keys = self._keys[:]
38         return dict
39
40     def items(self):
41         return zip(self._keys, self.values())
42
43     def keys(self):
44         return self._keys
45
46     def popitem(self):
47         try:
48             key = self._keys[-1]
49         except IndexError:
50             raise KeyError('dictionary is empty')
51
52         val = self[key]
53         del self[key]
54
55         return (key, val)
56
57     def setdefault(self, key, failobj = None):
58         dict.setdefault(self, key, failobj)
59         if key not in self._keys: self._keys.append(key)
60
61     def update(self, dict):
62         dict.update(self, dict)
63         for key in dict.keys():
64             if key not in self._keys: self._keys.append(key)
65
66     def values(self):
67         return map(self.get, self._keys)
68
69 class Object:
70     def __init__(self, name):
71         self._signals = OrderedDict()
72         self._args = OrderedDict()
73         self.name = name
74
75     def __repr__(self):
76         return "<Object %s>" % self.name
77
78     def add_signal(self, signal, overwrite=True):
79         if not overwrite and self._signals.has_key(signal.name):
80             raise IndexError, "signal %s already in %r" % (signal.name, self)
81         self._signals[signal.name] = signal
82
83     def add_arg(self, arg, overwrite=True):
84         if not overwrite and self._args.has_key(arg.name):
85             raise IndexError, "arg %s already in %r" % (arg.name, self)
86         self._args[arg.name] = arg
87
88 class Docable:
89     def __init__(self, **kwargs):
90         for key in self.attrs:
91             setattr(self, key, kwargs[key])
92         self.dict = kwargs
93
94     def __repr__(self):
95         return "<%r %s>" % (str(self.__class__), self.name)
96
97 class Signal(Docable):
98     attrs = ['name', 'returns', 'args']
99
100 class Arg(Docable):
101     attrs = ['name', 'type', 'range', 'flags', 'nick', 'blurb', 'default']
102
103 class GDoc:
104     def load_file(self, filename):
105         try:
106             lines = open(filename).readlines()
107             self.load_data("".join(lines))
108         except IOError:
109             print "WARNING - could not read from %s" % filename
110
111     def save_file(self, filename, backup=False):
112         """
113         Save the signals information to the given .signals file if the
114         file content changed.
115         """
116         olddata = None
117         try:
118             lines = open(filename).readlines()
119             olddata = "".join(lines)
120         except IOError:
121             print "WARNING - could not read from %s" % filename
122         newdata = self.get_data()
123         if olddata and olddata == newdata:
124             return
125
126         if olddata:
127             if backup:
128                 os.rename(filename, filename + '.bak')
129
130         handle = open(filename, "w")
131         handle.write(newdata)
132         handle.close()
133
134 class Signals(GDoc):
135     def __init__(self):
136         self._objects = OrderedDict()
137
138     def load_data(self, data):
139         """
140         Load the .signals lines, creating our list of objects and signals.
141         """
142         import re
143         smatcher = re.compile(
144             '(?s)'                                      # make . match \n
145             '<SIGNAL>\n(.*?)</SIGNAL>\n'
146             )
147         nmatcher = re.compile(
148             '<NAME>'
149             '(?P<object>\S*)'                           # store object
150             '::'
151             '(?P<signal>\S*)'                           # store signal
152             '</NAME>'
153         )
154         rmatcher = re.compile(
155             '(?s)'                                      # make . match \n
156             '<RETURNS>(?P<returns>\S*)</RETURNS>\n'     # store returns
157             '(?P<args>.*)'                              # store args
158         )
159         for block in smatcher.findall(data):
160             nmatch = nmatcher.search(block)
161             if nmatch:
162                 o = nmatch.group('object')
163                 debug("Found object", o)
164                 debug("Found signal", nmatch.group('signal'))
165                 if not self._objects.has_key(o):
166                     object = Object(o)
167                     self._objects[o] = object
168
169                 rmatch = rmatcher.search(block)
170                 if rmatch:
171                     dict = rmatch.groupdict().copy()
172                     dict['name'] = nmatch.group('signal')
173                     signal = Signal(**dict)
174                     self._objects[o].add_signal(signal)
175
176     def get_data(self):
177         lines = []
178         for o in self._objects.values():
179             for s in o._signals.values():
180                 block = """<SIGNAL>
181 <NAME>%(object)s::%(name)s</NAME>
182 <RETURNS>%(returns)s</RETURNS>
183 %(args)s</SIGNAL>
184 """
185                 d = s.dict.copy()
186                 d['object'] = o.name
187                 lines.append(block % d)
188
189         return "\n".join(lines) + '\n'
190
191 class Args(GDoc):
192     def __init__(self):
193         self._objects = OrderedDict()
194
195     def load_data(self, data):
196         """
197         Load the .args lines, creating our list of objects and args.
198         """
199         import re
200         amatcher = re.compile(
201             '(?s)'                                      # make . match \n
202             '<ARG>\n(.*?)</ARG>\n'
203             )
204         nmatcher = re.compile(
205             '<NAME>'
206             '(?P<object>\S*)'                           # store object
207             '::'
208             '(?P<arg>\S*)'                              # store arg
209             '</NAME>'
210         )
211         rmatcher = re.compile(
212             '(?s)'                                      # make . match \n
213             '<TYPE>(?P<type>\S*)</TYPE>\n'              # store type
214             '<RANGE>(?P<range>.*?)</RANGE>\n'           # store range
215             '<FLAGS>(?P<flags>\S*)</FLAGS>\n'           # store flags
216             '<NICK>(?P<nick>.*?)</NICK>\n'              # store nick
217             '<BLURB>(?P<blurb>.*?)</BLURB>\n'           # store blurb
218             '<DEFAULT>(?P<default>.*?)</DEFAULT>\n'     # store default
219         )
220         for block in amatcher.findall(data):
221             nmatch = nmatcher.search(block)
222             if nmatch:
223                 o = nmatch.group('object')
224                 debug("Found object", o)
225                 debug("Found arg", nmatch.group('arg'))
226                 if not self._objects.has_key(o):
227                     object = Object(o)
228                     self._objects[o] = object
229
230                 rmatch = rmatcher.search(block)
231                 if rmatch:
232                     dict = rmatch.groupdict().copy()
233                     dict['name'] = nmatch.group('arg')
234                     arg = Arg(**dict)
235                     self._objects[o].add_arg(arg)
236                 else:
237                     print "ERROR: could not match arg from block %s" % block
238
239     def get_data(self):
240         lines = []
241         for o in self._objects.values():
242             for a in o._args.values():
243                 block = """<ARG>
244 <NAME>%(object)s::%(name)s</NAME>
245 <TYPE>%(type)s</TYPE>
246 <RANGE>%(range)s</RANGE>
247 <FLAGS>%(flags)s</FLAGS>
248 <NICK>%(nick)s</NICK>
249 <BLURB>%(blurb)s</BLURB>
250 <DEFAULT>%(default)s</DEFAULT>
251 </ARG>
252 """
253                 d = a.dict.copy()
254                 d['object'] = o.name
255                 lines.append(block % d)
256
257         return "\n".join(lines) + '\n'
258
259 def main(argv):
260     modulename = None
261     try:
262         modulename = argv[1]
263     except IndexError:
264         sys.stderr.write('Please provide a documentation module name\n')
265         sys.exit(1)
266
267     print "Merging scangobj output for %s" % modulename
268     signals = Signals()
269     signals.load_file(modulename + '.signals')
270     signals.load_file(modulename + '.signals.new')
271     signals.save_file(modulename + '.signals', backup=True)
272     os.unlink(modulename + '.signals.new')
273
274     args = Args()
275     args.load_file(modulename + '.args')
276     args.load_file(modulename + '.args.new')
277     args.save_file(modulename + '.args', backup=True)
278     os.unlink(modulename + '.args.new')
279
280 main(sys.argv)