Example #1
0
 def transform(self, node, results):
     # before
     before = [b.clone() for b in results['before']]
     # tr | translate
     tr = results['tr']
     new_tr = [(tr[0] if isinstance(tr, list) else tr).clone()]
     # message
     message = results['message'].clone()
     for ch in (message.pre_order() if not isinstance(message, Leaf) else [message]):
         if isinstance(ch, Leaf):
             for i in range(N_ARGS):
                 # %1 -> {0}, ...
                 ch.value = ch.value.replace("%{0}".format(i+1), "{%d}" % i)
     new_tr += [ArgList([message])]
     # format
     def format_args():
         for key in sorted(results):
             if key.startswith('arg'):
                 arg = results[key]
                 if isinstance(arg, list):
                     for a in arg:
                         yield a.clone()
                 else:
                     yield arg.clone()
                 yield Comma()
                 yield String(' ')
                                                     # Skip last Comma, String
     new_format = [Dot(), Name('format'), ArgList(list(format_args())[:-2])]
     # rest
     rest = [r.clone() for r in results['rest']]
     # new node
     new = Node(syms.power, before + new_tr + new_format + rest)
     new.prefix = node.prefix
     new.parent = node.parent
     return new
Example #2
0
def ImportAsName(name, as_name, prefix=None):
    new_name = Name(name)
    new_as = Name(u"as", prefix=u" ")
    new_as_name = Name(as_name, prefix=u" ")
    new_node = Node(syms.import_as_name, [new_name, new_as, new_as_name])
    if prefix is not None:
        new_node.prefix = prefix
    return new_node
Example #3
0
    def transform(self, node, results):

        def process_arg(arg):
            if isinstance(arg, Leaf) and arg.type == token.COMMA:
                return
            elif isinstance(arg, Node) and arg.type == syms.argument:
                # keyword argument
                name, equal, value = arg.children
                assert name.type == token.NAME # what is the symbol for 1?
                assert equal.type == token.EQUAL # what is the symbol for 1?
                value = value.clone()
                value.prefix = " "
                kwargs[name.value] = value
            else:
                assert not kwargs, 'all positional args are assumed to come first'
                posargs.append(arg.clone())

        method = results['method'][0].value
        # map (deprecated) aliases to original to avoid analysing
        # the decorator function
        method = _method_aliases.get(method, method)

        posargs = []
        kwargs = {}

        # This is either a "arglist" or a single argument
        if results['arglist'].type == syms.arglist:
            for arg in results['arglist'].children:
                process_arg(arg)
        else:
            process_arg(results['arglist'])

        try:
            test_func = getattr(unittest.TestCase, method)
        except AttributeError:
            raise RuntimeError("Your unittest package does not support '%s'. "
                               "consider updating the package" % method)

        required_args, argsdict = utils.resolve_func_args(test_func, posargs, kwargs)

        if method.startswith(('assertRaises', 'assertWarns')):
            n_stmt = _method_map[method](*required_args,
                                         indent=find_indentation(node),
                                         kws=argsdict,
                                         arglist=results['arglist'])
        else:
            n_stmt = Node(syms.assert_stmt,
                          [Name('assert'),
                           _method_map[method](*required_args, kws=argsdict)])
        if argsdict.get('msg', None) is not None:
            n_stmt.children.extend((Name(','), argsdict['msg']))
        n_stmt.prefix = node.prefix

        return n_stmt
    def transform(self, node, results):

        def process_arg(arg):
            if isinstance(arg, Leaf) and arg.type == token.COMMA:
                return
            elif isinstance(arg, Node) and arg.type == syms.argument:
                # keyword argument
                name, equal, value = arg.children
                assert name.type == token.NAME # what is the symbol for 1?
                assert equal.type == token.EQUAL # what is the symbol for 1?
                value = value.clone()
                value.prefix = " "
                kwargs[name.value] = value
            else:
                assert not kwargs, 'all positional args are assumed to come first'
                posargs.append(arg.clone())

        method = results['method'][0].value
        # map (deprecated) aliases to original to avoid analysing
        # the decorator function
        method = _method_aliases.get(method, method)

        posargs = []
        kwargs = {}

        # This is either a "arglist" or a single argument
        if results['arglist'].type == syms.arglist:
            for arg in results['arglist'].children:
                process_arg(arg)
        else:
            process_arg(results['arglist'])
        
        try:
            test_func = getattr(unittest.TestCase, method)
        except AttributeError:
            raise RuntimeError("Your unittest package does not support '%s'. "
                               "consider updating the package" % method)

        required_args, argsdict = utils.resolve_func_args(test_func, posargs, kwargs)

        if method.startswith(('assertRaises', 'assertWarns')):
            n_stmt = _method_map[method](*required_args,
                                         indent=find_indentation(node),
                                         kws=argsdict,
                                         arglist=results['arglist'])
        else:
            n_stmt = Node(syms.assert_stmt,
                          [Name('assert'),
                           _method_map[method](*required_args, kws=argsdict)])
        if argsdict.get('msg', None) is not None:
            n_stmt.children.extend((Name(','), argsdict['msg']))
        n_stmt.prefix = node.prefix
        return n_stmt
    def transform(self, node, results):
        def process_arg(arg):
            if isinstance(arg, Leaf) and arg.type == token.COMMA:
                return
            elif (isinstance(arg, Node) and arg.type == syms.argument
                  and arg.children[1].type == token.EQUAL):
                # keyword argument
                name, equal, value = arg.children
                assert name.type == token.NAME
                assert equal.type == token.EQUAL
                value = value.clone()
                kwargs[name.value] = value
                if '\n' in arg.prefix:
                    value.prefix = arg.prefix
                else:
                    value.prefix = arg.prefix.strip() + " "
            else:
                if (isinstance(arg, Node) and arg.type == syms.argument
                        and arg.children[0].type == 36
                        and arg.children[0].value == '**'):
                    return
                assert not kwargs, 'all positional args are assumed to come first'
                if (isinstance(arg, Node) and arg.type == syms.argument
                        and arg.children[1].type == syms.comp_for):
                    # argument is a generator expression w/o
                    # parenthesis, add parenthesis
                    value = arg.clone()
                    value.children.insert(0, Leaf(token.LPAR, '('))
                    value.children.append(Leaf(token.RPAR, ')'))
                    posargs.append(value)
                else:
                    posargs.append(arg.clone())

        method = results['method'][0].value
        # map (deprecated) aliases to original to avoid analysing
        # the decorator function
        method = _method_aliases.get(method, method)

        posargs = []
        kwargs = {}

        # This is either a "arglist" or a single argument
        if results['arglist'].type == syms.arglist:
            for arg in results['arglist'].children:
                process_arg(arg)
        else:
            process_arg(results['arglist'])

        try:
            test_func = getattr(unittest.TestCase, method)
        except AttributeError:
            raise RuntimeError("Your unittest package does not support '%s'. "
                               "consider updating the package" % method)

        required_args, argsdict = utils.resolve_func_args(
            test_func, posargs, kwargs)

        if method.startswith(('assertRaises', 'assertWarns')):
            n_stmt = _method_map[method](*required_args,
                                         indent=find_indentation(node),
                                         kws=argsdict,
                                         arglist=results['arglist'],
                                         node=node)
        else:
            n_stmt = Node(syms.assert_stmt, [
                Name('assert'), _method_map[method](*required_args,
                                                    kws=argsdict)
            ])
        if argsdict.get('msg', None) is not None:
            n_stmt.children.extend((Name(','), argsdict['msg']))

        def fix_line_wrapping(x):
            for c in x.children:
                # no need to worry about wrapping of "[", "{" and "("
                if c.type in [token.LSQB, token.LBRACE, token.LPAR]:
                    break
                if c.prefix.startswith('\n'):
                    c.prefix = c.prefix.replace('\n', ' \\\n')
                fix_line_wrapping(c)

        fix_line_wrapping(n_stmt)
        # the prefix should be set only after fixing line wrapping because it can contain a '\n'
        n_stmt.prefix = node.prefix

        # add necessary imports
        if 'Raises' in method or 'Warns' in method:
            add_import('pytest', node)
        if ('Regex' in method and not 'Raises' in method
                and not 'Warns' in method):
            add_import('re', node)

        return n_stmt
Example #6
0
    def transform(self, node, results):
        if 'name' in results:
            # This matched an import statement. Fix that up:
            name = results["name"]
            name.replace(Name(self.DECORATOR_NAME, prefix=name.prefix))
        if 'rename' in results:
            # The import statement use import as
            self._add_pattern("'%s'" % results['rename'].value)
        if 'interface_rename' in results:
            self._add_pattern("'%s' trailer< '.' '%s' > " % (
                results['interface_rename'].value, self.FUNCTION_NAME))
        if 'statement' in results:
            # This matched a class that has an <FUNCTION_NAME>(IFoo) statement.
            # We must convert that statement to a class decorator
            # and put it before the class definition.

            statement = results['statement']
            if not isinstance(statement, list):
                statement = [statement]
            # Make a copy for insertion before the class:
            statement = [x.clone() for x in statement]
            # Get rid of leading whitespace:
            statement[0].prefix = ''
            # Rename function to decorator:
            if statement[-1].children:
                func = statement[-1].children[-1]
            else:
                func = statement[-1]
            if func.value == self.FUNCTION_NAME:
                func.value = self.DECORATOR_NAME

            interface = results['interface']
            if not isinstance(interface, list):
                interface = [interface]
            interface = [x.clone() for x in interface]

            # Create the decorator:
            decorator = Node(syms.decorator, [Leaf(50, '@'),] + statement +
                             [Leaf(7, '(')] + interface + [Leaf(8, ')')])

            # Take the current class constructor prefix, and stick it into
            # the decorator, to set the decorators indentation.
            nodeprefix = node.prefix
            decorator.prefix = nodeprefix
            # Preserve only the indent:
            if '\n' in nodeprefix:
                nodeprefix = nodeprefix[nodeprefix.rfind('\n')+1:]

            # Then find the last line of the previous node and use that as
            # indentation, and add that to the class constructors prefix.

            previous = node.prev_sibling
            if previous is None:
                prefix = ''
            else:
                prefix = str(previous)
            if '\n' in prefix:
                prefix = prefix[prefix.rfind('\n')+1:]
            prefix = prefix + nodeprefix

            if not prefix or prefix[0] != '\n':
                prefix = '\n' + prefix
            node.prefix = prefix
            new_node = Node(syms.decorated, [decorator, node.clone()])
            # Look for the actual function calls in the new node and remove it.
            for node in new_node.post_order():
                for pattern in self.function_patterns:
                    if pattern.match(node, results):
                        parent = node.parent
                        previous = node.prev_sibling
                        # Remove the node
                        node.remove()
                        if not str(parent).strip():
                            # This is an empty class. Stick in a pass
                            if (len(parent.children) < 3 or
                                ' ' in parent.children[2].value):
                                # This class had no body whitespace.
                                parent.insert_child(2, Leaf(0, '    pass'))
                            else:
                                # This class had body whitespace already.
                                parent.insert_child(2, Leaf(0, 'pass'))
                            parent.insert_child(3, Leaf(0, '\n'))
                        elif (prefix and isinstance(previous, Leaf) and
                            '\n' not in previous.value and
                            previous.value.strip() == ''):
                            # This is just whitespace, remove it:
                            previous.remove()

            return new_node
    def transform(self, node, results):

        def process_arg(arg):
            if isinstance(arg, Leaf) and arg.type == token.COMMA:
                return
            elif isinstance(arg, Node) and arg.type == syms.argument:
                # keyword argument
                name, equal, value = arg.children
                assert name.type == token.NAME # what is the symbol for 1?
                assert equal.type == token.EQUAL # what is the symbol for 1?
                value = value.clone()
                kwargs[name.value] = value
                if '\n' in arg.prefix:
                    value.prefix = arg.prefix
                else:
                    value.prefix = arg.prefix.strip() + " "
            else:
                assert not kwargs, 'all positional args are assumed to come first'
                posargs.append(arg.clone())

        method = results['method'][0].value
        # map (deprecated) aliases to original to avoid analysing
        # the decorator function
        method = _method_aliases.get(method, method)

        posargs = []
        kwargs = {}

        # This is either a "arglist" or a single argument
        if results['arglist'].type == syms.arglist:
            for arg in results['arglist'].children:
                process_arg(arg)
        else:
            process_arg(results['arglist'])

        try:
            test_func = getattr(unittest.TestCase, method)
        except AttributeError:
            raise RuntimeError("Your unittest package does not support '%s'. "
                               "consider updating the package" % method)

        required_args, argsdict = utils.resolve_func_args(test_func, posargs, kwargs)

        if method.startswith(('assertRaises', 'assertWarns')):
            n_stmt = _method_map[method](*required_args,
                                         indent=find_indentation(node),
                                         kws=argsdict,
                                         arglist=results['arglist'],
                                         node=node)
        else:
            n_stmt = Node(syms.assert_stmt,
                          [Name('assert'),
                           _method_map[method](*required_args, kws=argsdict)])
        if argsdict.get('msg', None) is not None:
            n_stmt.children.extend((Name(','), argsdict['msg']))

        def fix_line_wrapping(x):
            for c in x.children:
                # no need to worry about wrapping of "[", "{" and "("
                if c.type in [token.LSQB, token.LBRACE, token.LPAR]:
                    break
                if c.prefix.startswith('\n'):
                    c.prefix = c.prefix.replace('\n', ' \\\n')
                fix_line_wrapping(c)
        fix_line_wrapping(n_stmt)
        # the prefix should be set only after fixing line wrapping because it can contain a '\n'
        n_stmt.prefix = node.prefix

        # add necessary imports
        if 'Raises' in method or 'Warns' in method:
            add_import('pytest', node)
        if 'Regex' in method:
            add_import('re', node)

        return n_stmt