[Python-Dev] Adding a builtins parameter to eval(), exec() and import(). (original) (raw)
Mark Shannon mark at hotpy.org
Fri Mar 9 09:19:24 CET 2012
- Previous message: [Python-Dev] Adding a builtins parameter to eval(), exec() and __import__().
- Next message: [Python-Dev] Adding a builtins parameter to eval(), exec() and __import__().
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Guido van Rossum wrote:
On Thu, Mar 8, 2012 at 4:33 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:
On Fri, Mar 9, 2012 at 3:31 AM, Guido van Rossum <guido at python.org> wrote:
But the builtins that are actually used by any particular piece of code is not taken by importing builtins. It is taken from what the globals store under the key builtins.
This is a feature that was added specifically for sandboxing purposes, but I believe it has found other uses too. Agreed, but swapping out builtins for a different namespace is still the exception rather than the rule. My Impression of Mark's proposal was that this approach would become the preferred way of doing things, and that's the part I don't like at a conceptual level.
The key point is that every piece of code already inherits locals, globals and builtins from somewhere else. We can already control locals (by which parameters are passed in) and globals via exec, eval, import, and runpy (any others?) but we can't control builtins. Correct - because controlling builtins is the domain of sandboxes. Incorrect (unless I misunderstand the context) -- when you control the globals you control the builtins set there. And this is where I don't like the idea at a practical level. We already have a way to swap in a different set of builtins for a certain execution context (i.e. set "builtins" in the global namespace) for a small chunk of code, as well as allowing collections.ChainMap to insert additional namespaces into the name lookup path. This proposal suggests adding an additional mapping argument to every API that currently accepts a locals and/or globals mapping, thus achieving... well, nothing substantial, as far as I can tell (aside from a lot of pointless churn in a bunch of APIs, not all of which are under our direct control). In any case, the locals / globals / builtins chain is a simplification; there are also any number of intermediate scopes (between locals and globals) from which "nonlocal" variables may be used. Like optimized function globals, these don't use a dict lookup at all, they are determined by compile-time analysis. Acknowledged, but code executed via the exec API with both locals and globals passed in is actually one of the few places where that lookup chain survives in its original form (module level class definitions being the other). Now, rereading Mark's original message, a simpler proposal of having function objects do an early lookup of "self.globals['builtins']" at creation time and caching that somewhere such that the frame objects can get hold of it (rather than having to do the lookup every time the function gets called or a builtin gets referenced) might be a nice micro-optimisation. It's the gratuitous API changes that I'm objecting to, not the underlying idea of binding the reference to the builtins namespace earlier in the function definition process. I'd even be OK with leaving the default builtins reference out of the globals namespace in favour of storing a hidden reference on the frame objects. Agreed on the gratuitous API changes. I'd like to hear Mark's response. C API or Python API?
The Python API would be changed, but in a backwards compatible way. exec, eval and import would all gain an optional (keyword-only?) "builtins" parameter.
I see no reason to change any of the C API functions. New functions taking an extra parameter could be added, but it wouldn't be a requirement.
Cheers, Mark
- Previous message: [Python-Dev] Adding a builtins parameter to eval(), exec() and __import__().
- Next message: [Python-Dev] Adding a builtins parameter to eval(), exec() and __import__().
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]