Exemple #1
0
    def visit_Call(self, node):
        positional_final_wildcard = False
        for i, n in enumerate(node.args):
            if astcheck.is_ast_like(n, ast.Name(id=MULTIWILDCARD_NAME)):
                if i + 1 == len(node.args):
                    # Last positional argument - wildcard may extend to kwargs
                    positional_final_wildcard = True

                node.args = self._visit_list(node.args[:i]) + astcheck.listmiddle() \
                            + self._visit_list(node.args[i+1:])

                # Don't try to handle multiple multiwildcards
                break

        kwargs_are_subset = False
        if positional_final_wildcard and node.starargs is None:
            del node.starargs  # Accept any (or none) *args
            # f(a, ??) -> wildcarded kwargs as well
            kwargs_are_subset = True

        if kwargs_are_subset or any(k.arg == MULTIWILDCARD_NAME
                                    for k in node.keywords):
            template_keywords = [
                self.visit(k) for k in node.keywords
                if k.arg != MULTIWILDCARD_NAME
            ]

            def kwargs_checker(sample_keywords, path):
                sample_kwargs = {k.arg: k.value for k in sample_keywords}

                for k in template_keywords:
                    if k.arg == MULTIWILDCARD_NAME:
                        continue
                    if k.arg in sample_kwargs:
                        astcheck.assert_ast_like(sample_kwargs[k.arg], k.value,
                                                 path + [k.arg])
                    else:
                        raise astcheck.ASTMismatch(path, '(missing)',
                                                   'keyword arg %s' % k.arg)

            if template_keywords:
                node.keywords = kwargs_checker
            else:
                # Shortcut if there are no keywords to check
                del node.keywords

            # Accepting arbitrary keywords, so don't check absence of **kwargs
            if node.kwargs is None:
                del node.kwargs

        # In block contexts, we want to avoid checking empty lists (for optional
        # nodes), but here, an empty list should mean that there are no
        # arguments in that group. So we need to override the behaviour in
        # generic_visit
        if node.args == []:
            node.args = must_not_exist_checker
        if getattr(node, 'keywords', None) == []:
            node.keywords = must_not_exist_checker
        return self.generic_visit(node)
Exemple #2
0
    def visit_arguments(self, node):
        positional_final_wildcard = False
        for i, a in enumerate(node.args):
            if a.arg == MULTIWILDCARD_NAME:
                from_end = len(node.args) - (i + 1)
                if from_end == 0:
                    # Last positional argument - wildcard may extend to other groups
                    positional_final_wildcard = True

                args = self._visit_list(node.args[:i]) + astcheck.listmiddle() \
                            + self._visit_list(node.args[i+1:])
                break
        else:
            if node.args:
                args = self._visit_list(node.args)
            else:
                args = must_not_exist_checker

        defaults = [
            (a.arg, self.visit(d))
            for a, d in zip(node.args[-len(node.defaults):], node.defaults)
            if a.arg not in {WILDCARD_NAME, MULTIWILDCARD_NAME}
        ]

        if node.vararg is None:
            if positional_final_wildcard:
                vararg = None
            else:
                vararg = must_not_exist_checker
        else:
            vararg = self.visit(node.vararg)

        kwonly_args_dflts = [(self.visit(a),
                              (d if d is None else self.visit(d)))
                             for a, d in zip(node.kwonlyargs, node.kw_defaults)
                             if a.arg != MULTIWILDCARD_NAME]

        koa_subset = (positional_final_wildcard and vararg is None and (not node.kwonlyargs)) \
                    or any(a.arg == MULTIWILDCARD_NAME for a in node.kwonlyargs)

        if node.kwarg is None:
            if koa_subset:
                kwarg = None
            else:
                kwarg = must_not_exist_checker
        else:
            kwarg = self.visit(node.kwarg)

        return ArgsDefChecker(args=args,
                              defaults=defaults,
                              vararg=vararg,
                              kwonly_args_dflts=kwonly_args_dflts,
                              koa_subset=koa_subset,
                              kwarg=kwarg)
Exemple #3
0
    def visit_Call(self, node):
        positional_final_wildcard = False
        for i, n in enumerate(node.args):
            if astcheck.is_ast_like(n, ast.Name(id=MULTIWILDCARD_NAME)):
                if i+1 == len(node.args):
                    # Last positional argument - wildcard may extend to kwargs
                    positional_final_wildcard = True

                node.args = self._visit_list(node.args[:i]) + astcheck.listmiddle() \
                            + self._visit_list(node.args[i+1:])

                # Don't try to handle multiple multiwildcards
                break

        kwargs_are_subset = False
        if positional_final_wildcard and node.starargs is None:
            del node.starargs   # Accept any (or none) *args
            # f(a, ??) -> wildcarded kwargs as well
            kwargs_are_subset = True

        if kwargs_are_subset or any(k.arg==MULTIWILDCARD_NAME for k in node.keywords):
            template_keywords = [self.visit(k) for k in node.keywords
                                  if k.arg != MULTIWILDCARD_NAME]

            def kwargs_checker(sample_keywords, path):
                sample_kwargs = {k.arg: k.value for k in sample_keywords}

                for k in template_keywords:
                    if k.arg == MULTIWILDCARD_NAME:
                        continue
                    if k.arg in sample_kwargs:
                        astcheck.assert_ast_like(sample_kwargs[k.arg], k.value, path+[k.arg])
                    else:
                        raise astcheck.ASTMismatch(path, '(missing)', 'keyword arg %s' % k.arg)

            if template_keywords:
                node.keywords = kwargs_checker
            else:
                # Shortcut if there are no keywords to check
                del node.keywords

            # Accepting arbitrary keywords, so don't check absence of **kwargs
            if node.kwargs is None:
                del node.kwargs

        # In block contexts, we want to avoid checking empty lists (for optional
        # nodes), but here, an empty list should mean that there are no
        # arguments in that group. So we need to override the behaviour in
        # generic_visit
        if node.args == []:
            node.args = must_not_exist_checker
        if getattr(node, 'keywords', None) == []:
            node.keywords = must_not_exist_checker
        return self.generic_visit(node)
Exemple #4
0
    def visit_arguments(self, node):
        positional_final_wildcard = False
        for i, a in enumerate(node.args):
            if a.arg == MULTIWILDCARD_NAME:
                from_end = len(node.args) - (i+1)
                if from_end == 0:
                    # Last positional argument - wildcard may extend to other groups
                    positional_final_wildcard = True

                args = self._visit_list(node.args[:i]) + astcheck.listmiddle() \
                            + self._visit_list(node.args[i+1:])
                break
        else:
            if node.args:
                args = self._visit_list(node.args)
            else:
                args = must_not_exist_checker

        defaults = [(a.arg, self.visit(d))
                    for a,d in zip(node.args[-len(node.defaults):], node.defaults)
                    if a.arg not in {WILDCARD_NAME, MULTIWILDCARD_NAME}]

        if node.vararg is None:
            if positional_final_wildcard:
                vararg = None
            else:
                vararg = must_not_exist_checker
        else:
            vararg = self.visit(node.vararg)

        kwonly_args_dflts = [(self.visit(a), (d if d is None else self.visit(d)))
                            for a, d in zip(node.kwonlyargs, node.kw_defaults)
                            if a.arg != MULTIWILDCARD_NAME]

        koa_subset = (positional_final_wildcard and vararg is None and (not node.kwonlyargs)) \
                    or any(a.arg == MULTIWILDCARD_NAME for a in node.kwonlyargs)

        if node.kwarg is None:
            if koa_subset:
                kwarg = None
            else:
                kwarg = must_not_exist_checker
        else:
            kwarg = self.visit(node.kwarg)

        return ArgsDefChecker(args=args, defaults=defaults, vararg=vararg,
                              kwonly_args_dflts=kwonly_args_dflts,
                              koa_subset=koa_subset, kwarg=kwarg)
Exemple #5
0
    def prune_wildcard_body(self, node, attrname, must_exist=False):
        """Prunes a code block (e.g. function body) if it is a wildcard"""
        body = getattr(node, attrname, [])
        def _is_multiwildcard(n):
            return astcheck.is_ast_like(n,
                            ast.Expr(value=ast.Name(id=MULTIWILDCARD_NAME)))

        if len(body) == 1 and _is_multiwildcard(body[0]):
            setattr(node, attrname, must_exist_checker)
            return

        # Find a ?? node within the block, and replace it with listmiddle
        for i, n in enumerate(body):
            if _is_multiwildcard(n):
                newbody = body[:i] + astcheck.listmiddle() + body[i+1:]
                setattr(node, attrname, newbody)
Exemple #6
0
    def prune_wildcard_body(self, node, attrname, must_exist=False):
        """Prunes a code block (e.g. function body) if it is a wildcard"""
        body = getattr(node, attrname, [])

        def _is_multiwildcard(n):
            return astcheck.is_ast_like(
                n, ast.Expr(value=ast.Name(id=MULTIWILDCARD_NAME)))

        if len(body) == 1 and _is_multiwildcard(body[0]):
            setattr(node, attrname, must_exist_checker)
            return

        # Find a ?? node within the block, and replace it with listmiddle
        for i, n in enumerate(body):
            if _is_multiwildcard(n):
                newbody = body[:i] + astcheck.listmiddle() + body[i + 1:]
                setattr(node, attrname, newbody)
    print(y)
    c * 2
a = a*2
a = a - 3
x * 2
x += 1
sum(d + [1])
sysmod.version  # modules shouldn't become parameters.
"""

template = ast.Module(body=[
    ast.FunctionDef(
        name="foobar",
        args=ast.arguments(
            args=[mkarg(name) for name in ['z', 'y', 'a', 'x', 'd']]),
        body=listmiddle() + [
            ast.Return(value=ast.Tuple(elts=[
                ast.Name(id=n, ctx=ast.Load())
                for n in ['b', 'subfunc', 'a', 'x']
            ]))
        ]),
    ast.Assign(targets=[
        ast.Tuple(ctx=ast.Store(),
                  names=[
                      ast.Name(id=id, ctx=ast.Store())
                      for id in ['b', 'subfunc', 'a', 'x']
                  ])
    ],
               value=ast.Call(func=ast.Name(id="foobar", ctx=ast.Load()),
                              args=[
                                  ast.Name(id=id, ctx=ast.Load())
Exemple #8
0
        assert not is_ast_like(sample2, template2_wronglist)

def test_format_path():
    assert format_path(['tree', 'body', 0, 'name']) == 'tree.body[0].name'

sample3_code = """
del a
del b
del c
del d
"""

sample3 = ast.parse(sample3_code)

template3 = ast.Module(body=[ast.Delete(targets=[ast.Name(id='a')])] \
                        + listmiddle() \
                        + [ast.Delete(targets=[ast.Name(id='d')])])

template3_too_few_nodes = ast.Module(
    body=[ast.Delete(targets=[ast.Name(id=n)]) for n in 'abcde'] + listmiddle()
)

template3_wrong_front = ast.Module(
    body=[ast.Delete(targets=[ast.Name(id='q')])] + listmiddle()
)

template3_wrong_back = ast.Module(
    body= listmiddle() + [ast.Delete(targets=[ast.Name(id='q')])]
)

template3_wrong_node_type = ast.Module(
def subfunc(c=1, d=z):
    e = 99
    print(y)
    c * 2
a = a*2
a = a - 3
x * 2
x += 1
sum(d + [1])
sysmod.version  # modules shouldn't become parameters.
"""

template = ast.Module(body=[
    ast.FunctionDef(name="foobar", args=ast.arguments(args=[
                mkarg(name) for name in ['z', 'y', 'a', 'x', 'd']
    ]), body=listmiddle() + [
        ast.Return(value=ast.Tuple(elts=
            [ast.Name(id=n, ctx=ast.Load()) for n in ['b', 'subfunc', 'a', 'x']]
        ))
    ]),
    ast.Assign(targets=[ast.Tuple(ctx=ast.Store(), names=[
            ast.Name(id=id, ctx=ast.Store()) for id in ['b', 'subfunc', 'a', 'x']
            ])],
         value = ast.Call(func=ast.Name(id="foobar", ctx=ast.Load()),
                          args=[
              ast.Name(id=id, ctx=ast.Load()) for id in ['z', 'y', 'a', 'x', 'd']
            ])
        )
])

def test_makefunction():