summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShantanu <12621235+hauntsaninja@users.noreply.github.com>2022-10-04 00:30:04 (GMT)
committerGitHub <noreply@github.com>2022-10-04 00:30:04 (GMT)
commit72b5a55bc80676d57e492520d39aaf3fb6f186df (patch)
treec95d12a8cd8b5883bcfedb6e14c9999303bb98cd
parent9e8b86de4e7a65b6fc6389caf4fa506ebcf538f6 (diff)
downloadcpython-72b5a55bc80676d57e492520d39aaf3fb6f186df.zip
cpython-72b5a55bc80676d57e492520d39aaf3fb6f186df.tar.gz
cpython-72b5a55bc80676d57e492520d39aaf3fb6f186df.tar.bz2
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
-rw-r--r--Lib/dataclasses.py4
1 files changed, 4 insertions, 0 deletions
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 = {}