Add codegen to the tracked files
[platform/upstream/gst-editing-services.git] / bindings / python / codegen / override.py
1 # -*- Mode: Python; py-indent-offset: 4 -*-
2
3 # this file contains code for loading up an override file.  The override file
4 # provides implementations of functions where the code generator could not
5 # do its job correctly.
6
7 import fnmatch
8 import os
9 import re
10 import string
11 import sys
12
13 def class2cname(klass, method):
14     c_name = ''
15     for c in klass:
16         if c.isupper():
17             c_name += '_' + c.lower()
18         else:
19             c_name += c
20     return c_name[1:] + '_'  + method
21
22 import_pat = re.compile(r'\s*import\s+(\S+)\.([^\s.]+)\s+as\s+(\S+)')
23
24 class Overrides:
25     def __init__(self, filename=None, path=[]):
26         self.modulename = None
27         self.ignores = {}
28         self.glob_ignores = []
29         self.type_ignores = {}
30         self.overrides = {}
31         self.overridden = {}
32         self.kwargs = {}
33         self.noargs = {}
34         self.onearg = {}
35         self.staticmethod = {}
36         self.classmethod = {}
37         self.startlines = {}
38         self.override_attrs = {}
39         self.override_slots = {}
40         self.headers = ''
41         self.body = ''
42         self.init = ''
43         self.imports = []
44         self.defines = {}
45         self.functions = {}
46         self.newstyle_constructors = {}
47         self.path = [os.path.abspath(x) for x in path]
48         if filename:
49             self.handle_file(filename)
50
51     def handle_file(self, filename):
52         oldpath = os.getcwd()
53
54         fp = None
55         for path in self.path:
56             os.chdir(oldpath)
57             os.chdir(path)
58             try:
59                 fp = open(filename, 'r')
60                 break
61             except:
62                 os.chdir(oldpath)
63         if not fp:
64             raise Exception, "Couldn't find file %s" % filename
65         
66         dirname = path
67
68         if dirname != oldpath:
69             os.chdir(dirname)
70
71         # read all the components of the file ...
72         bufs = []
73         startline = 1
74         lines = []
75         line = fp.readline()
76         linenum = 1
77         while line:
78             if line == '%%\n' or line == '%%':
79                 if lines:
80                     bufs.append((string.join(lines, ''), startline))
81                 startline = linenum + 1
82                 lines = []
83             else:
84                 lines.append(line)
85             line = fp.readline()
86             linenum = linenum + 1
87         if lines:
88             bufs.append((string.join(lines, ''), startline))
89         if not bufs: return
90
91         for buf, startline in bufs:
92             self.__parse_override(buf, startline, filename)
93
94         os.chdir(oldpath)
95
96     def __parse_override(self, buffer, startline, filename):
97         pos = string.find(buffer, '\n')
98         if pos >= 0:
99             line = buffer[:pos]
100             rest = buffer[pos+1:]
101         else:
102             line = buffer ; rest = ''
103         words = string.split(line)
104         command = words[0]
105         if (command == 'ignore' or
106             command == 'ignore-' + sys.platform):
107             "ignore/ignore-platform [functions..]"
108             for func in words[1:]:
109                 self.ignores[func] = 1
110             for func in string.split(rest):
111                 self.ignores[func] = 1
112         elif (command == 'ignore-glob' or
113               command == 'ignore-glob-' + sys.platform):
114             "ignore-glob/ignore-glob-platform [globs..]"
115             for func in words[1:]:
116                 self.glob_ignores.append(func)
117             for func in string.split(rest):
118                 self.glob_ignores.append(func)
119         elif (command == 'ignore-type' or
120               command == 'ignore-type-' + sys.platform):
121             "ignore-type/ignore-type-platform [typenames..]"
122             for typename in words[1:]:
123                 self.type_ignores[typename] = 1
124             for typename in string.split(rest):
125                 self.type_ignores[typename] = 1
126         elif command == 'override':
127             "override function/method [kwargs|noargs|onearg] [staticmethod|classmethod]"
128             func = words[1]
129             if 'kwargs' in words[1:]:
130                 self.kwargs[func] = 1
131             elif 'noargs' in words[1:]:
132                 self.noargs[func] = 1
133             elif 'onearg' in words[1:]:
134                 self.onearg[func] = True
135
136             if 'staticmethod' in words[1:]:
137                 self.staticmethod[func] = True
138             elif 'classmethod' in words[1:]:
139                 self.classmethod[func] = True
140             if func in self.overrides:
141                 raise RuntimeError("Function %s is being overridden more than once" % (func,))
142             self.overrides[func] = rest
143             self.startlines[func] = (startline + 1, filename)
144         elif command == 'override-attr':
145             "override-slot Class.attr"
146             attr = words[1]
147             self.override_attrs[attr] = rest
148             self.startlines[attr] = (startline + 1, filename)
149         elif command == 'override-slot':
150             "override-slot Class.slot"
151             slot = words[1]
152             self.override_slots[slot] = rest
153             self.startlines[slot] = (startline + 1, filename)
154         elif command == 'headers':
155             "headers"
156             self.headers = '%s\n#line %d "%s"\n%s' % \
157                            (self.headers, startline + 1, filename, rest)
158         elif command == 'body':
159             "body"
160             self.body = '%s\n#line %d "%s"\n%s' % \
161                            (self.body, startline + 1, filename, rest)
162         elif command == 'init':
163             "init"
164             self.init = '%s\n#line %d "%s"\n%s' % \
165                         (self.init, startline + 1, filename, rest)
166         elif command == 'modulename':
167             "modulename name"
168             self.modulename = words[1]
169         elif command == 'include':
170             "include filename"
171             for filename in words[1:]:
172                 self.handle_file(filename)
173             for filename in string.split(rest):
174                 self.handle_file(filename)
175         elif command == 'import':
176             "import module1 [\n module2, \n module3 ...]"
177             for line in string.split(buffer, '\n'):
178                 match = import_pat.match(line)
179                 if match:
180                     self.imports.append(match.groups())
181         elif command == 'define':
182             "define funcname [kwargs|noargs|onearg] [classmethod|staticmethod]"
183             "define Class.method [kwargs|noargs|onearg] [classmethod|staticmethod]"
184             func = words[1]
185             klass = None
186             if func.find('.') != -1:
187                 klass, func = func.split('.', 1)
188
189                 if not self.defines.has_key(klass):
190                     self.defines[klass] = {}
191                 self.defines[klass][func] = rest
192             else:
193                 self.functions[func] = rest
194
195             if 'kwargs' in words[1:]:
196                 self.kwargs[func] = 1
197             elif 'noargs' in words[1:]:
198                 self.noargs[func] = 1
199             elif 'onearg' in words[1:]:
200                 self.onearg[func] = 1
201
202             if 'staticmethod' in words[1:]:
203                 self.staticmethod[func] = True
204             elif 'classmethod' in words[1:]:
205                 self.classmethod[func] = True
206
207             self.startlines[func] = (startline + 1, filename)
208
209         elif command == 'new-constructor':
210             "new-constructor GType"
211             gtype, = words[1:]
212             self.newstyle_constructors[gtype] = True
213
214     def is_ignored(self, name):
215         if self.ignores.has_key(name):
216             return 1
217         for glob in self.glob_ignores:
218             if fnmatch.fnmatchcase(name, glob):
219                 return 1
220         return 0
221
222     def is_type_ignored(self, name):
223         return name in self.type_ignores
224
225     def is_overriden(self, name):
226         return self.overrides.has_key(name)
227
228     def is_already_included(self, name):
229         return self.overridden.has_key(name)
230
231     def override(self, name):
232         self.overridden[name] = 1
233         return self.overrides[name]
234
235     def define(self, klass, name):
236         self.overridden[class2cname(klass, name)] = 1
237         return self.defines[klass][name]
238
239     def function(self, name):
240         return self.functions[name]
241
242     def getstartline(self, name):
243         return self.startlines[name]
244
245     def wants_kwargs(self, name):
246         return self.kwargs.has_key(name)
247
248     def wants_noargs(self, name):
249         return self.noargs.has_key(name)
250
251     def wants_onearg(self, name):
252         return self.onearg.has_key(name)
253
254     def is_staticmethod(self, name):
255         return self.staticmethod.has_key(name)
256
257     def is_classmethod(self, name):
258         return self.classmethod.has_key(name)
259
260     def attr_is_overriden(self, attr):
261         return self.override_attrs.has_key(attr)
262
263     def attr_override(self, attr):
264         return self.override_attrs[attr]
265
266     def slot_is_overriden(self, slot):
267         return self.override_slots.has_key(slot)
268
269     def slot_override(self, slot):
270         return self.override_slots[slot]
271
272     def get_headers(self):
273         return self.headers
274
275     def get_body(self):
276         return self.body
277
278     def get_init(self):
279         return self.init
280
281     def get_imports(self):
282         return self.imports
283
284     def get_defines_for(self, klass):
285         return self.defines.get(klass, {})
286
287     def get_functions(self):
288         return self.functions