Skip to content

Allow for flake8-bugbear behavior for B008, trigger on any function call even if immutable #18386

Open
@blackary

Description

@blackary

Summary

Ruff's handling of B008 is different from the flake8-bugbear behavior, in that it only catches cases where the default argument is a function AND the type is not annotated as something immutable.

On the other hand, flake8-bugbear catches any function that is called as a default argument, which catches more potential problematic code.

Here's a silly example:

import random

def get_random_number(num: int = random.randint(1, 100)) -> int:
    return num

Ruff's behavior

uvx ruff check --select B008 foo.py
All checks passed!

Flake8-bugbear's behavior

uvx --with flake8-bugbear flake8 --select B008 foo.py
foo.py:3:34: B008 Do not perform function calls in argument defaults.  The call is performed only once at function definition time. All calls to your function will reuse the result of that definition-time function call.  If this is intended, assign the function call to a module-level variable and use that variable as a default value.

While I understand that keeping the default behavior as-is might be preferable in many cases, there are also many cases where the return value of a function is not static, even if the return type is, and this can cause unintended issues. Here's a recent example that came up in one of the codebases I help maintain.

 def log_message(message: str, username: str = get_current_username()):
	...

In this case, there is a bug in this code when different users use this code running on the same server. Flake8-bugbear's default behavior would flag this, but ruff's implementation does not because the annotated type is str.

I'm not sure the best way to name such an option, but I would like to suggest adding a setting like

[tool.ruff.lint.flake8-bugbear]
# Don't allow any function calls in default arguments, even if they return immutable types
dont-allow-any-function-defaults = true

Metadata

Metadata

Assignees

No one assigned

    Labels

    configurationRelated to settings and configuration

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions