Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-pyupgrade for openSUSE:Factory checked in at 2021-08-11 11:47:15 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pyupgrade (Old) and /work/SRC/openSUSE:Factory/.python-pyupgrade.new.1899 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pyupgrade" Wed Aug 11 11:47:15 2021 rev:14 rq:911250 version:2.23.3 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pyupgrade/python-pyupgrade.changes 2021-07-21 19:07:55.527452627 +0200 +++ /work/SRC/openSUSE:Factory/.python-pyupgrade.new.1899/python-pyupgrade.changes 2021-08-11 11:47:53.441697892 +0200 @@ -1,0 +2,27 @@ +Sun Aug 8 19:23:58 UTC 2021 - Sebastian Wagner <sebix+novell....@sebix.at> + +- update to version 2.23.3: + - can't splat async generators + - cannot unpack async generators + - add extra test for pep584 +- update to version 2.23.2: + - correctly compute indent for typeddict after dedent +- update to version 2.23.1: + - fix bug in merge dicts: look for comma backwards +- update to version 2.23.0: + - rewrite type of primitive +- update to version 2.22.0: + - rewrite six.moves.range + - rewrite lru_cache with maxsize=None and typed=False + Co-authored-by: Max Rozentsveyg <m...@outlook.com> +- update to version 2.21.2: + - dont do generator rewrite if list comp contains await +- update to version 2.21.1: + - fix breakage from async generator + - Fix etree heading, non-breaking space to space +- update to version 2.21.0: + - remove redunant encoding even for f-strings +- update to version 2.20.1: + - dont rewrite fstring if await in py3 + +------------------------------------------------------------------- Old: ---- python-pyupgrade-2.20.0.tar.gz New: ---- python-pyupgrade-2.23.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pyupgrade.spec ++++++ --- /var/tmp/diff_new_pack.9ff5nE/_old 2021-08-11 11:47:53.901697338 +0200 +++ /var/tmp/diff_new_pack.9ff5nE/_new 2021-08-11 11:47:53.901697338 +0200 @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-pyupgrade -Version: 2.20.0 +Version: 2.23.3 Release: 0 Summary: A tool to automatically upgrade syntax for newer versions License: MIT ++++++ python-pyupgrade-2.20.0.tar.gz -> python-pyupgrade-2.23.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/.pre-commit-config.yaml new/pyupgrade-2.23.3/.pre-commit-config.yaml --- old/pyupgrade-2.20.0/.pre-commit-config.yaml 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/.pre-commit-config.yaml 2021-08-04 19:50:42.000000000 +0200 @@ -24,7 +24,7 @@ hooks: - id: autopep8 - repo: https://github.com/asottile/reorder_python_imports - rev: v2.5.0 + rev: v2.6.0 hooks: - id: reorder-python-imports args: [--py3-plus] @@ -34,7 +34,7 @@ - id: add-trailing-comma args: [--py36-plus] - repo: https://github.com/asottile/pyupgrade - rev: v2.20.0 + rev: v2.23.3 hooks: - id: pyupgrade args: [--py36-plus] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/README.md new/pyupgrade-2.23.3/README.md --- old/pyupgrade-2.20.0/README.md 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/README.md 2021-08-04 19:50:42.000000000 +0200 @@ -20,7 +20,7 @@ ```yaml - repo: https://github.com/asottile/pyupgrade - rev: v2.20.0 + rev: v2.23.3 hooks: - id: pyupgrade ``` @@ -308,6 +308,8 @@ six.advance_iterator(it) # next(it) six.next(it) # next(it) six.callable(x) # callable(x) +six.moves.range(x) # range(x) +six.moves.xrange(x) # range(x) from six import text_type text_type # str @@ -451,7 +453,7 @@ ``` -###??Rewrite `xml.etree.cElementTree` to `xml.etree.ElementTree` +### Rewrite `xml.etree.cElementTree` to `xml.etree.ElementTree` Availability: - `--py3-plus` is passed on the commandline. @@ -464,6 +466,23 @@ ``` +### Rewrite `type` of primitive + +Availability: +- `--py3-plus` is passed on the commandline. + +```diff +-type('') ++str +-type(b'') ++bytes +-type(0) ++int +-type(0.) ++float +``` + + ### `typing.NamedTuple` / `typing.TypedDict` py36+ syntax Availability: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/pyupgrade/_ast_helpers.py new/pyupgrade-2.23.3/pyupgrade/_ast_helpers.py --- old/pyupgrade-2.20.0/pyupgrade/_ast_helpers.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/pyupgrade/_ast_helpers.py 2021-08-04 19:50:42.000000000 +0200 @@ -42,3 +42,18 @@ any(k.arg is None for k in call.keywords) or any(isinstance(a, ast.Starred) for a in call.args) ) + + +def contains_await(node: ast.AST) -> bool: + for node_ in ast.walk(node): + if isinstance(node_, ast.Await): + return True + else: + return False + + +def is_async_listcomp(node: ast.ListComp) -> bool: + return ( + any(gen.is_async for gen in node.generators) or + contains_await(node) + ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/pyupgrade/_data.py new/pyupgrade-2.23.3/pyupgrade/_data.py --- old/pyupgrade-2.20.0/pyupgrade/_data.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/pyupgrade/_data.py 2021-08-04 19:50:42.000000000 +0200 @@ -48,6 +48,7 @@ 'mmap', 'select', 'six', + 'six.moves', 'socket', 'subprocess', 'sys', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/pyupgrade/_main.py new/pyupgrade-2.23.3/pyupgrade/_main.py --- old/pyupgrade-2.20.0/pyupgrade/_main.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/pyupgrade/_main.py 2021-08-04 19:50:42.000000000 +0200 @@ -25,6 +25,7 @@ from pyupgrade._ast_helpers import ast_parse from pyupgrade._ast_helpers import ast_to_offset +from pyupgrade._ast_helpers import contains_await from pyupgrade._ast_helpers import has_starargs from pyupgrade._data import FUNCS from pyupgrade._data import Settings @@ -521,12 +522,13 @@ class FindPy36Plus(ast.NodeVisitor): - def __init__(self) -> None: + def __init__(self, *, min_version: Version) -> None: self.fstrings: Dict[Offset, ast.Call] = {} self.named_tuples: Dict[Offset, ast.Call] = {} self.dict_typed_dicts: Dict[Offset, ast.Call] = {} self.kw_typed_dicts: Dict[Offset, ast.Call] = {} self._from_imports: Dict[str, Set[str]] = collections.defaultdict(set) + self.min_version = min_version def visit_ImportFrom(self, node: ast.ImportFrom) -> None: if node.level == 0 and node.module in {'typing', 'typing_extensions'}: @@ -591,7 +593,8 @@ if not candidate: i += 1 else: - self.fstrings[ast_to_offset(node)] = node + if self.min_version >= (3, 7) or not contains_await(node): + self.fstrings[ast_to_offset(node)] = node self.generic_visit(node) @@ -743,6 +746,8 @@ call: ast.Call, types: Dict[str, ast.expr], ) -> Tuple[int, str]: + while i > 0 and tokens[i - 1].name == 'DEDENT': + i -= 1 if i > 0 and tokens[i - 1].name in {'INDENT', UNIMPORTANT_WS}: indent = f'{tokens[i - 1].src}{" " * 4}' else: @@ -758,13 +763,13 @@ return end, attrs -def _fix_py36_plus(contents_text: str) -> str: +def _fix_py36_plus(contents_text: str, *, min_version: Version) -> str: try: ast_obj = ast_parse(contents_text) except SyntaxError: return contents_text - visitor = FindPy36Plus() + visitor = FindPy36Plus(min_version=min_version) visitor.visit(ast_obj) if not any(( @@ -871,7 +876,9 @@ ) contents_text = _fix_tokens(contents_text, min_version=args.min_version) if args.min_version >= (3, 6): - contents_text = _fix_py36_plus(contents_text) + contents_text = _fix_py36_plus( + contents_text, min_version=args.min_version, + ) if filename == '-': print(contents_text, end='') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/pyupgrade/_plugins/default_encoding.py new/pyupgrade-2.23.3/pyupgrade/_plugins/default_encoding.py --- old/pyupgrade-2.20.0/pyupgrade/_plugins/default_encoding.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/pyupgrade/_plugins/default_encoding.py 2021-08-04 19:50:42.000000000 +0200 @@ -31,7 +31,7 @@ if ( state.settings.min_version >= (3,) and isinstance(node.func, ast.Attribute) and - isinstance(node.func.value, ast.Str) and + isinstance(node.func.value, (ast.Str, ast.JoinedStr)) and node.func.attr == 'encode' and not has_starargs(node) and len(node.args) == 1 and diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/pyupgrade/_plugins/generator_expressions_pep289.py new/pyupgrade-2.23.3/pyupgrade/_plugins/generator_expressions_pep289.py --- old/pyupgrade-2.20.0/pyupgrade/_plugins/generator_expressions_pep289.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/pyupgrade/_plugins/generator_expressions_pep289.py 2021-08-04 19:50:42.000000000 +0200 @@ -8,6 +8,7 @@ from tokenize_rt import Token from pyupgrade._ast_helpers import ast_to_offset +from pyupgrade._ast_helpers import is_async_listcomp from pyupgrade._data import register from pyupgrade._data import State from pyupgrade._data import TokenFunc @@ -51,7 +52,8 @@ isinstance(node.func, ast.Name) and node.func.id in ALLOWED_FUNCS and node.args and - isinstance(node.args[0], ast.ListComp) + isinstance(node.args[0], ast.ListComp) and + not is_async_listcomp(node.args[0]) ): if len(node.args) == 1 and not node.keywords: yield ast_to_offset(node.args[0]), _delete_list_comp_brackets diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/pyupgrade/_plugins/lru_cache.py new/pyupgrade-2.23.3/pyupgrade/_plugins/lru_cache.py --- old/pyupgrade-2.20.0/pyupgrade/_plugins/lru_cache.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/pyupgrade/_plugins/lru_cache.py 2021-08-04 19:50:42.000000000 +0200 @@ -2,6 +2,7 @@ import functools from typing import Iterable from typing import List +from typing import Optional from typing import Tuple from tokenize_rt import Offset @@ -23,6 +24,34 @@ del tokens[i:j + 1] +def _is_literal_kwarg( + keyword: ast.keyword, name: str, value: Optional[bool], +) -> bool: + return ( + keyword.arg == name and + isinstance(keyword.value, ast.NameConstant) and + keyword.value.value is value + ) + + +def _eligible(keywords: List[ast.keyword]) -> bool: + if len(keywords) == 1: + return _is_literal_kwarg(keywords[0], 'maxsize', None) + elif len(keywords) == 2: + return ( + ( + _is_literal_kwarg(keywords[0], 'maxsize', None) and + _is_literal_kwarg(keywords[1], 'typed', False) + ) or + ( + _is_literal_kwarg(keywords[1], 'maxsize', None) and + _is_literal_kwarg(keywords[0], 'typed', False) + ) + ) + else: + return False + + @register(ast.Call) def visit_Call( state: State, @@ -48,10 +77,7 @@ 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 + _eligible(node.keywords) ): func = functools.partial( find_and_replace_call, template='functools.cache', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/pyupgrade/_plugins/pep584.py new/pyupgrade-2.23.3/pyupgrade/_plugins/pep584.py --- old/pyupgrade-2.20.0/pyupgrade/_plugins/pep584.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/pyupgrade/_plugins/pep584.py 2021-08-04 19:50:42.000000000 +0200 @@ -12,7 +12,6 @@ from pyupgrade._data import State from pyupgrade._data import TokenFunc from pyupgrade._token_helpers import find_closing_bracket -from pyupgrade._token_helpers import find_token def _replace_dict_brackets(i: int, tokens: List[Token]) -> None: @@ -39,8 +38,10 @@ def _replace_comma_with_pipe(i: int, tokens: List[Token]) -> None: - comma = find_token(tokens, i, ',') - tokens[comma] = Token('CODE', ' |') + j = i - 1 + while not (tokens[j].name == 'OP' and tokens[j].src == ','): + j -= 1 + tokens[j] = Token('CODE', ' |') @register(ast.Dict) @@ -54,8 +55,7 @@ if all(key is None for key in node.keys) and len(node.values) > 1: yield ast_to_offset(node), _replace_dict_brackets - arg_count = len(node.values) for idx, arg in enumerate(node.values): yield ast_to_offset(arg), _remove_double_star - if idx < arg_count - 1: + if idx > 0: yield ast_to_offset(arg), _replace_comma_with_pipe diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/pyupgrade/_plugins/six_simple.py new/pyupgrade-2.23.3/pyupgrade/_plugins/six_simple.py --- old/pyupgrade-2.20.0/pyupgrade/_plugins/six_simple.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/pyupgrade/_plugins/six_simple.py 2021-08-04 19:50:42.000000000 +0200 @@ -68,6 +68,16 @@ func = functools.partial(replace_name, name=node.attr, new=new) yield ast_to_offset(node), func + elif ( + state.settings.min_version >= (3,) and + isinstance(node.value, ast.Attribute) and + isinstance(node.value.value, ast.Name) and + node.value.value.id == 'six' and + node.value.attr == 'moves' and + node.attr in {'xrange', 'range'} + ): + func = functools.partial(replace_name, name=node.attr, new='range') + yield ast_to_offset(node), func @register(ast.Name) @@ -95,3 +105,10 @@ func = functools.partial(replace_name, name=node.id, new=new) yield ast_to_offset(node), func + elif ( + state.settings.min_version >= (3,) and + node.id in state.from_imports['six.moves'] and + node.id in {'xrange', 'range'} + ): + func = functools.partial(replace_name, name=node.id, new='range') + yield ast_to_offset(node), func diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/pyupgrade/_plugins/type_of_primitive.py new/pyupgrade-2.23.3/pyupgrade/_plugins/type_of_primitive.py --- old/pyupgrade-2.20.0/pyupgrade/_plugins/type_of_primitive.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pyupgrade-2.23.3/pyupgrade/_plugins/type_of_primitive.py 2021-08-04 19:50:42.000000000 +0200 @@ -0,0 +1,65 @@ +import ast +import functools +from typing import Iterable +from typing import List +from typing import Tuple + +from tokenize_rt import Offset +from tokenize_rt import Token + +from pyupgrade._ast_helpers import ast_to_offset +from pyupgrade._data import register +from pyupgrade._data import State +from pyupgrade._data import TokenFunc +from pyupgrade._token_helpers import find_closing_bracket +from pyupgrade._token_helpers import find_open_paren + +NUM_TYPES = { + int: 'int', + float: 'float', + complex: 'complex', +} + + +def _rewrite_type_of_primitive( + i: int, + tokens: List[Token], + *, + src: str, +) -> None: + open_paren = find_open_paren(tokens, i + 1) + j = find_closing_bracket(tokens, open_paren) + tokens[i] = tokens[i]._replace(src=src) + del tokens[i + 1:j + 1] + + +@register(ast.Call) +def visit_Call( + state: State, + node: ast.Call, + parent: ast.AST, +) -> Iterable[Tuple[Offset, TokenFunc]]: + if ( + state.settings.min_version >= (3,) and + isinstance(node.func, ast.Name) and + node.func.id == 'type' and + len(node.args) == 1 + ): + if isinstance(node.args[0], ast.Str): + func = functools.partial( + _rewrite_type_of_primitive, + src='str', + ) + yield ast_to_offset(node), func + elif isinstance(node.args[0], ast.Bytes): + func = functools.partial( + _rewrite_type_of_primitive, + src='bytes', + ) + yield ast_to_offset(node), func + elif isinstance(node.args[0], ast.Num): + func = functools.partial( + _rewrite_type_of_primitive, + src=NUM_TYPES[type(node.args[0].n)], + ) + yield ast_to_offset(node), func diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/pyupgrade/_plugins/unpack_list_comprehension.py new/pyupgrade-2.23.3/pyupgrade/_plugins/unpack_list_comprehension.py --- old/pyupgrade-2.20.0/pyupgrade/_plugins/unpack_list_comprehension.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/pyupgrade/_plugins/unpack_list_comprehension.py 2021-08-04 19:50:42.000000000 +0200 @@ -7,6 +7,7 @@ from tokenize_rt import Token from pyupgrade._ast_helpers import ast_to_offset +from pyupgrade._ast_helpers import is_async_listcomp from pyupgrade._data import register from pyupgrade._data import State from pyupgrade._data import TokenFunc @@ -31,6 +32,7 @@ state.settings.min_version >= (3,) and len(node.targets) == 1 and isinstance(node.targets[0], ast.Tuple) and - isinstance(node.value, ast.ListComp) + isinstance(node.value, ast.ListComp) and + not is_async_listcomp(node.value) ): yield ast_to_offset(node.value), _replace_list_comprehension diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/pyupgrade/_plugins/unpacking_argument_list_comprehensions.py new/pyupgrade-2.23.3/pyupgrade/_plugins/unpacking_argument_list_comprehensions.py --- old/pyupgrade-2.20.0/pyupgrade/_plugins/unpacking_argument_list_comprehensions.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/pyupgrade/_plugins/unpacking_argument_list_comprehensions.py 2021-08-04 19:50:42.000000000 +0200 @@ -5,6 +5,7 @@ from tokenize_rt import Offset from pyupgrade._ast_helpers import ast_to_offset +from pyupgrade._ast_helpers import is_async_listcomp from pyupgrade._data import register from pyupgrade._data import State from pyupgrade._data import TokenFunc @@ -19,6 +20,7 @@ ) -> Iterable[Tuple[Offset, TokenFunc]]: if ( state.settings.min_version >= (3,) and - isinstance(node.value, ast.ListComp) + isinstance(node.value, ast.ListComp) and + not is_async_listcomp(node.value) ): yield ast_to_offset(node.value), replace_list_comp_brackets diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/setup.cfg new/pyupgrade-2.23.3/setup.cfg --- old/pyupgrade-2.20.0/setup.cfg 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/setup.cfg 2021-08-04 19:50:42.000000000 +0200 @@ -1,6 +1,6 @@ [metadata] name = pyupgrade -version = 2.20.0 +version = 2.23.3 description = A tool to automatically upgrade syntax for newer versions. long_description = file: README.md long_description_content_type = text/markdown diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/tests/features/default_encoding_test.py new/pyupgrade-2.23.3/tests/features/default_encoding_test.py --- old/pyupgrade-2.20.0/tests/features/default_encoding_test.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/tests/features/default_encoding_test.py 2021-08-04 19:50:42.000000000 +0200 @@ -8,6 +8,10 @@ ('s', 'expected'), ( ('"asd".encode("utf-8")', '"asd".encode()'), + ('f"asd".encode("utf-8")', 'f"asd".encode()'), + ('f"{3}asd".encode("utf-8")', 'f"{3}asd".encode()'), + ('fr"asd".encode("utf-8")', 'fr"asd".encode()'), + ('r"asd".encode("utf-8")', 'r"asd".encode()'), ('"asd".encode("utf8")', '"asd".encode()'), ('"asd".encode("UTF-8")', '"asd".encode()'), pytest.param( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/tests/features/fstrings_test.py new/pyupgrade-2.23.3/tests/features/fstrings_test.py --- old/pyupgrade-2.20.0/tests/features/fstrings_test.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/tests/features/fstrings_test.py 2021-08-04 19:50:42.000000000 +0200 @@ -34,10 +34,13 @@ r'''"{}".format(a['\\'])''', '"{}".format(a["b"])', "'{}'.format(a['b'])", + # await only becomes keyword in Python 3.7+ + "async def c(): return '{}'.format(await 3)", + "async def c(): return '{}'.format(1 + await 3)", ), ) def test_fix_fstrings_noop(s): - assert _fix_py36_plus(s) == s + assert _fix_py36_plus(s, min_version=(3, 6)) == s @pytest.mark.parametrize( @@ -60,4 +63,10 @@ ), ) def test_fix_fstrings(s, expected): - assert _fix_py36_plus(s) == expected + assert _fix_py36_plus(s, min_version=(3, 6)) == expected + + +def test_fix_fstrings_await_py37(): + s = "async def c(): return '{}'.format(await 1+foo())" + expected = "async def c(): return f'{await 1+foo()}'" + assert _fix_py36_plus(s, min_version=(3, 7)) == expected diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/tests/features/generator_expressions_pep289_test.py new/pyupgrade-2.23.3/tests/features/generator_expressions_pep289_test.py --- old/pyupgrade-2.20.0/tests/features/generator_expressions_pep289_test.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/tests/features/generator_expressions_pep289_test.py 2021-08-04 19:50:42.000000000 +0200 @@ -20,6 +20,21 @@ '"".join([[i for _ in range(2)] for i in range(3)])\n', id='string join (left alone for perf reasons)', ), + pytest.param( + 'async def foo():\n' + ' for i in range(3):\n' + ' yield i\n' + 'async def bar():\n' + ' sum([i async for i in foo()])\n', + id='Contains async', + ), + pytest.param( + 'tuple([\n' + ' await self._configure_component(hass, controller_config)\n' + ' for controller_config in configs\n' + '])\n', + id='Contains await', + ), ), ) def test_fix_generator_expressions_noop(s): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/tests/features/lru_cache_test.py new/pyupgrade-2.23.3/tests/features/lru_cache_test.py --- old/pyupgrade-2.20.0/tests/features/lru_cache_test.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/tests/features/lru_cache_test.py 2021-08-04 19:50:42.000000000 +0200 @@ -101,6 +101,22 @@ (3, 9), id='unrelated parameter', ), + pytest.param( + 'import functools\n\n' + '@functools.lru_cache(maxsize=None, typed=True)\n' + 'def foo():\n' + ' pass\n', + (3, 9), + id='typed=True', + ), + pytest.param( + 'import functools\n\n' + '@functools.lru_cache(maxsize=None, typed=False, foo=False)\n' + 'def foo():\n' + ' pass\n', + (3, 9), + id='invalid keyword', + ), ), ) def test_fix_maxsize_none_decorators_noop(s, min_version): @@ -121,6 +137,28 @@ ' pass\n', id='call with attr', ), + pytest.param( + 'import functools\n\n' + '@functools.lru_cache(maxsize=None, typed=False)\n' + 'def foo():\n' + ' pass\n', + 'import functools\n\n' + '@functools.cache\n' + 'def foo():\n' + ' pass\n', + id='call with attr, maxsize=None then typed=False', + ), + pytest.param( + 'import functools\n\n' + '@functools.lru_cache(typed=False, maxsize=None)\n' + 'def foo():\n' + ' pass\n', + 'import functools\n\n' + '@functools.cache\n' + 'def foo():\n' + ' pass\n', + id='call with attr, typed=False then maxsize=None', + ), ), ) def test_fix_maxsize_none_decorators(s, expected): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/tests/features/pep584_test.py new/pyupgrade-2.23.3/tests/features/pep584_test.py --- old/pyupgrade-2.20.0/tests/features/pep584_test.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pyupgrade-2.23.3/tests/features/pep584_test.py 2021-08-04 19:50:42.000000000 +0200 @@ -0,0 +1,123 @@ +import pytest + +from pyupgrade._data import Settings +from pyupgrade._main import _fix_plugins + + +@pytest.mark.parametrize( + ('s', 'version'), + ( + pytest.param( + '{**a, **b}\n', + (3, 8), + id='<3.9', + ), + pytest.param( + '{"a": 0}\n', + (3, 9), + id='Dict without merge', + ), + pytest.param( + 'x = {**a}\n', + (3, 9), + id='Merge of only one dict', + ), + ), +) +def test_fix_pep584_noop(s, version): + assert _fix_plugins(s, settings=Settings(min_version=version)) == s + + +@pytest.mark.parametrize( + ('s', 'expected'), + ( + pytest.param( + 'x = {**a, **b}\n', + + 'x = a | b\n', + + id='Simple dict rewrite', + ), + pytest.param( + 'x = {**{**a, **b}, **c}\n', + + 'x = a | b | c\n', + + id='Nested merge of dicts', + ), + pytest.param( + 'x = {**a, **b,}\n', + + 'x = a | b\n', + + id='Trailing comma', + ), + pytest.param( + 'x = {\n' + ' **a, # foo\n' + ' **b # bar\n' + '}\n', + + 'x = (\n' + ' a | # foo\n' + ' b # bar\n' + ')\n', + + id='Multiple lines with comment', + ), + pytest.param( + 'x = {\n' + ' **a,\n' + ' **b\n' + '}\n', + + 'x = (\n' + ' a |\n' + ' b\n' + ')\n', + + id='Multiple lines', + ), + pytest.param( + 'x = {\n' + ' **a,\n' + ' **b,\n' + '}\n', + + 'x = (\n' + ' a |\n' + ' b\n' + ')\n', + + id='Multiple lines, trailing comma', + ), + pytest.param( + 'x = {\n' + ' **{a: a for a in range(3)},\n' + ' **b,\n' + '}\n', + + 'x = (\n' + ' {a: a for a in range(3)} |\n' + ' b\n' + ')\n', + + id='Dict comprehension within merge of dicts', + ), + pytest.param( + 'x = {\n' + ' **{a: b for a, b in zip(range(3), range(3))},\n' + ' **b,\n' + '}\n', + + 'x = (\n' + ' {a: b for a, b in zip(range(3), range(3))} |\n' + ' b\n' + ')\n', + + id='Dict with comma inside it', + ), + ), +) +def test_fix_pep584(s, expected): + assert _fix_plugins(s, settings=Settings(min_version=(3, 9))) == expected diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/tests/features/six_simple_test.py new/pyupgrade-2.23.3/tests/features/six_simple_test.py --- old/pyupgrade-2.20.0/tests/features/six_simple_test.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/tests/features/six_simple_test.py 2021-08-04 19:50:42.000000000 +0200 @@ -19,6 +19,10 @@ 'isinstance("foo", text_type)\n', id='relative import might not be six', ), + pytest.param( + 'foo.range(3)', + id='Range, but not from six.moves', + ), ), ) def test_six_simple_noop(s): @@ -63,6 +67,29 @@ 'from six import string_types\n' 'STRING_TYPES = (str,)\n', ), + pytest.param( + 'six.moves.range(3)\n', + + 'range(3)\n', + + id='six.moves.range', + ), + pytest.param( + 'six.moves.xrange(3)\n', + + 'range(3)\n', + + id='six.moves.xrange', + ), + pytest.param( + 'from six.moves import xrange\n' + 'xrange(3)\n', + + 'from six.moves import xrange\n' + 'range(3)\n', + + id='six.moves.xrange, from import', + ), ), ) def test_fix_six_simple(s, expected): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/tests/features/type_of_primitive_test.py new/pyupgrade-2.23.3/tests/features/type_of_primitive_test.py --- old/pyupgrade-2.20.0/tests/features/type_of_primitive_test.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pyupgrade-2.23.3/tests/features/type_of_primitive_test.py 2021-08-04 19:50:42.000000000 +0200 @@ -0,0 +1,74 @@ +import pytest + +from pyupgrade._data import Settings +from pyupgrade._main import _fix_plugins + + +@pytest.mark.parametrize( + ('s', 'version'), + ( + pytest.param( + 'type("")\n', + (2, 7), + id='not python 3+', + ), + pytest.param( + 'type(None)\n', + (3,), + id='NoneType', + ), + pytest.param( + 'foo = "foo"\n' + 'type(foo)\n', + (3,), + id='String assigned to variable', + ), + ), +) +def test_fix_type_of_primitive_noop(s, version): + assert _fix_plugins(s, settings=Settings(min_version=version)) == s + + +@pytest.mark.parametrize( + ('s', 'expected'), + ( + pytest.param( + 'type("")\n', + + 'str\n', + + id='Empty string -> str', + ), + pytest.param( + 'type(0)\n', + + 'int\n', + + id='zero -> int', + ), + pytest.param( + 'type(0.)\n', + + 'float\n', + + id='decimal zero -> float', + ), + pytest.param( + 'type(0j)\n', + + 'complex\n', + + id='0j -> complex', + ), + pytest.param( + 'type(b"")\n', + + 'bytes\n', + + id='Empty bytes string -> bytes', + ), + ), +) +def test_fix_type_of_primitive(s, expected): + ret = _fix_plugins(s, settings=Settings(min_version=(3,))) + assert ret == expected diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/tests/features/typing_584_test.py new/pyupgrade-2.23.3/tests/features/typing_584_test.py --- old/pyupgrade-2.20.0/tests/features/typing_584_test.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/tests/features/typing_584_test.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,97 +0,0 @@ -import pytest - -from pyupgrade._data import Settings -from pyupgrade._main import _fix_plugins - - -@pytest.mark.parametrize( - ('s', 'version'), - ( - pytest.param( - '{**a, **b}\n', - (3, 8), - id='<3.9', - ), - pytest.param( - '{"a": 0}\n', - (3, 9), - id='Dict without merge', - ), - pytest.param( - 'x = {**a}\n', - (3, 9), - id='Merge of only one dict', - ), - ), -) -def test_fix_pep584_noop(s, version): - assert _fix_plugins(s, settings=Settings(min_version=version)) == s - - -@pytest.mark.parametrize( - ('s', 'expected'), - ( - pytest.param( - 'x = {**a, **b}\n', - - 'x = a | b\n', - - id='Simple dict rewrite', - ), - pytest.param( - 'x = {**{**a, **b}, **c}\n', - - 'x = a | b | c\n', - - id='Nested merge of dicts', - ), - pytest.param( - 'x = {**a, **b,}\n', - - 'x = a | b\n', - - id='Trailing comma', - ), - pytest.param( - 'x = {\n' - ' **a, # foo\n' - ' **b # bar\n' - '}\n', - - 'x = (\n' - ' a | # foo\n' - ' b # bar\n' - ')\n', - - id='Multiple lines with comment', - ), - pytest.param( - 'x = {\n' - ' **a,\n' - ' **b\n' - '}\n', - - 'x = (\n' - ' a |\n' - ' b\n' - ')\n', - - id='Multiple lines', - ), - pytest.param( - 'x = {\n' - ' **a,\n' - ' **b,\n' - '}\n', - - 'x = (\n' - ' a |\n' - ' b\n' - ')\n', - - id='Multiple lines, trailing comma', - ), - ), -) -def test_fix_pep584(s, expected): - assert _fix_plugins(s, settings=Settings(min_version=(3, 9))) == expected diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/tests/features/typing_named_tuple_test.py new/pyupgrade-2.23.3/tests/features/typing_named_tuple_test.py --- old/pyupgrade-2.20.0/tests/features/typing_named_tuple_test.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/tests/features/typing_named_tuple_test.py 2021-08-04 19:50:42.000000000 +0200 @@ -57,7 +57,7 @@ ), ) def test_typing_named_tuple_noop(s): - assert _fix_py36_plus(s) == s + assert _fix_py36_plus(s, min_version=(3, 6)) == s @pytest.mark.parametrize( @@ -171,4 +171,4 @@ ), ) def test_fix_typing_named_tuple(s, expected): - assert _fix_py36_plus(s) == expected + assert _fix_py36_plus(s, min_version=(3, 6)) == expected diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/tests/features/typing_typed_dict_test.py new/pyupgrade-2.23.3/tests/features/typing_typed_dict_test.py --- old/pyupgrade-2.20.0/tests/features/typing_typed_dict_test.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/tests/features/typing_typed_dict_test.py 2021-08-04 19:50:42.000000000 +0200 @@ -46,7 +46,7 @@ ), ) def test_typing_typed_dict_noop(s): - assert _fix_py36_plus(s) == s + assert _fix_py36_plus(s, min_version=(3, 6)) == s @pytest.mark.parametrize( @@ -134,7 +134,23 @@ id='index unparse error', ), + pytest.param( + 'import typing\n' + 'if True:\n' + ' if False:\n' + ' pass\n' + ' D = typing.TypedDict("D", a=int)\n', + + 'import typing\n' + 'if True:\n' + ' if False:\n' + ' pass\n' + ' class D(typing.TypedDict):\n' + ' a: int\n', + + id='right after a dedent', + ), ), ) def test_typing_typed_dict(s, expected): - assert _fix_py36_plus(s) == expected + assert _fix_py36_plus(s, min_version=(3, 6)) == expected diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/tests/features/unpack_list_comprehension_test.py new/pyupgrade-2.23.3/tests/features/unpack_list_comprehension_test.py --- old/pyupgrade-2.20.0/tests/features/unpack_list_comprehension_test.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/tests/features/unpack_list_comprehension_test.py 2021-08-04 19:50:42.000000000 +0200 @@ -17,6 +17,11 @@ (3,), id='assignment to single variable', ), + pytest.param( + 'x, = [await foo for foo in bar]', + (3,), + id='async comprehension', + ), ), ) def test_fix_typing_text_noop(s, version): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyupgrade-2.20.0/tests/features/unpacking_argument_list_comprehensions_test.py new/pyupgrade-2.23.3/tests/features/unpacking_argument_list_comprehensions_test.py --- old/pyupgrade-2.20.0/tests/features/unpacking_argument_list_comprehensions_test.py 2021-07-03 21:01:26.000000000 +0200 +++ new/pyupgrade-2.23.3/tests/features/unpacking_argument_list_comprehensions_test.py 2021-08-04 19:50:42.000000000 +0200 @@ -32,6 +32,11 @@ (3,), id='Starred, no list comp', ), + pytest.param( + 'foo(*[x async for x in bar])', + (3,), + id='async listcomp', + ), ), ) def test_fix_unpack_argument_list_comp_noop(s, version):