Add warning to old/classic class inheritance problem#48
Add warning to old/classic class inheritance problem#48Eddy114514 wants to merge 1 commit intosoftdevteam:migrationfrom
Conversation
|
Can you fix the PR description (the formatting has gone wrong) and squash the commits to remove the ones that aren't relevant for review (note: I'm not necessarily saying squash down to one commit!). |
|
@Eddy114514 Ping. |
|
@ltratt Sorry I had 2 exam this week and I was preparing for it. fixed and squashed |
| err = set_bases(op, v); | ||
| if (err != NULL && *err == '\0') { | ||
| if (warn_classic_mro_risk(op) < 0) | ||
| return -1; |
There was a problem hiding this comment.
Is this supposed to be -1 and not 1? [There are no docs for the function, so I could be very off in my question!]
|
This is a very interesting PR, and something I had not even thought about -- I like it! |
|
@ltratt Thank you for your fix suggestions. I have fix them, and for the -1 question. -1 is correct here because class_setattr() is a tp_setattro slot where 0 means success and -1 means failure with an exception set. |
|
Please squash and rebase. |
|
@ltratt squashed. |
|
Please also rebase against master to resolve the conflict. |
Python 2 classic classes use depth-first, left-to-right method lookup. Python 3 only has new-style classes, which use C3 MRO. In classic multiple inheritance, this can silently change which base class provides an attribute after migration.
Example:
In Python 2 classic classes, D().do_this() resolves to A.
Under Python 3 / C3 MRO, the same hierarchy resolves to C.
Behavior Difference:
Python 2 classic lookup:
D -> B -> A -> CPython 3 / C3 lookup:
D -> B -> C -> ASo the same attribute name can resolve to a different provider.
To implement the warning I only consider the classic classes and classes with multiple inheritance. The code compare class MRO against hypothetical C3 MRO, and warn only when a real existing attribute would resolve to a different provider. It also warns when the hierarchy has no valid C3 linearization and would fail in python3.