Context
-------
Some classes have the variable __name__ in their namespace __dict__ ,
and one may wish to create more such classes with varied values of
__name__ . Some of those could be created with a metaclass whose
__prepare__ returns a mapping having key "__name__", for which the
value is created depending on the arguments of __prepare__ and can be
updated or deleted in the body of the class to be created. (See C
below for a very silly example of such a metaclass.)
Problem
-------
The value of __name__ given by __prepare__ becomes not just that in
the class body, but automatically also the value of __module__
there. As far as I could see, this is not documented, and the
programmer might not notice __module__ was messed up. I think this
behaviour is unexpected and problematic at least unless a warning is
given on it in the document.
Example
-------
Here's a code which produces a problem.
```
# In this example, the metaclass C is intended to be a class of
# subclasses of:
B = type
class C(type(B)):
@classmethod
def __prepare__(cls, /, *args, **kwargs):
return dict(__name__ = cls._name(*args, **kwargs))
@classmethod
def _name(cls, /, *args, **kwargs):
# The actual value of __name__ doesn't matter much to the
# issue, so I make this function always return the same silly
# thing in this example.
return type.__dict__["__name__"]
class O(B, metaclass=C):
print(__module__ == __name__) # True
# Could update or delete __name__ here.
```
Consequently,
>>> O.__module__
<attribute '__name__' of 'type' objects>
Discussion
----------
If the value of __name__ can be read from the scope
outside for the assignment to __module__, then that will erase this
unexpected behaviour and I think it would be a much safer thing to do.
Remarks
-------
The issue was previously
https://bugs.python.org/issue47136
which I'm going to close now since I failed to specify the issue
clearly enough there. Here I've made the issue more specific.
The issue is different from but seems related to
https://bugs.python.org/issue28869
I haven't figured out the exact relation.
Thanks.
|