From 113f9fa9467247dd0d968168ac617f8d98032998 Mon Sep 17 00:00:00 2001 From: David Hotham Date: Wed, 31 Aug 2022 20:08:58 +0100 Subject: [PATCH] fix: late binding closure in ApplicationPlugin 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. --- src/poetry/plugins/application_plugin.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/poetry/plugins/application_plugin.py b/src/poetry/plugins/application_plugin.py index 4dbdb92e5ac..7d9702e694d 100644 --- a/src/poetry/plugins/application_plugin.py +++ b/src/poetry/plugins/application_plugin.py @@ -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)