Skip to content

Fix: _overrides() resolves base-class names found via bytecode disassembly... - #137

Open
M001N wants to merge 1 commit into
mkorpela:mainfrom
M001N:oss-engine/f53d7861-1daa3ed2
Open

M001N wants to merge 1 commit into
mkorpela:mainfrom
M001N:oss-engine/f53d7861-1daa3ed2

Conversation

@M001N

@M001N M001N commented Aug 16, 2026

Copy link
Copy Markdown

Summary

Captured the calling frame in _overrides (sys._getframe(3)) and passed its f_locals through _get_base_classes into _get_base_class as a new local_vars parameter. _get_base_class now checks local_vars first (when the component name is present there) before falling back to the existing namespace (globals) lookup, matching normal Python scoping where locals shadow globals. This resolves nested/sibling class names correctly while leaving the existing top-level-class resolution path (which relies on globals) unchanged since local_vars simply won't contain those names.

Problem

mkorpela/overrides issue reference: #86

Root Cause

_overrides() resolves base-class names found via bytecode disassembly (_get_base_class_names) through _get_base_class(components, namespace), where namespace is only the module's global_vars (method.globals or vars(sys.modules[...])). It never consults the calling frame's f_locals. For a nested class body, the sibling class name (Bar) exists only as a local variable in the enclosing class's (Foo's) execution frame — it's never a module global — so lookup falls through to the builtins fallback, which naturally doesn't have it either, raising AttributeError.

Testing

PASS - all 70 tests in the suite pass, including the 2 new regression tests (one asserting the nested-sibling-class override works and returns the correct value, one asserting an incompatible override in the same nested scenario still correctly raises TypeError).

Related Issue

#86

_get_base_class only resolved base-class names via module globals,
never the calling frame's locals. For a nested class body
(class Foo: class Bar: ...; class Car(Bar): ...), Bar exists only as
a local variable in the enclosing Foo class body's execution frame,
so resolution fell through to a builtins lookup and raised
AttributeError. Thread the calling frame's f_locals into
_get_base_classes/_get_base_class and check it before globals
(locals shadow globals per normal Python scoping), fixing the nested
case while preserving the existing top-level behavior.

Fixes mkorpela#86
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant