-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Simplify FigureCanvas multiple inheritance init by swapping bases order. #23363
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Instead of having e.g. FigureCanvasQT inherit from QWidget and then FigureCanvasBase, which requires workarounds to handle the fact that PySide.QWidget does not participate in cooperative multiple inheritance (we work around that with _allow_super_init in qt, and manual super calls in other toolkits), just swap the order of bases to (FigureCanvasBase, QWidget) and make sure that FigureCanvasBase *does* participate in cooperative multiple inheritance. Also note the changes in FigureCanvasGTK{3,4}Agg.draw, where the new inheritance order also makes more sense.
Given the simplicity of this solution, why did we systematically have every class defined in a way that was as difficult as possible? |
@@ -1633,6 +1633,7 @@ def __init__(self, figure=None): | |||
# We don't want to scale up the figure DPI more than once. | |||
figure._original_dpi = figure.dpi | |||
self._device_pixel_ratio = 1 | |||
super().__init__() # Typically the GUI widget init (if any). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to pass *args, **kwargs
through here as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FigureCanvasBase.__init__
itself doesn't take *args, **kwargs
; let's not bother adding that unless there's a real reason to do so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am weakly in favor of atleast **kwargs
flowing through this init, but also fine with waiting until it actually is a need someone has.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think passing **kwargs
through only makes sense if figure
was kwonly as well (so that at least in theory, each class in the inheritance tree can pick out whatever kwargs they support). Once you start having positional arguments, the scheme breaks down anyways (as you can't tell which positional arguments you need to pick out).
Actually some classes are already set up the other(=new) way round (tkagg, tkcairo, wxagg); my (completely uneducated) guess is that this was probably random at the beginning (especially when people were not using |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mildly in favor of FigureCanvasBase.__init__
passing **kwargs
through to the super call but OK with this as-is.
Wow. Did you file a bug with PySide? |
No, I am 99.9% sure they are aware of this and have maintained the non-cooperative inheritance as an intentional design choice. For users there can be weird breakage when you switch to using [edited to add missing words 🤦🏻 ] |
That's really unfortunate.
I understand your point. But they could at least add a warning in class QWidget:
def __init__(self, ..., **kwargs: Any):
if super().__init__ is not object.__init__:
warnings.warn("Currently, QWidget doesn't participate in cooperative inheritance. However, in a future "
f"version of PySide, QWidget will call {super().__init__} "
f"with parameters {kwargs} "
f"for objects of type {type(self).__name__}.", DeprecationWarning) That way in a year or two, they can call super as they are "supposed to", and everyone is happy. |
@NeilGirdhar If you want to push on this I suggest you propose it upsteam with with Pyside (discussing it here is not going to change anything). While I agree it would be nicer if they did participate in cooperative MI, I do not think not doing so is wrong and that is not a windmill I want to tilt at right now ;) . |
@tacaswell Fair enough. At least you found a workaround. |
Instead of having e.g. FigureCanvasQT inherit from QWidget and then
FigureCanvasBase, which requires workarounds to handle the fact that
PySide.QWidget does not participate in cooperative multiple inheritance
(we work around that with _allow_super_init in qt, and manual super
calls in other toolkits), just swap the order of bases to
(FigureCanvasBase, QWidget) and make sure that FigureCanvasBase does
participate in cooperative multiple inheritance.
Also note the changes in FigureCanvasGTK{3,4}Agg.draw, where the new
inheritance order also makes more sense.
PR Summary
PR Checklist
Tests and Styling
pytest
passes).flake8-docstrings
and runflake8 --docstring-convention=all
).Documentation
doc/users/next_whats_new/
(follow instructions in README.rst there).doc/api/next_api_changes/
(follow instructions in README.rst there).