Repository navigation
fix(python-lsp): resolve super() through the C3 method resolution order - #2696
Merged
Merged
Conversation
The home-assistant radarr shape: RadarrCalendarEntity(RadarrEntity, CalendarEntity) where RadarrEntity reaches the common base Entity through CoordinatorEntity and CalendarEntity overrides Entity. In C3 order a common base comes after every class deriving from it, so super().write_state() and super().__init__() reach CalendarEntity, not Entity through the first base's ancestry. Single inheritance as the control; sequential and parallel. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
super() binds to the enclosing class's method resolution order, Python's C3 linearization, in which a common base follows every class deriving from it. The super() resolver walked the bases one by one, each through its whole ancestry, so with RadarrCalendarEntity(RadarrEntity, CalendarEntity) the first base reached Entity through CoordinatorEntity before CalendarEntity, which overrides it, was ever looked at. py_c3_linearize computes the order (memoized per lookup, capped in depth and length; -1 when the hierarchy has none), and super() takes the first class after the enclosing one that declares the member. A hierarchy without a C3 order keeps the base-by-base walk, as does the synthesized __init__ of an undeclared constructor. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This was referenced Oct 18, 2026
DeusData
added a commit
that referenced
this pull request
Oct 19, 2026
thugrock7
pushed a commit
to thugrock7/codebase-memory-mcp
that referenced
this pull request
Oct 19, 2026
…a#2680, DeusData#2690, DeusData#2695, DeusData#2696) py_lsp.c: the module-member lookup of this branch and the C3 super() lookup of DeusData#2696 were added at the same place; both are kept. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
super()binds to the enclosing class's method resolution order, which is Python's C3 linearization. Inthat order a common base follows every class that derives from it:
The super() resolver walked the bases one at a time, each through its whole ancestry. So the first base
reached the shared
EntitythroughCoordinatorEntitybeforeCalendarEntity, which overrides it, wasever looked at. For
super().__init__()it consulted only the first base. When that base was a mixinwithout a constructor, it synthesized
<mixin>.__init__, a QN that matches no node, and the call wasdropped.
py_lsp.cnow computes the C3 order.py_c3_linearizememoizes per lookup, is capped in depth and length,and reports when a hierarchy has no C3 order. super() takes the first class after the enclosing class that
declares the member itself. A hierarchy without a C3 order keeps the previous base-by-base walk, and so does
the synthesized constructor of an undeclared
__init__. Ordinary attribute lookup is unchanged.No index-format change.
Evidence
Base main 1346ac4 vs this change, 26 Python repos (manifest v1), production builds, macOS arm64,
--repeat 2, every repeat byte-identical.Every other edge type is identical, apart from SEMANTICALLY_RELATED, which is derived from the CALLS
neighbourhoods. All added edges are
lsp_super(54) orlsp_super_init(75).base the old walk reached first. Examples:
HuberRegressor.__sklearn_tags__reachesRegressorMixin, notBaseEstimator.MSDialect.do_savepointandMSDialect_pyodbc.do_executemanyreachDefaultDialect, notthe
engine.interfaces.Dialectstub.Airtouch5AC.async_added_to_hassreachesAirtouch5Entity, nothelpers.entity.Entity.FigureCanvasQTCairo.drawreachesFigureCanvasQT.draw.StringArray.__setitem__reachesNDArrayBackedExtensionArray.CallableType.__init__reachesFunctionLike.__init__.lsp_super_init):super().__init__()in classes whose first base is a mixin without aconstructor. Examples:
AdaBoostRegressor/AdaBoostClassifierreachBaseWeightBoosting.__init__.AdminUserCreationFormreachesBaseUserCreationForm.__init__, and GISScalereachesGeoFuncMixin.__init__.UpdatereachesValuesBase.__init__.CalendarEntity, but only becauseRadarrEntity's ancestry is unresolved. Once relative imports resolve (fix(python): from . import x names the importing package, not its parent #2680), main resolves it toEntity._async_write_ha_state, and with this change toCalendarEntity._async_write_ha_state(checkedon home-assistant with both changes merged).
Tests
pipeline_python_super_follows_c3_mro{,_parallel}: the radarr shape across two files.super().write_state()andsuper().__init__()reachCalendarEntity, neverEntity, and asingle-inheritance class is the control. Sequential and parallel. RED without the fix (
ASSERT(m_c3)).py_lsp_scale, py_lsp_bench, lsp_resolution_probe, edge_types_probe, convergence_probe,
matrix_known_classes, parallel, incremental, integration) pass.