[vlc-commits] commit: python-vlc: modify function parameter handling (Jean Brouwers )

git at videolan.org git at videolan.org
Tue Nov 16 14:29:32 CET 2010


vlc/python | branch: master | Jean Brouwers <MrJean1 at Gmail.com> | Tue Nov 16 11:50:37 2010 +0100| [157b3cef24e0bc6fce0ef6639dd4fcd40cded321] | committer: Olivier Aubert 

python-vlc: modify function parameter handling

Signed-off-by: Olivier Aubert <olivier.aubert at liris.cnrs.fr>

> http://git.videolan.org/gitweb.cgi/vlc/python.git/?a=commit;h=157b3cef24e0bc6fce0ef6639dd4fcd40cded321
---

 generate.py |  135 ++++++++++++++++++++++++++++++-----------------------------
 1 files changed, 68 insertions(+), 67 deletions(-)

diff --git a/generate.py b/generate.py
index ea94a72..6e19687 100755
--- a/generate.py
+++ b/generate.py
@@ -36,24 +36,6 @@ import operator
 import itertools
 from optparse import OptionParser
 
-# DefaultDict from ASPN python cookbook
-import copy
-class DefaultDict(dict):
-    """Dictionary with a default value for unknown keys."""
-    def __init__(self, default=None, **items):
-        dict.__init__(self, **items)
-        self.default = default
-
-    def __getitem__(self, key):
-        if key in self:
-            return self.get(key)
-        else:
-            ## Need copy in case self.default is something like []
-            return self.setdefault(key, copy.deepcopy(self.default))
-
-    def __copy__(self):
-        return DefaultDict(self.default, **self)
-
 # Methods not decorated/not referenced
 blacklist=[
     "libvlc_set_exit_handler",
@@ -69,10 +51,29 @@ python_param_re=re.compile('(@param\s+\S+)(.+)')
 forward_re=re.compile('.+\(\s*(.+?)\s*\)(\s*\S+)')
 enum_re=re.compile('(?:typedef\s+)?(enum)\s*(\S+)\s*\{\s*(.+)\s*\}\s*(?:\S+)?;')
 
-# Definition of parameter passing mode for types.  This should not be
-# hardcoded this way, but works alright ATM.
-parameter_passing=DefaultDict(default=1)
-parameter_passing['libvlc_exception_t*']=3
+
+# Parameter direction definitions.
+class Flag(object):
+    """Enum-like, parameter direction flag constants.
+    """
+    In = 1     # input only
+    Out = 2    # output only
+    InOut = 3  # in- and output
+    InZero = 4 # input, default int 0
+    def __init__(self):
+        raise TypeError('Constants only')
+
+# Parameter passing flags for types.  This shouldn't
+# be hardcoded this way, but works all right ATM.
+def paramFlag3(typ, *name_default):
+    # return the parameter flags as 1-, 2- or 3-tuple for the
+    # given type and optional parameter name and default value
+    t=( { 'int*':                Flag.Out,  # _video_get_cursor
+          'unsigned*':           Flag.Out,  # _video_get_size
+          'libvlc_exception_t*': Flag.InOut,
+          }.get(typ, Flag.In), )
+    return str(t + name_default)
+
 
 class Parser(object):
     def __init__(self, list_of_files):
@@ -493,24 +494,24 @@ class _Enum(ctypes.c_ulong):
             # FIXME
             return
 
-        self.output("""if hasattr(dll, '%s'):""" % method)
-        if params:
-            self.output("    prototype=ctypes.CFUNCTYPE(%s, %s)" % (self.type2class.get(rtype, 'FIXME_%s' % rtype),
-                                                                ", ".join( self.type2class[p[0]] for p in params )))
-        else:
-            self.output("    prototype=ctypes.CFUNCTYPE(%s)" % self.type2class.get(rtype, 'FIXME_%s' % rtype))
+         # return value and arg types
+        args = ", ".join( [self.type2class.get(rtype, 'FIXME_%s' % (rtype,))]
+                          + [self.type2class[p[0]] for p in params] )
 
+         # tuple of arg flag tuples
+        flags = ", ".join( paramFlag3(p[0]) for p in params )
+        if flags:
+            flags += ','
 
-        if not params:
-            flags='    paramflags= tuple()'
-        elif len(params) == 1:
-            flags="    paramflags=( (%d, ), )" % parameter_passing[params[0][0]]
-        else:
-            flags="    paramflags=%s" % ", ".join( '(%d,)' % parameter_passing[p[0]] for p in params )
-        self.output(flags)
-        self.output('    %s = prototype( ("%s", dll), paramflags )' % (method, method))
-        self.output('    %s.__doc__ = """%s"""' % (method, comment))
-        self.output()
+        comment = self.epydoc_comment(comment)
+
+        self.output('''if hasattr(dll, '%(method)s'):
+    p = ctypes.CFUNCTYPE(%(args)s)
+    f = (%(flags)s)
+    %(method)s = p( ('%(method)s', dll), f )
+    %(method)s.__doc__ = """%(comment)s
+"""
+''' % locals())
 
     def parse_override(self, name):
         """Parse override definitions file.
@@ -549,26 +550,23 @@ class _Enum(ctypes.c_ulong):
 
         return code, overridden_methods, docstring
 
-    def fix_python_comment(self, c, in_class=False):
-        """Transform comment into python syntax.
+    def epydoc_comment(self, comment, fix_first=False):
+        """Transform Doxygen into epydoc syntax and fix first parameter.
         """
-        # Transform Doxygen syntax into epydoc syntax
-        c=c.replace('@{', '').replace('@see', 'See').replace('\\see', 'See').replace('\\ingroup', '').replace('\\param', '@param').replace('\\return', '@return')
-        if in_class:
-            # Class method, remove first parameter (self)
-            data=c.splitlines()
-            body=itertools.takewhile(lambda l: not '@param' in l and not '@return' in l, data)
-            param=[ python_param_re.sub('\\1:\\2', l) for l in  itertools.ifilter(lambda l: '@param' in l, data) ]
-            ret=[ l.replace('@return', '@return:') for l in itertools.ifilter(lambda l: '@return' in l, data) ]
-
-            if len(param) >= 2:
-                param=param[1:]
-            elif len(param) == 1:
-                param=[]
-
-            return "\n".join(itertools.chain(body, param, ret))
-        else:
-            return c
+        lines=comment.replace('@{', '').replace('\\ingroup', '') \
+                     .replace('@see', 'See').replace('\\see', 'See') \
+                     .replace('\\note', 'NOTE:').replace('\\warning', 'WARNING:') \
+                     .replace('\\param', '@param').replace('\\return', '@return') \
+                     .strip().splitlines()
+
+        doc = [ l for l in lines if '@param' not in l and '@return' not in l ]
+        ret = [ l.replace('@return', '@return:') for l in lines if '@return' in l ]
+
+        params = [ python_param_re.sub('\\1:\\2', l) for l in lines if '@param' in l ]
+        if fix_first and params:  # remove (self)
+            params = params[1:]
+
+        return "\n".join( doc + params + ret )
 
     def generate_wrappers(self, methods):
         """Generate class wrappers for all appropriate methods.
@@ -615,27 +613,30 @@ class _Enum(ctypes.c_ulong):
             if classname in overrides:
                 self.output(overrides[classname])
 
-            prefix=self.prefixes.get(classname, '')
+            prefix = self.prefixes.get(classname, '')
 
             for cl, rtype, method, params, comment in el:
                 if method in blacklist:
                     continue
                 # Strip prefix
-                name=method.replace(prefix, '').replace('libvlc_', '')
+                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')
-                args=", ".join( p[1] for p in params )
-
-                self.output("    if hasattr(dll, '%s'):" % method)
-                self.output("        def %s(%s):" % (name, args))
-                self.output('            """%s\n        """' % self.fix_python_comment(comment, in_class=True))
-                self.output("            return %s(%s)" % (method, args))
-                self.output()
+                    params[0] = (params[0][0], 'self')
+                args = ", ".join( p[1] for p in params )
+
+                comment = self.epydoc_comment(comment, fix_first=True)
+
+                self.output('''    if hasattr(dll, '%(method)s'):
+        def %(name)s(%(args)s):
+            """%(comment)s
+            """
+            return %(method)s(%(args)s)
+''' % locals())
 
                 # Check for standard methods
                 if name == 'count':



More information about the vlc-commits mailing list