Ejemplo n.º 1
0
    def generate(self, module, destFile=None):
        stream = Utf8EncodingStream()

        # process the module object and its child objects
        self.generateModule(module, stream)

        # Write the contents of the stream to the destination file
        if not destFile:
            name = module.module
            if name.startswith('_'):
                name = name[1:]
            destFile = os.path.join(phoenixRoot, 'wx', name)

        destFile_pi = destFile + '.pi'
        destFile_pyi = destFile + '.pyi'

        def _checkAndWriteHeader(destFile, header, docstring):
            if not os.path.exists(destFile):
                # create the file and write the header
                f = textfile_open(destFile, 'wt')
                f.write(header)
                if docstring:
                    f.write('\n"""\n%s"""\n' % docstring)
                f.close()

        if not SKIP_PI_FILE:
            _checkAndWriteHeader(destFile_pi, header_pi, module.docstring)
            self.writeSection(destFile_pi, module.name, stream.getvalue())

        if not SKIP_PYI_FILE:
            _checkAndWriteHeader(destFile_pyi, header_pyi, module.docstring)
            self.writeSection(destFile_pyi, module.name, stream.getvalue())
Ejemplo n.º 2
0
    def generate(self, module, destFile=None):
        stream = Utf8EncodingStream()

        # generate SIP code from the module and its objects
        self.generateModule(module, stream)

        # Write the contents of the stream to the destination file
        if not destFile:
            destFile = os.path.join(phoenixRoot, 'sip/gen', module.name + '.sip')
        with textfile_open(destFile, 'wt') as f:
            f.write(stream.getvalue())
Ejemplo n.º 3
0
    def generate(self, module, destFile=None):
        stream = Utf8EncodingStream()

        # process the module object and its child objects
        self.generateModule(module, stream)

        # Write the contents of the stream to the destination file
        if not destFile:
            name = module.module + '.pi'
            if name.startswith('_'):
                name = name[1:]
            destFile = os.path.join(phoenixRoot, 'wx', name)

        if not os.path.exists(destFile):
            # create the file and write the header
            f = textfile_open(destFile, 'wt')
            f.write(header)
            f.close()

        self.writeSection(destFile, module.name, stream.getvalue())
Ejemplo n.º 4
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)