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
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
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
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))))
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
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
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
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
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