import argparse
import ast
import sys
from _typeshed import Incomplete
from collections.abc import Generator, Iterable, Sequence
from functools import partial
from logging import Logger
from typing import Any, ClassVar, Final, Literal, NamedTuple, Protocol, overload

__version__: Final[str]
LOG: Logger
CONTEXTFUL_NODES: Final[tuple[type[ast.AST], ...]]
FUNCTION_NODES: Final[tuple[type[ast.AST], ...]]
B908_pytest_functions: Final[set[str]]
B908_unittest_methods: Final[set[str]]
B902_default_decorators: Final[set[str]]

class Context(NamedTuple):
    node: ast.AST
    stack: list[str]

class BugBearChecker:
    name: ClassVar[str]
    version: ClassVar[str]
    tree: ast.AST | None
    filename: str
    lines: Sequence[str] | None
    max_line_length: int
    visitor: ast.NodeVisitor
    options: argparse.Namespace | None
    def run(self) -> Iterable[tuple[int, int, str, type[BugBearChecker]]]: ...
    def gen_line_based_checks(self) -> Generator[error]: ...
    @classmethod
    def adapt_error(cls, e: error) -> tuple[int, int, str, type[BugBearChecker]]: ...
    def load_file(self) -> None: ...
    @staticmethod
    def add_options(optmanager: Any) -> None: ...
    def __init__(
        self,
        tree: ast.AST | None = ...,
        filename: str = ...,
        lines: Sequence[str] | None = ...,
        max_line_length: int = ...,
        options: argparse.Namespace | None = ...,
    ) -> None: ...
    def should_warn(self, code: str) -> bool: ...

def names_from_assignments(assign_target: ast.AST) -> Generator[str]: ...
def children_in_scope(node: ast.AST) -> Generator[ast.AST]: ...
def walk_list(nodes: Iterable[ast.AST]) -> Generator[ast.AST]: ...

class ExceptBaseExceptionVisitor(ast.NodeVisitor):
    root: ast.ExceptHandler
    def __init__(self, except_node: ast.ExceptHandler) -> None: ...
    def re_raised(self) -> bool: ...
    def visit_Raise(self, node: ast.Raise) -> Incomplete | None: ...
    def visit_ExceptHandler(self, node: ast.ExceptHandler) -> Incomplete | None: ...

class B040CaughtException:
    name: str
    has_note: bool
    def __init__(self, name: str, has_note: bool) -> None: ...

class B041UnhandledKeyType: ...

class B041VariableKeyType:
    name: str
    def __init__(self, name: str) -> None: ...

class AstPositionNode(Protocol):
    lineno: int
    col_offset: int

class BugBearVisitor(ast.NodeVisitor):
    filename: str
    lines: Sequence[str] | None
    b008_b039_extend_immutable_calls: set[str]
    b902_classmethod_decorators: set[str]
    node_window: list[ast.AST]
    errors: list[error]
    contexts: list[Context]
    b040_caught_exception: B040CaughtException | None
    NODE_WINDOW_SIZE: ClassVar[int] = 4
    in_trystar: str
    def __init__(
        self,
        filename: str,
        lines: Sequence[str] | None,
        b008_b039_extend_immutable_calls: set[str] = ...,
        b902_classmethod_decorators: set[str] = ...,
        node_window: list[ast.AST] = ...,
        errors: list[error] = ...,
        contexts: list[Context] = ...,
        b040_caught_exception: B040CaughtException | None = None,
        in_trystar: str = "",
    ) -> None: ...
    def add_error(self, code: str, node: AstPositionNode, *vars: object) -> None: ...
    @property
    def node_stack(self) -> list[Context]: ...
    def in_class_init(self) -> bool: ...
    def visit_Return(self, node: ast.Return) -> None: ...
    def visit_Yield(self, node: ast.Yield) -> None: ...
    def visit_YieldFrom(self, node: ast.YieldFrom) -> None: ...
    def visit(self, node: ast.AST) -> None: ...
    def visit_ExceptHandler(self, node: ast.ExceptHandler) -> None: ...
    def visit_UAdd(self, node: ast.UAdd) -> None: ...
    def visit_Call(self, node: ast.Call) -> None: ...
    def visit_Module(self, node: ast.Module) -> None: ...
    def visit_Assign(self, node: ast.Assign) -> None: ...
    def visit_For(self, node: ast.For) -> None: ...
    def visit_AsyncFor(self, node: ast.AsyncFor) -> None: ...
    def visit_While(self, node: ast.While) -> None: ...
    def visit_ListComp(self, node: ast.ListComp) -> None: ...
    def visit_SetComp(self, node: ast.SetComp) -> None: ...
    def visit_DictComp(self, node: ast.DictComp) -> None: ...
    def visit_GeneratorExp(self, node: ast.GeneratorExp) -> None: ...
    def visit_Assert(self, node: ast.Assert) -> None: ...
    def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None: ...
    def visit_FunctionDef(self, node: ast.FunctionDef) -> None: ...
    def visit_ClassDef(self, node: ast.ClassDef) -> None: ...
    def visit_Try(self, node: ast.Try) -> None: ...
    if sys.version_info >= (3, 11):
        def visit_TryStar(self, node: ast.TryStar) -> None: ...
    else:
        def visit_TryStar(self, node: ast.Try) -> None: ...

    def visit_Compare(self, node: ast.Compare) -> None: ...
    def visit_Raise(self, node: ast.Raise) -> None: ...
    def visit_With(self, node: ast.With) -> None: ...
    def visit_JoinedStr(self, node: ast.JoinedStr) -> None: ...
    def visit_AnnAssign(self, node: ast.AnnAssign) -> None: ...
    def visit_Import(self, node: ast.Import) -> None: ...
    def visit_ImportFrom(self, node: ast.ImportFrom) -> None: ...
    def visit_Set(self, node: ast.Set) -> None: ...
    def visit_Dict(self, node: ast.Dict) -> None: ...
    def check_for_b041(self, node: ast.Dict) -> None: ...
    def check_for_b005(self, node: ast.Import | ast.ImportFrom | ast.Call) -> None: ...
    def check_for_b006_and_b008(self, node: ast.FunctionDef | ast.AsyncFunctionDef) -> None: ...
    def check_for_b039(self, node: ast.Call) -> None: ...
    def check_for_b007(self, node: ast.For | ast.AsyncFor) -> None: ...
    def check_for_b011(self, node: ast.Assert) -> None: ...
    if sys.version_info >= (3, 11):
        def check_for_b012(self, node: ast.Try | ast.TryStar) -> None: ...
    else:
        def check_for_b012(self, node: ast.Try) -> None: ...

    def check_for_b013_b014_b029_b030(self, node: ast.ExceptHandler) -> list[str]: ...
    def check_for_b015(self, node: ast.Compare) -> None: ...
    def check_for_b016(self, node: ast.Raise) -> None: ...
    def check_for_b017(self, node: ast.With | ast.AsyncWith) -> None: ...
    def check_for_b019(self, node: ast.FunctionDef | ast.AsyncFunctionDef) -> None: ...
    def check_for_b020(self, node: ast.For | ast.AsyncFor | ast.comprehension) -> None: ...
    def check_for_b023(
        self, loop_node: ast.For | ast.AsyncFor | ast.While | ast.GeneratorExp | ast.SetComp | ast.ListComp | ast.DictComp
    ) -> None: ...
    def check_for_b024_and_b027(self, node: ast.ClassDef) -> None: ...
    def check_for_b026(self, call: ast.Call) -> None: ...
    def check_for_b031(self, loop_node: ast.For | ast.AsyncFor) -> None: ...
    def check_for_b035(self, node: ast.DictComp) -> None: ...
    def check_for_b040_add_note(self, node: ast.Attribute) -> bool: ...
    def check_for_b040_usage(self, node: ast.expr | None) -> None: ...
    def check_for_b904(self, node: ast.Raise) -> None: ...
    def walk_function_body(
        self, node: ast.FunctionDef | ast.AsyncFunctionDef
    ) -> tuple[ast.FunctionDef | ast.AsyncFunctionDef, ast.stmt]: ...
    def check_for_b901(self, node: ast.FunctionDef | ast.AsyncFunctionDef) -> None: ...

    @overload
    @classmethod
    def find_decorator_name(cls, d: ast.Name | ast.Attribute | ast.Call) -> str: ...
    @overload
    @classmethod
    def find_decorator_name(cls, d: ast.AST) -> str | None: ...

    def check_for_b902(self, node: ast.FunctionDef | ast.AsyncFunctionDef) -> None: ...
    def check_for_b903(self, node: ast.ClassDef) -> None: ...
    def check_for_b018(self, node: ast.Expr) -> None: ...
    def check_for_b021(self, node: ast.AsyncFunctionDef | ast.FunctionDef | ast.ClassDef | ast.Module) -> None: ...
    def check_for_b022(self, node: ast.With | ast.AsyncWith) -> None: ...
    def check_for_b908(self, node: ast.With) -> None: ...
    def check_for_b025(self, node: ast.Try) -> None: ...
    def check_for_b905(self, node: ast.Call) -> None: ...
    def check_for_b912(self, node: ast.Call) -> None: ...
    def check_for_b906(self, node: ast.FunctionDef) -> None: ...
    def check_for_b907(self, node: ast.JoinedStr) -> None: ...
    def check_for_b028(self, node: ast.Call) -> None: ...
    def check_for_b032(self, node: ast.AnnAssign) -> None: ...
    def check_for_b033(self, node: ast.Set | ast.List | ast.Tuple) -> None: ...
    def check_for_b034(self, node: ast.Call) -> None: ...
    def check_for_b042(self, node: ast.ClassDef) -> None: ...
    def check_for_b909(self, node: ast.For) -> None: ...
    def check_for_b910(self, node: ast.Call) -> None: ...
    def check_for_b911(self, node: ast.Call) -> None: ...

def compose_call_path(node: ast.expr) -> Generator[str]: ...
def is_name(node: ast.expr, name: str) -> bool: ...

class B909Checker(ast.NodeVisitor):
    MUTATING_FUNCTIONS: ClassVar[tuple[str, ...]]
    name: str
    key: str
    mutations: dict[int, list[ast.Assign | ast.AugAssign | ast.Delete | ast.Call]]
    def __init__(self, name: str, key: str) -> None: ...
    def visit_Assign(self, node: ast.Assign) -> None: ...
    def visit_AugAssign(self, node: ast.AugAssign) -> None: ...
    def visit_Delete(self, node: ast.Delete) -> None: ...
    def visit_Call(self, node: ast.Call) -> None: ...
    def visit_If(self, node: ast.If) -> None: ...
    def visit(self, node: ast.AST | list[ast.AST]) -> Any: ...

class NameFinder(ast.NodeVisitor):
    names: dict[str, list[ast.Name]]
    def __init__(self, names: dict[str, list[ast.Name]] = ...) -> None: ...
    def visit_Name(self, node: ast.Name) -> None: ...
    def visit(self, node: ast.AST | list[ast.AST]) -> Any: ...

class NamedExprFinder(ast.NodeVisitor):
    names: dict[str, list[ast.Name]]
    def __init__(self, names: dict[str, list[ast.Name]] = ...) -> None: ...
    def visit_NamedExpr(self, node: ast.NamedExpr) -> None: ...
    def visit(self, node: ast.AST | list[ast.AST]) -> Any: ...

class FunctionDefDefaultsVisitor(ast.NodeVisitor):
    def __init__(
        self,
        error_code_calls: partial[error],
        error_code_literals: partial[error],
        b008_b039_extend_immutable_calls: set[str] | None = None,
    ) -> None: ...
    def visit_mutable_literal_or_comprehension(
        self, node: ast.List | ast.Dict | ast.Set | ast.ListComp | ast.DictComp | ast.SetComp
    ) -> None: ...
    def visit_Call(self, node: ast.Call) -> None: ...
    def visit_Lambda(self, node: ast.Lambda) -> None: ...
    def visit(self, node: ast.AST | list[ast.AST]) -> None: ...

class B020NameFinder(NameFinder):
    def visit_GeneratorExp(self, node: ast.GeneratorExp) -> None: ...
    def visit_ListComp(self, node: ast.ListComp) -> None: ...
    def visit_DictComp(self, node: ast.DictComp) -> None: ...
    def visit_comprehension(self, node: ast.comprehension) -> None: ...
    def visit_Lambda(self, node: ast.Lambda) -> None: ...

B005_METHODS: Final[set[str]]
B006_MUTABLE_LITERALS: Final[tuple[Literal["Dict"], Literal["List"], Literal["Set"]]]
B006_MUTABLE_COMPREHENSIONS: Final[tuple[Literal["ListComp"], Literal["DictComp"], Literal["SetComp"]]]
B006_MUTABLE_CALLS: Final[set[str]]
B008_IMMUTABLE_CALLS: Final[set[str]]
B014_REDUNDANT_EXCEPTIONS: Final[dict[Literal["OSError", "ValueError"], set[str]]]
B019_CACHES: Final[set[str]]
B902_IMPLICIT_CLASSMETHODS: Final[set[str]]
B902_SELF: Final[list[str]]
B902_CLS: Final[list[str]]
B902_METACLS: Final[list[str]]

class error(NamedTuple):
    lineno: int
    col: int
    message: str
    type: type[BugBearChecker]
    # Arguments for formatting the message, i.e. message.format(*vars).
    vars: tuple[object, ...]

class Error:
    message: str
    def __init__(self, message: str) -> None: ...
    def __call__(self, lineno: int, col: int, vars: tuple[object, ...] = ()) -> error: ...

error_codes: Final[dict[str, Error]]
disabled_by_default: Final[list[str]]
