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