def _use_capture_output( i: int, tokens: List[Token], *, stdout_arg_idx: int, stderr_arg_idx: int, ) -> None: j = find_open_paren(tokens, i) func_args, _ = parse_call_args(tokens, j) if stdout_arg_idx < stderr_arg_idx: delete_argument(stderr_arg_idx, tokens, func_args) replace_argument( stdout_arg_idx, tokens, func_args, new='capture_output=True', ) else: replace_argument( stdout_arg_idx, tokens, func_args, new='capture_output=True', ) delete_argument(stderr_arg_idx, tokens, func_args)
def _fix_add_metaclass(i: int, tokens: List[Token]) -> None: j = find_open_paren(tokens, i) func_args, end = parse_call_args(tokens, j) metaclass = f'metaclass={arg_str(tokens, *func_args[0])}' # insert `metaclass={args[0]}` into `class:` # search forward for the `class` token j = i + 1 while tokens[j].src != 'class': j += 1 class_token = j # then search forward for a `:` token, not inside a brace j = find_block_start(tokens, j) last_paren = -1 for k in range(class_token, j): if tokens[k].src == ')': last_paren = k if last_paren == -1: tokens.insert(j, Token('CODE', f'({metaclass})')) else: insert = last_paren - 1 while tokens[insert].name in NON_CODING_TOKENS: insert -= 1 if tokens[insert].src == '(': # no bases src = metaclass elif tokens[insert].src != ',': src = f', {metaclass}' else: src = f' {metaclass},' tokens.insert(insert + 1, Token('CODE', src)) remove_decorator(i, tokens)
def _fix_native_str(i: int, tokens: List[Token]) -> None: j = find_open_paren(tokens, i) func_args, end = parse_call_args(tokens, j) if any(tok.name == 'NL' for tok in tokens[i:end]): return if func_args: replace_call(tokens, i, end, func_args, '{args[0]}') else: tokens[i:end] = [tokens[i]._replace(name='STRING', src="''")]
def _replace_universal_newlines_with_text( i: int, tokens: List[Token], *, arg_idx: int, ) -> None: j = find_open_paren(tokens, i) func_args, _ = parse_call_args(tokens, j) for i in range(*func_args[arg_idx]): if tokens[i].src == 'universal_newlines': tokens[i] = tokens[i]._replace(src='text') break else: raise AssertionError('`universal_newlines` argument not found')
def _fix_with_metaclass(i: int, tokens: List[Token]) -> None: j = find_open_paren(tokens, i) func_args, end = parse_call_args(tokens, j) if len(func_args) == 1: tmpl = 'metaclass={args[0]}' elif len(func_args) == 2: base = arg_str(tokens, *func_args[1]) if base == 'object': tmpl = 'metaclass={args[0]}' else: tmpl = '{rest}, metaclass={args[0]}' else: tmpl = '{rest}, metaclass={args[0]}' replace_call(tokens, i, end, func_args, tmpl)
def _fix_open_mode(i: int, tokens: List[Token]) -> None: j = find_open_paren(tokens, i) func_args, end = parse_call_args(tokens, j) mode = tokens_to_src(tokens[slice(*func_args[1])]) mode_stripped = mode.strip().strip('"\'') if mode_stripped in U_MODE_REMOVE: del tokens[func_args[0][1]:func_args[1][1]] elif mode_stripped in U_MODE_REPLACE_R: new_mode = mode.replace('U', 'r') tokens[slice(*func_args[1])] = [Token('SRC', new_mode)] elif mode_stripped in U_MODE_REMOVE_U: new_mode = mode.replace('U', '') tokens[slice(*func_args[1])] = [Token('SRC', new_mode)] else: raise AssertionError(f'unreachable: {mode!r}')
def _fix_open_mode(i: int, tokens: List[Token], *, arg_idx: int) -> None: j = find_open_paren(tokens, i) func_args, end = parse_call_args(tokens, j) mode = tokens_to_src(tokens[slice(*func_args[arg_idx])]) mode_stripped = mode.split('=')[-1] mode_stripped = ast.literal_eval(mode_stripped.strip()) if mode_stripped in U_MODE_REMOVE: delete_argument(arg_idx, tokens, func_args) elif mode_stripped in U_MODE_REPLACE_R: new_mode = mode.replace('U', 'r') tokens[slice(*func_args[arg_idx])] = [Token('SRC', new_mode)] elif mode_stripped in U_MODE_REMOVE_U: new_mode = mode.replace('U', '') tokens[slice(*func_args[arg_idx])] = [Token('SRC', new_mode)] else: raise AssertionError(f'unreachable: {mode!r}')
def _fix_oserror_except( i: int, tokens: List[Token], *, from_imports: Dict[str, Set[str]], ) -> None: # find all the arg strs in the tuple except_index = i while tokens[except_index].src != 'except': except_index -= 1 start = find_open_paren(tokens, except_index) func_args, end = parse_call_args(tokens, start) # save the exceptions and remove the block arg_strs = [arg_str(tokens, *arg) for arg in func_args] del tokens[start:end] # rewrite the block without dupes args = [] for arg in arg_strs: left, part, right = arg.partition('.') if left in ERROR_MODULES and part == '.' and right == 'error': args.append('OSError') elif left in ERROR_NAMES and part == right == '': args.append('OSError') elif (left == 'error' and part == right == '' and any('error' in from_imports[mod] for mod in ERROR_MODULES)): args.append('OSError') else: args.append(arg) unique_args = tuple(dict.fromkeys(args)) if len(unique_args) > 1: joined = '({})'.format(', '.join(unique_args)) elif tokens[start - 1].name != 'UNIMPORTANT_WS': joined = ' {}'.format(unique_args[0]) else: joined = unique_args[0] new = Token('CODE', joined) tokens.insert(start, new)
def _fix_default_encoding(i: int, tokens: List[Token]) -> None: i = find_open_paren(tokens, i + 1) j = find_closing_bracket(tokens, i) del tokens[i + 1:j]
def _remove_call(i: int, tokens: List[Token]) -> None: i = find_open_paren(tokens, i) j = find_token(tokens, i, ')') del tokens[i:j + 1]
def _replace_io_open(i: int, tokens: List[Token]) -> None: j = find_open_paren(tokens, i) tokens[i:j] = [tokens[i]._replace(name='NAME', src='open')]
def _fix_six_b(i: int, tokens: List[Token]) -> None: j = find_open_paren(tokens, i) if (tokens[j + 1].name == 'STRING' and is_ascii(tokens[j + 1].src) and tokens[j + 2].src == ')'): func_args, end = parse_call_args(tokens, j) replace_call(tokens, i, end, func_args, 'b{args[0]}')