comfy_api: remove usage of "Type","List" and "Dict" types (#11238)

This commit is contained in:
Alexander Piskun 2025-12-16 02:01:10 +02:00 committed by GitHub
parent dbd330454a
commit 43e0d4e3cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 38 additions and 40 deletions

View File

@ -5,12 +5,12 @@ This module handles capability negotiation between frontend and backend,
allowing graceful protocol evolution while maintaining backward compatibility. allowing graceful protocol evolution while maintaining backward compatibility.
""" """
from typing import Any, Dict from typing import Any
from comfy.cli_args import args from comfy.cli_args import args
# Default server capabilities # Default server capabilities
SERVER_FEATURE_FLAGS: Dict[str, Any] = { SERVER_FEATURE_FLAGS: dict[str, Any] = {
"supports_preview_metadata": True, "supports_preview_metadata": True,
"max_upload_size": args.max_upload_size * 1024 * 1024, # Convert MB to bytes "max_upload_size": args.max_upload_size * 1024 * 1024, # Convert MB to bytes
"extension": {"manager": {"supports_v4": True}}, "extension": {"manager": {"supports_v4": True}},
@ -18,7 +18,7 @@ SERVER_FEATURE_FLAGS: Dict[str, Any] = {
def get_connection_feature( def get_connection_feature(
sockets_metadata: Dict[str, Dict[str, Any]], sockets_metadata: dict[str, dict[str, Any]],
sid: str, sid: str,
feature_name: str, feature_name: str,
default: Any = False default: Any = False
@ -42,7 +42,7 @@ def get_connection_feature(
def supports_feature( def supports_feature(
sockets_metadata: Dict[str, Dict[str, Any]], sockets_metadata: dict[str, dict[str, Any]],
sid: str, sid: str,
feature_name: str feature_name: str
) -> bool: ) -> bool:
@ -60,7 +60,7 @@ def supports_feature(
return get_connection_feature(sockets_metadata, sid, feature_name, False) is True return get_connection_feature(sockets_metadata, sid, feature_name, False) is True
def get_server_features() -> Dict[str, Any]: def get_server_features() -> dict[str, Any]:
""" """
Get the server's feature flags. Get the server's feature flags.

View File

@ -1,4 +1,4 @@
from typing import Type, List, NamedTuple from typing import NamedTuple
from comfy_api.internal.singleton import ProxiedSingleton from comfy_api.internal.singleton import ProxiedSingleton
from packaging import version as packaging_version from packaging import version as packaging_version
@ -10,7 +10,7 @@ class ComfyAPIBase(ProxiedSingleton):
class ComfyAPIWithVersion(NamedTuple): class ComfyAPIWithVersion(NamedTuple):
version: str version: str
api_class: Type[ComfyAPIBase] api_class: type[ComfyAPIBase]
def parse_version(version_str: str) -> packaging_version.Version: def parse_version(version_str: str) -> packaging_version.Version:
@ -23,16 +23,16 @@ def parse_version(version_str: str) -> packaging_version.Version:
return packaging_version.parse(version_str) return packaging_version.parse(version_str)
registered_versions: List[ComfyAPIWithVersion] = [] registered_versions: list[ComfyAPIWithVersion] = []
def register_versions(versions: List[ComfyAPIWithVersion]): def register_versions(versions: list[ComfyAPIWithVersion]):
versions.sort(key=lambda x: parse_version(x.version)) versions.sort(key=lambda x: parse_version(x.version))
global registered_versions global registered_versions
registered_versions = versions registered_versions = versions
def get_all_versions() -> List[ComfyAPIWithVersion]: def get_all_versions() -> list[ComfyAPIWithVersion]:
""" """
Returns a list of all registered ComfyAPI versions. Returns a list of all registered ComfyAPI versions.
""" """

View File

@ -8,7 +8,7 @@ import os
import textwrap import textwrap
import threading import threading
from enum import Enum from enum import Enum
from typing import Optional, Type, get_origin, get_args, get_type_hints from typing import Optional, get_origin, get_args, get_type_hints
class TypeTracker: class TypeTracker:
@ -193,7 +193,7 @@ class AsyncToSyncConverter:
return result_container["result"] return result_container["result"]
@classmethod @classmethod
def create_sync_class(cls, async_class: Type, thread_pool_size=10) -> Type: def create_sync_class(cls, async_class: type, thread_pool_size=10) -> type:
""" """
Creates a new class with synchronous versions of all async methods. Creates a new class with synchronous versions of all async methods.
@ -563,7 +563,7 @@ class AsyncToSyncConverter:
@classmethod @classmethod
def _generate_imports( def _generate_imports(
cls, async_class: Type, type_tracker: TypeTracker cls, async_class: type, type_tracker: TypeTracker
) -> list[str]: ) -> list[str]:
"""Generate import statements for the stub file.""" """Generate import statements for the stub file."""
imports = [] imports = []
@ -628,7 +628,7 @@ class AsyncToSyncConverter:
return imports return imports
@classmethod @classmethod
def _get_class_attributes(cls, async_class: Type) -> list[tuple[str, Type]]: def _get_class_attributes(cls, async_class: type) -> list[tuple[str, type]]:
"""Extract class attributes that are classes themselves.""" """Extract class attributes that are classes themselves."""
class_attributes = [] class_attributes = []
@ -654,7 +654,7 @@ class AsyncToSyncConverter:
def _generate_inner_class_stub( def _generate_inner_class_stub(
cls, cls,
name: str, name: str,
attr: Type, attr: type,
indent: str = " ", indent: str = " ",
type_tracker: Optional[TypeTracker] = None, type_tracker: Optional[TypeTracker] = None,
) -> list[str]: ) -> list[str]:
@ -782,7 +782,7 @@ class AsyncToSyncConverter:
return processed return processed
@classmethod @classmethod
def generate_stub_file(cls, async_class: Type, sync_class: Type) -> None: def generate_stub_file(cls, async_class: type, sync_class: type) -> None:
""" """
Generate a .pyi stub file for the sync class to help IDEs with type checking. Generate a .pyi stub file for the sync class to help IDEs with type checking.
""" """
@ -988,7 +988,7 @@ class AsyncToSyncConverter:
logging.error(traceback.format_exc()) logging.error(traceback.format_exc())
def create_sync_class(async_class: Type, thread_pool_size=10) -> Type: def create_sync_class(async_class: type, thread_pool_size=10) -> type:
""" """
Creates a sync version of an async class Creates a sync version of an async class

View File

@ -1,4 +1,4 @@
from typing import Type, TypeVar from typing import TypeVar
class SingletonMetaclass(type): class SingletonMetaclass(type):
T = TypeVar("T", bound="SingletonMetaclass") T = TypeVar("T", bound="SingletonMetaclass")
@ -11,13 +11,13 @@ class SingletonMetaclass(type):
) )
return cls._instances[cls] return cls._instances[cls]
def inject_instance(cls: Type[T], instance: T) -> None: def inject_instance(cls: type[T], instance: T) -> None:
assert cls not in SingletonMetaclass._instances, ( assert cls not in SingletonMetaclass._instances, (
"Cannot inject instance after first instantiation" "Cannot inject instance after first instantiation"
) )
SingletonMetaclass._instances[cls] = instance SingletonMetaclass._instances[cls] = instance
def get_instance(cls: Type[T], *args, **kwargs) -> T: def get_instance(cls: type[T], *args, **kwargs) -> T:
""" """
Gets the singleton instance of the class, creating it if it doesn't exist. Gets the singleton instance of the class, creating it if it doesn't exist.
""" """

View File

@ -1,7 +1,7 @@
from __future__ import annotations from __future__ import annotations
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Type, TYPE_CHECKING from typing import TYPE_CHECKING
from comfy_api.internal import ComfyAPIBase from comfy_api.internal import ComfyAPIBase
from comfy_api.internal.singleton import ProxiedSingleton from comfy_api.internal.singleton import ProxiedSingleton
from comfy_api.internal.async_to_sync import create_sync_class from comfy_api.internal.async_to_sync import create_sync_class
@ -113,7 +113,7 @@ ComfyAPI = ComfyAPI_latest
if TYPE_CHECKING: if TYPE_CHECKING:
import comfy_api.latest.generated.ComfyAPISyncStub # type: ignore import comfy_api.latest.generated.ComfyAPISyncStub # type: ignore
ComfyAPISync: Type[comfy_api.latest.generated.ComfyAPISyncStub.ComfyAPISyncStub] ComfyAPISync: type[comfy_api.latest.generated.ComfyAPISyncStub.ComfyAPISyncStub]
ComfyAPISync = create_sync_class(ComfyAPI_latest) ComfyAPISync = create_sync_class(ComfyAPI_latest)
# create new aliases for io and ui # create new aliases for io and ui

View File

@ -1,5 +1,5 @@
import torch import torch
from typing import TypedDict, List, Optional from typing import TypedDict, Optional
ImageInput = torch.Tensor ImageInput = torch.Tensor
""" """
@ -39,4 +39,4 @@ class LatentInput(TypedDict):
Optional noise mask tensor in the same format as samples. Optional noise mask tensor in the same format as samples.
""" """
batch_index: Optional[List[int]] batch_index: Optional[list[int]]

View File

@ -5,7 +5,6 @@ import os
import random import random
import uuid import uuid
from io import BytesIO from io import BytesIO
from typing import Type
import av import av
import numpy as np import numpy as np
@ -83,7 +82,7 @@ class ImageSaveHelper:
return PILImage.fromarray(np.clip(255.0 * image_tensor.cpu().numpy(), 0, 255).astype(np.uint8)) return PILImage.fromarray(np.clip(255.0 * image_tensor.cpu().numpy(), 0, 255).astype(np.uint8))
@staticmethod @staticmethod
def _create_png_metadata(cls: Type[ComfyNode] | None) -> PngInfo | None: def _create_png_metadata(cls: type[ComfyNode] | None) -> PngInfo | None:
"""Creates a PngInfo object with prompt and extra_pnginfo.""" """Creates a PngInfo object with prompt and extra_pnginfo."""
if args.disable_metadata or cls is None or not cls.hidden: if args.disable_metadata or cls is None or not cls.hidden:
return None return None
@ -96,7 +95,7 @@ class ImageSaveHelper:
return metadata return metadata
@staticmethod @staticmethod
def _create_animated_png_metadata(cls: Type[ComfyNode] | None) -> PngInfo | None: def _create_animated_png_metadata(cls: type[ComfyNode] | None) -> PngInfo | None:
"""Creates a PngInfo object with prompt and extra_pnginfo for animated PNGs (APNG).""" """Creates a PngInfo object with prompt and extra_pnginfo for animated PNGs (APNG)."""
if args.disable_metadata or cls is None or not cls.hidden: if args.disable_metadata or cls is None or not cls.hidden:
return None return None
@ -121,7 +120,7 @@ class ImageSaveHelper:
return metadata return metadata
@staticmethod @staticmethod
def _create_webp_metadata(pil_image: PILImage.Image, cls: Type[ComfyNode] | None) -> PILImage.Exif: def _create_webp_metadata(pil_image: PILImage.Image, cls: type[ComfyNode] | None) -> PILImage.Exif:
"""Creates EXIF metadata bytes for WebP images.""" """Creates EXIF metadata bytes for WebP images."""
exif_data = pil_image.getexif() exif_data = pil_image.getexif()
if args.disable_metadata or cls is None or cls.hidden is None: if args.disable_metadata or cls is None or cls.hidden is None:
@ -137,7 +136,7 @@ class ImageSaveHelper:
@staticmethod @staticmethod
def save_images( def save_images(
images, filename_prefix: str, folder_type: FolderType, cls: Type[ComfyNode] | None, compress_level = 4, images, filename_prefix: str, folder_type: FolderType, cls: type[ComfyNode] | None, compress_level = 4,
) -> list[SavedResult]: ) -> list[SavedResult]:
"""Saves a batch of images as individual PNG files.""" """Saves a batch of images as individual PNG files."""
full_output_folder, filename, counter, subfolder, _ = folder_paths.get_save_image_path( full_output_folder, filename, counter, subfolder, _ = folder_paths.get_save_image_path(
@ -155,7 +154,7 @@ class ImageSaveHelper:
return results return results
@staticmethod @staticmethod
def get_save_images_ui(images, filename_prefix: str, cls: Type[ComfyNode] | None, compress_level=4) -> SavedImages: def get_save_images_ui(images, filename_prefix: str, cls: type[ComfyNode] | None, compress_level=4) -> SavedImages:
"""Saves a batch of images and returns a UI object for the node output.""" """Saves a batch of images and returns a UI object for the node output."""
return SavedImages( return SavedImages(
ImageSaveHelper.save_images( ImageSaveHelper.save_images(
@ -169,7 +168,7 @@ class ImageSaveHelper:
@staticmethod @staticmethod
def save_animated_png( def save_animated_png(
images, filename_prefix: str, folder_type: FolderType, cls: Type[ComfyNode] | None, fps: float, compress_level: int images, filename_prefix: str, folder_type: FolderType, cls: type[ComfyNode] | None, fps: float, compress_level: int
) -> SavedResult: ) -> SavedResult:
"""Saves a batch of images as a single animated PNG.""" """Saves a batch of images as a single animated PNG."""
full_output_folder, filename, counter, subfolder, _ = folder_paths.get_save_image_path( full_output_folder, filename, counter, subfolder, _ = folder_paths.get_save_image_path(
@ -191,7 +190,7 @@ class ImageSaveHelper:
@staticmethod @staticmethod
def get_save_animated_png_ui( def get_save_animated_png_ui(
images, filename_prefix: str, cls: Type[ComfyNode] | None, fps: float, compress_level: int images, filename_prefix: str, cls: type[ComfyNode] | None, fps: float, compress_level: int
) -> SavedImages: ) -> SavedImages:
"""Saves an animated PNG and returns a UI object for the node output.""" """Saves an animated PNG and returns a UI object for the node output."""
result = ImageSaveHelper.save_animated_png( result = ImageSaveHelper.save_animated_png(
@ -209,7 +208,7 @@ class ImageSaveHelper:
images, images,
filename_prefix: str, filename_prefix: str,
folder_type: FolderType, folder_type: FolderType,
cls: Type[ComfyNode] | None, cls: type[ComfyNode] | None,
fps: float, fps: float,
lossless: bool, lossless: bool,
quality: int, quality: int,
@ -238,7 +237,7 @@ class ImageSaveHelper:
def get_save_animated_webp_ui( def get_save_animated_webp_ui(
images, images,
filename_prefix: str, filename_prefix: str,
cls: Type[ComfyNode] | None, cls: type[ComfyNode] | None,
fps: float, fps: float,
lossless: bool, lossless: bool,
quality: int, quality: int,
@ -267,7 +266,7 @@ class AudioSaveHelper:
audio: dict, audio: dict,
filename_prefix: str, filename_prefix: str,
folder_type: FolderType, folder_type: FolderType,
cls: Type[ComfyNode] | None, cls: type[ComfyNode] | None,
format: str = "flac", format: str = "flac",
quality: str = "128k", quality: str = "128k",
) -> list[SavedResult]: ) -> list[SavedResult]:
@ -372,7 +371,7 @@ class AudioSaveHelper:
@staticmethod @staticmethod
def get_save_audio_ui( def get_save_audio_ui(
audio, filename_prefix: str, cls: Type[ComfyNode] | None, format: str = "flac", quality: str = "128k", audio, filename_prefix: str, cls: type[ComfyNode] | None, format: str = "flac", quality: str = "128k",
) -> SavedAudios: ) -> SavedAudios:
"""Save and instantly wrap for UI.""" """Save and instantly wrap for UI."""
return SavedAudios( return SavedAudios(
@ -388,7 +387,7 @@ class AudioSaveHelper:
class PreviewImage(_UIOutput): class PreviewImage(_UIOutput):
def __init__(self, image: Image.Type, animated: bool = False, cls: Type[ComfyNode] = None, **kwargs): def __init__(self, image: Image.Type, animated: bool = False, cls: type[ComfyNode] = None, **kwargs):
self.values = ImageSaveHelper.save_images( self.values = ImageSaveHelper.save_images(
image, image,
filename_prefix="ComfyUI_temp_" + ''.join(random.choice("abcdefghijklmnopqrstupvxyz") for _ in range(5)), filename_prefix="ComfyUI_temp_" + ''.join(random.choice("abcdefghijklmnopqrstupvxyz") for _ in range(5)),
@ -412,7 +411,7 @@ class PreviewMask(PreviewImage):
class PreviewAudio(_UIOutput): class PreviewAudio(_UIOutput):
def __init__(self, audio: dict, cls: Type[ComfyNode] = None, **kwargs): def __init__(self, audio: dict, cls: type[ComfyNode] = None, **kwargs):
self.values = AudioSaveHelper.save_audio( self.values = AudioSaveHelper.save_audio(
audio, audio,
filename_prefix="ComfyUI_temp_" + "".join(random.choice("abcdefghijklmnopqrstuvwxyz") for _ in range(5)), filename_prefix="ComfyUI_temp_" + "".join(random.choice("abcdefghijklmnopqrstuvwxyz") for _ in range(5)),

View File

@ -2,9 +2,8 @@ from comfy_api.latest import ComfyAPI_latest
from comfy_api.v0_0_2 import ComfyAPIAdapter_v0_0_2 from comfy_api.v0_0_2 import ComfyAPIAdapter_v0_0_2
from comfy_api.v0_0_1 import ComfyAPIAdapter_v0_0_1 from comfy_api.v0_0_1 import ComfyAPIAdapter_v0_0_1
from comfy_api.internal import ComfyAPIBase from comfy_api.internal import ComfyAPIBase
from typing import List, Type
supported_versions: List[Type[ComfyAPIBase]] = [ supported_versions: list[type[ComfyAPIBase]] = [
ComfyAPI_latest, ComfyAPI_latest,
ComfyAPIAdapter_v0_0_2, ComfyAPIAdapter_v0_0_2,
ComfyAPIAdapter_v0_0_1, ComfyAPIAdapter_v0_0_1,