Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not perform function call in argument defaults #74

Conversation

cclauss
Copy link
Contributor

@cclauss cclauss commented May 16, 2024

Any function call that's used in a default argument will only be performed once, at definition time.
The returned value will then be reused by all calls to the function, which can lead to unexpected behavior.

% ruff check --select=B008

puremagic/main.py:68:41: B008 Do not perform function call `os.path.join` in argument defaults;
    instead, perform the call within the function, or read the default from a module-level singleton
    variable
Found 1 error.

% ruff rule B008

function-call-in-default-argument (B008)

Derived from the flake8-bugbear linter.

What it does

Checks for function calls in default function arguments.

Why is this bad?

Any function call that's used in a default argument will only be performed
once, at definition time. The returned value will then be reused by all
calls to the function, which can lead to unexpected behaviour.

Calls can be marked as an exception to this rule with the
[lint.flake8-bugbear.extend-immutable-calls] configuration option.

Arguments with immutable type annotations will be ignored by this rule.
Types outside of the standard library can be marked as immutable with the
[lint.flake8-bugbear.extend-immutable-calls] configuration option as well.

Example

def create_list() -> list[int]:
    return [1, 2, 3]


def mutable_default(arg: list[int] = create_list()) -> list[int]:
    arg.append(4)
    return arg

Use instead:

def better(arg: list[int] | None = None) -> list[int]:
    if arg is None:
        arg = create_list()

    arg.append(4)
    return arg

If the use of a singleton is intentional, assign the result call to a
module-level variable, and use that variable in the default argument:

ERROR = ValueError("Hosts weren't successfully added")


def add_host(error: Exception = ERROR) -> None:
    ...

Options

  • lint.flake8-bugbear.extend-immutable-calls

@cdgriffith
Copy link
Owner

I do only want that call to happen once at startup and stay as the default that way, this is intended behavior. May need to be re-written to just have that as a pre-defined global and use it in the function args that way

@cclauss cclauss force-pushed the do-not-perform-function-call-in-argument-defaults branch from c3cd333 to 8cd7225 Compare May 18, 2024 04:33
@cclauss cclauss changed the base branch from master to develop May 18, 2024 05:00
@cclauss cclauss force-pushed the do-not-perform-function-call-in-argument-defaults branch 3 times, most recently from 1752f66 to 8d5a5e2 Compare May 22, 2024 12:22
@cclauss cclauss force-pushed the do-not-perform-function-call-in-argument-defaults branch from 8d5a5e2 to 7bd9f40 Compare May 28, 2024 09:41
@cclauss cclauss force-pushed the do-not-perform-function-call-in-argument-defaults branch from 7bd9f40 to bc61d9a Compare May 28, 2024 09:43
@cdgriffith cdgriffith deleted the branch cdgriffith:develop June 16, 2024 23:46
@cdgriffith cdgriffith closed this Jun 16, 2024
@cclauss cclauss deleted the do-not-perform-function-call-in-argument-defaults branch June 16, 2024 23:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants