Exemplo n.º 1
0
 def get_doc(obj, indent=False):
     doc = inspect.getdoc(obj)
     if doc:
         doc = ('r"""\n%s\n"""\n' % doc)
         if indent:
             doc = common.indent_block(doc)
         return doc
     return ''
Exemplo n.º 2
0
 def get_doc(obj, indent=False):
     doc = inspect.getdoc(obj)
     if doc:
         doc = ('r"""\n%s\n"""\n' % doc)
         if indent:
             doc = common.indent_block(doc)
         return doc
     return ''
Exemplo n.º 3
0
def _generate_code(scope, mixin_funcs={}, depth=0):
    """
    Generate a string, which uses python syntax as an input to the
    PyFuzzyParser.
    """
    def get_doc(obj, indent=False):
        doc = inspect.getdoc(obj)
        if doc:
            doc = ('r"""\n%s\n"""\n' % doc)
            if indent:
                doc = common.indent_block(doc)
            return doc
        return ''

    def is_in_base_classes(cls, name, comparison):
        """ Base classes may contain the exact same object """
        if name in mixin_funcs:
            return False
        try:
            mro = cls.mro()
        except TypeError:
            # this happens, if cls == type
            return False
        for base in mro[1:]:
            try:
                attr = getattr(base, name)
            except AttributeError:
                continue
            if attr == comparison:
                return True
        return False

    def get_scope_objects(names):
        """
        Looks for the names defined with dir() in an objects and divides
        them into different object types.
        """
        classes = {}
        funcs = {}
        stmts = {}
        members = {}
        for n in names:
            try:
                # this has a builtin_function_or_method
                exe = getattr(scope, n)
            except AttributeError:
                # happens e.g. in properties of
                # PyQt4.QtGui.QStyleOptionComboBox.currentText
                # -> just set it to None
                members[n] = None
            else:
                if inspect.isclass(scope):
                    if is_in_base_classes(scope, n, exe):
                        continue
                if inspect.isbuiltin(exe) or inspect.ismethod(exe) \
                            or inspect.ismethoddescriptor(exe):
                    funcs[n] = exe
                elif inspect.isclass(exe):
                    classes[n] = exe
                elif inspect.ismemberdescriptor(exe):
                    members[n] = exe
                else:
                    stmts[n] = exe
        return classes, funcs, stmts, members

    code = ''
    if inspect.ismodule(scope):  # generate comment where the code's from.
        try:
            path = scope.__file__
        except AttributeError:
            path = '?'
        code += '# Generated module %s from %s\n' % (scope.__name__, path)

    code += get_doc(scope)

    names = set(dir(scope)) - set(['__file__', '__name__', '__doc__',
                                            '__path__', '__package__']) \
                            | set(['mro'])

    classes, funcs, stmts, members = get_scope_objects(names)

    # classes
    for name, cl in classes.items():
        bases = (c.__name__ for c in cl.__bases__)
        code += 'class %s(%s):\n' % (name, ','.join(bases))
        if depth == 0:
            try:
                mixin = mixin_funcs[name]
            except KeyError:
                mixin = {}
            cl_code = _generate_code(cl, mixin, depth + 1)
            code += common.indent_block(cl_code)
        code += '\n'

    # functions
    for name, func in funcs.items():
        params, ret = parse_function_doc(func)
        if depth > 0:
            params = 'self, ' + params
        doc_str = get_doc(func, indent=True)
        try:
            mixin = mixin_funcs[name]
        except KeyError:
            # normal code generation
            code += 'def %s(%s):\n' % (name, params)
            code += doc_str
            code += common.indent_block('%s\n\n' % ret)
        else:
            # generation of code with mixins
            # the parser only supports basic functions with a newline after
            # the double dots
            # find doc_str place
            try:
                pos = re.search(r'\):\s*\n', mixin).end()
            except TypeError:
                # pypy uses a different reversed builtin
                if name == 'reversed':
                    mixin = 'def reversed(sequence):\n' \
                            '    for i in self.__sequence: yield i'
                    pos = 24
                else:
                    debug.warning('mixin trouble in pypy: %s', name)
                    raise
            if pos is None:
                raise Exception("Builtin function not parsed correctly")
            code += mixin[:pos] + doc_str + mixin[pos:]

    # class members (functions) properties?
    for name, func in members.items():
        # recursion problem in properties TODO remove
        if name in ['fget', 'fset', 'fdel']:
            continue
        ret = 'pass'
        code += '@property\ndef %s(self):\n' % (name)
        code += common.indent_block(get_doc(func) + '%s\n\n' % ret)

    # variables
    for name, value in stmts.items():
        if is_py3k:
            file_type = io.TextIOWrapper
        else:
            file_type = types.FileType
        if type(value) == file_type:
            value = 'open()'
        elif name == 'None':
            value = ''
        elif type(value).__name__ in ['int', 'bool', 'float',
                                      'dict', 'list', 'tuple']:
            value = repr(value)
        else:
            # get the type, if the type is not simple.
            mod = type(value).__module__
            value = type(value).__name__ + '()'
            if mod != '__builtin__':
                value = '%s.%s' % (mod, value)
        code += '%s = %s\n' % (name, value)

    if depth == 0:
        #with open('writeout.py', 'w') as f:
        #    f.write(code)
        #import sys
        #sys.stdout.write(code)
        #exit()
        pass
    return code
Exemplo n.º 4
0
def _generate_code(scope, mixin_funcs={}, depth=0):
    """
    Generate a string, which uses python syntax as an input to the
    PyFuzzyParser.
    """
    def get_doc(obj, indent=False):
        doc = inspect.getdoc(obj)
        if doc:
            doc = ('r"""\n%s\n"""\n' % doc)
            if indent:
                doc = common.indent_block(doc)
            return doc
        return ''

    def is_in_base_classes(cls, name, comparison):
        """ Base classes may contain the exact same object """
        if name in mixin_funcs:
            return False
        try:
            mro = cls.mro()
        except TypeError:
            # this happens, if cls == type
            return False
        for base in mro[1:]:
            try:
                attr = getattr(base, name)
            except AttributeError:
                continue
            if attr == comparison:
                return True
        return False

    def get_scope_objects(names):
        """
        Looks for the names defined with dir() in an objects and divides
        them into different object types.
        """
        classes = {}
        funcs = {}
        stmts = {}
        members = {}
        for n in names:
            try:
                # this has a builtin_function_or_method
                exe = getattr(scope, n)
            except AttributeError:
                # happens e.g. in properties of
                # PyQt4.QtGui.QStyleOptionComboBox.currentText
                # -> just set it to None
                members[n] = None
            else:
                if inspect.isclass(scope):
                    if is_in_base_classes(scope, n, exe):
                        continue
                if inspect.isbuiltin(exe) or inspect.ismethod(exe) \
                            or inspect.ismethoddescriptor(exe):
                    funcs[n] = exe
                elif inspect.isclass(exe):
                    classes[n] = exe
                elif inspect.ismemberdescriptor(exe):
                    members[n] = exe
                else:
                    stmts[n] = exe
        return classes, funcs, stmts, members

    code = ''
    if inspect.ismodule(scope):  # generate comment where the code's from.
        try:
            path = scope.__file__
        except AttributeError:
            path = '?'
        code += '# Generated module %s from %s\n' % (scope.__name__, path)

    code += get_doc(scope)

    names = set(dir(scope)) - set(['__file__', '__name__', '__doc__',
                                            '__path__', '__package__']) \
                            | set(['mro'])

    classes, funcs, stmts, members = get_scope_objects(names)

    # classes
    for name, cl in classes.items():
        bases = (c.__name__ for c in cl.__bases__)
        code += 'class %s(%s):\n' % (name, ','.join(bases))
        if depth == 0:
            try:
                mixin = mixin_funcs[name]
            except KeyError:
                mixin = {}
            cl_code = _generate_code(cl, mixin, depth + 1)
            code += common.indent_block(cl_code)
        code += '\n'

    # functions
    for name, func in funcs.items():
        params, ret = parse_function_doc(func)
        if depth > 0:
            params = 'self, ' + params
        doc_str = get_doc(func, indent=True)
        try:
            mixin = mixin_funcs[name]
        except KeyError:
            # normal code generation
            code += 'def %s(%s):\n' % (name, params)
            code += doc_str
            code += common.indent_block('%s\n\n' % ret)
        else:
            # generation of code with mixins
            # the parser only supports basic functions with a newline after
            # the double dots
            # find doc_str place
            try:
                pos = re.search(r'\):\s*\n', mixin).end()
            except TypeError:
                # pypy uses a different reversed builtin
                if name == 'reversed':
                    mixin = 'def reversed(sequence):\n' \
                            '    for i in self.__sequence: yield i'
                    pos = 24
                else:
                    debug.warning('mixin trouble in pypy: %s', name)
                    raise
            if pos is None:
                raise Exception("Builtin function not parsed correctly")
            code += mixin[:pos] + doc_str + mixin[pos:]

    # class members (functions) properties?
    for name, func in members.items():
        # recursion problem in properties TODO remove
        if name in ['fget', 'fset', 'fdel']:
            continue
        ret = 'pass'
        code += '@property\ndef %s(self):\n' % (name)
        code += common.indent_block(get_doc(func) + '%s\n\n' % ret)

    # variables
    for name, value in stmts.items():
        if is_py3k:
            file_type = io.TextIOWrapper
        else:
            file_type = types.FileType
        if type(value) == file_type:
            value = 'open()'
        elif name == 'None':
            value = ''
        elif type(value).__name__ in [
                'int', 'bool', 'float', 'dict', 'list', 'tuple'
        ]:
            value = repr(value)
        else:
            # get the type, if the type is not simple.
            mod = type(value).__module__
            value = type(value).__name__ + '()'
            if mod != '__builtin__':
                value = '%s.%s' % (mod, value)
        code += '%s = %s\n' % (name, value)

    if depth == 0:
        #with open('writeout.py', 'w') as f:
        #    f.write(code)
        #import sys
        #sys.stdout.write(code)
        #exit()
        pass
    return code