Beispiel #1
0
def visit_ClassDef(
        state: State,
        node: ast.ClassDef,
        parent: ast.AST,
) -> Iterable[Tuple[Offset, TokenFunc]]:
    if state.settings.min_version < (3,):
        return

    for decorator in node.decorator_list:
        if (
                isinstance(decorator, ast.Call) and
                is_name_attr(
                    decorator.func,
                    state.from_imports,
                    'six',
                    ('add_metaclass',),
                ) and
                not has_starargs(decorator)
        ):
            yield ast_to_offset(decorator), _fix_add_metaclass

    if (
            len(node.bases) == 1 and
            isinstance(node.bases[0], ast.Call) and
            is_name_attr(
                node.bases[0].func,
                state.from_imports,
                'six',
                ('with_metaclass',),
            ) and
            not has_starargs(node.bases[0])
    ):
        yield ast_to_offset(node.bases[0]), _fix_with_metaclass
Beispiel #2
0
def visit_Subscript(
    state: State,
    node: ast.Subscript,
    parent: ast.AST,
) -> Iterable[Tuple[Offset, TokenFunc]]:
    if not _supported_version(state):
        return

    if is_name_attr(node.value, state.from_imports, 'typing', ('Optional', )):
        yield ast_to_offset(node), _fix_optional
    elif is_name_attr(node.value, state.from_imports, 'typing', ('Union', )):
        if sys.version_info >= (3, 9):  # pragma: no cover (py39+)
            node_slice: ast.expr = node.slice
        elif isinstance(node.slice, ast.Index):  # pragma: no cover (<py39)
            node_slice = node.slice.value
        else:  # pragma: no cover (<py39)
            return  # unexpected slice type

        if isinstance(node_slice, ast.Tuple):
            if node_slice.elts:
                arg_count = len(node_slice.elts)
            else:
                return  # empty Union
        else:
            arg_count = 1

        func = functools.partial(_fix_union, arg_count=arg_count)
        yield ast_to_offset(node), func
Beispiel #3
0
def visit_Call(
    state: State,
    node: ast.Call,
    parent: ast.AST,
) -> Iterable[Tuple[Offset, TokenFunc]]:
    if (state.settings.min_version >= (3, 8) and not node.args
            and not node.keywords and is_name_attr(
                node.func,
                state.from_imports,
                'functools',
                ('lru_cache', ),
            )):
        yield ast_to_offset(node), _remove_call
    elif (state.settings.min_version >= (3, 9)
          and isinstance(node.func, ast.Attribute)
          and node.func.attr == 'lru_cache'
          and isinstance(node.func.value, ast.Name)
          and node.func.value.id == 'functools' and not node.args
          and len(node.keywords) == 1 and node.keywords[0].arg == 'maxsize'
          and isinstance(node.keywords[0].value, ast.NameConstant)
          and node.keywords[0].value.value is None):
        func = functools.partial(
            find_and_replace_call,
            template='functools.cache',
        )
        yield ast_to_offset(node), func
Beispiel #4
0
def is_a_native_literal_call(
    node: ast.Call,
    from_imports: Dict[str, Set[str]],
) -> bool:
    return ((is_name_attr(node.func, from_imports, 'six', SIX_NATIVE_STR)
             or isinstance(node.func, ast.Name) and node.func.id == 'str')
            and not node.keywords and not has_starargs(node)
            and (len(node.args) == 0 or
                 (len(node.args) == 1 and isinstance(node.args[0], ast.Str))))
Beispiel #5
0
def visit_ClassDef(
    state: State,
    node: ast.ClassDef,
    parent: ast.AST,
) -> Iterable[Tuple[Offset, TokenFunc]]:
    if state.settings.min_version >= (3, ):
        for base in node.bases:
            if is_name_attr(base, state.from_imports, 'six', ('Iterator', )):
                yield ast_to_offset(base), remove_base_class
Beispiel #6
0
def visit_Call(
    state: State,
    node: ast.Call,
    parent: ast.AST,
) -> Iterable[Tuple[Offset, TokenFunc]]:
    if (state.settings.min_version >= (3, 7) and is_name_attr(
            node.func,
            state.from_imports,
            'subprocess',
        ('run', ),
    )):
        stdout_idx = None
        stderr_idx = None
        universal_newlines_idx = None
        for n, keyword in enumerate(node.keywords):
            if keyword.arg == 'stdout' and is_name_attr(
                    keyword.value,
                    state.from_imports,
                    'subprocess',
                ('PIPE', ),
            ):
                stdout_idx = n
            elif keyword.arg == 'stderr' and is_name_attr(
                    keyword.value,
                    state.from_imports,
                    'subprocess',
                ('PIPE', ),
            ):
                stderr_idx = n
            elif keyword.arg == 'universal_newlines':
                universal_newlines_idx = n
        if universal_newlines_idx is not None:
            func = functools.partial(
                _replace_universal_newlines_with_text,
                arg_idx=len(node.args) + universal_newlines_idx,
            )
            yield ast_to_offset(node), func
        if stdout_idx is not None and stderr_idx is not None:
            func = functools.partial(
                _use_capture_output,
                stdout_arg_idx=len(node.args) + stdout_idx,
                stderr_arg_idx=len(node.args) + stderr_idx,
            )
            yield ast_to_offset(node), func
Beispiel #7
0
def visit_Call(
    state: State,
    node: ast.Call,
    parent: ast.AST,
) -> Iterable[Tuple[Offset, TokenFunc]]:
    if (state.settings.min_version >= (3, 8) and not node.args
            and not node.keywords and is_name_attr(
                node.func,
                state.from_imports,
                'functools',
                ('lru_cache', ),
            )):
        yield ast_to_offset(node), _remove_call
def visit_ClassDef(
    state: State,
    node: ast.ClassDef,
    parent: ast.AST,
) -> Iterable[Tuple[Offset, TokenFunc]]:
    if state.settings.min_version >= (3, ):
        for decorator in node.decorator_list:
            if is_name_attr(
                    decorator,
                    state.from_imports,
                    'six',
                ('python_2_unicode_compatible', ),
            ):
                yield ast_to_offset(decorator), remove_decorator
Beispiel #9
0
def visit_If(
    state: State,
    node: ast.If,
    parent: ast.AST,
) -> Iterable[Tuple[Offset, TokenFunc]]:
    if (state.settings.min_version >= (3, ) and (
            # if six.PY2:
            is_name_attr(node.test, state.from_imports, 'six', ('PY2', )) or
            # if not six.PY3:
        (isinstance(node.test, ast.UnaryOp)
         and isinstance(node.test.op, ast.Not) and is_name_attr(
             node.test.operand,
             state.from_imports,
             'six',
             ('PY3', ),
         )) or
            # sys.version_info == 2 or < (3,)
        (isinstance(node.test, ast.Compare) and is_name_attr(
            node.test.left,
            state.from_imports,
            'sys',
            ('version_info', ),
        ) and len(node.test.ops) == 1 and
         (_eq(node.test, 2) or _compare_to_3(node.test, ast.Lt))))):
        if node.orelse and not isinstance(node.orelse[0], ast.If):
            yield ast_to_offset(node), _fix_py2_block
    elif (state.settings.min_version >= (3, ) and (
            # if six.PY3:
            is_name_attr(node.test, state.from_imports, 'six', ('PY3', )) or
            # if not six.PY2:
        (isinstance(node.test, ast.UnaryOp)
         and isinstance(node.test.op, ast.Not) and is_name_attr(
             node.test.operand,
             state.from_imports,
             'six',
             ('PY2', ),
         )) or
            # sys.version_info == 3 or >= (3,) or > (3,)
        (isinstance(node.test, ast.Compare) and is_name_attr(
            node.test.left,
            state.from_imports,
            'sys',
            ('version_info', ),
        ) and len(node.test.ops) == 1 and
         (_eq(node.test, 3) or _compare_to_3(node.test, (ast.Gt, ast.GtE)))))):
        if node.orelse and not isinstance(node.orelse[0], ast.If):
            yield ast_to_offset(node), _fix_py3_block_else
        elif not node.orelse:
            yield ast_to_offset(node), _fix_py3_block
Beispiel #10
0
def visit_Call(
    state: State,
    node: ast.Call,
    parent: ast.AST,
) -> Iterable[Tuple[Offset, TokenFunc]]:
    if state.settings.min_version < (3, ):
        return

    if isinstance(node.func, ast.Name):
        name = node.func.id
    elif isinstance(node.func, ast.Attribute):
        name = node.func.attr
    else:
        return

    if (is_name_attr(
            node.func,
            state.from_imports,
            'six',
        ('iteritems', 'iterkeys', 'itervalues'),
    ) and node.args and not has_starargs(node) and
            # parent is next(...)
            isinstance(parent, ast.Call) and isinstance(parent.func, ast.Name)
            and parent.func.id == 'next'):
        func = functools.partial(
            find_and_replace_call,
            template=f'iter({SIX_CALLS[name]})',
        )
        yield ast_to_offset(node), func
    elif (is_name_attr(node.func, state.from_imports, 'six', SIX_CALLS)
          and node.args and not has_starargs(node)):
        if isinstance(node.args[0], _EXPR_NEEDS_PARENS):
            parens: Tuple[int, ...] = (0, )
        else:
            parens = ()
        func = functools.partial(
            find_and_replace_call,
            template=SIX_CALLS[name],
            parens=parens,
        )
        yield ast_to_offset(node), func
    elif (is_name_attr(
            node.func,
            state.from_imports,
            'six',
        ('int2byte', ),
    ) and node.args and not has_starargs(node)):
        func = functools.partial(
            find_and_replace_call,
            template=SIX_INT2BYTE_TMPL,
        )
        yield ast_to_offset(node), func
    elif (state.settings.min_version >= (3, ) and is_name_attr(
            node.func,
            state.from_imports,
            'six',
        ('b', 'ensure_binary'),
    ) and not node.keywords and not has_starargs(node) and len(node.args) == 1
          and isinstance(node.args[0], ast.Str)):
        yield ast_to_offset(node), _fix_six_b
    elif (isinstance(parent, ast.Expr) and is_name_attr(
            node.func,
            state.from_imports,
            'six',
        ('raise_from', ),
    ) and node.args and not has_starargs(node)):
        func = functools.partial(
            find_and_replace_call,
            template=RAISE_FROM_TMPL,
        )
        yield ast_to_offset(node), func
    elif (isinstance(parent, ast.Expr) and is_name_attr(
            node.func,
            state.from_imports,
            'six',
        ('reraise', ),
    )):
        if len(node.args) == 2 and not has_starargs(node):
            func = functools.partial(
                find_and_replace_call,
                template=RERAISE_2_TMPL,
            )
            yield ast_to_offset(node), func
        elif len(node.args) == 3 and not has_starargs(node):
            func = functools.partial(
                find_and_replace_call,
                template=RERAISE_3_TMPL,
            )
            yield ast_to_offset(node), func
        elif (len(node.args) == 1 and isinstance(node.args[0], ast.Starred)
              and isinstance(node.args[0].value, ast.Call) and is_name_attr(
                  node.args[0].value.func,
                  state.from_imports,
                  'sys',
                  ('exc_info', ),
              )):
            func = functools.partial(
                find_and_replace_call,
                template=RERAISE_TMPL,
            )
            yield ast_to_offset(node), func