On Tue, Jul 30, 2019 at 12:13 PM Steven D'Aprano <st...@pearwood.info> wrote: > > On Mon, Jul 29, 2019 at 09:53:38PM -0400, Ricky Teachey wrote: > > > But I ask: how is it possible, then, to create a with block that "gobbles > > up" things declared in it and adds those things to some namespace using > > existing python syntax...? > [...] > > I currently can't create an object that allows this to work: > > > > with NameSpace('ns') as ns: > > a = 1 > > assert ns.a=1 > > Neither can I, and I've been mucking about with this idea for about > three years. (To be honest, I poke it with a stick about every six > months, so its not like I've spend a lot of time on it.) > > I kinda-sorta got it to work with a class statement plus a decorator, > not too different from your metaclass example, but couldn't get > functions to work correctly.
A class + decorator gets so almost there that it might be possible with just a tiny bit of language support. What if there could be a way to change a function's __globals__? Currently that's readonly according to funcobject.c, but by hacking that flag out, I can create the following example: def namespace(cls): """Decorate a class to turn it into a namespace""" ns = dict(cls.__dict__) for member in ns.values(): if hasattr(member, "__globals__"): member.__globals__ = ns return cls @namespace class ns: x = 1 def foo(y): return x + y def replace(new_x): global x x = new_x print(ns.foo(4)) # 5 ns.replace(100) print(ns.foo(4)) # 104 Due to CPython limitations, the new __globals__ MUST be a plain dict (not the mappingproxy that cls.__dict__ is, and not a ChainMap), but this is extremely close to what could actually be quite useful. Also, since the function objects get mutated by the decorator, calling a function during the namespace's construction will have the wrong behaviour. Maybe the only language support needed is some way to say "from now on, functions should be created with THIS value for their globals"? It might be possible to get even closer using a metaclass rather than a decorator. ChrisA _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/FAE7WDCKTH272M6LTUJ3QEUIOEMKJIVD/ Code of Conduct: http://python.org/psf/codeofconduct/