Skip to content

Commit

Permalink
fix: late binding closure in ApplicationPlugin
Browse files Browse the repository at this point in the history
B023:  Functions defined inside a loop must not use variables redefined in the loop, because late-binding closures are a classic gotcha.

Here's some sample code approximating the poetry code:
```python
#!/usr/bin/env python3


def one() -> int:
    return 1


def two() -> int:
    return 2


def three() -> int:
    return 3


factories = [one, two, three]

registered = []
for factory in factories:
    registered.append(lambda: factory())

for registered_factory in registered:
    print(f"result is {registered_factory()}")
```
output is
```
result is 3
result is 3
result is 3
```
which is exactly the gotcha that flake8-bugbear's B023 was trying to warn about.

I've applied one of the workarounds that various parts of the internet recommend, and you can verify for yourself if you're so inclined that doing the same in the toy script gives the expected output.
  • Loading branch information
dimbleby authored Aug 31, 2022
1 parent 0a5e4b5 commit 113f9fa
Showing 1 changed file with 1 addition and 3 deletions.
4 changes: 1 addition & 3 deletions src/poetry/plugins/application_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,4 @@ def commands(self) -> list[type[Command]]:
def activate(self, application: Application) -> None:
for command in self.commands:
assert command.name is not None
application.command_loader.register_factory(
command.name, lambda: command() # noqa: B023
)
application.command_loader.register_factory(command.name, command)

0 comments on commit 113f9fa

Please sign in to comment.