Details
Description
When implementing pickling for Qt Enum objects, I suddenly was reminded of a
Known Old Quirk of PySide:
Given modules MA and MB, and classes CC and CD.
We traverse this list when accessing CD and think we touched
MA.MB.CC.CD
PySide instead erroneously reports
MA.MB.MC.CD
Example:
>>> QtCore.Qt.Key.__module__ 'PySide2.QtCore.Qt' >>> QtCore.Qt.Key.__name__ 'Key' >>> QtCore.Qt.Key.__qualname__ 'Key'
Correct would be
>>> QtCore.Qt.Key.__module__ 'PySide2.QtCore' >>> QtCore.Qt.Key.__name__ 'Key' >>> QtCore.Qt.Key.__qualname__ 'Qt.Key'
That means: The class CC is reported as module MC.
And because Python is thinking it is doing right,
there is no way, not even with meta classes,
to fix the problem, until MC is reported as CC.
This seems to be an old work-around for Python 2 where it was convenient to
get the full path from the top module to the deepest class by adding __module__ and __name__.
Pickling of nested classes was not supported, so this quirk was not relevant.
But pickling of nested classes could be supported with some effort.
This effect was the implicit action that computes names from the given type
creation arguments, which is wrong for nested types. No names were explicitly
set at all but the name attribute of an enclosing class.
In Python 3, the __qualname__ attribute was grown and pickling of nested
classes was now supported internally. That meant that all participants in pickling
had to use the builtin support, otherwise pickling would break.
The Planned Fix
To get rid of this workaround and maximize compatibility, we should
- keep __name__ as it is
- change __qualname__ to give the full class path
- change __module__ to give only the full module path
This will fix the problem for Python 3.
For Python 2 the non-existing __qualname__ will be implemented for PySide classes,
only. Pickling support for nested classes might then be supported, too.