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 2026-01-08 15:28:35
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pyupgrade (Old)
 and      /work/SRC/openSUSE:Factory/.python-pyupgrade.new.1928 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pyupgrade"

Thu Jan  8 15:28:35 2026 rev:38 rq:1325884 version:3.21.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pyupgrade/python-pyupgrade.changes        
2025-08-13 16:33:49.012682367 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-pyupgrade.new.1928/python-pyupgrade.changes  
    2026-01-08 15:29:24.345999561 +0100
@@ -1,0 +2,9 @@
+Thu Jan  8 04:06:59 UTC 2026 - Steve Kowalik <[email protected]>
+
+- Update to 3.21.2:
+  * fix unstringing multiline string annotations
+  * vendor cookie_re from cpython
+  * regenerate symbols for --py314-plus
+  * Rewrite version_info[0] and version_info.major
+
+-------------------------------------------------------------------

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

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

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

Other differences:
------------------
++++++ python-pyupgrade.spec ++++++
--- /var/tmp/diff_new_pack.XrVKjZ/_old  2026-01-08 15:29:24.858021318 +0100
+++ /var/tmp/diff_new_pack.XrVKjZ/_new  2026-01-08 15:29:24.862021489 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-pyupgrade
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,23 +18,23 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-pyupgrade
-Version:        3.20.0
+Version:        3.21.2
 Release:        0
 Summary:        A tool to automatically upgrade syntax for newer versions
 License:        MIT
-Group:          Development/Languages/Python
 URL:            https://github.com/asottile/pyupgrade
 Source:         
https://github.com/asottile/pyupgrade/archive/refs/tags/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
+BuildRequires:  %{python_module base >= 3.10}
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  %{python_module wheel}
 BuildRequires:  python-rpm-macros
 # SECTION test requirements
 BuildRequires:  %{python_module pytest}
-BuildRequires:  %{python_module tokenize-rt >= 3.2.0}
+BuildRequires:  %{python_module tokenize-rt >= 6.1.0}
 # /SECTION
 BuildRequires:  fdupes
-Requires:       python-tokenize-rt >= 3.2.0
+Requires:       python-tokenize-rt >= 6.1.0
 Requires(post): update-alternatives
 Requires(postun): update-alternatives
 BuildArch:      noarch

++++++ python-pyupgrade-3.20.0.tar.gz -> python-pyupgrade-3.21.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyupgrade-3.20.0/.github/workflows/main.yml 
new/pyupgrade-3.21.2/.github/workflows/main.yml
--- old/pyupgrade-3.20.0/.github/workflows/main.yml     2025-05-23 
20:55:31.000000000 +0200
+++ new/pyupgrade-3.21.2/.github/workflows/main.yml     2025-11-19 
01:39:36.000000000 +0100
@@ -10,10 +10,10 @@
   main-windows:
     uses: asottile/workflows/.github/workflows/[email protected]
     with:
-      env: '["py39"]'
+      env: '["py310"]'
       os: windows-latest
   main-linux:
     uses: asottile/workflows/.github/workflows/[email protected]
     with:
-      env: '["py39", "py310", "py311", "py312"]'
+      env: '["py310", "py311", "py312", "py313"]'
       os: ubuntu-latest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyupgrade-3.20.0/.pre-commit-config.yaml 
new/pyupgrade-3.21.2/.pre-commit-config.yaml
--- old/pyupgrade-3.20.0/.pre-commit-config.yaml        2025-05-23 
20:55:31.000000000 +0200
+++ new/pyupgrade-3.21.2/.pre-commit-config.yaml        2025-11-19 
01:39:36.000000000 +0100
@@ -1,6 +1,6 @@
 repos:
 -   repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v5.0.0
+    rev: v6.0.0
     hooks:
     -   id: trailing-whitespace
     -   id: end-of-file-fixer
@@ -10,32 +10,32 @@
     -   id: name-tests-test
     -   id: requirements-txt-fixer
 -   repo: https://github.com/asottile/setup-cfg-fmt
-    rev: v2.8.0
+    rev: v3.1.0
     hooks:
     -   id: setup-cfg-fmt
 -   repo: https://github.com/asottile/reorder-python-imports
-    rev: v3.14.0
+    rev: v3.16.0
     hooks:
     -   id: reorder-python-imports
-        args: [--py39-plus, --add-import, 'from __future__ import annotations']
+        args: [--py310-plus, --add-import, 'from __future__ import 
annotations']
 -   repo: https://github.com/asottile/add-trailing-comma
-    rev: v3.1.0
+    rev: v4.0.0
     hooks:
     -   id: add-trailing-comma
 -   repo: https://github.com/asottile/pyupgrade
-    rev: v3.20.0
+    rev: v3.21.2
     hooks:
     -   id: pyupgrade
-        args: [--py39-plus]
+        args: [--py310-plus]
 -   repo: https://github.com/hhatto/autopep8
     rev: v2.3.2
     hooks:
     -   id: autopep8
 -   repo: https://github.com/PyCQA/flake8
-    rev: 7.2.0
+    rev: 7.3.0
     hooks:
     -   id: flake8
 -   repo: https://github.com/pre-commit/mirrors-mypy
-    rev: v1.15.0
+    rev: v1.18.2
     hooks:
     -   id: mypy
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyupgrade-3.20.0/README.md 
new/pyupgrade-3.21.2/README.md
--- old/pyupgrade-3.20.0/README.md      2025-05-23 20:55:31.000000000 +0200
+++ new/pyupgrade-3.21.2/README.md      2025-11-19 01:39:36.000000000 +0100
@@ -21,7 +21,7 @@
 
 ```yaml
 -   repo: https://github.com/asottile/pyupgrade
-    rev: v3.20.0
+    rev: v3.21.2
     hooks:
     -   id: pyupgrade
 ```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyupgrade-3.20.0/pyupgrade/_data.py 
new/pyupgrade-3.21.2/pyupgrade/_data.py
--- old/pyupgrade-3.20.0/pyupgrade/_data.py     2025-05-23 20:55:31.000000000 
+0200
+++ new/pyupgrade-3.21.2/pyupgrade/_data.py     2025-11-19 01:39:36.000000000 
+0100
@@ -3,8 +3,8 @@
 import ast
 import collections
 import pkgutil
+from collections.abc import Callable
 from collections.abc import Iterable
-from typing import Callable
 from typing import NamedTuple
 from typing import Protocol
 from typing import TypeVar
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyupgrade-3.20.0/pyupgrade/_main.py 
new/pyupgrade-3.21.2/pyupgrade/_main.py
--- old/pyupgrade-3.20.0/pyupgrade/_main.py     2025-05-23 20:55:31.000000000 
+0200
+++ new/pyupgrade-3.21.2/pyupgrade/_main.py     2025-11-19 01:39:36.000000000 
+0100
@@ -276,6 +276,10 @@
     del tokens[victims]
 
 
+# copied from 3.15 @ 0ac890bea7
+_cookie_re = re.compile(r'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)', re.ASCII)
+
+
 def _fix_tokens(contents_text: str) -> str:
     try:
         tokens = src_to_tokens(contents_text)
@@ -294,7 +298,7 @@
                 token.utf8_byte_offset == 0 and
                 token.line < 3 and
                 token.name == 'COMMENT' and
-                tokenize.cookie_re.match(token.src)
+                _cookie_re.match(token.src)
         ):
             del tokens[i]
             assert tokens[i].name == 'NL', tokens[i].name
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyupgrade-3.20.0/pyupgrade/_plugins/imports.py 
new/pyupgrade-3.21.2/pyupgrade/_plugins/imports.py
--- old/pyupgrade-3.20.0/pyupgrade/_plugins/imports.py  2025-05-23 
20:55:31.000000000 +0200
+++ new/pyupgrade-3.21.2/pyupgrade/_plugins/imports.py  2025-11-19 
01:39:36.000000000 +0100
@@ -21,7 +21,7 @@
 from pyupgrade._token_helpers import indented_amount
 
 # GENERATED VIA generate-imports
-# Using reorder-python-imports==3.15.0
+# Using reorder-python-imports==3.16.0
 REMOVALS = {
     (3,): {
         '__future__': {
@@ -242,6 +242,9 @@
         ('typing_extensions', 'is_protocol'): 'typing',
         ('typing_extensions', 'runtime_checkable'): 'typing',
     },
+    (3, 14): {
+        ('typing_extensions', 'evaluate_forward_ref'): 'typing',
+    },
 }
 REPLACE_MODS = {
     'six.moves.BaseHTTPServer': 'http.server',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pyupgrade-3.20.0/pyupgrade/_plugins/percent_format.py 
new/pyupgrade-3.21.2/pyupgrade/_plugins/percent_format.py
--- old/pyupgrade-3.20.0/pyupgrade/_plugins/percent_format.py   2025-05-23 
20:55:31.000000000 +0200
+++ new/pyupgrade-3.21.2/pyupgrade/_plugins/percent_format.py   2025-11-19 
01:39:36.000000000 +0100
@@ -195,7 +195,7 @@
         elif k.value in KEYWORDS:
             return
         seen_keys.add(k.value)
-        keys[ast_to_offset(k)] = k
+        keys[ast_to_offset(k)] = k.value
 
     # TODO: this is overly timid
     brace = i + 4
@@ -211,13 +211,13 @@
         if key is None:
             continue
         # we found the key, but the string didn't match (implicit join?)
-        elif ast.literal_eval(token.src) != key.value:
+        elif ast.literal_eval(token.src) != key:
             return
         # the map uses some strange syntax that's not `'key': value`
         elif tokens[j + 1].src != ':' or tokens[j + 2].src != ' ':
             return
         else:
-            key_indices.append((j, key.value))
+            key_indices.append((j, key))
     assert not keys, keys
 
     tokens[brace_end] = tokens[brace_end]._replace(src=')')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyupgrade-3.20.0/pyupgrade/_plugins/typing_pep563.py 
new/pyupgrade-3.21.2/pyupgrade/_plugins/typing_pep563.py
--- old/pyupgrade-3.20.0/pyupgrade/_plugins/typing_pep563.py    2025-05-23 
20:55:31.000000000 +0200
+++ new/pyupgrade-3.21.2/pyupgrade/_plugins/typing_pep563.py    2025-11-19 
01:39:36.000000000 +0100
@@ -6,6 +6,7 @@
 from collections.abc import Iterable
 from collections.abc import Sequence
 
+from tokenize_rt import NON_CODING_TOKENS
 from tokenize_rt import Offset
 
 from pyupgrade._ast_helpers import ast_to_offset
@@ -23,7 +24,15 @@
 
 
 def _dequote(i: int, tokens: list[Token], *, new: str) -> None:
-    tokens[i] = tokens[i]._replace(src=new)
+    end = i + 1
+    for j in range(end, len(tokens)):
+        if tokens[j].name == 'STRING':
+            end = j + 1
+        elif tokens[j].name not in NON_CODING_TOKENS:
+            break
+    else:
+        raise AssertionError('past end?')
+    tokens[i:end] = [tokens[i]._replace(src=new)]
 
 
 def _get_name(node: ast.expr) -> str:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pyupgrade-3.20.0/pyupgrade/_plugins/versioned_branches.py 
new/pyupgrade-3.21.2/pyupgrade/_plugins/versioned_branches.py
--- old/pyupgrade-3.20.0/pyupgrade/_plugins/versioned_branches.py       
2025-05-23 20:55:31.000000000 +0200
+++ new/pyupgrade-3.21.2/pyupgrade/_plugins/versioned_branches.py       
2025-11-19 01:39:36.000000000 +0100
@@ -82,8 +82,20 @@
 
 
 def _eq(test: ast.Compare, n: int) -> bool:
+    return _cmp(test, ast.Eq, n)
+
+
+def _lt(test: ast.Compare, n: int) -> bool:
+    return _cmp(test, ast.Lt, n)
+
+
+def _gte(test: ast.Compare, n: int) -> bool:
+    return _cmp(test, ast.GtE, n)
+
+
+def _cmp(test: ast.Compare, op: type[ast.cmpop], n: int) -> bool:
     return (
-        isinstance(test.ops[0], ast.Eq) and
+        isinstance(test.ops[0], op) and
         isinstance(test.comparators[0], ast.Constant) and
         test.comparators[0].value == n
     )
@@ -164,6 +176,33 @@
                         for minor in range(min_version[1])
                     )
                 )
+            ) or
+            # sys.version_info[0] == 2 or < 3
+            # sys.version_info.major == 2 or < 3
+            (
+                isinstance(node.test, ast.Compare) and
+                (
+                    (
+                        isinstance(node.test.left, ast.Subscript) and
+                        isinstance(node.test.left.slice, ast.Constant) and
+                        node.test.left.slice.value == 0
+                    ) or
+                    (
+                        isinstance(node.test.left, ast.Attribute) and
+                        node.test.left.attr == 'major'
+                    )
+                ) and
+                is_name_attr(
+                    node.test.left.value,
+                    state.from_imports,
+                    ('sys',),
+                    ('version_info',),
+                ) and
+                len(node.test.ops) == 1 and
+                (
+                    _eq(node.test, 2) or
+                    _lt(node.test, 3)
+                )
             )
     ):
         if len(node.orelse) == 1 and isinstance(node.orelse[0], ast.If):
@@ -211,6 +250,33 @@
                         for minor in range(min_version[1])
                     )
                 )
+            ) or
+            # sys.version_info[0] == 3 or >= 3
+            # sys.version_info.major == 3 or >= 3
+            (
+                isinstance(node.test, ast.Compare) and
+                (
+                    (
+                        isinstance(node.test.left, ast.Subscript) and
+                        isinstance(node.test.left.slice, ast.Constant) and
+                        node.test.left.slice.value == 0
+                    ) or
+                    (
+                        isinstance(node.test.left, ast.Attribute) and
+                        node.test.left.attr == 'major'
+                    )
+                ) and
+                is_name_attr(
+                    node.test.left.value,
+                    state.from_imports,
+                    ('sys',),
+                    ('version_info',),
+                ) and
+                len(node.test.ops) == 1 and
+                (
+                    _eq(node.test, 3) or
+                    _gte(node.test, 3)
+                )
             )
     ):
         if len(node.orelse) == 1 and isinstance(node.orelse[0], ast.If):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyupgrade-3.20.0/setup.cfg 
new/pyupgrade-3.21.2/setup.cfg
--- old/pyupgrade-3.20.0/setup.cfg      2025-05-23 20:55:31.000000000 +0200
+++ new/pyupgrade-3.21.2/setup.cfg      2025-11-19 01:39:36.000000000 +0100
@@ -1,6 +1,6 @@
 [metadata]
 name = pyupgrade
-version = 3.20.0
+version = 3.21.2
 description = A tool to automatically upgrade syntax for newer versions.
 long_description = file: README.md
 long_description_content_type = text/markdown
@@ -19,7 +19,7 @@
 packages = find:
 install_requires =
     tokenize-rt>=6.1.0
-python_requires = >=3.9
+python_requires = >=3.10
 
 [options.packages.find]
 exclude =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pyupgrade-3.20.0/tests/features/typing_pep563_test.py 
new/pyupgrade-3.21.2/tests/features/typing_pep563_test.py
--- old/pyupgrade-3.20.0/tests/features/typing_pep563_test.py   2025-05-23 
20:55:31.000000000 +0200
+++ new/pyupgrade-3.21.2/tests/features/typing_pep563_test.py   2025-11-19 
01:39:36.000000000 +0100
@@ -365,6 +365,20 @@
 
             id='posonly args',
         ),
+        pytest.param(
+            'from __future__ import annotations\n'
+            'x: (\n'
+            '    "int | "\n'
+            '    "str"\n'
+            ')\n',
+
+            'from __future__ import annotations\n'
+            'x: (\n'
+            '    int | str\n'
+            ')\n',
+
+            id='multiline implicit-concat annotation',
+        ),
     ),
 )
 def test_fix_typing_pep563(s, expected):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pyupgrade-3.20.0/tests/features/versioned_branches_test.py 
new/pyupgrade-3.21.2/tests/features/versioned_branches_test.py
--- old/pyupgrade-3.20.0/tests/features/versioned_branches_test.py      
2025-05-23 20:55:31.000000000 +0200
+++ new/pyupgrade-3.21.2/tests/features/versioned_branches_test.py      
2025-11-19 01:39:36.000000000 +0100
@@ -317,6 +317,46 @@
             id='sys.version_info == 2',
         ),
         pytest.param(
+            'if sys.version_info[0] == 2:\n'
+            '    2\n'
+            'else:\n'
+            '    3\n',
+
+            '3\n',
+
+            id='sys.version_info[0] == 2',
+        ),
+        pytest.param(
+            'if sys.version_info[0] < 3:\n'
+            '    2\n'
+            'else:\n'
+            '    3\n',
+
+            '3\n',
+
+            id='sys.version_info[0] < 3',
+        ),
+        pytest.param(
+            'if sys.version_info.major == 2:\n'
+            '    2\n'
+            'else:\n'
+            '    3\n',
+
+            '3\n',
+
+            id='sys.version_info.major == 2',
+        ),
+        pytest.param(
+            'if sys.version_info.major < 3:\n'
+            '    2\n'
+            'else:\n'
+            '    3\n',
+
+            '3\n',
+
+            id='sys.version_info.major < 3',
+        ),
+        pytest.param(
             'if sys.version_info < (3,):\n'
             '    2\n'
             'else:\n'
@@ -367,6 +407,46 @@
             id='sys.version_info >= (3,)',
         ),
         pytest.param(
+            'if sys.version_info[0] == 3:\n'
+            '    3\n'
+            'else:\n'
+            '    2\n',
+
+            '3\n',
+
+            id='sys.version_info[0]== 3',
+        ),
+        pytest.param(
+            'if sys.version_info[0] >= 3:\n'
+            '    3\n'
+            'else:\n'
+            '    2\n',
+
+            '3\n',
+
+            id='sys.version_info[0] >= 3',
+        ),
+        pytest.param(
+            'if sys.version_info.major == 3:\n'
+            '    3\n'
+            'else:\n'
+            '    2\n',
+
+            '3\n',
+
+            id='testme sys.version_info.major == 3',
+        ),
+        pytest.param(
+            'if sys.version_info.major >= 3:\n'
+            '    3\n'
+            'else:\n'
+            '    2\n',
+
+            '3\n',
+
+            id='sys.version_info.major >= 3',
+        ),
+        pytest.param(
             'from sys import version_info\n'
             'if version_info > (3,):\n'
             '    3\n'
@@ -379,6 +459,102 @@
             id='from sys import version_info, > (3,)',
         ),
         pytest.param(
+            'from sys import version_info\n'
+            'if version_info[0] == 2:\n'
+            '    2\n'
+            'else:\n'
+            '    3\n',
+
+            'from sys import version_info\n'
+            '3\n',
+
+            id='from sys import version_info, [0] == 2',
+        ),
+        pytest.param(
+            'from sys import version_info\n'
+            'if version_info[0] < 3:\n'
+            '    2\n'
+            'else:\n'
+            '    3\n',
+
+            'from sys import version_info\n'
+            '3\n',
+
+            id='from sys import version_info, [0] < 3',
+        ),
+        pytest.param(
+            'from sys import version_info\n'
+            'if version_info.major == 2:\n'
+            '    2\n'
+            'else:\n'
+            '    3\n',
+
+            'from sys import version_info\n'
+            '3\n',
+
+            id='from sys import version_info, .major == 2',
+        ),
+        pytest.param(
+            'from sys import version_info\n'
+            'if version_info.major < 3:\n'
+            '    2\n'
+            'else:\n'
+            '    3\n',
+
+            'from sys import version_info\n'
+            '3\n',
+
+            id='from sys import version_info, .major < 3',
+        ),
+        pytest.param(
+            'from sys import version_info\n'
+            'if version_info[0] == 3:\n'
+            '    3\n'
+            'else:\n'
+            '    2\n',
+
+            'from sys import version_info\n'
+            '3\n',
+
+            id='from sys import version_info, [0] == 3',
+        ),
+        pytest.param(
+            'from sys import version_info\n'
+            'if version_info[0] >= 3:\n'
+            '    3\n'
+            'else:\n'
+            '    2\n',
+
+            'from sys import version_info\n'
+            '3\n',
+
+            id='from sys import version_info, [0] >= 3',
+        ),
+        pytest.param(
+            'from sys import version_info\n'
+            'if version_info.major == 3:\n'
+            '    3\n'
+            'else:\n'
+            '    2\n',
+
+            'from sys import version_info\n'
+            '3\n',
+
+            id='from sys import version_info, .major == 3',
+        ),
+        pytest.param(
+            'from sys import version_info\n'
+            'if version_info.major >= 3:\n'
+            '    3\n'
+            'else:\n'
+            '    2\n',
+
+            'from sys import version_info\n'
+            '3\n',
+
+            id='from sys import version_info, .major >= 3',
+        ),
+        pytest.param(
             'if True:\n'
             '    print(1)\n'
             'elif six.PY2:\n'

Reply via email to