From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Tue, 4 Oct 2022 00:30:04 +0000 (-0700) Subject: Add comment to subtle dataclass code (gh-96133) X-Git-Tag: v3.12.0a1~287 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=72b5a55bc80676d57e492520d39aaf3fb6f186df;p=thirdparty%2FPython%2Fcpython.git Add comment to subtle dataclass code (gh-96133) In the PR that made this change, 1st1 left a "note to self: add a comment explaining this". This comment was never added. https://github.com/python/cpython/pull/9518/files#r280608117 I was reading this code and it wasn't obvious to me why we weren't exec-ing directly into locals. So I got to learn something new :-) https://docs.python.org/3/reference/executionmodel.html#interaction-with-dynamic-features --- diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 05d62b625760..efd83467bfa9 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -429,6 +429,10 @@ def _create_fn(name, args, body, *, globals=None, locals=None, # Compute the text of the entire function. txt = f' def {name}({args}){return_annotation}:\n{body}' + # Free variables in exec are resolved in the global namespace. + # The global namespace we have is user-provided, so we can't modify it for + # our purposes. So we put the things we need into locals and introduce a + # scope to allow the function we're creating to close over them. local_vars = ', '.join(locals.keys()) txt = f"def __create_fn__({local_vars}):\n{txt}\n return {name}" ns = {}