From 77845e2f7ddadf123084bf99dff9cbff341fbcf9 Mon Sep 17 00:00:00 2001 From: LuisFigueroaG Date: Sat, 24 Oct 2026 21:27:28 -0300 Subject: [PATCH] B042: don't treat a class whose only base is object as an exception A class named like an exception was checked as one as long as it had any base, so old-style classes such as `class ParsedException(object)` were reported even though they can't be raised. `object` no longer counts as that base, the same way parameterized generics don't. Refs #538 --- README.rst | 2 ++ bugbear.py | 10 ++++++++-- tests/eval_files/b042.py | 6 ++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 8c8c725..da27510 100644 --- a/README.rst +++ b/README.rst @@ -613,6 +613,8 @@ UNRELEASED ``map(print, items)`` on its own line never calls ``print`` (#452) * B909: also check mutations in ``if`` conditions and ``elif``/``else`` branches inside loops (#606) +* B042: don't treat a class named like an exception as one when its only base is + ``object``, as in ``class ParsedException(object)`` (#538) 26.9.30 ~~~~~~~ diff --git a/bugbear.py b/bugbear.py index 5b65b23..2afce72 100644 --- a/bugbear.py +++ b/bugbear.py @@ -3011,8 +3011,14 @@ def is_exception(s: str): # A class must inherit from a super class to be an exception, and we also # require the class name or any of the base names to look like an exception name. # A parameterized generic base such as `ContextManager[T]` does not count as - # that super class unless its own name looks like an exception name. - concrete_bases = [b for b in node.bases if not isinstance(b, ast.Subscript)] + # that super class unless its own name looks like an exception name, and + # neither does `object`, as in `class ParsedException(object)`. + concrete_bases = [ + b + for b in node.bases + if not isinstance(b, ast.Subscript) + and not (isinstance(b, ast.Name) and b.id == "object") + ] if not (is_exception(node.name) and concrete_bases): for base in node.bases: if isinstance(base, ast.Subscript): diff --git a/tests/eval_files/b042.py b/tests/eval_files/b042.py index bfd26d4..39eef13 100644 --- a/tests/eval_files/b042.py +++ b/tests/eval_files/b042.py @@ -96,6 +96,12 @@ def __init__(self, x): ... # safe class FooException: # safe, doesn't inherit from anything def __init__(self, x): ... +# `object` is not an exception base either +class ParsedException(object): # safe + def __init__(self, x): ... +class ObjectError(Anything, object): + def __init__(self, x): ... # B042: 4 + # a parameterized generic base is not an exception class unless its name says so class FailOnException(typing.ContextManager[int]): # safe def __init__(self, x): ...