예제 #1
0
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)
예제 #2
0
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)
예제 #3
0
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="''")]
예제 #4
0
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')
예제 #5
0
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)
예제 #6
0
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}')
예제 #7
0
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}')
예제 #8
0
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)
예제 #9
0
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]
예제 #10
0
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]
예제 #11
0
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')]
예제 #12
0
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]}')