Skip to content

boolean-type-hint-positional-argument (FBT001)

Derived from the flake8-boolean-trap linter.

What it does

Checks for the use of boolean positional arguments in function definitions, as determined by the presence of a bool type hint.

Why is this bad?

Calling a function with boolean positional arguments is confusing as the meaning of the boolean value is not clear to the caller and to future readers of the code.

The use of a boolean will also limit the function to only two possible behaviors, which makes the function difficult to extend in the future.

Instead, consider refactoring into separate implementations for the True and False cases, using an Enum, or making the argument a keyword-only argument, to force callers to be explicit when providing the argument.

Dunder methods that define operators are exempt from this rule, as are setters and @override definitions.

In preview, this rule will also flag annotations that include boolean variants, like bool | int.

Example

from math import ceil, floor


def round_number(number: float, up: bool) -> int:
    return ceil(number) if up else floor(number)


round_number(1.5, True)  # What does `True` mean?
round_number(1.5, False)  # What does `False` mean?

Instead, refactor into separate implementations:

from math import ceil, floor


def round_up(number: float) -> int:
    return ceil(number)


def round_down(number: float) -> int:
    return floor(number)


round_up(1.5)
round_down(1.5)

Or, refactor to use an Enum:

from enum import Enum


class RoundingMethod(Enum):
    UP = 1
    DOWN = 2


def round_number(value: float, method: RoundingMethod) -> float: ...

Or, make the argument a keyword-only argument:

from math import ceil, floor


def round_number(number: float, *, up: bool) -> int:
    return ceil(number) if up else floor(number)


round_number(1.5, up=True)
round_number(1.5, up=False)

References