示例#1
0
 def generatePyFunction(self, pf, stream, indent=''):
     assert isinstance(pf, extractors.PyFunctionDef)
     if len(indent) == 0:
         stream.write('%%Extract(id=pycode%s' % self.module_name)
         if pf.order is not None:
             stream.write(', order=%d' % pf.order)
         stream.write(')\n')
     if pf.deprecated:
         if isinstance(pf.deprecated, int):
             stream.write('%[email protected]\n' % indent)
         else:
             stream.write('%[email protected]("%s")\n' %
                          (indent, pf.deprecated))
     if pf.isStatic:
         stream.write('%s@staticmethod\n' % indent)
     stream.write('%sdef %s%s:\n' % (indent, pf.name, pf.argsString))
     indent2 = indent + ' ' * 4
     if pf.briefDoc:
         stream.write('%s"""\n' % indent2)
         stream.write(nci(pf.briefDoc, len(indent2)))
         stream.write('%s"""\n' % indent2)
     stream.write(nci(pf.body, len(indent2)))
     if len(indent) == 0:
         stream.write('\n%End\n')
     stream.write('\n')
示例#2
0
    def generateFunction(self, function, stream, _needDocstring=True):
        assert isinstance(function, extractors.FunctionDef)
        if not function.ignored:
            stream.write('%s %s(' % (function.type, function.name))
            if function.items:
                stream.write('\n')
                self.generateParameters(function.items, stream, ' ' * 4)
            stream.write(')%s;\n' % self.annotate(function))

            if _needDocstring:
                self.generateDocstring(function, stream, '')
                # We only write a docstring for the first overload, otherwise
                # SIP appends them all together.
                _needDocstring = False

            if function.mustHaveAppFlag:
                stream.write('%PreMethodCode\n')
                stream.write(nci("if (!wxPyCheckForApp()) return NULL;\n", 4))
                stream.write('%End\n')

            if function.cppCode:
                code, codeType = function.cppCode
                if codeType == 'sip':
                    stream.write('%MethodCode\n')
                    stream.write(nci(code, 4))
                    stream.write('%End\n')
                elif codeType == 'function':
                    raise NotImplementedError(
                    )  # TODO: See generateMethod for an example, refactor to share code...
        for f in function.overloads:
            self.generateFunction(f, stream, _needDocstring)
        stream.write('\n')
示例#3
0
    def generateFunction(self, function, stream, _needDocstring=True):
        assert isinstance(function, extractors.FunctionDef)
        if not function.ignored:
            stream.write('%s %s(' % (function.type, function.name))
            if function.items:
                stream.write('\n')
                self.generateParameters(function.items, stream, ' '*4)
            stream.write(')%s;\n' % self.annotate(function))

            if  _needDocstring:
                self.generateDocstring(function, stream, '')
                # We only write a docstring for the first overload, otherwise
                # SIP appends them all together.
                _needDocstring = False

            if function.mustHaveAppFlag:
                stream.write('%PreMethodCode\n')
                stream.write(nci("if (!wxPyCheckForApp()) return NULL;\n", 4))
                stream.write('%End\n')

            if function.cppCode:
                code, codeType = function.cppCode
                if codeType == 'sip':
                    stream.write('%MethodCode\n')
                    stream.write(nci(code, 4))
                    stream.write('%End\n')
                elif codeType == 'function':
                    raise NotImplementedError() # TODO: See generateMethod for an example, refactor to share code...
        for f in function.overloads:
            self.generateFunction(f, stream, _needDocstring)
        stream.write('\n')
示例#4
0
 def generateMethod(self, method, stream, indent):
     assert isinstance(method, extractors.MethodDef)
     _needDocstring = getattr(method, '_needDocstring', True)
     checkOverloads = True
     if not method.ignored:
         if method.isVirtual:
             stream.write("%svirtual\n" % indent)
         if method.isStatic:
             stream.write("%sstatic\n" % indent)
         if method.isCtor or method.isDtor:
             stream.write('%s%s(' % (indent, method.name))
         else:
             stream.write('%s%s %s(' % (indent, method.type, method.name))
         if method.items:
             stream.write('\n')
             self.generateParameters(method.items, stream, indent+' '*4)
             stream.write(indent)
         stream.write(')')
         if method.isConst:
             stream.write(' const')
         if method.isPureVirtual:
             stream.write(' = 0')
         cppSig = " [ %s ]" % method.cppSignature if method.cppSignature else ""                
         if cppSig:
             stream.write(cppSig)
         stream.write('%s;\n' % self.annotate(method))
                     
         if  _needDocstring and not (method.isCtor or method.isDtor):
             self.generateDocstring(method, stream, indent)
             # We only write a docstring for the first overload, otherwise
             # SIP appends them all together.
             _needDocstring = False
             
         if method.cppCode:
             #checkOverloads = False   ## SIP now allows overloads to have %MethodCode
             code, codeType = method.cppCode
             if codeType == 'sip':
                 stream.write('%s%%MethodCode\n' % indent)
                 stream.write(nci(code, len(indent)+4))
                 stream.write('%s%%End\n' % indent)
             elif codeType == 'function':
                 cm = extractors.CppMethodDef.FromMethod(method)
                 cm.body = code
                 self.generateCppMethod(cm, stream, indent, skipDeclaration=True)
                 # generateCppMethod will have already done the overloads
                 # and virtual catcher code, so we can just return from
                 # here.
                 return
             
         if method.virtualCatcherCode:
             stream.write('%s%%VirtualCatcherCode\n' % indent)
             stream.write(nci(method.virtualCatcherCode, len(indent)+4))
             stream.write('%s%%End\n' % indent)
             
         stream.write('\n')
         
     if checkOverloads and method.overloads:
         for m in method.overloads:
             m._needDocstring = _needDocstring
             self.dispatchClassItem(method.klass, m, stream, indent)
示例#5
0
 def generatePyMethod(self, pm, stream, indent):
     assert isinstance(pm, extractors.PyMethodDef)
     if pm.ignored:
         return
     if pm.klass.generatingInClass:
         pm.klass.generateAfterClass.append(pm)
     else:
         klassName = pm.klass.pyName or pm.klass.name
         stream.write("%%Extract(id=pycode%s)\n" % self.module_name)
         stream.write("def _%s_%s%s:\n" %
                      (klassName, pm.name, pm.argsString))
         pm.pyDocstring = ""
         if pm.briefDoc:
             doc = nci(pm.briefDoc)
             pm.pyDocstring = doc
             stream.write(nci('"""\n%s"""\n' % doc, 4))
         stream.write(nci(pm.body, 4))
         stream.write('%s.%s = ' % (klassName, pm.name))
         end = '\n'
         if pm.isStatic:
             stream.write('staticmethod(')
             end = ')' + end
         if pm.deprecated:
             stream.write('wx.deprecated(')
             end = ')' + end
         stream.write('_%s_%s' % (klassName, pm.name))
         if pm.deprecated and not isinstance(pm.deprecated, int):
             stream.write(', "%s"' % pm.deprecated)
         stream.write(end)
         stream.write('del _%s_%s\n' % (klassName, pm.name))
         stream.write('%End\n\n')
示例#6
0
 def generatePyMethod(self, pm, stream, indent):
     assert isinstance(pm, extractors.PyMethodDef)
     if pm.ignored:
         return
     if pm.klass.generatingInClass:
         pm.klass.generateAfterClass.append(pm)
     else:
         klassName = pm.klass.pyName or pm.klass.name
         stream.write("%%Extract(id=pycode%s)\n" % self.module_name)
         stream.write("def _%s_%s%s:\n" % (klassName, pm.name, pm.argsString))
         pm.pyDocstring = ""
         if pm.briefDoc:
             doc = nci(pm.briefDoc)
             pm.pyDocstring = doc
             stream.write(nci('"""\n%s"""\n' % doc, 4))
         stream.write(nci(pm.body, 4))
         stream.write('%s.%s = ' % (klassName, pm.name))
         end = '\n'
         if pm.isStatic:
             stream.write('staticmethod(')
             end = ')' + end
         if pm.deprecated:
             stream.write('wx.deprecated(')
             end = ')' + end
         stream.write('_%s_%s' % (klassName, pm.name))
         if pm.deprecated and not isinstance(pm.deprecated, int):
             stream.write(', "%s"' % pm.deprecated)
         stream.write(end)
         stream.write('del _%s_%s\n' % (klassName, pm.name))
         stream.write('%End\n\n')
示例#7
0
    def generateDocstring(self, item, stream, indent):
        item.pyDocstring = ""

        if item.name.startswith('operator'):
            return  # Apparently sip doesn't like operators to have docstrings...

        # get the docstring text
        text = nci(extractors.flattenNode(item.briefDoc, False))
        text = wrapText(text)


        #if isinstance(item, extractors.ClassDef):
        #    # append the function signatures for the class constructors (if any) to the class' docstring
        #    try:
        #        ctor = item.find(item.name)
        #        sigs = ctor.collectPySignatures()
        #        if sigs:
        #            text += '\n' + '\n'.join(sigs)
        #    except extractors.ExtractorError:
        #        pass
        #else:
        #    # Prepend function signature string(s) for functions and methods
        #    sigs = item.collectPySignatures()
        #    if sigs:
        #        if text:
        #            text = '\n\n' + text
        #        text = '\n'.join(sigs) + text

        sigs = None
        if isinstance(item, extractors.ClassDef):
            try:
                ctor = item.find(item.name)
                sigs = ctor.collectPySignatures()
            except extractors.ExtractorError:
                pass
        else:
            sigs = item.collectPySignatures()
        if sigs:
            if text:
                text = '\n\n' + text
            text = '\n'.join(sigs) + text

        # write the docstring directive and the text
        stream.write('%s%%Docstring\n' % indent)
        stream.write(nci(text, len(indent)+4))

        stream.write('%s%%End\n' % indent)

        # and save the docstring back into item in case it is needed by other
        # generators later on
        item.pyDocstring = nci(text)
示例#8
0
    def generateDocstring(self, item, stream, indent):
        item.pyDocstring = ""

        if item.name.startswith('operator'):
            return  # Apparently sip doesn't like operators to have docstrings...

        # get the docstring text
        text = nci(extractors.flattenNode(item.briefDoc, False))
        text = wrapText(text)


        #if isinstance(item, extractors.ClassDef):
        #    # append the function signatures for the class constructors (if any) to the class' docstring
        #    try:
        #        ctor = item.find(item.name)
        #        sigs = ctor.collectPySignatures()
        #        if sigs:
        #            text += '\n' + '\n'.join(sigs)
        #    except extractors.ExtractorError:
        #        pass
        #else:
        #    # Prepend function signature string(s) for functions and methods
        #    sigs = item.collectPySignatures()
        #    if sigs:
        #        if text:
        #            text = '\n\n' + text
        #        text = '\n'.join(sigs) + text

        sigs = None
        if isinstance(item, extractors.ClassDef):
            try:
                ctor = item.find(item.name)
                sigs = ctor.collectPySignatures()
            except extractors.ExtractorError:
                pass
        else:
            sigs = item.collectPySignatures()
        if sigs:
            if text:
                text = '\n\n' + text
            text = '\n'.join(sigs) + text

        # write the docstring directive and the text
        stream.write('%s%%Docstring\n' % indent)
        stream.write(nci(text, len(indent)+4))
        stream.write('%s%%End\n' % indent)

        # and save the docstring back into item in case it is needed by other
        # generators later on
        item.pyDocstring = nci(text)
示例#9
0
    def generatePyClass(self, pc, stream, indent=""):
        assert isinstance(pc, extractors.PyClassDef)

        # write the class declaration and docstring
        if pc.deprecated:
            stream.write("%[email protected]\n" % indent)
        stream.write("%sclass %s" % (indent, pc.name))
        if pc.bases:
            stream.write("(%s):\n" % ", ".join(pc.bases))
        else:
            stream.write("(object):\n")
        indent2 = indent + " " * 4
        if pc.briefDoc:
            stream.write('%s"""\n' % indent2)
            stream.write(nci(pc.briefDoc, len(indent2)))
            stream.write('%s"""\n' % indent2)

        # these are the only kinds of items allowed to be items in a PyClass
        dispatch = {
            extractors.PyFunctionDef: self.generatePyFunction,
            extractors.PyPropertyDef: self.generatePyProperty,
            extractors.PyCodeDef: self.generatePyCode,
            extractors.PyClassDef: self.generatePyClass,
        }
        for item in pc.items:
            item.klass = pc
            f = dispatch[item.__class__]
            f(item, stream, indent2)
示例#10
0
    def generatePyClass(self, pc, stream, indent=''):
        assert isinstance(pc, extractors.PyClassDef)

        # write the class declaration and docstring
        if pc.deprecated:
            stream.write('%[email protected]\n' % indent)
        stream.write('%sclass %s' % (indent, pc.name))
        if pc.bases:
            stream.write('(%s):\n' % ', '.join(pc.bases))
        else:
            stream.write('(object):\n')
        indent2 = indent + ' '*4
        if pc.briefDoc:
            stream.write('%s"""\n' % indent2)
            stream.write(nci(pc.briefDoc, len(indent2)))
            stream.write('%s"""\n' % indent2)

        # these are the only kinds of items allowed to be items in a PyClass
        dispatch = {
            extractors.PyFunctionDef    : self.generatePyFunction,
            extractors.PyPropertyDef    : self.generatePyProperty,
            extractors.PyCodeDef        : self.generatePyCode,
            extractors.PyClassDef       : self.generatePyClass,
        }
        for item in pc.items:
            item.klass = pc
            f = dispatch[item.__class__]
            f(item, stream, indent2)
示例#11
0
 def generatePyCode(self, pc, stream, indent=''):
     assert isinstance(pc, extractors.PyCodeDef)
     code = pc.code
     if hasattr(pc, 'klass'):
         code = code.replace(pc.klass.pyName+'.', '')
     stream.write('\n')
     stream.write(nci(code, len(indent)))
示例#12
0
    def generateMethod(self,
                       method,
                       stream,
                       indent,
                       name=None,
                       docstring=None):
        assert isinstance(method, extractors.MethodDef)
        for m in method.all(
        ):  # use the first not ignored if there are overloads
            if not m.ignored or piIgnored(m):
                method = m
                break
        else:
            return
        if method.isDtor:
            return

        name = name or method.pyName or method.name
        if name in magicMethods:
            name = magicMethods[name]

        # write the method declaration
        if method.isStatic:
            stream.write('\n%s@staticmethod' % indent)
        stream.write('\n%sdef %s' % (indent, name))
        if method.hasOverloads():
            if not method.isStatic:
                stream.write('(self, *args, **kw)')
            else:
                stream.write('(*args, **kw)')
        else:
            argsString = method.pyArgsString
            if not argsString:
                argsString = '()'
            if '->' in argsString:
                pos = argsString.find(') ->')
                argsString = argsString[:pos + 1]
            if '(' != argsString[0]:
                pos = argsString.find('(')
                argsString = argsString[pos:]
            if not method.isStatic:
                if argsString == '()':
                    argsString = '(self)'
                else:
                    argsString = '(self, ' + argsString[1:]
            argsString = argsString.replace('::', '.')
            stream.write(argsString)
        stream.write(':\n')
        indent2 = indent + ' ' * 4

        # docstring
        if not docstring:
            if hasattr(method, 'pyDocstring'):
                docstring = method.pyDocstring
            else:
                docstring = ""
        stream.write('%s"""\n' % indent2)
        if docstring.strip():
            stream.write(nci(docstring, len(indent2)))
        stream.write('%s"""\n' % indent2)
示例#13
0
 def generatePyCode(self, pc, stream, indent=""):
     assert isinstance(pc, extractors.PyCodeDef)
     code = pc.code
     if hasattr(pc, "klass"):
         code = code.replace(pc.klass.pyName + ".", "")
     stream.write("\n")
     stream.write(nci(code, len(indent)))
示例#14
0
 def generateCppMethod_sip(self, method, stream, indent=''):
     # Add a new C++ method to a class without the extra generated
     # function, so SIP specific stuff can be done in the function body.
     assert isinstance(method, extractors.CppMethodDef_sip)
     if method.ignored:
         return
     _needDocstring = getattr(method, '_needDocstring', True)
     cppSig = " [ %s ]" % method.cppSignature if method.cppSignature else ""
     if method.isCtor:
         stream.write('%s%s%s%s%s;\n' %
                      (indent, method.name, method.argsString,
                       self.annotate(method), cppSig))
     else:
         virtual = "virtual " if method.isVirtual else ""
         stream.write('%s%s%s %s%s%s%s;\n' %
                      (indent, virtual, method.type, method.name,
                       method.argsString, self.annotate(method), cppSig))
     # write the docstring
     if _needDocstring and not (method.isCtor or method.isDtor):
         self.generateDocstring(method, stream, indent)
         # We only write a docstring for the first overload, otherwise
         # SIP appends them all together.
         _needDocstring = False
     stream.write('%s%%MethodCode\n' % indent)
     if not (method.isCtor or method.isDtor):
         stream.write('%sPyErr_Clear();\n' % (indent + ' ' * 4))
         stream.write('%sPy_BEGIN_ALLOW_THREADS\n' % (indent + ' ' * 4))
     stream.write(nci(method.body, len(indent) + 4))
     if not (method.isCtor or method.isDtor):
         stream.write('%sPy_END_ALLOW_THREADS\n' % (indent + ' ' * 4))
         stream.write('%sif (PyErr_Occurred()) sipIsErr = 1;\n' %
                      (indent + ' ' * 4))
     stream.write('%s%%End\n\n' % indent)
示例#15
0
    def generateTypedef(self, typedef, stream, indent=''):
        assert isinstance(typedef, extractors.TypedefDef)
        if typedef.ignored or piIgnored(typedef):
            return

        # If it's not a template instantiation, or has not been flagged by
        # the tweaker script that it should be treated as a class, then just
        # ignore the typedef and return.
        if not ('<' in typedef.type and '>' in typedef.type) and not typedef.docAsClass:
            return

        # Otherwise write a mock class for it that combines the template and class.
        # First, extract the info we need.
        if typedef.docAsClass:
            bases = [self.fixWxPrefix(b, True) for b in typedef.bases]
            name = self.fixWxPrefix(typedef.name)

        elif '<' in typedef.type and '>' in typedef.type:
            t = typedef.type.replace('>', '')
            t = t.replace(' ', '')
            bases = t.split('<')
            bases = [self.fixWxPrefix(b, True) for b in bases]
            name = self.fixWxPrefix(typedef.name)

        # Now write the Python equivalent class for the typedef
        if not bases:
            bases = ['object']  # this should not happpen, but just in case...
        stream.write('%sclass %s(%s):\n' % (indent, name, ', '.join(bases)))
        indent2 = indent + ' '*4
        if typedef.briefDoc:
            stream.write('%s"""\n' % indent2)
            stream.write(nci(typedef.briefDoc, len(indent2)))
            stream.write('%s"""\n' % indent2)
        else:
            stream.write('%spass\n\n' % indent2)
示例#16
0
 def generatePyCode(self, pc, stream, indent=''):
     assert isinstance(pc, extractors.PyCodeDef)
     code = pc.code
     if hasattr(pc, 'klass'):
         code = code.replace(pc.klass.pyName+'.', '')
     stream.write('\n')
     stream.write(nci(code, len(indent)))
示例#17
0
    def generateTypedef(self, typedef, stream, indent=""):
        assert isinstance(typedef, extractors.TypedefDef)
        if typedef.ignored:
            return

        # If it's not a template instantiation, or has not been flagged by
        # the tweaker script that it should be treated as a class, then just
        # ignore the typedef and return.
        if not ("<" in typedef.type and ">" in typedef.type) and not typedef.docAsClass:
            return

        # Otherwise write a mock class for it that combines the template and class.
        # First, extract the info we need.
        if typedef.docAsClass:
            bases = [self.fixWxPrefix(b, True) for b in typedef.bases]
            name = self.fixWxPrefix(typedef.name)

        elif "<" in typedef.type and ">" in typedef.type:
            t = typedef.type.replace(">", "")
            t = t.replace(" ", "")
            bases = t.split("<")
            bases = [self.fixWxPrefix(b, True) for b in bases]
            name = self.fixWxPrefix(typedef.name)

        # Now write the Python equivallent class for the typedef
        if not bases:
            bases = ["object"]  # this should not happpen, but just in case...
        stream.write("%sclass %s(%s):\n" % (indent, name, ", ".join(bases)))
        indent2 = indent + " " * 4
        if typedef.briefDoc:
            stream.write('%s"""\n' % indent2)
            stream.write(nci(typedef.briefDoc, len(indent2)))
            stream.write('%s"""\n' % indent2)
        else:
            stream.write("%spass\n\n" % indent2)
示例#18
0
 def generateMemberVar(self, memberVar, stream, indent):
     assert isinstance(memberVar, extractors.MemberVarDef)
     if memberVar.ignored:
         return
     stream.write('%s%s %s' % (indent, memberVar.type, memberVar.name))
     stream.write(self.annotate(memberVar))
     if memberVar.getCode or memberVar.setCode:
         stream.write('\n%s{\n' % (indent, ))
         if memberVar.getCode:
             stream.write('%s%%GetCode\n' % (indent))
             stream.write(nci(memberVar.getCode, len(indent) + 4))
             stream.write('%s%%End\n' % (indent))
         if memberVar.setCode:
             stream.write('%s%%SetCode\n' % (indent))
             stream.write(nci(memberVar.setCode, len(indent) + 4))
             stream.write('%s%%End\n' % (indent))
         stream.write('%s}' % (indent, ))
     stream.write(';\n\n')
示例#19
0
    def generateMethod(self, method, stream, indent, name=None, docstring=None):
        assert isinstance(method, extractors.MethodDef)
        for m in method.all():  # use the first not ignored if there are overloads
            if not m.ignored or piIgnored(m):
                method = m
                break
        else:
            return
        if method.isDtor:
            return

        name = name or method.pyName or method.name
        if name in magicMethods:
            name = magicMethods[name]

        # write the method declaration
        if method.isStatic:
            stream.write('\n%s@staticmethod' % indent)
        stream.write('\n%sdef %s' % (indent, name))
        if method.hasOverloads():
            if not method.isStatic:
                stream.write('(self, *args, **kw)')
            else:
                stream.write('(*args, **kw)')
        else:
            argsString = method.pyArgsString
            if not argsString:
                argsString = '()'
            if '->' in argsString:
                pos = argsString.find(') ->')
                argsString = argsString[:pos+1]
            if '(' != argsString[0]:
                pos = argsString.find('(')
                argsString = argsString[pos:]
            if not method.isStatic:
                if argsString == '()':
                    argsString = '(self)'
                else:
                    argsString = '(self, ' + argsString[1:]
            argsString = argsString.replace('::', '.')
            stream.write(argsString)
        stream.write(':\n')
        indent2 = indent + ' '*4

        # docstring
        if not docstring:
            if hasattr(method, 'pyDocstring'):
                docstring = method.pyDocstring
            else:
                docstring = ""
        stream.write('%s"""\n' % indent2)
        if docstring.strip():
            stream.write(nci(docstring, len(indent2)))
        stream.write('%s"""\n' % indent2)
示例#20
0
    def generateMethod(self, method, stream, indent, name=None, docstring=None):
        assert isinstance(method, extractors.MethodDef)
        for m in method.all():  # use the first not ignored if there are overloads
            if not m.ignored:
                method = m
                break
        else:
            return
        if method.isDtor:
            return

        name = name or method.pyName or method.name
        if name in magicMethods:
            name = magicMethods[name]

        # write the method declaration
        if method.isStatic:
            stream.write("\n%s@staticmethod" % indent)
        stream.write("\n%sdef %s" % (indent, name))
        if method.hasOverloads():
            if not method.isStatic:
                stream.write("(self, *args, **kw)")
            else:
                stream.write("(*args, **kw)")
        else:
            argsString = method.pyArgsString
            if not argsString:
                argsString = "()"
            if "->" in argsString:
                pos = argsString.find(") ->")
                argsString = argsString[: pos + 1]
            if "(" != argsString[0]:
                pos = argsString.find("(")
                argsString = argsString[pos:]
            if not method.isStatic:
                if argsString == "()":
                    argsString = "(self)"
                else:
                    argsString = "(self, " + argsString[1:]
            argsString = argsString.replace("::", ".")
            stream.write(argsString)
        stream.write(":\n")
        indent2 = indent + " " * 4

        # docstring
        if not docstring:
            if hasattr(method, "pyDocstring"):
                docstring = method.pyDocstring
            else:
                docstring = ""
        stream.write('%s"""\n' % indent2)
        if docstring.strip():
            stream.write(nci(docstring, len(indent2)))
        stream.write('%s"""\n' % indent2)
示例#21
0
    def generateFunction(self, function, stream, _needDocstring=True):
        assert isinstance(function, extractors.FunctionDef)
        if not function.ignored:
            stream.write('%s %s(' % (function.type, function.name))
            if function.items:
                stream.write('\n')
                self.generateParameters(function.items, stream, ' ' * 4)
            stream.write(')%s;\n' % self.annotate(function))

            if _needDocstring:
                self.generateDocstring(function, stream, '')
                # We only write a docstring for the first overload, otherwise
                # SIP appends them all together.
                _needDocstring = False

            if function.preMethodCode:
                stream.write('%PreMethodCode\n')
                stream.write(nci(function.preMethodCode, 4))
                stream.write('%End\n')

            if function.cppCode:
                code, codeType = function.cppCode
                if codeType == 'sip':
                    stream.write('%MethodCode\n')
                    stream.write(nci(code, 4))
                    stream.write('%End\n')
                elif codeType == 'function':
                    ## raise NotImplementedError() # TODO: See generateMethod for an example, refactor to share code...
                    cm = extractors.CppMethodDef.FromMethod(function)
                    cm.body = code
                    self.generateCppMethod(cm,
                                           stream,
                                           "",
                                           skipDeclaration=True)
                    # generateCppMethod will have already done the overloads
                    # and virtual catcher code, so we can just return from
                    # here.
                    return
        for f in function.overloads:
            self.generateFunction(f, stream, _needDocstring)
        stream.write('\n')
示例#22
0
    def generatePyMethod(self, pm, stream, indent):
        assert isinstance(pm, extractors.PyMethodDef)
        if pm.ignored or piIgnored(pm):
            return
        if pm.isStatic:
            stream.write('\n%s@staticmethod' % indent)
        stream.write('\n%sdef %s' % (indent, pm.name))
        stream.write(getattr(pm, 'piArgsString', pm.argsString))
        stream.write(':\n')
        indent2 = indent + ' '*4

        stream.write('%s"""\n' % indent2)
        stream.write(nci(pm.pyDocstring, len(indent2)))
        stream.write('%s"""\n' % indent2)
示例#23
0
 def generatePyFunction(self, pf, stream, indent=''):
     assert isinstance(pf, extractors.PyFunctionDef)
     stream.write('\n')
     if pf.deprecated:
         stream.write('%[email protected]\n' % indent)
     if pf.isStatic:
         stream.write('%s@staticmethod\n' % indent)
     stream.write('%sdef %s%s:\n' % (indent, pf.name, pf.argsString))
     indent2 = indent + ' '*4
     if pf.briefDoc:
         stream.write('%s"""\n' % indent2)
         stream.write(nci(pf.briefDoc, len(indent2)))
         stream.write('%s"""\n' % indent2)
     stream.write('%spass\n' % indent2)
示例#24
0
    def generatePyMethod(self, pm, stream, indent):
        assert isinstance(pm, extractors.PyMethodDef)
        if pm.ignored or piIgnored(pm):
            return
        if pm.isStatic:
            stream.write('\n%s@staticmethod' % indent)
        stream.write('\n%sdef %s' % (indent, pm.name))
        stream.write(getattr(pm, 'piArgsString', pm.argsString))
        stream.write(':\n')
        indent2 = indent + ' '*4

        stream.write('%s"""\n' % indent2)
        stream.write(nci(pm.pyDocstring, len(indent2)))
        stream.write('%s"""\n' % indent2)
示例#25
0
    def generatePyMethod(self, pm, stream, indent):
        assert isinstance(pm, extractors.PyMethodDef)
        if pm.ignored:
            return
        if pm.isStatic:
            stream.write("\n%s@staticmethod" % indent)
        stream.write("\n%sdef %s" % (indent, pm.name))
        stream.write(pm.argsString)
        stream.write(":\n")
        indent2 = indent + " " * 4

        stream.write('%s"""\n' % indent2)
        stream.write(nci(pm.pyDocstring, len(indent2)))
        stream.write('%s"""\n' % indent2)
示例#26
0
 def generatePyFunction(self, pf, stream, indent=""):
     assert isinstance(pf, extractors.PyFunctionDef)
     stream.write("\n")
     if pf.deprecated:
         stream.write("%[email protected]\n" % indent)
     if pf.isStatic:
         stream.write("%s@staticmethod\n" % indent)
     stream.write("%sdef %s%s:\n" % (indent, pf.name, pf.argsString))
     indent2 = indent + " " * 4
     if pf.briefDoc:
         stream.write('%s"""\n' % indent2)
         stream.write(nci(pf.briefDoc, len(indent2)))
         stream.write('%s"""\n' % indent2)
     stream.write("%spass\n" % indent2)
示例#27
0
 def generatePyFunction(self, pf, stream, indent=''):
     assert isinstance(pf, extractors.PyFunctionDef)
     if len(indent) == 0:
         stream.write('%%Extract(id=pycode%s' % self.module_name)
         if pf.order is not None:
             stream.write(', order=%d' % pf.order)
         stream.write(')\n')
     if pf.deprecated:
         if isinstance(pf.deprecated, int):
             stream.write('%[email protected]\n' % indent)
         else:
             stream.write('%[email protected]("%s")\n' % (indent, pf.deprecated))
     if pf.isStatic:
         stream.write('%s@staticmethod\n' % indent)
     stream.write('%sdef %s%s:\n' % (indent, pf.name, pf.argsString))
     indent2 = indent + ' '*4
     if pf.briefDoc:
         stream.write('%s"""\n' % indent2)
         stream.write(nci(pf.briefDoc, len(indent2)))
         stream.write('%s"""\n' % indent2)
     stream.write(nci(pf.body, len(indent2)))
     if len(indent) == 0:
         stream.write('\n%End\n')
     stream.write('\n')
示例#28
0
    def generatePyCode(self, pc, stream, indent=''):
        assert isinstance(pc, extractors.PyCodeDef)
        if hasattr(pc, 'klass') and isinstance(pc.klass, extractors.ClassDef) and pc.klass.generatingInClass:
            pc.klass.generateAfterClass.append(pc)
        else:
            if len(indent) == 0:
                stream.write('%%Extract(id=pycode%s' % self.module_name)
                if pc.order is not None:
                    stream.write(', order=%d' % pc.order)
                stream.write(')\n')

            stream.write(nci(pc.code, len(indent)))

            if len(indent) == 0:
                stream.write('\n%End\n\n')
示例#29
0
    def generatePyCode(self, pc, stream, indent=''):
        assert isinstance(pc, extractors.PyCodeDef)
        if hasattr(pc, 'klass') and isinstance(pc.klass, extractors.ClassDef) and pc.klass.generatingInClass:
            pc.klass.generateAfterClass.append(pc)
        else:
            if len(indent) == 0:
                stream.write('%%Extract(id=pycode%s' % self.module_name)
                if pc.order is not None:
                    stream.write(', order=%d' % pc.order)
                stream.write(')\n')

            stream.write(nci(pc.code, len(indent)))

            if len(indent) == 0:
                stream.write('\n%End\n\n')
示例#30
0
 def generateCppMethod_sip(self, method, stream, indent=''):
     # Add a new C++ method to a class without the extra generated
     # function, so SIP specific stuff can be done in the function body.
     assert isinstance(method, extractors.CppMethodDef_sip)
     if method.ignored:
         return
     cppSig = " [ %s ]" % method.cppSignature if method.cppSignature else ""                
     if method.isCtor:
         stream.write('%s%s%s%s%s;\n' % 
                      (indent, method.name, method.argsString, self.annotate(method), cppSig))
     else:
         stream.write('%s%s %s%s%s%s;\n' % 
                      (indent, method.type, method.name, method.argsString, 
                       self.annotate(method), cppSig))
     stream.write('%s%%MethodCode\n' % indent)
     stream.write(nci(method.body, len(indent)+4))
     stream.write('%s%%End\n\n' % indent)
示例#31
0
 def generateCppMethod_sip(self, method, stream, indent=''):
     # Add a new C++ method to a class without the extra generated
     # function, so SIP specific stuff can be done in the function body.
     assert isinstance(method, extractors.CppMethodDef_sip)
     if method.ignored:
         return
     cppSig = " [ %s ]" % method.cppSignature if method.cppSignature else ""
     if method.isCtor:
         stream.write('%s%s%s%s%s;\n' %
                      (indent, method.name, method.argsString, self.annotate(method), cppSig))
     else:
         stream.write('%s%s %s%s%s%s;\n' %
                      (indent, method.type, method.name, method.argsString,
                       self.annotate(method), cppSig))
     stream.write('%s%%MethodCode\n' % indent)
     stream.write(nci(method.body, len(indent)+4))
     stream.write('%s%%End\n\n' % indent)
示例#32
0
    def generatePyClass(self, pc, stream, indent=''):
        assert isinstance(pc, extractors.PyClassDef)
        if len(indent) == 0:
            stream.write('%%Extract(id=pycode%s' % self.module_name)
            if pc.order is not None:
                stream.write(', order=%d' % pc.order)
            stream.write(')\n')

        # write the class declaration and docstring
        if pc.deprecated:
            if isinstance(pc.deprecated, int):
                stream.write('%[email protected]\n' % indent)
            else:
                stream.write('%[email protected]("%s")\n' %
                             (indent, pc.deprecated))
        stream.write('%sclass %s' % (indent, pc.name))
        if pc.bases:
            stream.write('(%s):\n' % ', '.join(pc.bases))
        else:
            stream.write('(object):\n')
        indent2 = indent + ' ' * 4
        if pc.briefDoc:
            stream.write('%s"""\n' % indent2)
            stream.write(nci(pc.briefDoc, len(indent2)))
            stream.write('%s"""\n' % indent2)

        # these are the only kinds of items allowed to be items in a PyClass
        dispatch = {
            extractors.PyFunctionDef: self.generatePyFunction,
            extractors.PyPropertyDef: self.generatePyProperty,
            extractors.PyCodeDef: self.generatePyCode,
            extractors.PyClassDef: self.generatePyClass,
        }
        for item in pc.items:
            item.klass = pc
            f = dispatch[item.__class__]
            f(item, stream, indent2)

        if len(indent) == 0:
            stream.write('\n%End\n')
        stream.write('\n')
示例#33
0
    def generatePyClass(self, pc, stream, indent=''):
        assert isinstance(pc, extractors.PyClassDef)
        if len(indent) == 0:
            stream.write('%%Extract(id=pycode%s' % self.module_name)
            if pc.order is not None:
                stream.write(', order=%d' % pc.order)
            stream.write(')\n')

        # write the class declaration and docstring
        if pc.deprecated:
            if isinstance(pc.deprecated, int):
                stream.write('%[email protected]\n' % indent)
            else:
                stream.write('%[email protected]("%s")\n' % (indent, pc.deprecated))
        stream.write('%sclass %s' % (indent, pc.name))
        if pc.bases:
            stream.write('(%s):\n' % ', '.join(pc.bases))
        else:
            stream.write('(object):\n')
        indent2 = indent + ' '*4
        if pc.briefDoc:
            stream.write('%s"""\n' % indent2)
            stream.write(nci(pc.briefDoc, len(indent2)))
            stream.write('%s"""\n' % indent2)

        # these are the only kinds of items allowed to be items in a PyClass
        dispatch = {
            extractors.PyFunctionDef    : self.generatePyFunction,
            extractors.PyPropertyDef    : self.generatePyProperty,
            extractors.PyCodeDef        : self.generatePyCode,
            extractors.PyClassDef       : self.generatePyClass,
        }
        for item in pc.items:
            item.klass = pc
            f = dispatch[item.__class__]
            f(item, stream, indent2)
 
        if len(indent) == 0:
            stream.write('\n%End\n')
        stream.write('\n')
示例#34
0
 def generateFunction(self, function, stream):
     assert isinstance(function, extractors.FunctionDef)
     if not function.pyName:
         return
     stream.write('\ndef %s' % function.pyName)
     if function.hasOverloads():
         stream.write('(*args, **kw)')
     else:
         argsString = function.pyArgsString
         if not argsString:
             argsString = '()'
         if '->' in argsString:
             pos = argsString.find(')')
             argsString = argsString[:pos+1]
         if '(' != argsString[0]:
             pos = argsString.find('(')
             argsString = argsString[pos:]
         argsString = argsString.replace('::', '.')
         stream.write(argsString)
     stream.write(':\n')
     stream.write('    """\n')
     stream.write(nci(function.pyDocstring, 4))
     stream.write('    """\n')
示例#35
0
 def generateFunction(self, function, stream):
     assert isinstance(function, extractors.FunctionDef)
     if not function.pyName:
         return
     stream.write("\ndef %s" % function.pyName)
     if function.hasOverloads():
         stream.write("(*args, **kw)")
     else:
         argsString = function.pyArgsString
         if not argsString:
             argsString = "()"
         if "->" in argsString:
             pos = argsString.find(")")
             argsString = argsString[: pos + 1]
         if "(" != argsString[0]:
             pos = argsString.find("(")
             argsString = argsString[pos:]
         argsString = argsString.replace("::", ".")
         stream.write(argsString)
     stream.write(":\n")
     stream.write('    """\n')
     stream.write(nci(function.pyDocstring, 4))
     stream.write('    """\n')
示例#36
0
 def generateFunction(self, function, stream):
     assert isinstance(function, extractors.FunctionDef)
     if not function.pyName:
         return
     stream.write('\ndef %s' % function.pyName)
     if function.hasOverloads():
         stream.write('(*args, **kw)')
     else:
         argsString = function.pyArgsString
         if not argsString:
             argsString = '()'
         if '->' in argsString:
             pos = argsString.find(')')
             argsString = argsString[:pos+1]
         if '(' != argsString[0]:
             pos = argsString.find('(')
             argsString = argsString[pos:]
         argsString = argsString.replace('::', '.')
         stream.write(argsString)
     stream.write(':\n')
     stream.write('    """\n')
     stream.write(nci(function.pyDocstring, 4))
     stream.write('    """\n')
示例#37
0
    def generateMethod(self, method, stream, indent):
        assert isinstance(method, extractors.MethodDef)
        _needDocstring = getattr(method, '_needDocstring', True)
        checkOverloads = True
        if not method.ignored:
            if method.isVirtual:
                stream.write("%svirtual\n" % indent)
            if method.isStatic:
                stream.write("%sstatic\n" % indent)
            if method.isCtor or method.isDtor:
                stream.write('%s%s(' % (indent, method.name))
            else:
                stream.write('%s%s %s(' % (indent, method.type, method.name))
            if method.items:
                stream.write('\n')
                self.generateParameters(method.items, stream, indent + ' ' * 4)
                stream.write(indent)
            stream.write(')')
            if method.isConst:
                stream.write(' const')
            if method.isPureVirtual:
                stream.write(' = 0')
            cppSig = " [ %s ]" % method.cppSignature if method.cppSignature else ""
            if cppSig:
                stream.write(cppSig)
            stream.write('%s;\n' % self.annotate(method))

            if _needDocstring and not (method.isCtor or method.isDtor):
                self.generateDocstring(method, stream, indent)
                # We only write a docstring for the first overload, otherwise
                # SIP appends them all together.
                _needDocstring = False

            if method.mustHaveAppFlag:
                stream.write('%s%%PreMethodCode\n' % indent)
                stream.write(
                    nci("if (!wxPyCheckForApp()) return NULL;\n",
                        len(indent) + 4))
                stream.write('%s%%End\n' % indent)

            if method.cppCode:
                #checkOverloads = False   ## SIP now allows overloads to have %MethodCode
                code, codeType = method.cppCode
                if codeType == 'sip':
                    stream.write('%s%%MethodCode\n' % indent)
                    stream.write(nci(code, len(indent) + 4))
                    stream.write('%s%%End\n' % indent)
                elif codeType == 'function':
                    cm = extractors.CppMethodDef.FromMethod(method)
                    cm.body = code
                    self.generateCppMethod(cm,
                                           stream,
                                           indent,
                                           skipDeclaration=True)
                    # generateCppMethod will have already done the overloads
                    # and virtual catcher code, so we can just return from
                    # here.
                    return

            if method.virtualCatcherCode:
                stream.write('%s%%VirtualCatcherCode\n' % indent)
                stream.write(nci(method.virtualCatcherCode, len(indent) + 4))
                stream.write('%s%%End\n' % indent)

            stream.write('\n')

        if checkOverloads and method.overloads:
            for m in method.overloads:
                m._needDocstring = _needDocstring
                self.dispatchClassItem(method.klass, m, stream, indent)
示例#38
0
    def generateCppMethod(self, method, stream, indent='', skipDeclaration=False):
        # Add a new C++ method to a class. This one adds the code as a
        # separate function and then adds a call to that function in the
        # MethodCode directive.
        
        def _removeIgnoredParams(argsString, paramList):
            # if there are ignored parameters adjust the argsString to match
            lastP = argsString.rfind(')')
            args = argsString[:lastP].strip('()').split(',')
            for idx, p in enumerate(paramList):
                if p.ignored:
                    args[idx] = ''
            args = [a for a in args if a != '']
            return '(' + ', '.join(args) + ')'
        
        assert isinstance(method, extractors.CppMethodDef)
        if method.ignored:
            return

        _needDocstring = getattr(method, '_needDocstring', True)
        argsString = _removeIgnoredParams(method.argsString, method.items)
        lastP = argsString.rfind(')')
        pnames = argsString[:lastP].strip('()').split(',')
        for idx, pn in enumerate(pnames):
            # take only the part before the =, if there is one
            name = pn.split('=')[0].strip()   
            # remove annotations
            name = re.sub('/[A-Za-z]*/', '', name) 
            name = name.strip()
            # now get just the part after any space, * or &, which should be
            # the parameter name
            name = re.split(r'[ \*\&]+', name)[-1] 
            pnames[idx] = name
        pnames = ', '.join(pnames)
        typ = method.type

        if not skipDeclaration:
            cppSig = " [ %s ]" % method.cppSignature if method.cppSignature else ""                
            # First insert the method declaration
            if method.isCtor or method.isDtor:
                virtual = 'virtual ' if method.isVirtual else ''
                stream.write('%s%s%s%s%s%s;\n' % 
                             (indent, virtual, method.name, argsString, self.annotate(method), cppSig))
            else:
                constMod = " const" if method.isConst else ""
                static = "static " if method.isStatic else ""
                virtual = "virtual " if method.isVirtual else ""                
                pure = " = 0" if method.isPureVirtual else ""
                stream.write('%s%s%s%s %s%s%s%s%s%s;\n' % 
                             (indent, static, virtual, typ, 
                              method.name, argsString, constMod, pure, self.annotate(method), cppSig))
    
            # write the docstring
            if  _needDocstring and not (method.isCtor or method.isDtor):
                self.generateDocstring(method, stream, indent)
                # We only write a docstring for the first overload, otherwise
                # SIP appends them all together.
                _needDocstring = False
                
        klass = method.klass
        if klass:
            assert isinstance(klass, extractors.ClassDef)

        # create the new function
        fstream = Utf8EncodingStream()  # using a new stream so we can do the actual write a little later
        lastP = argsString.rfind(')')
        fargs = argsString[:lastP].strip('()').split(',')
        for idx, arg in enumerate(fargs):
            # take only the part before the =, if there is one
            arg = arg.split('=')[0].strip()   
            arg = arg.replace('&', '*')  # SIP will always want to use pointers for parameters
            arg = re.sub('/[A-Za-z]*/', '', arg)  # remove annotations
            fargs[idx] = arg
        fargs = ', '.join(fargs)
        if method.isCtor:
            fname = '_%s_ctor' % klass.name
            fargs = '(%s)' % fargs
            fstream.write('%s%%TypeCode\n' % indent)
            typ = klass.name
            if method.useDerivedName:
                typ = 'sip'+klass.name
                fstream.write('%sclass %s;\n' % (indent, typ))   # forward declare the derived class
            fstream.write('%s%s* %s%s\n%s{\n' % (indent, typ, fname, fargs, indent))
            fstream.write(nci(method.body, len(indent)+4))
            fstream.write('%s}\n' % indent)
            fstream.write('%s%%End\n' % indent)
            
        elif method.isDtor:
            fname = '_%s_dtor' % klass.name
            fargs = '(%s* self)' % klass.name
            fstream.write('%s%%TypeCode\n' % indent)
            fstream.write('%svoid %s%s\n%s{\n' % (indent, fname, fargs, indent))
            fstream.write(nci(method.body, len(indent)+4))
            fstream.write('%s}\n' % indent)
            fstream.write('%s%%End\n' % indent)
            
        else:
            if klass:
                fname = '_%s_%s' % (klass.name, method.name)
                if method.isStatic:
                    # If the method is static then there is no sipCpp to send to
                    # the new function, so it should not have a self parameter.
                    fargs = '(%s)' % fargs
                else:
                    if fargs:
                        fargs = ', ' + fargs
                    selfConst = ''
                    if method.isConst:
                        selfConst = 'const '
                    fargs = '(%s%s* self%s)' % (selfConst, klass.name, fargs)
                fstream.write('%s%%TypeCode\n' % indent)
            else:
                fname = '_%s_function' % method.name
                fargs = '(%s)' % fargs
                fstream.write('%s%%ModuleCode\n' % indent)
            
            # If the return type is in the forcePtrTypes list then make sure
            # that it is a pointer, not a return by value or reference, since
            # SIP almost always deals with pointers to newly allocated
            # objects.
            typPtr = method.type
            if typPtr in forcePtrTypes:
                if '&' in typPtr:
                    typPtr.replace('&', '*')
                elif '*' not in typPtr:
                    typPtr += '*'
        
            fstream.write('%s%s %s%s\n%s{\n' % (indent, typPtr, fname, fargs, indent))
            fstream.write(nci(method.body, len(indent)+4))
            fstream.write('%s}\n' % indent)
            fstream.write('%s%%End\n' % indent)

        # Write the code that will call the new function
        stream.write('%s%%MethodCode\n' % indent)
        stream.write(indent+' '*4)
        if method.isCtor:
            stream.write('sipCpp = %s(%s);\n' % (fname, pnames))
        
        elif method.isDtor:
            stream.write('PyErr_Clear();\n')
            stream.write('%sPy_BEGIN_ALLOW_THREADS\n' % (indent+' '*4))
            stream.write(indent+' '*4)
            stream.write('%s(sipCpp);\n' % fname)
            stream.write('%sPy_END_ALLOW_THREADS\n' % (indent+' '*4))            
            
        else:
            stream.write('PyErr_Clear();\n')
            stream.write('%sPy_BEGIN_ALLOW_THREADS\n' % (indent+' '*4))
            stream.write(indent+' '*4)
            if method.type != 'void':
                stream.write('sipRes = ')
            if klass:
                if method.isStatic:
                    # If the method is static then there is no sipCpp to send to
                    # the new function, so it should not have a self parameter.
                    stream.write('%s(%s);\n' % (fname, pnames))
                else:
                    if pnames:
                        pnames = ', ' + pnames
                    stream.write('%s(sipCpp%s);\n' % (fname, pnames))
            else:
                stream.write('%s(%s);\n' % (fname, pnames))
            stream.write('%sPy_END_ALLOW_THREADS\n' % (indent+' '*4))            
            stream.write('%sif (PyErr_Occurred()) sipIsErr = 1;\n' % (indent+' '*4))
        stream.write('%s%%End\n' % indent)

        if method.virtualCatcherCode:
            stream.write('%s%%VirtualCatcherCode\n' % indent)
            stream.write(nci(method.virtualCatcherCode, len(indent)+4))
            stream.write('%s%%End\n' % indent)
            
        # and finally, add the new function itself
        stream.write(fstream.getvalue())
        stream.write('\n')

        if method.overloads:
            for m in method.overloads:
                m._needDocstring = _needDocstring
                self.dispatchClassItem(method.klass, m, stream, indent)
示例#39
0
    def generateClass(self, klass, stream, indent=""):
        assert isinstance(klass, extractors.ClassDef)
        if klass.ignored:
            return

        # check if there is a pi-customized version of the base class names
        if hasattr(klass, "piBases"):
            bases = klass.piBases

        else:
            # check if it's a template with the template parameter as the base class
            bases = klass.bases[:]
            for tp in klass.templateParams:
                if tp in bases:
                    bases.remove(tp)

        # write class declaration
        klassName = klass.pyName or klass.name
        stream.write("\n%sclass %s" % (indent, klassName))
        if bases:
            stream.write("(")
            bases = [self.fixWxPrefix(b, True) for b in bases]
            stream.write(", ".join(bases))
            stream.write(")")
        else:
            stream.write("(object)")
        stream.write(":\n")
        indent2 = indent + " " * 4

        # docstring
        stream.write('%s"""\n' % indent2)
        stream.write(nci(klass.pyDocstring, len(indent2)))
        stream.write('%s"""\n' % indent2)

        # generate nested classes
        for item in klass.innerclasses:
            self.generateClass(item, stream, indent2)

        # Split the items into public and protected groups
        enums = [i for i in klass if isinstance(i, extractors.EnumDef) and i.protection == "public"]
        ctors = [
            i
            for i in klass
            if isinstance(i, extractors.MethodDef) and i.protection == "public" and (i.isCtor or i.isDtor)
        ]
        public = [i for i in klass if i.protection == "public" and i not in ctors and i not in enums]
        protected = [i for i in klass if i.protection == "protected"]

        dispatch = {
            extractors.MemberVarDef: self.generateMemberVar,
            extractors.TypedefDef: lambda a, b, c: None,
            extractors.PropertyDef: self.generateProperty,
            extractors.PyPropertyDef: self.generatePyProperty,
            extractors.MethodDef: self.generateMethod,
            extractors.EnumDef: self.generateEnum,
            extractors.CppMethodDef: self.generateCppMethod,
            extractors.CppMethodDef_sip: self.generateCppMethod_sip,
            extractors.PyMethodDef: self.generatePyMethod,
            extractors.PyCodeDef: self.generatePyCode,
            extractors.WigCode: self.generateWigCode,
        }

        for item in enums:
            item.klass = klass
            self.generateEnum(item, stream, indent2)

        for item in ctors:
            if item.isCtor:
                item.klass = klass
                self.generateMethod(item, stream, indent2, name="__init__", docstring=klass.pyDocstring)

        for item in public:
            item.klass = klass
            f = dispatch[item.__class__]
            f(item, stream, indent2)

        for item in protected:
            item.klass = klass
            f = dispatch[item.__class__]
            f(item, stream, indent2)

        stream.write("%s# end of class %s\n\n" % (indent, klassName))
示例#40
0
 def generateConvertCode(self, kind, code, stream, indent):
     stream.write('%s%s\n' % (indent, kind))
     stream.write(nci(code, len(indent)+4))
     stream.write('%s%%End\n' % indent)
示例#41
0
 def generateWigCode(self, wig, stream, indent=''):
     assert isinstance(wig, extractors.WigCode)
     stream.write(nci(wig.code, len(indent), False))
     stream.write('\n\n')
示例#42
0
    def generateClass(self, klass, stream, indent=''):
        assert isinstance(klass, extractors.ClassDef)
        if klass.ignored or piIgnored(klass):
            return

        # check if there is a pi-customized version of the base class names
        if hasattr(klass, 'piBases'):
            bases = klass.piBases

        else:
            # check if it's a template with the template parameter as the base class
            bases = klass.bases[:]
            for tp in klass.templateParams:
                if tp in bases:
                    bases.remove(tp)

        # write class declaration
        klassName = klass.pyName or klass.name
        stream.write('\n%sclass %s' % (indent, klassName))
        if bases:
            stream.write('(')
            bases = [self.fixWxPrefix(b, True) for b in bases]
            stream.write(', '.join(bases))
            stream.write(')')
        else:
            stream.write('(object)')
        stream.write(':\n')
        indent2 = indent + ' '*4

        # docstring
        stream.write('%s"""\n' % indent2)
        stream.write(nci(klass.pyDocstring, len(indent2)))
        stream.write('%s"""\n' % indent2)

        # generate nested classes
        for item in klass.innerclasses:
            self.generateClass(item, stream, indent2)

        # Split the items into public and protected groups
        enums = [i for i in klass if
                     isinstance(i, extractors.EnumDef) and
                     i.protection == 'public']
        ctors = [i for i in klass if
                     isinstance(i, extractors.MethodDef) and
                     i.protection == 'public' and (i.isCtor or i.isDtor)]
        public = [i for i in klass if i.protection == 'public' and
                     i not in ctors and i not in enums]
        protected = [i for i in klass if i.protection == 'protected']

        dispatch = {
            extractors.MemberVarDef     : self.generateMemberVar,
            extractors.TypedefDef       : lambda a,b,c: None,
            extractors.PropertyDef      : self.generateProperty,
            extractors.PyPropertyDef    : self.generatePyProperty,
            extractors.MethodDef        : self.generateMethod,
            extractors.EnumDef          : self.generateEnum,
            extractors.CppMethodDef     : self.generateCppMethod,
            extractors.CppMethodDef_sip : self.generateCppMethod_sip,
            extractors.PyMethodDef      : self.generatePyMethod,
            extractors.PyCodeDef        : self.generatePyCode,
            extractors.WigCode          : self.generateWigCode,
            }

        for item in enums:
            item.klass = klass
            self.generateEnum(item, stream, indent2)

        for item in ctors:
            if item.isCtor:
                item.klass = klass
                self.generateMethod(item, stream, indent2,
                                    name='__init__', docstring=klass.pyDocstring)

        for item in public:
            item.klass = klass
            f = dispatch[item.__class__]
            f(item, stream, indent2)

        for item in protected:
            item.klass = klass
            f = dispatch[item.__class__]
            f(item, stream, indent2)

        stream.write('%s# end of class %s\n\n' % (indent, klassName))
示例#43
0
    def generateClass(self, klass, stream, indent=''):
        assert isinstance(klass, extractors.ClassDef)
        if klass.ignored:
            return
        
        # write the class header
        if klass.templateParams:
            stream.write('%stemplate<%s>\n' % (indent, ', '.join(klass.templateParams)))
        stream.write('%s%s %s' % (indent, klass.kind, klass.name))
        if klass.bases:
            stream.write(' : ')
            stream.write(', '.join(klass.bases))
        stream.write(self.annotate(klass))
        stream.write('\n%s{\n' % indent)
        indent2 = indent + ' '*4

        if klass.briefDoc is not None:
            self.generateDocstring(klass, stream, indent2)

        if klass.includes:
            stream.write('%s%%TypeHeaderCode\n' % indent2)
            for inc in klass.includes:
                stream.write('%s    #include <%s>\n' % (indent2, inc))
            stream.write('%s%%End\n\n' % indent2)

        # C++ code to be written to the Type's header 
        if klass.headerCode:
            stream.write("%s%%TypeHeaderCode\n" % indent2)
            for c in klass.headerCode:
                stream.write(nci(c, len(indent2)+4))
            stream.write("%s%%End\n" % indent2)
                
        # C++ code to be written out to the this Type's wrapper code module
        if klass.cppCode:
            stream.write("%s%%TypeCode\n" % indent2)
            for c in klass.cppCode:
                stream.write(nci(c, len(indent2)+4))
            stream.write("%s%%End\n" % indent2)
            
        # C++ code to create a new instance of this class
        if klass.instanceCode:
            stream.write("%s%%InstanceCode\n" % indent2)
            stream.write(nci(klass.instanceCode, len(indent2)+4))
            stream.write("%s%%End\n" % indent2)

        # is the generator currently inside the class or after it?
        klass.generatingInClass = True 

        # Split the items into public and protected groups
        ctors = [i for i in klass if 
                    isinstance(i, extractors.MethodDef) and 
                    i.protection == 'public' and (i.isCtor or i.isDtor)]
        enums = [i for i in klass if 
                    isinstance(i, extractors.EnumDef) and 
                    i.protection == 'public']
        public = [i for i in klass if i.protection == 'public' and i not in ctors+enums]
        protected = [i for i in klass if i.protection == 'protected']
        private = [i for i in klass if i.protection == 'private']
   
        if klass.kind == 'class':
            stream.write('%spublic:\n' % indent)

        # Write enums first since they may be used as default values in
        # methods or in nested classes
        for item in enums:
            self.dispatchClassItem(klass, item, stream, indent2)
            
        # Next do inner classes
        for item in klass.innerclasses:
            if klass.kind == 'class':
                stream.write('%s%s:\n' % (indent, item.protection))
            item.klass = klass
            self.generateClass(item, stream, indent2)
    
        # and then the ctors and the rest of the items in the class
        for item in ctors:
            self.dispatchClassItem(klass, item, stream, indent2)
            
        for item in public:
            self.dispatchClassItem(klass, item, stream, indent2)

        if protected and [i for i in protected if not i.ignored]:
            stream.write('\nprotected:\n')
            for item in protected:
                self.dispatchClassItem(klass, item, stream, indent2)

        if private and [i for i in private if not i.ignored]:
            stream.write('\nprivate:\n')
            for item in private:
                self.dispatchClassItem(klass, item, stream, indent2)

        if klass.convertFromPyObject:
            self.generateConvertCode('%ConvertToTypeCode',
                                     klass.convertFromPyObject,
                                     stream, indent + ' '*4)

        if klass.convertToPyObject:
            self.generateConvertCode('%ConvertFromTypeCode',
                                     klass.convertToPyObject,
                                     stream, indent + ' '*4)
            
        stream.write('%s};  // end of class %s\n\n\n' % (indent, klass.name))
        
        # Now generate anything that was deferred until after the class is finished
        klass.generatingInClass = False
        for item in klass.generateAfterClass:
            self.dispatchClassItem(klass, item, stream, indent)
示例#44
0
    def generateCppMethod(self,
                          method,
                          stream,
                          indent='',
                          skipDeclaration=False):
        # Add a new C++ method to a class. This one adds the code as a
        # separate function and then adds a call to that function in the
        # MethodCode directive.

        def _removeIgnoredParams(argsString, paramList):
            # if there are ignored parameters adjust the argsString to match
            lastP = argsString.rfind(')')
            args = argsString[:lastP].strip('()').split(',')
            for idx, p in enumerate(paramList):
                if p.ignored:
                    args[idx] = ''
            args = [a for a in args if a != '']
            return '(' + ', '.join(args) + ')'

        assert isinstance(method, extractors.CppMethodDef)
        if method.ignored:
            return

        _needDocstring = getattr(method, '_needDocstring', True)
        argsString = _removeIgnoredParams(method.argsString, method.items)
        lastP = argsString.rfind(')')
        pnames = argsString[:lastP].strip('()').split(',')
        for idx, pn in enumerate(pnames):
            # take only the part before the =, if there is one
            name = pn.split('=')[0].strip()
            # remove annotations
            name = re.sub('/[A-Za-z]*/', '', name)
            name = name.strip()
            # now get just the part after any space, * or &, which should be
            # the parameter name
            name = re.split(r'[ \*\&]+', name)[-1]
            pnames[idx] = name
        pnames = ', '.join(pnames)
        typ = method.type

        if not skipDeclaration:
            cppSig = " [ %s ]" % method.cppSignature if method.cppSignature else ""
            # First insert the method declaration
            if method.isCtor or method.isDtor:
                virtual = 'virtual ' if method.isVirtual else ''
                stream.write('%s%s%s%s%s%s;\n' %
                             (indent, virtual, method.name, argsString,
                              self.annotate(method), cppSig))
            else:
                constMod = " const" if method.isConst else ""
                static = "static " if method.isStatic else ""
                virtual = "virtual " if method.isVirtual else ""
                pure = " = 0" if method.isPureVirtual else ""
                stream.write(
                    '%s%s%s%s %s%s%s%s%s%s;\n' %
                    (indent, static, virtual, typ, method.name, argsString,
                     constMod, pure, self.annotate(method), cppSig))

            # write the docstring
            if _needDocstring and not (method.isCtor or method.isDtor):
                self.generateDocstring(method, stream, indent)
                # We only write a docstring for the first overload, otherwise
                # SIP appends them all together.
                _needDocstring = False

        klass = method.klass
        if klass:
            assert isinstance(klass, extractors.ClassDef)

        # create the new function
        fstream = Utf8EncodingStream(
        )  # using a new stream so we can do the actual write a little later
        lastP = argsString.rfind(')')
        fargs = argsString[:lastP].strip('()').split(',')
        for idx, arg in enumerate(fargs):
            # take only the part before the =, if there is one
            arg = arg.split('=')[0].strip()
            arg = arg.replace(
                '&',
                '*')  # SIP will always want to use pointers for parameters
            arg = re.sub('/[A-Za-z]*/', '', arg)  # remove annotations
            fargs[idx] = arg
        fargs = ', '.join(fargs)
        if method.isCtor:
            fname = '_%s_ctor' % klass.name
            fargs = '(%s)' % fargs
            fstream.write('%s%%TypeCode\n' % indent)
            typ = klass.name
            if method.useDerivedName:
                typ = 'sip' + klass.name
                fstream.write(
                    '%sclass %s;\n' %
                    (indent, typ))  # forward declare the derived class
            fstream.write('%s%s* %s%s\n%s{\n' %
                          (indent, typ, fname, fargs, indent))
            fstream.write(nci(method.body, len(indent) + 4))
            fstream.write('%s}\n' % indent)
            fstream.write('%s%%End\n' % indent)

        elif method.isDtor:
            fname = '_%s_dtor' % klass.name
            fargs = '(%s* self)' % klass.name
            fstream.write('%s%%TypeCode\n' % indent)
            fstream.write('%svoid %s%s\n%s{\n' %
                          (indent, fname, fargs, indent))
            fstream.write(nci(method.body, len(indent) + 4))
            fstream.write('%s}\n' % indent)
            fstream.write('%s%%End\n' % indent)

        else:
            if klass:
                fname = '_%s_%s' % (klass.name, method.name)
                if method.isStatic:
                    # If the method is static then there is no sipCpp to send to
                    # the new function, so it should not have a self parameter.
                    fargs = '(%s)' % fargs
                else:
                    if fargs:
                        fargs = ', ' + fargs
                    selfConst = ''
                    if method.isConst:
                        selfConst = 'const '
                    fargs = '(%s%s* self%s)' % (selfConst, klass.name, fargs)
                fstream.write('%s%%TypeCode\n' % indent)
            else:
                fname = '_%s_function' % method.name
                fargs = '(%s)' % fargs
                fstream.write('%s%%ModuleCode\n' % indent)

            # If the return type is in the forcePtrTypes list then make sure
            # that it is a pointer, not a return by value or reference, since
            # SIP almost always deals with pointers to newly allocated
            # objects.
            typPtr = method.type
            if typPtr in forcePtrTypes:
                if '&' in typPtr:
                    typPtr.replace('&', '*')
                elif '*' not in typPtr:
                    typPtr += '*'

            fstream.write('%s%s %s%s\n%s{\n' %
                          (indent, typPtr, fname, fargs, indent))
            fstream.write(nci(method.body, len(indent) + 4))
            fstream.write('%s}\n' % indent)
            fstream.write('%s%%End\n' % indent)

        # Write the code that will call the new function
        stream.write('%s%%MethodCode\n' % indent)
        stream.write(indent + ' ' * 4)
        if method.isCtor:
            # _THREAD macros are intentionally not used in this case
            stream.write('PyErr_Clear();\n')
            stream.write('%ssipCpp = %s(%s);\n' %
                         (indent + ' ' * 4, fname, pnames))

        elif method.isDtor:
            stream.write('PyErr_Clear();\n')
            stream.write('%sPy_BEGIN_ALLOW_THREADS\n' % (indent + ' ' * 4))
            stream.write(indent + ' ' * 4)
            stream.write('%s(sipCpp);\n' % fname)
            stream.write('%sPy_END_ALLOW_THREADS\n' % (indent + ' ' * 4))

        else:
            stream.write('PyErr_Clear();\n')
            stream.write('%sPy_BEGIN_ALLOW_THREADS\n' % (indent + ' ' * 4))
            stream.write(indent + ' ' * 4)
            if method.type != 'void':
                stream.write('sipRes = ')
            if klass:
                if method.isStatic:
                    # If the method is static then there is no sipCpp to send to
                    # the new function, so it should not have a self parameter.
                    stream.write('%s(%s);\n' % (fname, pnames))
                else:
                    if pnames:
                        pnames = ', ' + pnames
                    if method.isSlot:
                        argname = 'a0'
                    else:
                        argname = 'sipCpp'
                    stream.write('%s(%s%s);\n' % (fname, argname, pnames))
            else:
                stream.write('%s(%s);\n' % (fname, pnames))
            stream.write('%sPy_END_ALLOW_THREADS\n' % (indent + ' ' * 4))
            stream.write('%sif (PyErr_Occurred()) sipIsErr = 1;\n' %
                         (indent + ' ' * 4))
        stream.write('%s%%End\n' % indent)

        if method.virtualCatcherCode:
            stream.write('%s%%VirtualCatcherCode\n' % indent)
            stream.write(nci(method.virtualCatcherCode, len(indent) + 4))
            stream.write('%s%%End\n' % indent)

        # and finally, add the new function itself
        stream.write(fstream.getvalue())
        stream.write('\n')

        if method.overloads:
            for m in method.overloads:
                m._needDocstring = _needDocstring
                self.dispatchClassItem(method.klass, m, stream, indent)
示例#45
0
 def generateWigCode(self, wig, stream, indent=''):
     assert isinstance(wig, extractors.WigCode)
     stream.write(nci(wig.code, len(indent), False))
     stream.write('\n\n')
示例#46
0
 def generateConvertCode(self, kind, code, stream, indent):
     stream.write('%s%s\n' % (indent, kind))
     stream.write(nci(code, len(indent) + 4))
     stream.write('%s%%End\n' % indent)
示例#47
0
    def generateClass(self, klass, stream, indent=''):
        assert isinstance(klass, extractors.ClassDef)
        if klass.ignored:
            return

        # Propagate mustHaveApp setting to the ctors
        if klass.mustHaveAppFlag:
            for item in klass.allItems():
                if isinstance(item, extractors.MethodDef) and item.isCtor:
                    item.mustHaveApp(True)

        # write the class header
        if klass.templateParams:
            stream.write('%stemplate<%s>\n' %
                         (indent, ', '.join(klass.templateParams)))
        stream.write('%s%s %s' % (indent, klass.kind, klass.name))
        if klass.bases:
            stream.write(' : ')
            stream.write(', '.join(klass.bases))
        stream.write(self.annotate(klass))
        stream.write('\n%s{\n' % indent)
        indent2 = indent + ' ' * 4

        if klass.briefDoc is not None:
            self.generateDocstring(klass, stream, indent2)

        if klass.includes:
            stream.write('%s%%TypeHeaderCode\n' % indent2)
            for inc in klass.includes:
                stream.write('%s    #include <%s>\n' % (indent2, inc))
            stream.write('%s%%End\n\n' % indent2)

        # C++ code to be written to the Type's header
        if klass.headerCode:
            stream.write("%s%%TypeHeaderCode\n" % indent2)
            for c in klass.headerCode:
                stream.write(nci(c, len(indent2) + 4))
            stream.write("%s%%End\n" % indent2)

        # C++ code to be written out to the this Type's wrapper code module
        if klass.cppCode:
            stream.write("%s%%TypeCode\n" % indent2)
            for c in klass.cppCode:
                stream.write(nci(c, len(indent2) + 4))
            stream.write("%s%%End\n" % indent2)

        # C++ code to create a new instance of this class
        if klass.instanceCode:
            stream.write("%s%%InstanceCode\n" % indent2)
            stream.write(nci(klass.instanceCode, len(indent2) + 4))
            stream.write("%s%%End\n" % indent2)

        # is the generator currently inside the class or after it?
        klass.generatingInClass = True

        # Split the items into public and protected groups
        ctors = [
            i for i in klass if isinstance(i, extractors.MethodDef)
            and i.protection == 'public' and (i.isCtor or i.isDtor)
        ]
        enums = [
            i for i in klass
            if isinstance(i, extractors.EnumDef) and i.protection == 'public'
        ]
        public = [
            i for i in klass
            if i.protection == 'public' and i not in ctors + enums
        ]
        protected = [i for i in klass if i.protection == 'protected']
        private = [i for i in klass if i.protection == 'private']

        if klass.kind == 'class':
            stream.write('%spublic:\n' % indent)

        # Write enums first since they may be used as default values in
        # methods or in nested classes
        for item in enums:
            self.dispatchClassItem(klass, item, stream, indent2)

        # Next do inner classes
        for item in klass.innerclasses:
            if klass.kind == 'class':
                stream.write('%s%s:\n' % (indent, item.protection))
            item.klass = klass
            self.generateClass(item, stream, indent2)

        # and then the ctors and the rest of the items in the class
        for item in ctors:
            self.dispatchClassItem(klass, item, stream, indent2)

        for item in public:
            self.dispatchClassItem(klass, item, stream, indent2)

        if protected and [i for i in protected if not i.ignored]:
            stream.write('\nprotected:\n')
            for item in protected:
                self.dispatchClassItem(klass, item, stream, indent2)

        if private and [i for i in private if not i.ignored]:
            stream.write('\nprivate:\n')
            for item in private:
                self.dispatchClassItem(klass, item, stream, indent2)

        if klass.convertFromPyObject:
            self.generateConvertCode('%ConvertToTypeCode',
                                     klass.convertFromPyObject, stream,
                                     indent + ' ' * 4)

        if klass.convertToPyObject:
            self.generateConvertCode('%ConvertFromTypeCode',
                                     klass.convertToPyObject, stream,
                                     indent + ' ' * 4)

        stream.write('%s};  // end of class %s\n\n\n' % (indent, klass.name))

        # Now generate anything that was deferred until after the class is finished
        klass.generatingInClass = False
        for item in klass.generateAfterClass:
            self.dispatchClassItem(klass, item, stream, indent)