From a87077ef6911b79dc32aae3d37a5198f106fe0a8 Mon Sep 17 00:00:00 2001 From: LeoBorcherding Date: Thu, 14 May 2026 13:50:09 -0500 Subject: [PATCH] =?UTF-8?q?worker:=20fix=20torchao=20stub=20=E2=80=94=20re?= =?UTF-8?q?turn=20stub=20classes=20not=20modules=20for=20isinstance()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit peft/tuners/lora/torchao.py does: from torchao.dtypes import AffineQuantizedTensor, LinearActivationQuantizedTensor isinstance(weight, (AffineQuantizedTensor, LinearActivationQuantizedTensor)) The stub __getattr__ was returning stub modules, which isinstance() rejects with "arg 2 must be a type, a tuple of types, or a union". Add _StubTypeMeta metaclass whose __instancecheck__ always returns False, and _make_stub_type() to create stub classes via it. Change _make_mod_stub __getattr__ to return stub classes instead of stub modules for leaf attribute access, so isinstance() gets a valid type and returns False. _StubSubpackageFinder still handles import-style subpackage creation (those still need module objects in sys.modules); __getattr__ only fires for from-import or direct attribute access, which are the isinstance paths. --- studio/backend/core/training/worker.py | 30 +++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/studio/backend/core/training/worker.py b/studio/backend/core/training/worker.py index e1b7d3156b..75c1bd76e8 100644 --- a/studio/backend/core/training/worker.py +++ b/studio/backend/core/training/worker.py @@ -1099,6 +1099,30 @@ def run_training_process( _STUB_SENTINEL = object() + # Metaclass for stub types so that isinstance(x, StubClass) returns False + # instead of raising TypeError ("arg 2 must be a type"). + # peft/tuners/lora/torchao.py does: + # from torchao.dtypes import AffineQuantizedTensor, LinearActivationQuantizedTensor + # isinstance(weight, (AffineQuantizedTensor, LinearActivationQuantizedTensor)) + # If those names resolve to stub modules rather than types, isinstance() raises. + class _StubTypeMeta(type): + def __instancecheck__(cls, instance): + return False + def __subclasscheck__(cls, subclass): + return False + def __getattr__(cls, attr): + if attr.startswith("__"): + raise AttributeError(attr) + child = _StubTypeMeta(attr, (), {}) + setattr(cls, attr, child) + return child + def __call__(cls, *args, **kwargs): + return None + + def _make_stub_type(name): + """Stub class: accepted by isinstance() (always False), supports attr access.""" + return _StubTypeMeta(name, (), {}) + def _make_mod_stub(mod_name): m = _types.ModuleType(mod_name) m.__path__ = [] @@ -1108,9 +1132,9 @@ def run_training_process( def _ga(attr, _m=m, _n=mod_name): if attr.startswith("__"): raise AttributeError(attr) - child_name = f"{_n}.{attr}" - child = _make_mod_stub(child_name) - sys.modules.setdefault(child_name, child) + # Return a stub CLASS (not a module) so that isinstance(x, attr) + # works and returns False instead of raising TypeError. + child = _make_stub_type(f"{_n}.{attr}") setattr(_m, attr, child) return child m.__getattr__ = _ga