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-05-16 23:41:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pyupgrade (Old)
 and      /work/SRC/openSUSE:Factory/.python-pyupgrade.new.2988 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pyupgrade"

Sun May 16 23:41:58 2021 rev:10 rq:893450 version:2.15.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pyupgrade/python-pyupgrade.changes        
2021-05-10 15:41:10.965132527 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-pyupgrade.new.2988/python-pyupgrade.changes  
    2021-05-16 23:44:15.609105466 +0200
@@ -1,0 +2,8 @@
+Sun May  9 09:50:40 UTC 2021 - Sebastian Wagner <sebix+novell....@sebix.at>
+
+- update to version 2.15.0:
+ - only replace argument token
+ - CLN only replace argument token
+ - replace stdout=PIPE and stderr=PIPE with capture_output=True
+
+-------------------------------------------------------------------

Old:
----
  python-pyupgrade-2.14.0.tar.gz

New:
----
  python-pyupgrade-2.15.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pyupgrade.spec ++++++
--- /var/tmp/diff_new_pack.3I3Fgk/_old  2021-05-16 23:44:16.101103558 +0200
+++ /var/tmp/diff_new_pack.3I3Fgk/_new  2021-05-16 23:44:16.105103543 +0200
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define skip_python2 1
 Name:           python-pyupgrade
-Version:        2.14.0
+Version:        2.15.0
 Release:        0
 Summary:        A tool to automatically upgrade syntax for newer versions
 License:        MIT

++++++ python-pyupgrade-2.14.0.tar.gz -> python-pyupgrade-2.15.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyupgrade-2.14.0/.pre-commit-config.yaml 
new/pyupgrade-2.15.0/.pre-commit-config.yaml
--- old/pyupgrade-2.14.0/.pre-commit-config.yaml        2021-05-01 
22:38:32.000000000 +0200
+++ new/pyupgrade-2.15.0/.pre-commit-config.yaml        2021-05-08 
23:13:59.000000000 +0200
@@ -20,7 +20,7 @@
     -   id: flake8
         additional_dependencies: [flake8-typing-imports==1.7.0]
 -   repo: https://github.com/pre-commit/mirrors-autopep8
-    rev: v1.5.6
+    rev: v1.5.7
     hooks:
     -   id: autopep8
 -   repo: https://github.com/asottile/reorder_python_imports
@@ -34,7 +34,7 @@
     -   id: add-trailing-comma
         args: [--py36-plus]
 -   repo: https://github.com/asottile/pyupgrade
-    rev: v2.14.0
+    rev: v2.15.0
     hooks:
     -   id: pyupgrade
         args: [--py36-plus]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyupgrade-2.14.0/README.md 
new/pyupgrade-2.15.0/README.md
--- old/pyupgrade-2.14.0/README.md      2021-05-01 22:38:32.000000000 +0200
+++ new/pyupgrade-2.15.0/README.md      2021-05-08 23:13:59.000000000 +0200
@@ -20,7 +20,7 @@
 
 ```yaml
 -   repo: https://github.com/asottile/pyupgrade
-    rev: v2.14.0
+    rev: v2.15.0
     hooks:
     -   id: pyupgrade
 ```
@@ -474,6 +474,17 @@
 ```
 
 
+### `subprocess.run`: replace `stdout=subprocess.PIPE, stderr=subprocess.PIPE` 
with `capture_output=True`
+
+Availability:
+- `--py37-plus` is passed on the commandline.
+
+```diff
+-output = subprocess.run(['foo'], stdout=subprocess.PIPE, 
stderr=subprocess.PIPE)
++output = subprocess.run(['foo'], capture_output=True)
+```
+
+
 ### remove parentheses from `@functools.lru_cache()`
 
 Availability:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyupgrade-2.14.0/pyupgrade/_plugins/open_mode.py 
new/pyupgrade-2.15.0/pyupgrade/_plugins/open_mode.py
--- old/pyupgrade-2.14.0/pyupgrade/_plugins/open_mode.py        2021-05-01 
22:38:32.000000000 +0200
+++ new/pyupgrade-2.15.0/pyupgrade/_plugins/open_mode.py        2021-05-08 
23:13:59.000000000 +0200
@@ -14,6 +14,7 @@
 from pyupgrade._data import register
 from pyupgrade._data import State
 from pyupgrade._data import TokenFunc
+from pyupgrade._token_helpers import delete_argument
 from pyupgrade._token_helpers import find_open_paren
 from pyupgrade._token_helpers import parse_call_args
 
@@ -35,10 +36,7 @@
     mode_stripped = mode.split('=')[-1]
     mode_stripped = mode_stripped.strip().strip('"\'')
     if mode_stripped in U_MODE_REMOVE:
-        if arg_idx == 0:
-            del tokens[func_args[arg_idx][0]: func_args[arg_idx + 1][0]]
-        else:
-            del tokens[func_args[arg_idx - 1][1]:func_args[arg_idx][1]]
+        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)]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pyupgrade-2.14.0/pyupgrade/_plugins/subprocess_run.py 
new/pyupgrade-2.15.0/pyupgrade/_plugins/subprocess_run.py
--- old/pyupgrade-2.14.0/pyupgrade/_plugins/subprocess_run.py   1970-01-01 
01:00:00.000000000 +0100
+++ new/pyupgrade-2.15.0/pyupgrade/_plugins/subprocess_run.py   2021-05-08 
23:13:59.000000000 +0200
@@ -0,0 +1,111 @@
+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._ast_helpers import is_name_attr
+from pyupgrade._data import register
+from pyupgrade._data import State
+from pyupgrade._data import TokenFunc
+from pyupgrade._token_helpers import delete_argument
+from pyupgrade._token_helpers import find_open_paren
+from pyupgrade._token_helpers import parse_call_args
+from pyupgrade._token_helpers import replace_argument
+
+
+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 _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')
+
+
+@register(ast.Call)
+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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pyupgrade-2.14.0/pyupgrade/_plugins/universal_newlines_to_text.py 
new/pyupgrade-2.15.0/pyupgrade/_plugins/universal_newlines_to_text.py
--- old/pyupgrade-2.14.0/pyupgrade/_plugins/universal_newlines_to_text.py       
2021-05-01 22:38:32.000000000 +0200
+++ new/pyupgrade-2.15.0/pyupgrade/_plugins/universal_newlines_to_text.py       
1970-01-01 01:00:00.000000000 +0100
@@ -1,61 +0,0 @@
-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 tokenize_rt import tokens_to_src
-
-from pyupgrade._ast_helpers import ast_to_offset
-from pyupgrade._ast_helpers import is_name_attr
-from pyupgrade._data import register
-from pyupgrade._data import State
-from pyupgrade._data import TokenFunc
-from pyupgrade._token_helpers import find_open_paren
-from pyupgrade._token_helpers import parse_call_args
-
-
-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)
-    src = tokens_to_src(tokens[slice(*func_args[arg_idx])])
-    new_src = src.replace('universal_newlines', 'text', 1)
-    tokens[slice(*func_args[arg_idx])] = [Token('SRC', new_src)]
-
-
-@register(ast.Call)
-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',),
-            )
-    ):
-        kwarg_idx = next(
-            (
-                n
-                for n, keyword in enumerate(node.keywords)
-                if keyword.arg == 'universal_newlines'
-            ),
-            None,
-        )
-        if kwarg_idx is not None:
-            func = functools.partial(
-                _replace_universal_newlines_with_text,
-                arg_idx=len(node.args) + kwarg_idx,
-            )
-            yield ast_to_offset(node), func
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyupgrade-2.14.0/pyupgrade/_token_helpers.py 
new/pyupgrade-2.15.0/pyupgrade/_token_helpers.py
--- old/pyupgrade-2.14.0/pyupgrade/_token_helpers.py    2021-05-01 
22:38:32.000000000 +0200
+++ new/pyupgrade-2.15.0/pyupgrade/_token_helpers.py    2021-05-08 
23:13:59.000000000 +0200
@@ -434,3 +434,32 @@
             return
         j += 1
     tokens[i:j + 1] = [new_token]
+
+
+def delete_argument(
+        i: int, tokens: List[Token],
+        func_args: Sequence[Tuple[int, int]],
+) -> None:
+    if i == 0:
+        # delete leading whitespace before next token
+        end_idx, _ = func_args[i + 1]
+        while tokens[end_idx].name == 'UNIMPORTANT_WS':
+            end_idx += 1
+
+        del tokens[func_args[i][0]:end_idx]
+    else:
+        del tokens[func_args[i - 1][1]:func_args[i][1]]
+
+
+def replace_argument(
+        i: int,
+        tokens: List[Token],
+        func_args: Sequence[Tuple[int, int]],
+        *,
+        new: str,
+) -> None:
+    start_idx, end_idx = func_args[i]
+    # don't replace leading whitespace / newlines
+    while tokens[start_idx].name in {'UNIMPORTANT_WS', 'NL'}:
+        start_idx += 1
+    tokens[start_idx:end_idx] = [Token('SRC', new)]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyupgrade-2.14.0/setup.cfg 
new/pyupgrade-2.15.0/setup.cfg
--- old/pyupgrade-2.14.0/setup.cfg      2021-05-01 22:38:32.000000000 +0200
+++ new/pyupgrade-2.15.0/setup.cfg      2021-05-08 23:13:59.000000000 +0200
@@ -1,6 +1,6 @@
 [metadata]
 name = pyupgrade
-version = 2.14.0
+version = 2.15.0
 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.14.0/tests/features/capture_output_test.py 
new/pyupgrade-2.15.0/tests/features/capture_output_test.py
--- old/pyupgrade-2.14.0/tests/features/capture_output_test.py  1970-01-01 
01:00:00.000000000 +0100
+++ new/pyupgrade-2.15.0/tests/features/capture_output_test.py  2021-05-08 
23:13:59.000000000 +0200
@@ -0,0 +1,116 @@
+import pytest
+
+from pyupgrade._data import Settings
+from pyupgrade._main import _fix_plugins
+
+
+@pytest.mark.parametrize(
+    ('s', 'version'),
+    (
+        pytest.param(
+            'import subprocess\n'
+            'subprocess.run(["foo"], stdout=subprocess.PIPE, '
+            'stderr=subprocess.PIPE)\n',
+            (3,),
+            id='not Python3.7+',
+        ),
+        pytest.param(
+            'from foo import run\n'
+            'import subprocess\n'
+            'run(["foo"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n',
+            (3, 7),
+            id='run imported, but not from subprocess',
+        ),
+        pytest.param(
+            'from foo import PIPE\n'
+            'from subprocess import run\n'
+            'subprocess.run(["foo"], stdout=PIPE, stderr=PIPE)\n',
+            (3, 7),
+            id='PIPE imported, but not from subprocess',
+        ),
+        pytest.param(
+            'from subprocess import run\n'
+            'run(["foo"], stdout=None, stderr=PIPE)\n',
+            (3, 7),
+            id='stdout not subprocess.PIPE',
+        ),
+    ),
+)
+def test_fix_capture_output_noop(s, version):
+    assert _fix_plugins(s, settings=Settings(min_version=version)) == s
+
+
+@pytest.mark.parametrize(
+    ('s', 'expected'),
+    (
+        pytest.param(
+            'import subprocess\n'
+            'subprocess.run(["foo"], stdout=subprocess.PIPE, '
+            'stderr=subprocess.PIPE)\n',
+            'import subprocess\n'
+            'subprocess.run(["foo"], capture_output=True)\n',
+            id='subprocess.run and subprocess.PIPE attributes',
+        ),
+        pytest.param(
+            'from subprocess import run, PIPE\n'
+            'run(["foo"], stdout=PIPE, stderr=PIPE)\n',
+            'from subprocess import run, PIPE\n'
+            'run(["foo"], capture_output=True)\n',
+            id='run and PIPE imported from subprocess',
+        ),
+        pytest.param(
+            'from subprocess import run, PIPE\n'
+            'run(["foo"], shell=True, stdout=PIPE, stderr=PIPE)\n',
+            'from subprocess import run, PIPE\n'
+            'run(["foo"], shell=True, capture_output=True)\n',
+            id='other argument used too',
+        ),
+        pytest.param(
+            'import subprocess\n'
+            'subprocess.run(["foo"], stderr=subprocess.PIPE, '
+            'stdout=subprocess.PIPE)\n',
+            'import subprocess\n'
+            'subprocess.run(["foo"], capture_output=True)\n',
+            id='stderr used before stdout',
+        ),
+        pytest.param(
+            'import subprocess\n'
+            'subprocess.run(stderr=subprocess.PIPE, args=["foo"], '
+            'stdout=subprocess.PIPE)\n',
+            'import subprocess\n'
+            'subprocess.run(args=["foo"], capture_output=True)\n',
+            id='stdout is first argument',
+        ),
+        pytest.param(
+            'import subprocess\n'
+            'subprocess.run(\n'
+            '    stderr=subprocess.PIPE, \n'
+            '    args=["foo"], \n'
+            '    stdout=subprocess.PIPE,\n'
+            ')\n',
+            'import subprocess\n'
+            'subprocess.run(\n'
+            '    args=["foo"], \n'
+            '    capture_output=True,\n'
+            ')\n',
+            id='stdout is first argument, multiline',
+        ),
+        pytest.param(
+            'subprocess.run(\n'
+            '    "foo",\n'
+            '    stdout=subprocess.PIPE,\n'
+            '    stderr=subprocess.PIPE,\n'
+            '    universal_newlines=True,\n'
+            ')',
+            'subprocess.run(\n'
+            '    "foo",\n'
+            '    capture_output=True,\n'
+            '    text=True,\n'
+            ')',
+            id='both universal_newlines and capture_output rewrite',
+        ),
+    ),
+)
+def test_fix_capture_output(s, expected):
+    ret = _fix_plugins(s, settings=Settings(min_version=(3, 7)))
+    assert ret == expected
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyupgrade-2.14.0/tests/features/open_mode_test.py 
new/pyupgrade-2.15.0/tests/features/open_mode_test.py
--- old/pyupgrade-2.14.0/tests/features/open_mode_test.py       2021-05-01 
22:38:32.000000000 +0200
+++ new/pyupgrade-2.15.0/tests/features/open_mode_test.py       2021-05-08 
23:13:59.000000000 +0200
@@ -60,7 +60,7 @@
         ),
         (
             'open(mode="r", encoding="UTF-8", file="t.py")',
-            'open( encoding="UTF-8", file="t.py")',
+            'open(encoding="UTF-8", file="t.py")',
         ),
     ),
 )

Reply via email to