[prev in list] [next in list] [prev in thread] [next in thread] 

List:       python-ideas
Subject:    [Python-ideas] Make it easier to set function globals
From:       Steven D'Aprano <steve () pearwood ! info>
Date:       2021-12-12 2:19:51
Message-ID: 20211212021951.GL21647 () ando ! pearwood ! info
[Download RAW message or body]

TL;DR: it is hard, but not impossible, to set function `__globals__` 
dunder to a ChainMap. Let's make it easier!


Background:

(1) Comprehensions skip class scope, leading to bug reports like these:

https://bugs.python.org/issue3692
https://bugs.python.org/issue26951

Note Guido's comment in the first:

"perhaps __globals__ could be set to a chainmap referencing the class 
dict and the globals?"


(2) I want to experiment with namespaces, similar to the C++ feature. 
The details don't matter, but one way I can do that experiment is to use 
a class and ChainMap.

So let's try an experiment: set up a namespace using ChainMap, and try 
to monkey-patch a function to use it instead of the regular globals.

Here is my setup code:

def func():
    return (a, b, c)

a = b = c = "global"
from collections import ChainMap
ns = ChainMap({'a': 'CM-0'}, {'b': 'CM-1'}, globals())

Let's see what it takes to set func.__globals__ to ns.


Attempt 1: set __globals__ directly.

> > > func.__globals__ = ns
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: readonly attribute



Attempt 2: use the FunctionType constructor.


> > > from types import FunctionType
> > > f = FunctionType(func.__code__, globals=ns)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: function() argument 'globals' must be dict, not ChainMap


Attempt 3: fool the constructor.

> > > class MyChainMap(ChainMap, dict):
...     pass
...
> > > ns = MyChainMap({'a': 'CM-0'}, {'b': 'CM-1'}, globals())
> > > f = FunctionType(func.__code__, globals=ns)

Success!

And now the function behaves as desired:

> > > f()
('CM-0', 'CM-1', 'global')

This was too hard! What can we do to make it easier?

I think we should have:

- allow func.__globals__ to be writable;

- allow anything that inherits from the Mapping ABC.


Thoughts?



-- 
Steve
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@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/5AUFO6NMDR5XABYCEU2LKXVDBQDXORUT/
 Code of Conduct: http://python.org/psf/codeofconduct/


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic