def transform(self, node, results):
     if 'sys_import' in results:
         if self.sys_import is None:
             self.sys_import = results['sys_import']
         return
     else:
         func = results['func'].clone()
         func.prefix = u''
         register = pytree.Node(syms.power, Attr(Name(u'atexit'), Name(u'register')))
         call = Call(register, [func], node.prefix)
         node.replace(call)
         if self.sys_import is None:
             self.warning(node, "Can't find sys import; Please add an atexit import at the top of your file.")
             return
         names = self.sys_import.children[1]
         if names.type == syms.dotted_as_names:
             names.append_child(Comma())
             names.append_child(Name(u'atexit', u' '))
         else:
             containing_stmt = self.sys_import.parent
             position = containing_stmt.children.index(self.sys_import)
             stmt_container = containing_stmt.parent
             new_import = pytree.Node(syms.import_name, [Name(u'import'), Name(u'atexit', u' ')])
             new = pytree.Node(syms.simple_stmt, [new_import])
             containing_stmt.insert_child(position + 1, Newline())
             containing_stmt.insert_child(position + 2, new)
         return
Beispiel #2
0
    def transform(self, node, results):
        signame = results['signame']

        if 'emitter' in results:
            emitter = results.get("emitter")
            emitter = Name(''.join(map(str, emitter)))

            if 'sigarg' in results:
                args = results.get("args").clone()
                args.children = args.children[2:]
                if args.children:
                    args.children[0].prefix = ''
                res = Node(syms.power, [emitter, Name('.'), Name(signame), Name('.'), Name('emit')] + [ArgList([args])])
            else:
                res = Node(syms.power, [emitter, Name('.'), Name(signame), Name('.'), Name('emit()')])

        else:
            sender = results.get("sender").clone()
            method = results.get("method")
            if isinstance(method, list):
                method = method[0]
            method = method.clone()
            sender.prefix = node.prefix
            slot = results.get("slot").clone()
            slot.prefix = ""
            res = Node(syms.power, [sender, Name('.'), Name(signame), Name('.'), method] + [ArgList([slot])])
        return res
Beispiel #3
0
def RaisesOp(context, exceptionClass, indent, kws, arglist, node):
    with_item = Call(Name(context), [exceptionClass])
    with_item.prefix = " "
    args = []
    arglist = [a.clone() for a in arglist.children[4:]]
    if arglist:
        arglist[0].prefix = ""

    func = None

    # :fixme: this uses hardcoded parameter names, which may change
    if 'callableObj' in kws:
        func = kws['callableObj']
    elif 'callable_obj' in kws:
        func = kws['callable_obj']
    elif kws['args']:  # any arguments assigned to `*args`
        func = kws['args'][0]
    else:
        func = None

    if func is None:
        # Context manager
        return Node(syms.with_stmt, [with_item])

    if func.type == syms.lambdef:
        suite = func.children[-1].clone()
    else:
        suite = Call(func, arglist)

    suite.prefix = indent + (4 * " ")
    return Node(
        syms.with_stmt,
        [Name('with'), with_item,
         Name(':'), Newline(), suite])
Beispiel #4
0
def RaisesRegexOp(context, designator, exceptionClass, expected_regex, indent,
                  kws, arglist, node):
    expected_regex.prefix = ""
    arglist = [a.clone() for a in arglist.children]
    del arglist[2:4]  # remove pattern and comma
    arglist = Node(syms.arglist, arglist)
    with_stmt = RaisesOp(context, exceptionClass, indent, kws, arglist, node)
    with_stmt.insert_child(2, Name('as', prefix=" "))
    with_stmt.insert_child(3, Name(designator, prefix=" "))

    # if this is already part of a with statement we need to insert re.search
    # after the last leaf with content
    if node.parent.type == syms.with_stmt:
        parent_with = node.parent
        for leaf in reversed(list(parent_with.leaves())):
            if leaf.value.strip():
                break
        i = leaf.parent.children.index(leaf)
        leaf.parent.insert_child(i + 1, Newline())
        leaf.parent.insert_child(
            i + 2,
            Name('assert %s.match(%s)' % (designator, expected_regex),
                 prefix=indent))
        return with_stmt
    else:
        return Node(syms.suite, [
            with_stmt,
            Newline(),
            Name('assert %s.match(%s)' % (designator, expected_regex),
                 prefix=indent)
        ])
Beispiel #5
0
 def handle_name(name, prefix):
     if name.type == syms.import_as_name:
         kids = [Name(name.children[0].value, prefix=prefix),
                 name.children[1].clone(),
                 name.children[2].clone()]
         return [Node(syms.import_as_name, kids)]
     return [Name(name.value, prefix=prefix)]
Beispiel #6
0
    def transform(self, node, results):
        cls = node.parent.parent.parent.parent
        assert cls.type == syms.classdef, (
            "Internal error in the fields annotator"
        )

        ast_node_name = cls.children[1].value
        ast_node = self.astnodes()[ast_node_name]
        ":type: langkit.compiled_types.ASTNodeType"

        field_name = node.parent.children[0].value
        field = ast_node.get_abstract_node_data_dict()[field_name]
        field_type_name = field.type.dsl_name

        # This assumes that a typerepo instance of name T is available in
        # the environment in which nodes are defined.
        type_expr = build_attr("T", field_type_name)
        if field.type.is_list_type:
            type_expr = build_attr(
                build_attr("T", field.type.element_type.dsl_name),
                "list"
            )

        return Call(Name(" Field"),
                    [KeywordArg(Name("type"), type_expr)])
 def transform(self, node, results):
     u"""
     Call __builtins__.long() with the value and the base of the value.
     This works because 0b10 is int("10", 2), 0o10 is int("10", 8), etc.
     """
     val = node.value
     base_ = base(val)
     if base_ == 8:
         assert val.strip().startswith(u"0o") or \
             val.strip().startswith(
                 u"0O"), u"Invalid format for octal literal"
         node.changed()
         node.value = u"".join((u"0", val[2:]))
     elif base_ == 2:
         assert val.startswith(u"0") and val[1] in u"bB", \
             u"Invalid format for binary literal"
         # __builtins__.long
         func_name = Node(syms.power,
                          Attr(Name(u"__builtins__"), Name(u"long")))
         # ("...", 2)
         func_args = [
             String(u"".join((u"\"", val.strip()[2:], u"\""))),
             Comma(),
             Number(2, prefix=u" ")
         ]
         new_node = Call(func_name, func_args, node.prefix)
         return new_node
Beispiel #8
0
 def transform(self, node, results):
     import_mod = results.get("module_name")
     if import_mod:
         mod_name = import_mod.value
         new_name = unicode(self.mapping[mod_name])
         import_mod.replace(Name(new_name, prefix=import_mod.prefix))
         if "name_import" in results:
             # If it's not a "from x import x, y" or "import x as y" import,
             # marked its usage to be replaced.
             self.replace[mod_name] = new_name
         if "multiple_imports" in results:
             # This is a nasty hack to fix multiple imports on a line (e.g.,
             # "import StringIO, urlparse"). The problem is that I can't
             # figure out an easy way to make a pattern recognize the keys of
             # MAPPING randomly sprinkled in an import statement.
             results = self.match(node)
             if results:
                 self.transform(node, results)
     else:
         # Replace usage of the module.
         import pdb
         pdb.set_trace()
         bare_name = results["bare_with_attr"][0]
         new_name = self.replace.get(bare_name.value)
         if new_name:
             bare_name.replace(Name(new_name, prefix=bare_name.prefix))
Beispiel #9
0
    def transform(self, node, results):
        # Mostly copied from fix_imports.py
        import_mod = results.get("module_name")
        if import_mod:
            try:
                mod_name = import_mod.value
            except AttributeError:
                # XXX: A hack to remove whitespace prefixes and suffixes
                mod_name = str(import_mod).strip()
            new_name = self.mapping[mod_name]
            import_mod.replace(Name(new_name, prefix=import_mod.prefix))
            if "name_import" in results:
                # If it's not a "from x import x, y" or "import x as y" import,
                # marked its usage to be replaced.
                self.replace[mod_name] = new_name
            if "multiple_imports" in results:
                # This is a nasty hack to fix multiple imports on a line (e.g.,
                # "import StringIO, urlparse"). The problem is that I can't
                # figure out an easy way to make a pattern recognize the keys of
                # MAPPING randomly sprinkled in an import statement.
                results = self.match(node)
                if results:
                    self.transform(node, results)
        else:
            # Replace usage of the module.
            bare_name_text = ''.join(map(str,
                                         results['bare_with_attr'])).strip()
            new_name = self.replace.get(bare_name_text)
            bare_name = results["bare_with_attr"][0]

            if new_name:
                node.replace(Name(new_name, prefix=bare_name.prefix))
Beispiel #10
0
    def transform(self, node: LN, capture: Capture) -> None:
        if node.type == syms.simple_stmt:
            trust_trace_headers_value = None
            header_trust_handler_seen = False

            for prev_argument, argument in pairwise(capture["arguments"]):
                if argument.type == syms.argument:
                    if argument.children[0].value == "trust_trace_headers":
                        assert argument.children[1].value == "="
                        trust_trace_headers_value = argument.children[2].clone()
                        argument.remove()

                        if prev_argument.type == token.COMMA:
                            prev_argument.remove()
                    elif argument.children[0].value == "header_trust_handler":
                        header_trust_handler_seen = True

            if trust_trace_headers_value and not header_trust_handler_seen:
                capture["arglist"].append_child(Comma())

                handler_kwarg = KeywordArg(
                    Name("trust_headers"), trust_trace_headers_value
                )
                handler = Call(Name("StaticTrustHandler"), args=[handler_kwarg])

                kwarg = KeywordArg(Name("header_trust_handler"), handler)
                kwarg.prefix = " "
                capture["arglist"].append_child(kwarg)

                self.added_static_trust_handler = True
Beispiel #11
0
def RaisesOp(context, exceptionClass, indent, kws, arglist):
    with_item = Call(Name(context), [exceptionClass])
    with_item.prefix = " "
    args = []
    arglist = [a.clone() for a in arglist.children[4:]]
    if arglist:
        arglist[0].prefix=""

    func = None

    # :fixme: this uses hardcoded parameter names, which may change
    if 'callableObj' in kws:
        func = kws['callableObj']
    elif 'callable_obj' in kws:
        func = kws['callable_obj']
    elif kws['args']: # any arguments assigned to `*args`
        func = kws['args'][0]
    else:
        raise NotImplementedError('with %s is not implemented' % context)

    if func is unittest.case._sentinel:
        # with self.assertRaises(SomeException):
        return Node(syms.with_stmt,
                    [with_item])

    suite = Call(func, arglist)

    suite.prefix = indent + (4 * " ")
    return Node(syms.with_stmt,
                [Name('with'),
                 with_item,
                 Name(':'),
                 Newline(),
                 suite])
Beispiel #12
0
 def fix_dotted_name(self, node, mapping=MAPPING):
     u"""
     Accepts either a DottedName node or a power node with a trailer.
     If mapping is given, use it; otherwise use our MAPPING
     Returns a node that can be in-place replaced by the node given
     """
     if node.type == syms.dotted_name:
         _name = node.children[0]
         _attr = node.children[2]
     elif node.type == syms.power:
         _name = node.children[0]
         _attr = node.children[1].children[1]
     name = _name.value
     attr = _attr.value
     full_name = name + u'.' + attr
     if not full_name in mapping:
         return
     to_repl = mapping[full_name]
     if u'.' in to_repl:
         repl_name, repl_attr = to_repl.split(u'.')
         _name.replace(Name(repl_name, prefix=_name.prefix))
         _attr.replace(Name(repl_attr, prefix=_attr.prefix))
     elif node.type == syms.dotted_name:
         node.replace(Name(to_repl, prefix=node.prefix))
     elif node.type == syms.power:
         _name.replace(Name(to_repl, prefix=_name.prefix))
         parent = _attr.parent
         _attr.remove()
         parent.remove()
Beispiel #13
0
    def transform(self, node, results):
        head = results["head"]
        method = results["method"][0]  # Extract node for method name
        tail = results["tail"]
        syms = self.syms
        method_name = method.value
        isiter = method_name.startswith(u"iter")
        isview = method_name.startswith(u"view")
        head = [n.clone() for n in head]
        tail = [n.clone() for n in tail]
        # no changes neccessary if the call is in a special context
        special = not tail and self.in_special_context(node, isiter)
        new = pytree.Node(syms.power, head)
        new.prefix = u""
        if isiter or isview:
            # replace the method with the six function
            # e.g. d.iteritems() -> from six import iteritems\n iteritems(d)
            new = Call(Name(method_name), [new])
            touch_import_top('six', method_name, node)
        elif special:
            # it is not neccessary to change this case
            return node
        elif method_name in ("items", "values"):
            # ensure to return a list in python 3
            new = Call(Name(u"list" + method_name), [new])
            touch_import_top('future.utils', 'list' + method_name, node)
        else:
            # method_name is "keys"; removed it and cast the dict to list
            new = Call(Name(u"list"), [new])

        if tail:
            new = pytree.Node(syms.power, [new] + tail)
        new.prefix = node.prefix
        return new
Beispiel #14
0
def ImportAsName(name: str, nick: Optional[str], prefix: Optional[str] = None) -> Node:
    if not nick:
        return Name(name, prefix=prefix)
    return Node(
        syms.import_as_name,
        [Name(name), Name("as", prefix=" "), Name(nick, prefix=" ")],
        prefix=prefix,
    )
 def transform(self, node, results):
     tb = results['tb'].clone()
     tb.prefix = ''
     with_tb = Attr(results['val'].clone(), Name('with_traceback')) + \
               [ArgList([tb])]
     new = pytree.Node(self.syms.simple_stmt, [Name("raise")] + with_tb)
     new.prefix = node.prefix
     return new
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
Beispiel #17
0
def name_import_replacement(name, attr):
    children = [Name("import")]
    for c in all_candidates(name.value, attr.value):
        children.append(Name(c, prefix=" "))
        children.append(Comma())
    children.pop()
    replacement = Node(syms.import_name, children)
    return replacement
Beispiel #18
0
    def transform(self, node, results):
        func = results['func']

        touch_import(None, 'collections', node=node)

        args = [func.clone(), String(', ')]
        args.extend(Attr(Name('collections'), Name('Callable')))
        return Call(Name('isinstance'), args, prefix=node.prefix)
Beispiel #19
0
        def _CreateCode(indent, package, symbols, comment):
            """
            Create code:
                from <package> import <symbols> # <comment>
            """
            # children: the children nodes for the final from-import statement
            children = [
                Name('from', prefix=' ' * indent),
                Name(package, prefix=' '),
                Name('import', prefix=' '),
            ]

            # name_leaf: list of leaf nodes with the symbols to import
            name_leafs = []
            symbols = sorted(symbols)
            for i, i_symbol in enumerate(symbols):
                prefix = ' ' if i == 0 else ', '
                name_leafs.append(i_symbol.CreateNameNode(prefix))

            # nodes_wrap: if true, we need to wrap the import statement
            nodes_wrap = False
            line_len = 0
            line_len += six.moves.reduce(lambda x, y: x + y,
                                         map(len, map(str, children)), 0)
            line_len += six.moves.reduce(lambda x, y: x + y,
                                         map(len, map(str, name_leafs)), 0)
            if line_len > page_width:
                # Add parenthesis around the "from" names
                name_leafs[0].prefix = ''
                name_leafs.insert(0, Name('(', prefix=' '))
                name_leafs.append(Name(')'))
                nodes_wrap = True

            # Adds the name_leafs to the children list
            children += [
                Node(pygram.python_symbols.import_as_names, name_leafs)
            ]

            # from_import: the final node for the import statement
            from_import = Node(pygram.python_symbols.import_from, children)

            # result: a simple-statement node with the import statement and
            # EOL.
            new_line = Newline()
            new_line.prefix = comment
            result = Node(
                pygram.python_symbols.simple_stmt,
                children=[
                    from_import,
                    new_line,
                ],
            )

            # Wrap nodes if necessary (see nodes_wrap above)
            if nodes_wrap:
                ImportBlock.TextWrapForNode(result, page_width, indent)

            return result
Beispiel #20
0
def assignment_source(num_pre, num_post, LISTNAME, ITERNAME):
    u"""
    Accepts num_pre and num_post, which are counts of values
    before and after the starg (not including the starg)
    Returns a source fit for Assign() from fixer_util
    """
    children = []
    pre = unicode(num_pre)
    post = unicode(num_post)
    # This code builds the assignment source from lib2to3 tree primitives.
    # It's not very readable, but it seems like the most correct way to do it.
    if num_pre > 0:
        pre_part = Node(syms.power, [
            Name(LISTNAME),
            Node(syms.trailer, [
                Leaf(token.LSQB, u"["),
                Node(syms.subscript, [Leaf(token.COLON, u":"),
                                      Number(pre)]),
                Leaf(token.RSQB, u"]")
            ])
        ])
        children.append(pre_part)
        children.append(Leaf(token.PLUS, u"+", prefix=u" "))
    main_part = Node(syms.power, [
        Leaf(token.LSQB, u"[", prefix=u" "),
        Name(LISTNAME),
        Node(syms.trailer, [
            Leaf(token.LSQB, u"["),
            Node(syms.subscript, [
                Number(pre) if num_pre > 0 else Leaf(1, u""),
                Leaf(token.COLON, u":"),
                Node(syms.factor, [Leaf(token.MINUS, u"-"),
                                   Number(post)]) if num_post > 0 else Leaf(
                                       1, u"")
            ]),
            Leaf(token.RSQB, u"]"),
            Leaf(token.RSQB, u"]")
        ])
    ])
    children.append(main_part)
    if num_post > 0:
        children.append(Leaf(token.PLUS, u"+", prefix=u" "))
        post_part = Node(syms.power, [
            Name(LISTNAME, prefix=u" "),
            Node(syms.trailer, [
                Leaf(token.LSQB, u"["),
                Node(syms.subscript, [
                    Node(syms.factor, [Leaf(token.MINUS, u"-"),
                                       Number(post)]),
                    Leaf(token.COLON, u":")
                ]),
                Leaf(token.RSQB, u"]")
            ])
        ])
        children.append(post_part)
    source = Node(syms.arith_expr, children)
    return source
Beispiel #21
0
    def transform_import(self, node, results):
        import_mod = results.get('module')
        pref = import_mod.prefix
        names = []
        for name in MAPPING[import_mod.value][:-1]:
            names.extend([Name(name[0], prefix=pref), Comma()])

        names.append(Name(MAPPING[import_mod.value][-1][0], prefix=pref))
        import_mod.replace(names)
Beispiel #22
0
def UnaryOp(prefix, postfix, value, kws):
    kids = []
    if prefix:
        kids.append(Name(prefix, prefix=" "))
    value.prefix = " "
    kids.append(value)
    if postfix:
        kids.append(Name(postfix, prefix=" "))
    return Node(syms.test, kids, prefix=" ")
Beispiel #23
0
    def _handle_buildin(self, node, method_name):
        if method_name == "open":
            arglist = node.children[1].children[1]
            first_arg, remaining_args = self._split_arguments(arglist)

            x = Call(Name("Path"), first_arg, prefix=node.prefix)
            x.append_child(Call(Name("open"), remaining_args, prefix="."))
            return x
        else:
            raise ValueError("Method not found")
Beispiel #24
0
    def _handle_no_args(self, node, method_name):
        if method_name == "getcwd":
            method_name = "cwd"

        if method_name == "listdir":
            return Call(Name('list'),
                        [Call(Name('Path(".").glob'), args=[String('"*"')])],
                        prefix=node.prefix)

        return Call(Name('Path.{}'.format(method_name)), prefix=node.prefix)
Beispiel #25
0
 def new_future_import(self, old):
     new = FromImport("__future__", [
         Name("absolute_import", prefix=" "),
         Comma(),
         Name("division", prefix=" "),
         Comma(),
         Name("print_function", prefix=" ")
     ])
     if old is not None:
         new.prefix = old.prefix
     return new
Beispiel #26
0
 def transform(self, node, results):
     if 'name' in results:
         touch_import(None, u'six', node)
         name = results['name']
         name.replace(Name(u'six.text_type', prefix=name.prefix))
     elif node.type == token.STRING and _literal_re.match(node.value):
         touch_import(None, u'six', node)
         new = node.clone()
         new.value = new.value[1:]
         new.prefix = ''
         node.replace(Call(Name(u'six.u', prefix=node.prefix), [new]))
Beispiel #27
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 NameImport(package, as_name=None, prefix=None):
    """
    Accepts a package (Name node), name to import it as (string), and
    optional prefix and returns a node:
    import <package> [as <as_name>]
    """
    if prefix is None:
        prefix = u""
    children = [Name(u"import", prefix=prefix), package]
    if as_name is not None:
        children.extend([Name(u"as", prefix=u" "), Name(as_name, prefix=u" ")])
    return Node(syms.import_name, children)
 def transform_import(self, node, results):
     """Transform for the basic import case. Replaces the old
        import name with a comma separated list of its
        replacements.
     """
     import_mod = results.get('module')
     pref = import_mod.prefix
     names = []
     for name in MAPPING[import_mod.value][:-1]:
         names.extend([Name(name[0], prefix=pref), Comma()])
     names.append(Name(MAPPING[import_mod.value][-1][0], prefix=pref))
     import_mod.replace(names)
def UnaryOp(prefix, postfix, value, kws):
    if prefix or postfix:
        value = parenthesize_expression(value)

    kids = []
    if prefix:
        kids.append(Name(prefix, prefix=" "))
    value.prefix = " "
    kids.append(value)
    if postfix:
        kids.append(Name(postfix, prefix=" "))
    return Node(syms.test, kids, prefix=" ")
Beispiel #31
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())

        func = results['func'].value

        custom_helper = False

        if node.parent.type == syms.return_stmt:
            # custom helper with `return eq_(...)`
            # We're not rendering the `assert` in that case
            # to allow the code to continue functioning
            custom_helper = True

        posargs = []
        kwargs = []

        if results['arglist'].type == syms.arglist:
            for arg in results['arglist'].children:
                process_arg(arg)
        else:
            process_arg(results['arglist'])

        if len(posargs) == 2:
            left, right = posargs
        elif len(posargs) == 3:
            left, right, _ = posargs

        left.prefix = " "
        right.prefix = " "

        strip_newlines(left)
        strip_newlines(right)

        # Ignore customized assert messages for now
        if isinstance(right, Leaf) and right.value in ('None', 'True', 'False'):
            op = Name('is', prefix=' ')
            body = [Node(syms.comparison, (left, op, right))]
        else:
            op = Name('==', prefix=' ')
            body = [Node(syms.comparison, (left, op, right))]

        indent = find_indentation(node)

        ret = Name('assert')

        if node.parent.prefix.endswith(indent):
            ret.prefix = indent

        if custom_helper:
            return body

        return [ret] + body