]> git.sesse.net Git - vlc/blobdiff - bindings/python-ctypes/generate.py
python-ctypes: update README
[vlc] / bindings / python-ctypes / generate.py
index 473980c0d27cbe960a6da34da07963dcb4e2fe4c..e86e1718a9abecd4ba42469bf3e0af0e82ad265f 100755 (executable)
@@ -384,6 +384,7 @@ def parse_include(name):
                    method,
                    params,
                    comment)
+            comment=''
 
 def output_ctypes(rtype, method, params, comment):
     """Output ctypes decorator for the given method.
@@ -417,8 +418,11 @@ def parse_override(name):
     """Parse override definitions file.
 
     It is possible to override methods definitions in classes.
+    
+    It returns a tuple
+    (code, overriden_methods, docstring)
     """
-    res={}
+    code={}
 
     data=[]
     current=None
@@ -428,14 +432,24 @@ def parse_override(name):
         if m:
             # Dump old data
             if current is not None:
-                res[current]="\n".join(data)
+                code[current]="".join(data)
             current=m.group(1)
             data=[]
             continue
         data.append(l)
-    res[current]="\n".join(data)
+    code[current]="".join(data)
     f.close()
-    return res
+
+    docstring={}
+    for k, v in code.iteritems():
+        if v.lstrip().startswith('"""'):
+            # Starting comment. Use it as docstring.
+            dummy, docstring[k], code[k]=v.split('"""', 2)
+
+    # Not robust wrt. internal methods, but this works for the moment.
+    overridden_methods=dict( (k, re.findall('^\s+def\s+(\w+)', v, re.MULTILINE)) for (k, v) in code.iteritems() )
+
+    return code, overridden_methods, docstring
 
 def fix_python_comment(c):
     """Fix comment by removing first and last parameters (self and exception)
@@ -465,17 +479,25 @@ def generate_wrappers(methods):
                        ),
                      key=operator.itemgetter(0))
 
-    overrides=parse_override('override.py')
+    overrides, overriden_methods, docstring=parse_override('override.py')
 
     for classname, el in itertools.groupby(elements, key=operator.itemgetter(0)):
+        print """class %(name)s(object):""" % {'name': classname}
+        if classname in docstring:
+            print '    """%s\n    """' % docstring[classname]
+
         print """
-class %(name)s(object):
-    def __init__(self, pointer=None):
+    def __new__(cls, pointer=None):
         '''Internal method used for instanciating wrappers from ctypes.
         '''
         if pointer is None:
             raise Exception("Internal method. You should instanciate objects through other class methods (probably named 'new' or ending with 'new')")
-        self._as_parameter_=ctypes.c_void_p(pointer)
+        if pointer == 0:
+            return None
+        else:
+            o=object.__new__(cls)
+            o._as_parameter_=ctypes.c_void_p(pointer)
+            return o
 
     @staticmethod
     def from_param(arg):
@@ -495,6 +517,10 @@ class %(name)s(object):
             # Strip prefix
             name=method.replace(prefix, '').replace('libvlc_', '')
             ret.add(method)
+            if name in overriden_methods.get(cl, []):
+                # Method already defined in override.py
+                continue
+
             if params:
                 params[0]=(params[0][0], 'self')
             if params and params[-1][0] in ('libvlc_exception_t*', 'mediacontrol_Exception*'):
@@ -503,7 +529,7 @@ class %(name)s(object):
                 args=", ".join( p[1] for p in params )
 
             print "    def %s(%s):" % (name, args)
-            print '        """%s\n"""' % fix_python_comment(comment)
+            print '        """%s\n        """' % fix_python_comment(comment)
             if params and params[-1][0] == 'libvlc_exception_t*':
                 # Exception handling
                 print "        e=VLCException()"
@@ -515,6 +541,26 @@ class %(name)s(object):
             else:
                 print "        return %s(%s)" % (method, args)
             print
+
+            # Check for standard methods
+            if name == 'count':
+                # There is a count method. Generate a __len__ one.
+                print "    def __len__(self):"
+                print "        e=VLCException()"
+                print "        return %s(self, e)" % method
+                print
+            elif name.endswith('item_at_index'):
+                # Indexable (and thus iterable)"
+                print "    def __getitem__(self, i):"
+                print "        e=VLCException()"
+                print "        return %s(self, i, e)" % method
+                print
+                print "    def __iter__(self):"
+                print "        e=VLCException()"
+                print "        for i in xrange(len(self)):"
+                print "            yield self[i]"
+                print
+
     return ret
 
 if __name__ == '__main__':