gh-92203: Add closure support to exec(). by larryhastings · Pull Request #92204 · python/cpython (original) (raw)
GitHub isn't letting me reply to your comments individually, so I'll post one big comment here.
Why not add this feature in eval() too?
I don't know how to create a code object which represents an expression that has a free variable, except by manually assembling bytecode. We have a use case for using a closure with exec
, we don't have a use case for using a closure with eval
.
What if change it to "closure should be None or a tuple of cells of exactly length %zd"?
This specific exception is thrown when the code object has free variables, but the user supplied a closure
that didn't match exactly. The message I'm trying to convey is "this specific code object can only be executed with a closure of length N". Making the error message more generic seems unhelpful.
I've changed the formatter to %zd
.
PyFunction_SetClosure() accepts subclasses of tuple.
TARGET(COPY_FREE_VARS)
in ceval.c
uses PyTuple_GET_ITEM
to access the cell vars in the closure object. My understanding was that the ALL_CAPS APIs for PyTuple (et al) required that exact type.
PyFunction_SetClosure() does not check the length of the tuple or the type of items, so perhaps it is not necessary here too, if the following code raises an exception of appropriate type.
PyFunction_SetClosure()
is called only from C code, which we don't have to worry about being malicious. (If you're running a malicious C extension, you have worse problems than someone passing in a malformed closure object.)
But here we're permitting user code (Python code) to pass in an object used as a closure. I though it safest to ensure the object is correct before passing it in to Python's tender internals.