From 72b5a55bc80676d57e492520d39aaf3fb6f186df Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Mon, 3 Oct 2022 17:30:04 -0700 Subject: 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 --- Lib/dataclasses.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 05d62b6..efd8346 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 = {} -- cgit v0.12