From e5a9e36527e6bf45fb7a64309800a4dc51da9b40 Mon Sep 17 00:00:00 2001 From: ogabrielluiz Date: Mon, 15 Jun 2026 19:38:48 -0300 Subject: [PATCH] fix(api/v2): move FrameSourceFactory alias under TYPE_CHECKING As a module-level runtime value, FrameSourceFactory = Callable[..., Any] is a GenericAlias that passes isinstance(obj, type) but makes issubclass(obj, Service) raise on Python 3.10/3.14. The service factory scans this module for Service subclasses (services/factory.py:90), so the runtime alias crashed service initialization on those interpreters with 'issubclass() arg 1 must be a class' -> 'Could not initialize services', erroring out dozens of unrelated tests at setup (3.13 was unaffected, which is why local runs passed). The alias is only referenced in a lazy annotation (from __future__ import annotations), so moving it + the Callable import under TYPE_CHECKING removes it from the runtime namespace with no behavior change. Verified: alias absent from runtime module namespace, factory scan finds BackgroundExecutionService cleanly, durable service tests 26/26 pass. --- .../services/background_execution/service.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/backend/base/langflow/services/background_execution/service.py b/src/backend/base/langflow/services/background_execution/service.py index 3adb98683a..bea177bb69 100644 --- a/src/backend/base/langflow/services/background_execution/service.py +++ b/src/backend/base/langflow/services/background_execution/service.py @@ -20,7 +20,6 @@ import contextlib import json import os import tempfile -from collections.abc import Callable from pathlib import Path from typing import TYPE_CHECKING, Any from uuid import uuid4 @@ -37,7 +36,7 @@ from langflow.services.deps import get_job_service from langflow.services.jobs.exceptions import DuplicateJobError if TYPE_CHECKING: - from collections.abc import AsyncIterator + from collections.abc import AsyncIterator, Callable from uuid import UUID from lfx.services.settings.service import SettingsService @@ -45,10 +44,16 @@ if TYPE_CHECKING: from langflow.services.database.models.jobs.model import Job, JobEvent from langflow.services.database.models.user.model import UserRead -# A frame-source factory returns the async-generator callable the runner drives. -# Default wiring (Task 2.7) returns ``_stream_event_frames`` bound to the run's -# adapter + flow; tests inject a scripted generator. -FrameSourceFactory = Callable[..., Any] + # A frame-source factory returns the async-generator callable the runner drives. + # Default wiring (Task 2.7) returns ``_stream_event_frames`` bound to the run's + # adapter + flow; tests inject a scripted generator. + # + # Defined under TYPE_CHECKING on purpose: as a module-level runtime value, + # ``Callable[..., Any]`` is a GenericAlias that passes ``isinstance(obj, type)`` + # but makes ``issubclass(obj, Service)`` raise on Python 3.10/3.14. The service + # factory scans this module for ``Service`` subclasses (services/factory.py), so a + # runtime alias here crashes service initialization on those interpreters. + FrameSourceFactory = Callable[..., Any] # Durable statuses that mean the run is over. ``events()`` keys off these (not the # process-local live bus) so a reattach to a finished job replays and returns