GitNexus/gitnexus/test/fixtures/lang-resolution/python-mixin-self-dispatch/worker.py
EVA f6e70016d6
fix(python): resolve mixin self calls to subtype implementations (#3390)
* fix(python): resolve missing mixin self members through subtypes

* fix: honor Python effective MRO and static mixin targets

* fix: bind Python subtype dispatch to receiver provenance

* fix(python): limit mixin fanout to instance receivers

* fix(python): capture call arity and invalidate stale parsed facts

* fix(python): count bound receivers by method context

Preserve static, free, nested and typed variadic parameters; test renamed target receivers without weakening incompatible-arity rejection. Regenerate capture goldens for receiver metadata and eight mixin fixtures. Record the deliberate missing_target coverage outcome: CI measured Python call drops 5->6 and total call drops 113->114; no shape or scaling threshold relaxed.

* test(python): require a call capture before checking unknown arity

* fix(python): bind subtype dispatch to receiver definition

* test(python): include conditional renamed-receiver target

* fix(python): prove positional mixin targets and report partial coverage

Preserve upstream notebook coordinate mapping and maintainer changes. Reject incompatible/implicit-class targets, retain proven targets across ambiguous alternatives, and report capped or unresolved coverage without confusing edge deduplication.

* fix(python): isolate subtype call proof and preserve lookup boundaries

---------

Co-authored-by: Eva <eva@100yen.org>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
2026-09-28 09:42:56 +05:30

139 lines
2.8 KiB
Python

from abc import ABC, abstractmethod
from mixins import (
AbstractBoundaryMixin,
ArgumentForwardingMixin,
ArgumentShapeMixin,
ClassReceiverMixin,
DuplicateDefinitionMixin,
FieldShadowMixin,
GenericMixin,
HookMixin,
LifecycleReceiverMixin,
MroOrderMixin,
NestedClassReceiverMixin,
PrivateNameMixin,
VariadicPseudoReceiverMixin,
)
class Worker(HookMixin):
def helper(instance) -> int:
return 1
class ClassReceiverWorker(ClassReceiverMixin):
def class_only(self) -> int:
return 1
class VariadicPseudoReceiverWorker(VariadicPseudoReceiverMixin):
def variadic_target(self) -> int:
return 1
class NestedClassReceiverWorker(NestedClassReceiverMixin):
def instance_only(self) -> int:
return 1
class OrderX:
def order_hook(self) -> int:
return 1
class OrderA(OrderX):
pass
class OrderB:
def order_hook(self) -> int:
return 2
class OrderedWorker(MroOrderMixin, OrderA, OrderB):
pass
class ShadowBlocker:
shadow_hook = None
class ShadowProvider:
def shadow_hook(self) -> int:
return 1
class ShadowWorker(FieldShadowMixin, ShadowBlocker, ShadowProvider):
pass
class LifecycleReceiverWorker(LifecycleReceiverMixin):
def lifecycle_hook(self) -> int:
return 1
def new_hook(self) -> int:
return 1
class GenericWorker(GenericMixin):
def class_only(self) -> int:
return 1
class CompatibleArgumentBase:
def keyword_only_target(self, value: int) -> int:
return value
class ArgumentShapeWorker(ArgumentShapeMixin, CompatibleArgumentBase):
def keyword_only_target(self, *, value: int) -> int:
return value
def positional_only_target(self, value: int, /) -> int:
return value
def required_keyword_target(self, value: int = 0, *, required: int) -> int:
return value + required
class ArgumentForwardingWorker(ArgumentForwardingMixin):
def forward_target(self, value: int) -> int:
return value
class PrivateNameWorker(PrivateNameMixin):
def __private_hook(self) -> int:
return 1
class AbstractBoundaryX(ABC):
@abstractmethod
def abstract_hook(self) -> int:
raise NotImplementedError
class AbstractBoundaryA(AbstractBoundaryX):
pass
class AbstractBoundaryB:
def abstract_hook(self) -> int:
return 1
class AbstractBoundaryWorker(AbstractBoundaryMixin, AbstractBoundaryA, AbstractBoundaryB):
pass
class ConcreteAbstractWorker(AbstractBoundaryWorker):
def abstract_hook(self) -> int:
return 2
class DuplicateDefinitionWorker(DuplicateDefinitionMixin):
def duplicate_hook(self, value: int) -> int:
return value
def duplicate_hook(self, left: int, right: int) -> int:
return left + right