Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-flake8-bugbear for 
openSUSE:Factory checked in at 2023-07-12 17:27:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-flake8-bugbear (Old)
 and      /work/SRC/openSUSE:Factory/.python-flake8-bugbear.new.8922 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-flake8-bugbear"

Wed Jul 12 17:27:24 2023 rev:15 rq:1098207 version:23.7.10

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-flake8-bugbear/python-flake8-bugbear.changes  
    2023-06-11 19:58:36.872366122 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-flake8-bugbear.new.8922/python-flake8-bugbear.changes
    2023-07-12 17:27:50.466706226 +0200
@@ -1,0 +2,10 @@
+Tue Jul 11 14:10:46 UTC 2023 - Dirk Müller <dmuel...@suse.com>
+
+- update to 23.7.10:
+  * Add B034: re.sub/subn/split must pass flags/count/maxsplit as
+    keyword arguments.
+  * Fix a crash and several test failures on Python 3.12, all
+    relating to the B907 * check.
+  * Declare support for Python 3.12.
+
+-------------------------------------------------------------------

Old:
----
  flake8-bugbear-23.6.5.tar.gz

New:
----
  flake8-bugbear-23.7.10.tar.gz

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

Other differences:
------------------
++++++ python-flake8-bugbear.spec ++++++
--- /var/tmp/diff_new_pack.znxZnQ/_old  2023-07-12 17:27:51.086710518 +0200
+++ /var/tmp/diff_new_pack.znxZnQ/_new  2023-07-12 17:27:51.090710546 +0200
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-flake8-bugbear
-Version:        23.6.5
+Version:        23.7.10
 Release:        0
 Summary:        A plugin for flake8 finding likely bugs and design problems in 
your program
 License:        MIT

++++++ flake8-bugbear-23.6.5.tar.gz -> flake8-bugbear-23.7.10.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8-bugbear-23.6.5/PKG-INFO 
new/flake8-bugbear-23.7.10/PKG-INFO
--- old/flake8-bugbear-23.6.5/PKG-INFO  2023-06-05 18:20:50.367162500 +0200
+++ new/flake8-bugbear-23.7.10/PKG-INFO 2023-07-10 18:29:34.876180400 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: flake8-bugbear
-Version: 23.6.5
+Version: 23.7.10
 Summary: A plugin for flake8 finding likely bugs and design problems in your 
program. Contains warnings that don't belong in pyflakes and pycodestyle.
 Author-email: Łukasz Langa <luk...@langa.pl>
 License: MIT
@@ -19,6 +19,7 @@
 Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
 Classifier: Programming Language :: Python :: 3 :: Only
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
 Classifier: Topic :: Software Development :: Quality Assurance
@@ -217,6 +218,8 @@
 
 **B033**: Sets should not contain duplicate items. Duplicate items will be 
replaced with a single item at runtime.
 
+**B034**: Calls to `re.sub`, `re.subn` or `re.split` should pass `flags` or 
`count`/`maxsplit` as keyword arguments. It is commonly assumed that `flags` is 
the third positional parameter, forgetting about `count`/`maxsplit`, since many 
other `re` module functions are of the form `f(pattern, string, flags)`.
+
 Opinionated warnings
 ~~~~~~~~~~~~~~~~~~~~
 
@@ -249,8 +252,11 @@
 for details.
 
 **B905**: ``zip()`` without an explicit `strict=` parameter set. 
``strict=True`` causes the resulting iterator
-to raise a ``ValueError`` if the arguments are exhausted at differing lengths. 
The ``strict=`` argument
-was added in Python 3.10, so don't enable this flag for code that should work 
on <3.10.
+to raise a ``ValueError`` if the arguments are exhausted at differing lengths.
+
+Exclusions are `itertools.count 
<https://docs.python.org/3/library/itertools.html#itertools.count>`_, 
`itertools.cycle 
<https://docs.python.org/3/library/itertools.html#itertools.cycle>`_ and 
`itertools.repeat 
<https://docs.python.org/3/library/itertools.html#itertools.repeat>`_ (with 
times=None) since they are infinite iterators.
+
+The ``strict=`` argument was added in Python 3.10, so don't enable this flag 
for code that should work on <3.10.
 For more information: https://peps.python.org/pep-0618/
 
 **B906**: ``visit_`` function with no further call to a ``visit`` function. 
This is often an error, and will stop the visitor from recursing into the 
subnodes of a visited node. Consider adding a call ``self.generic_visit(node)`` 
at the end of the function.
@@ -358,6 +364,14 @@
 Change Log
 ----------
 
+23.7.10
+~~~~~~~~~~
+
+* Add B034: re.sub/subn/split must pass flags/count/maxsplit as keyword 
arguments.
+* Fix a crash and several test failures on Python 3.12, all relating to the 
B907
+  check.
+* Declare support for Python 3.12.
+
 23.6.5
 ~~~~~~
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8-bugbear-23.6.5/README.rst 
new/flake8-bugbear-23.7.10/README.rst
--- old/flake8-bugbear-23.6.5/README.rst        2023-06-05 18:20:41.000000000 
+0200
+++ new/flake8-bugbear-23.7.10/README.rst       2023-07-10 18:29:25.000000000 
+0200
@@ -188,6 +188,8 @@
 
 **B033**: Sets should not contain duplicate items. Duplicate items will be 
replaced with a single item at runtime.
 
+**B034**: Calls to `re.sub`, `re.subn` or `re.split` should pass `flags` or 
`count`/`maxsplit` as keyword arguments. It is commonly assumed that `flags` is 
the third positional parameter, forgetting about `count`/`maxsplit`, since many 
other `re` module functions are of the form `f(pattern, string, flags)`.
+
 Opinionated warnings
 ~~~~~~~~~~~~~~~~~~~~
 
@@ -220,8 +222,11 @@
 for details.
 
 **B905**: ``zip()`` without an explicit `strict=` parameter set. 
``strict=True`` causes the resulting iterator
-to raise a ``ValueError`` if the arguments are exhausted at differing lengths. 
The ``strict=`` argument
-was added in Python 3.10, so don't enable this flag for code that should work 
on <3.10.
+to raise a ``ValueError`` if the arguments are exhausted at differing lengths.
+
+Exclusions are `itertools.count 
<https://docs.python.org/3/library/itertools.html#itertools.count>`_, 
`itertools.cycle 
<https://docs.python.org/3/library/itertools.html#itertools.cycle>`_ and 
`itertools.repeat 
<https://docs.python.org/3/library/itertools.html#itertools.repeat>`_ (with 
times=None) since they are infinite iterators.
+
+The ``strict=`` argument was added in Python 3.10, so don't enable this flag 
for code that should work on <3.10.
 For more information: https://peps.python.org/pep-0618/
 
 **B906**: ``visit_`` function with no further call to a ``visit`` function. 
This is often an error, and will stop the visitor from recursing into the 
subnodes of a visited node. Consider adding a call ``self.generic_visit(node)`` 
at the end of the function.
@@ -329,6 +334,14 @@
 Change Log
 ----------
 
+23.7.10
+~~~~~~~~~~
+
+* Add B034: re.sub/subn/split must pass flags/count/maxsplit as keyword 
arguments.
+* Fix a crash and several test failures on Python 3.12, all relating to the 
B907
+  check.
+* Declare support for Python 3.12.
+
 23.6.5
 ~~~~~~
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8-bugbear-23.6.5/bugbear.py 
new/flake8-bugbear-23.7.10/bugbear.py
--- old/flake8-bugbear-23.6.5/bugbear.py        2023-06-05 18:20:41.000000000 
+0200
+++ new/flake8-bugbear-23.7.10/bugbear.py       2023-07-10 18:29:25.000000000 
+0200
@@ -5,6 +5,7 @@
 import math
 import re
 import sys
+import warnings
 from collections import namedtuple
 from contextlib import suppress
 from functools import lru_cache, partial
@@ -13,7 +14,7 @@
 import attr
 import pycodestyle
 
-__version__ = "23.6.5"
+__version__ = "23.7.10"
 
 LOG = logging.getLogger("flake8.bugbear")
 CONTEXTFUL_NODES = (
@@ -200,7 +201,7 @@
     if not isinstance(arg, ast.Constant) or not isinstance(arg.value, str):
         return False
 
-    return re.match(r"^[A-Za-z_][A-Za-z0-9_]*$", arg.s) is not None
+    return re.match(r"^[A-Za-z_][A-Za-z0-9_]*$", arg.value) is not None
 
 
 def _flatten_excepthandler(node):
@@ -401,14 +402,14 @@
             with suppress(AttributeError, IndexError):
                 if (
                     node.func.id in ("getattr", "hasattr")
-                    and node.args[1].s == "__call__"
+                    and node.args[1].value == "__call__"
                 ):
                     self.errors.append(B004(node.lineno, node.col_offset))
                 if (
                     node.func.id == "getattr"
                     and len(node.args) == 2
                     and _is_identifier(node.args[1])
-                    and not iskeyword(node.args[1].s)
+                    and not iskeyword(node.args[1].value)
                 ):
                     self.errors.append(B009(node.lineno, node.col_offset))
                 elif (
@@ -416,14 +417,15 @@
                     and node.func.id == "setattr"
                     and len(node.args) == 3
                     and _is_identifier(node.args[1])
-                    and not iskeyword(node.args[1].s)
+                    and not iskeyword(node.args[1].value)
                 ):
                     self.errors.append(B010(node.lineno, node.col_offset))
 
             self.check_for_b026(node)
 
-        self.check_for_b905(node)
         self.check_for_b028(node)
+        self.check_for_b034(node)
+        self.check_for_b905(node)
         self.generic_visit(node)
 
     def visit_Module(self, node):
@@ -556,11 +558,11 @@
             if call_path in B005.valid_paths:
                 return  # path is exempt
 
-            s = node.args[0].s
-            if len(s) == 1:
+            value = node.args[0].value
+            if len(value) == 1:
                 return  # stripping just one character
 
-            if len(s) == len(set(s)):
+            if len(value) == len(set(value)):
                 return  # no characters appear more than once
 
             self.errors.append(B005(node.lineno, node.col_offset))
@@ -1168,12 +1170,46 @@
         for duplicate in duplicates:
             self.errors.append(B025(node.lineno, node.col_offset, 
vars=(duplicate,)))
 
-    def check_for_b905(self, node):
-        if (
-            isinstance(node.func, ast.Name)
-            and node.func.id == "zip"
-            and not any(kw.arg == "strict" for kw in node.keywords)
+    @staticmethod
+    def _is_infinite_iterator(node: ast.expr) -> bool:
+        if not (
+            isinstance(node, ast.Call)
+            and isinstance(node.func, ast.Attribute)
+            and isinstance(node.func.value, ast.Name)
+            and node.func.value.id == "itertools"
         ):
+            return False
+        if node.func.attr in {"cycle", "count"}:
+            return True
+        elif node.func.attr == "repeat":
+            if len(node.args) == 1 and len(node.keywords) == 0:
+                # itertools.repeat(iterable)
+                return True
+            if (
+                len(node.args) == 2
+                and isinstance(node.args[1], ast.Constant)
+                and node.args[1].value is None
+            ):
+                # itertools.repeat(iterable, None)
+                return True
+            for kw in node.keywords:
+                # itertools.repeat(iterable, times=None)
+                if (
+                    kw.arg == "times"
+                    and isinstance(kw.value, ast.Constant)
+                    and kw.value.value is None
+                ):
+                    return True
+
+        return False
+
+    def check_for_b905(self, node):
+        if not (isinstance(node.func, ast.Name) and node.func.id == "zip"):
+            return
+        for arg in node.args:
+            if self._is_infinite_iterator(arg):
+                return
+        if not any(kw.arg == "strict" for kw in node.keywords):
             self.errors.append(B905(node.lineno, node.col_offset))
 
     def check_for_b906(self, node: ast.FunctionDef):
@@ -1182,7 +1218,12 @@
 
         # extract what's visited
         class_name = node.name[len("visit_") :]
-        class_type = getattr(ast, class_name, None)
+
+        # silence any DeprecationWarnings
+        # that might come from accessing a deprecated AST node
+        with warnings.catch_warnings():
+            warnings.simplefilter("ignore", category=DeprecationWarning)
+            class_type = getattr(ast, class_name, None)
 
         if (
             # not a valid ast subclass
@@ -1239,36 +1280,34 @@
         current_mark = None
         variable = None
         for value in node.values:
-            # check for quote mark after pre-marked variable
-            if (
-                current_mark is not None
-                and variable is not None
-                and isinstance(value, ast.Constant)
-                and isinstance(value.value, str)
-                and value.value[0] == current_mark
-            ):
-                self.errors.append(
-                    B907(
-                        variable.lineno,
-                        variable.col_offset,
-                        vars=(myunparse(variable.value),),
-                    )
-                )
-                current_mark = variable = None
-                # don't continue with length>1, so we can detect a new pre-mark
-                # in the same string as a post-mark, e.g. `"{foo}" "{bar}"`
-                if len(value.value) == 1:
+            if isinstance(value, ast.Constant) and isinstance(value.value, 
str):
+                if not value.value:
                     continue
 
-            # detect pre-mark
-            if (
-                isinstance(value, ast.Constant)
-                and isinstance(value.value, str)
-                and value.value[-1] in quote_marks
-            ):
-                current_mark = value.value[-1]
-                variable = None
-                continue
+                # check for quote mark after pre-marked variable
+                if (
+                    current_mark is not None
+                    and variable is not None
+                    and value.value[0] == current_mark
+                ):
+                    self.errors.append(
+                        B907(
+                            variable.lineno,
+                            variable.col_offset,
+                            vars=(myunparse(variable.value),),
+                        )
+                    )
+                    current_mark = variable = None
+                    # don't continue with length>1, so we can detect a new 
pre-mark
+                    # in the same string as a post-mark, e.g. `"{foo}" "{bar}"`
+                    if len(value.value) == 1:
+                        continue
+
+                # detect pre-mark
+                if value.value[-1] in quote_marks:
+                    current_mark = value.value[-1]
+                    variable = None
+                    continue
 
             # detect variable, if there's a pre-mark
             if (
@@ -1362,6 +1401,27 @@
             else:
                 seen.add(elt.value)
 
+    def check_for_b034(self, node: ast.Call):
+        if not isinstance(node.func, ast.Attribute):
+            return
+        if not isinstance(node.func.value, ast.Name) or node.func.value.id != 
"re":
+            return
+
+        def check(num_args, param_name):
+            if len(node.args) > num_args:
+                self.errors.append(
+                    B034(
+                        node.args[num_args].lineno,
+                        node.args[num_args].col_offset,
+                        vars=(node.func.attr, param_name),
+                    )
+                )
+
+        if node.func.attr in ("sub", "subn"):
+            check(3, "count")
+        elif node.func.attr == "split":
+            check(2, "maxsplit")
+
 
 def compose_call_path(node):
     if isinstance(node, ast.Attribute):
@@ -1766,6 +1826,13 @@
     )
 )
 
+B034 = Error(
+    message=(
+        "B034 {} should pass `{}` and `flags` as keyword arguments to avoid 
confusion"
+        " due to unintuitive argument positions."
+    )
+)
+
 # Warnings disabled by default.
 B901 = Error(
     message=(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/flake8-bugbear-23.6.5/flake8_bugbear.egg-info/PKG-INFO 
new/flake8-bugbear-23.7.10/flake8_bugbear.egg-info/PKG-INFO
--- old/flake8-bugbear-23.6.5/flake8_bugbear.egg-info/PKG-INFO  2023-06-05 
18:20:50.000000000 +0200
+++ new/flake8-bugbear-23.7.10/flake8_bugbear.egg-info/PKG-INFO 2023-07-10 
18:29:34.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: flake8-bugbear
-Version: 23.6.5
+Version: 23.7.10
 Summary: A plugin for flake8 finding likely bugs and design problems in your 
program. Contains warnings that don't belong in pyflakes and pycodestyle.
 Author-email: Łukasz Langa <luk...@langa.pl>
 License: MIT
@@ -19,6 +19,7 @@
 Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
 Classifier: Programming Language :: Python :: 3 :: Only
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
 Classifier: Topic :: Software Development :: Quality Assurance
@@ -217,6 +218,8 @@
 
 **B033**: Sets should not contain duplicate items. Duplicate items will be 
replaced with a single item at runtime.
 
+**B034**: Calls to `re.sub`, `re.subn` or `re.split` should pass `flags` or 
`count`/`maxsplit` as keyword arguments. It is commonly assumed that `flags` is 
the third positional parameter, forgetting about `count`/`maxsplit`, since many 
other `re` module functions are of the form `f(pattern, string, flags)`.
+
 Opinionated warnings
 ~~~~~~~~~~~~~~~~~~~~
 
@@ -249,8 +252,11 @@
 for details.
 
 **B905**: ``zip()`` without an explicit `strict=` parameter set. 
``strict=True`` causes the resulting iterator
-to raise a ``ValueError`` if the arguments are exhausted at differing lengths. 
The ``strict=`` argument
-was added in Python 3.10, so don't enable this flag for code that should work 
on <3.10.
+to raise a ``ValueError`` if the arguments are exhausted at differing lengths.
+
+Exclusions are `itertools.count 
<https://docs.python.org/3/library/itertools.html#itertools.count>`_, 
`itertools.cycle 
<https://docs.python.org/3/library/itertools.html#itertools.cycle>`_ and 
`itertools.repeat 
<https://docs.python.org/3/library/itertools.html#itertools.repeat>`_ (with 
times=None) since they are infinite iterators.
+
+The ``strict=`` argument was added in Python 3.10, so don't enable this flag 
for code that should work on <3.10.
 For more information: https://peps.python.org/pep-0618/
 
 **B906**: ``visit_`` function with no further call to a ``visit`` function. 
This is often an error, and will stop the visitor from recursing into the 
subnodes of a visited node. Consider adding a call ``self.generic_visit(node)`` 
at the end of the function.
@@ -358,6 +364,14 @@
 Change Log
 ----------
 
+23.7.10
+~~~~~~~~~~
+
+* Add B034: re.sub/subn/split must pass flags/count/maxsplit as keyword 
arguments.
+* Fix a crash and several test failures on Python 3.12, all relating to the 
B907
+  check.
+* Declare support for Python 3.12.
+
 23.6.5
 ~~~~~~
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/flake8-bugbear-23.6.5/flake8_bugbear.egg-info/SOURCES.txt 
new/flake8-bugbear-23.7.10/flake8_bugbear.egg-info/SOURCES.txt
--- old/flake8-bugbear-23.6.5/flake8_bugbear.egg-info/SOURCES.txt       
2023-06-05 18:20:50.000000000 +0200
+++ new/flake8-bugbear-23.7.10/flake8_bugbear.egg-info/SOURCES.txt      
2023-07-10 18:29:34.000000000 +0200
@@ -48,6 +48,7 @@
 tests/b031.py
 tests/b032.py
 tests/b033.py
+tests/b034.py
 tests/b901.py
 tests/b902.py
 tests/b902_py38.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8-bugbear-23.6.5/pyproject.toml 
new/flake8-bugbear-23.7.10/pyproject.toml
--- old/flake8-bugbear-23.6.5/pyproject.toml    2023-06-05 18:20:41.000000000 
+0200
+++ new/flake8-bugbear-23.7.10/pyproject.toml   2023-07-10 18:29:25.000000000 
+0200
@@ -30,6 +30,7 @@
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
+    "Programming Language :: Python :: 3.12",
     "Programming Language :: Python :: 3 :: Only",
     "Topic :: Software Development :: Libraries :: Python Modules",
     "Topic :: Software Development :: Quality Assurance",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8-bugbear-23.6.5/tests/b034.py 
new/flake8-bugbear-23.7.10/tests/b034.py
--- old/flake8-bugbear-23.6.5/tests/b034.py     1970-01-01 01:00:00.000000000 
+0100
+++ new/flake8-bugbear-23.7.10/tests/b034.py    2023-07-10 18:29:25.000000000 
+0200
@@ -0,0 +1,30 @@
+import re
+from re import sub
+
+# error
+re.sub("a", "b", "aaa", re.IGNORECASE)
+re.sub("a", "b", "aaa", 5)
+re.sub("a", "b", "aaa", 5, re.IGNORECASE)
+re.subn("a", "b", "aaa", re.IGNORECASE)
+re.subn("a", "b", "aaa", 5)
+re.subn("a", "b", "aaa", 5, re.IGNORECASE)
+re.split(" ", "a a a a", re.I)
+re.split(" ", "a a a a", 2)
+re.split(" ", "a a a a", 2, re.I)
+
+# okay
+re.sub("a", "b", "aaa")
+re.sub("a", "b", "aaa", flags=re.IGNORECASE)
+re.sub("a", "b", "aaa", count=5)
+re.sub("a", "b", "aaa", count=5, flags=re.IGNORECASE)
+re.subn("a", "b", "aaa")
+re.subn("a", "b", "aaa", flags=re.IGNORECASE)
+re.subn("a", "b", "aaa", count=5)
+re.subn("a", "b", "aaa", count=5, flags=re.IGNORECASE)
+re.split(" ", "a a a a", flags=re.I)
+re.split(" ", "a a a a", maxsplit=2)
+re.split(" ", "a a a a", maxsplit=2, flags=re.I)
+
+
+# not covered
+sub("a", "b", "aaa", re.IGNORECASE)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8-bugbear-23.6.5/tests/b905_py310.py 
new/flake8-bugbear-23.7.10/tests/b905_py310.py
--- old/flake8-bugbear-23.6.5/tests/b905_py310.py       2023-06-05 
18:20:41.000000000 +0200
+++ new/flake8-bugbear-23.7.10/tests/b905_py310.py      2023-07-10 
18:29:25.000000000 +0200
@@ -8,3 +8,15 @@
 zip(range(3), strict=True)
 zip("a", "b", strict=False)
 zip("a", "b", "c", strict=True)
+
+# infinite iterators from itertools module should not raise errors
+import itertools
+
+zip([1, 2, 3], itertools.cycle("ABCDEF"))
+zip([1, 2, 3], itertools.count())
+zip([1, 2, 3], itertools.repeat(1))
+zip([1, 2, 3], itertools.repeat(1, None))
+zip([1, 2, 3], itertools.repeat(1, times=None))
+
+zip([1, 2, 3], itertools.repeat(1, 1))
+zip([1, 2, 3], itertools.repeat(1, times=4))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8-bugbear-23.6.5/tests/b907.py 
new/flake8-bugbear-23.7.10/tests/b907.py
--- old/flake8-bugbear-23.6.5/tests/b907.py     2023-06-05 18:20:41.000000000 
+0200
+++ new/flake8-bugbear-23.7.10/tests/b907.py    2023-07-10 18:29:25.000000000 
+0200
@@ -17,12 +17,12 @@
 f'a "{foo()}" b'
 
 # fmt: off
-k = (f'"' # error emitted on this line since all values are assigned the same 
lineno
+k = (f'"' # Error emitted here on <py312 (all values assigned the same lineno)
      f'{var}'
      f'"'
      f'"')
 
-k = (f'"' # error emitted on this line
+k = (f'"' # error emitted on this line on <py312
      f'{var}'
      '"'
      f'"')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8-bugbear-23.6.5/tests/test_bugbear.py 
new/flake8-bugbear-23.7.10/tests/test_bugbear.py
--- old/flake8-bugbear-23.6.5/tests/test_bugbear.py     2023-06-05 
18:20:41.000000000 +0200
+++ new/flake8-bugbear-23.7.10/tests/test_bugbear.py    2023-07-10 
18:29:25.000000000 +0200
@@ -8,9 +8,6 @@
 from argparse import Namespace
 from pathlib import Path
 
-from hypothesis import HealthCheck, given, settings
-from hypothesmith import from_grammar
-
 from bugbear import (
     B001,
     B002,
@@ -45,6 +42,7 @@
     B031,
     B032,
     B033,
+    B034,
     B901,
     B902,
     B903,
@@ -505,6 +503,23 @@
         )
         self.assertEqual(errors, expected)
 
+    def test_b034(self):
+        filename = Path(__file__).absolute().parent / "b034.py"
+        bbc = BugBearChecker(filename=str(filename))
+        errors = list(bbc.run())
+        expected = self.errors(
+            B034(5, 24, vars=("sub", "count")),
+            B034(6, 24, vars=("sub", "count")),
+            B034(7, 24, vars=("sub", "count")),
+            B034(8, 25, vars=("subn", "count")),
+            B034(9, 25, vars=("subn", "count")),
+            B034(10, 25, vars=("subn", "count")),
+            B034(11, 25, vars=("split", "maxsplit")),
+            B034(12, 25, vars=("split", "maxsplit")),
+            B034(13, 25, vars=("split", "maxsplit")),
+        )
+        self.assertEqual(errors, expected)
+
     def test_b908(self):
         filename = Path(__file__).absolute().parent / "b908.py"
         bbc = BugBearChecker(filename=str(filename))
@@ -524,43 +539,51 @@
         filename = Path(__file__).absolute().parent / "b907.py"
         bbc = BugBearChecker(filename=str(filename))
         errors = list(bbc.run())
-        expected = self.errors(
-            B907(8, 0, vars=("var",)),
-            B907(9, 0, vars=("var",)),
-            B907(10, 0, vars=("var",)),
-            B907(12, 0, vars=("var",)),
-            B907(13, 0, vars=("var",)),
-            B907(14, 0, vars=("var",)),
-            B907(16, 0, vars=("'hello'",)),
-            B907(17, 0, vars=("foo()",)),
-            B907(20, 5, vars=("var",)),
-            B907(25, 5, vars=("var",)),
-            B907(31, 0, vars=("var",)),
-            B907(32, 0, vars=("var",)),
-            B907(33, 0, vars=("var",)),
-            B907(33, 0, vars=("var2",)),
-            B907(34, 0, vars=("var",)),
-            B907(34, 0, vars=("var2",)),
-            B907(35, 0, vars=("var",)),
-            B907(35, 0, vars=("var2",)),
-            B907(38, 0, vars=("var2",)),
-            B907(41, 0, vars=("var",)),
-            B907(42, 0, vars=("var.__str__",)),
-            B907(43, 0, vars=("var.__str__.__repr__",)),
-            B907(44, 0, vars=("3 + 5" if sys.version_info >= (3, 9) else 
"BinOp",)),
-            B907(45, 0, vars=("foo()",)),
-            B907(46, 0, vars=("None",)),
-            B907(47, 0, vars=("..." if sys.version_info >= (3, 9) else 
"Ellipsis",)),
-            B907(48, 0, vars=("True",)),
-            B907(51, 0, vars=("var",)),
-            B907(52, 0, vars=("var",)),
-            B907(53, 0, vars=("var",)),
-            B907(54, 0, vars=("var",)),
-            B907(57, 0, vars=("var",)),
-            B907(60, 0, vars=("var",)),
-            B907(64, 0, vars=("var",)),
-            B907(66, 0, vars=("var",)),
-            B907(68, 0, vars=("var",)),
+        py39 = sys.version_info >= (3, 9)
+        py312 = sys.version_info >= (3, 12)
+
+        def on_py312(number):
+            """F-string nodes have column numbers set to 0 on <py312"""
+            return number if py312 else 0
+
+        expected = self.errors(
+            B907(8, on_py312(9), vars=("var",)),
+            B907(9, on_py312(3), vars=("var",)),
+            B907(10, on_py312(9), vars=("var",)),
+            B907(12, on_py312(9), vars=("var",)),
+            B907(13, on_py312(3), vars=("var",)),
+            B907(14, on_py312(9), vars=("var",)),
+            B907(16, on_py312(5), vars=("'hello'",)),
+            B907(17, on_py312(5), vars=("foo()",)),
+            # Multiline f-strings have lineno changes as well as colno changes 
on py312+
+            B907(21 if py312 else 20, 7 if py312 else 5, vars=("var",)),
+            B907(26 if py312 else 25, 7 if py312 else 5, vars=("var",)),
+            B907(31, on_py312(12), vars=("var",)),
+            B907(32, on_py312(3), vars=("var",)),
+            B907(33, on_py312(3), vars=("var",)),
+            B907(33, on_py312(29), vars=("var2",)),
+            B907(34, on_py312(3), vars=("var",)),
+            B907(34, on_py312(15), vars=("var2",)),
+            B907(35, on_py312(3), vars=("var",)),
+            B907(35, on_py312(10), vars=("var2",)),
+            B907(38, on_py312(13), vars=("var2",)),
+            B907(41, on_py312(3), vars=("var",)),
+            B907(42, on_py312(3), vars=("var.__str__",)),
+            B907(43, on_py312(3), vars=("var.__str__.__repr__",)),
+            B907(44, on_py312(3), vars=("3 + 5" if py39 else "BinOp",)),
+            B907(45, on_py312(3), vars=("foo()",)),
+            B907(46, on_py312(3), vars=("None",)),
+            B907(47, on_py312(3), vars=("..." if py39 else "Ellipsis",)),
+            B907(48, on_py312(3), vars=("True",)),
+            B907(51, on_py312(3), vars=("var",)),
+            B907(52, on_py312(3), vars=("var",)),
+            B907(53, on_py312(3), vars=("var",)),
+            B907(54, on_py312(3), vars=("var",)),
+            B907(57, on_py312(3), vars=("var",)),
+            B907(60, on_py312(3), vars=("var",)),
+            B907(64, on_py312(5), vars=("var",)),
+            B907(66, on_py312(3), vars=("var",)),
+            B907(68, on_py312(3), vars=("var",)),
         )
         self.assertEqual(errors, expected)
 
@@ -695,6 +718,8 @@
             B905(4, 15),
             B905(5, 4),
             B905(6, 0),
+            B905(21, 0),
+            B905(22, 0),
         ]
         self.assertEqual(errors, self.errors(*expected))
 
@@ -795,13 +820,18 @@
 
 
 class TestFuzz(unittest.TestCase):
-    @settings(suppress_health_check=[HealthCheck.too_slow])
-    @given(from_grammar().map(ast.parse))
-    def test_does_not_crash_on_any_valid_code(self, syntax_tree):
-        # Given any syntatically-valid source code, flake8-bugbear should
-        # not crash.  This tests doesn't check that we do the *right* thing,
-        # just that we don't crash on valid-if-poorly-styled code!
-        BugBearVisitor(filename="<string>", lines=[]).visit(syntax_tree)
+    # TODO: enable this test on py312 once hypothesmith supports py312
+    if sys.version_info < (3, 12):
+        from hypothesis import HealthCheck, given, settings
+        from hypothesmith import from_grammar
+
+        @settings(suppress_health_check=[HealthCheck.too_slow])
+        @given(from_grammar().map(ast.parse))
+        def test_does_not_crash_on_any_valid_code(self, syntax_tree):
+            # Given any syntatically-valid source code, flake8-bugbear should
+            # not crash.  This tests doesn't check that we do the *right* 
thing,
+            # just that we don't crash on valid-if-poorly-styled code!
+            BugBearVisitor(filename="<string>", lines=[]).visit(syntax_tree)
 
     def test_does_not_crash_on_site_code(self):
         # Because the generator isn't perfect, we'll also test on all the code
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8-bugbear-23.6.5/tox.ini 
new/flake8-bugbear-23.7.10/tox.ini
--- old/flake8-bugbear-23.6.5/tox.ini   2023-06-05 18:20:41.000000000 +0200
+++ new/flake8-bugbear-23.7.10/tox.ini  2023-07-10 18:29:25.000000000 +0200
@@ -1,7 +1,7 @@
 # The test environment and commands
 [tox]
 # default environments to run without `-e`
-envlist = py38, py39, py310, py311
+envlist = py38, py39, py310, py311, py312
 
 [gh-actions]
 python =
@@ -9,8 +9,9 @@
     3.9: py39
     3.10: py310
     3.11: py311
+    3.12: py312
 
-[testenv:{py38, py39, py310, py311}]
+[testenv]
 description = Run coverage
 deps =
     coverage
@@ -19,3 +20,8 @@
 commands =
     coverage run tests/test_bugbear.py {posargs}
     coverage report -m
+
+[testenv:py312]
+deps =
+    # the other dependencies aren't yet installable on py312+
+    coverage

Reply via email to