mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-01-10 06:10:50 +08:00
Fix CLIPLoader node, fix CustomNode typing, improve digest
This commit is contained in:
parent
bae2068111
commit
e6623a1359
@ -2,10 +2,19 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
|
from typing_extensions import Buffer
|
||||||
|
|
||||||
|
|
||||||
def digest(data: dict | str) -> str:
|
def digest(data: dict | str | Buffer) -> str:
|
||||||
json_str = data if isinstance(data, str) else json.dumps(data, separators=(',', ':'))
|
|
||||||
hash_object = hashlib.sha256()
|
hash_object = hashlib.sha256()
|
||||||
hash_object.update(json_str.encode())
|
if isinstance(data, Buffer):
|
||||||
|
hash_object.update(data)
|
||||||
|
else:
|
||||||
|
if isinstance(data, str):
|
||||||
|
json_str = data
|
||||||
|
elif isinstance(data, dict):
|
||||||
|
json_str = json.dumps(data, separators=(',', ':'))
|
||||||
|
else:
|
||||||
|
raise RuntimeError("invalid data type")
|
||||||
|
hash_object.update(json_str.encode())
|
||||||
return hash_object.hexdigest()
|
return hash_object.hexdigest()
|
||||||
|
|||||||
@ -833,9 +833,9 @@ class CLIPLoader:
|
|||||||
CATEGORY = "advanced/loaders"
|
CATEGORY = "advanced/loaders"
|
||||||
|
|
||||||
def load_clip(self, clip_name, type="stable_diffusion"):
|
def load_clip(self, clip_name, type="stable_diffusion"):
|
||||||
clip_type = comfy.sd.CLIPType.STABLE_DIFFUSION
|
clip_type = sd.CLIPType.STABLE_DIFFUSION
|
||||||
if type == "stable_cascade":
|
if type == "stable_cascade":
|
||||||
clip_type = comfy.sd.CLIPType.STABLE_CASCADE
|
clip_type = sd.CLIPType.STABLE_CASCADE
|
||||||
|
|
||||||
clip_path = folder_paths.get_full_path("clip", clip_name)
|
clip_path = folder_paths.get_full_path("clip", clip_name)
|
||||||
clip = sd.load_clip(ckpt_paths=[clip_path], embedding_directory=folder_paths.get_folder_paths("embeddings"), clip_type=clip_type)
|
clip = sd.load_clip(ckpt_paths=[clip_path], embedding_directory=folder_paths.get_folder_paths("embeddings"), clip_type=clip_type)
|
||||||
|
|||||||
@ -1,50 +1,96 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import TypedDict, Union, Optional, Sequence, Dict, ClassVar, Protocol, Tuple, TypeVar, Any, Literal, \
|
from typing_extensions import TypedDict, NotRequired, Generic
|
||||||
Callable
|
from typing import Union, Optional, Sequence, Dict, ClassVar, Protocol, Tuple, TypeVar, Any, Literal, \
|
||||||
|
Callable, List
|
||||||
|
|
||||||
T = TypeVar('T')
|
T = TypeVar('T')
|
||||||
|
|
||||||
|
|
||||||
class NumberSpecOptions(TypedDict, total=False):
|
class IntSpecOptions(TypedDict, total=True):
|
||||||
default: Union[int, float]
|
default: int
|
||||||
min: Union[int, float]
|
min: int
|
||||||
max: Union[int, float]
|
max: int
|
||||||
step: Union[int, float]
|
step: NotRequired[int]
|
||||||
round: int
|
display: NotRequired[Literal["number", "slider"]]
|
||||||
|
|
||||||
|
|
||||||
IntSpec = Dict[str, Union[
|
class FloatSpecOptions(TypedDict, total=True):
|
||||||
Literal["INT"],
|
default: float
|
||||||
Tuple[Literal["INT"], Dict[str, Union[int, float, str]]]
|
min: float
|
||||||
]]
|
max: float
|
||||||
FloatSpec = Dict[str, Union[
|
step: NotRequired[float]
|
||||||
Literal["FLOAT"],
|
round: NotRequired[float]
|
||||||
Tuple[Literal["FLOAT"], Dict[str, Union[int, float, str]]]
|
display: NotRequired[Literal["number", "slider"]]
|
||||||
]]
|
|
||||||
StringSpec = Dict[str, Union[
|
|
||||||
Literal["STRING"],
|
|
||||||
Tuple[Literal["STRING"], Dict[str, str]]
|
|
||||||
]]
|
|
||||||
ChoiceSpec = Dict[str, Union[
|
|
||||||
Sequence[str], # Directly a list of choices
|
|
||||||
Tuple[Sequence[str], Dict[str, Any]] # Choices with additional specifications
|
|
||||||
]]
|
|
||||||
|
|
||||||
ComplexInputSpec = Dict[str, Any]
|
|
||||||
InputTypeSpec = Union[IntSpec, FloatSpec, StringSpec, ChoiceSpec, ComplexInputSpec]
|
|
||||||
|
|
||||||
|
|
||||||
class InputTypes(Protocol):
|
class StringSpecOptions(TypedDict, total=True):
|
||||||
|
multiline: NotRequired[bool]
|
||||||
|
default: NotRequired[str]
|
||||||
|
|
||||||
|
|
||||||
|
# todo: analyze the base_nodes for these types
|
||||||
|
CommonReturnTypes = Union[
|
||||||
|
Literal["IMAGE", "STRING", "INT", "FLOAT", "CONDITIONING", "LATENT", "MASK", "MODEL", "VAE", "CLIP"], str]
|
||||||
|
|
||||||
|
IntSpec = Tuple[Literal["INT"], IntSpecOptions]
|
||||||
|
|
||||||
|
FloatSpec = Tuple[Literal["FLOAT"], FloatSpecOptions]
|
||||||
|
|
||||||
|
StringSpec = Tuple[Literal["STRING"], StringSpecOptions]
|
||||||
|
|
||||||
|
ChoiceSpec = Tuple[Union[Sequence[str], Sequence[float], Sequence[int]]]
|
||||||
|
|
||||||
|
NonPrimitiveTypeSpec = Tuple[CommonReturnTypes]
|
||||||
|
|
||||||
|
InputTypeSpec = Union[IntSpec, FloatSpec, StringSpec, ChoiceSpec, NonPrimitiveTypeSpec]
|
||||||
|
|
||||||
|
|
||||||
|
class HiddenSpec(TypedDict, total=True):
|
||||||
|
prompt: Literal["PROMPT"]
|
||||||
|
extra_pnginfo: Literal["EXTRA_PNGINFO"]
|
||||||
|
|
||||||
|
|
||||||
|
class InputTypes(TypedDict, total=True):
|
||||||
required: Dict[str, InputTypeSpec]
|
required: Dict[str, InputTypeSpec]
|
||||||
optional: Optional[Dict[str, InputTypeSpec]]
|
optional: NotRequired[Dict[str, InputTypeSpec]]
|
||||||
hidden: Optional[Dict[str, InputTypeSpec]]
|
hidden: NotRequired[HiddenSpec]
|
||||||
|
|
||||||
|
|
||||||
ValidateInputsMethod = Optional[Callable[..., Union[bool, str]]]
|
ValidateInputsMethod = Optional[Callable[..., Union[bool, str]]]
|
||||||
|
|
||||||
|
|
||||||
|
class FunctionReturnsUIVariables(TypedDict):
|
||||||
|
ui: dict
|
||||||
|
|
||||||
|
|
||||||
|
class SaveNodeResult(TypedDict, total=True):
|
||||||
|
abs_path: NotRequired[str]
|
||||||
|
filename: str
|
||||||
|
subfolder: str
|
||||||
|
type: Literal["output", "input", "temp"]
|
||||||
|
|
||||||
|
|
||||||
|
class UIImagesImagesResult(TypedDict, total=True):
|
||||||
|
images: List[SaveNodeResult]
|
||||||
|
|
||||||
|
|
||||||
|
class UIImagesResult(TypedDict, total=True):
|
||||||
|
ui: UIImagesImagesResult
|
||||||
|
|
||||||
|
|
||||||
|
class UILatentsLatentsResult(TypedDict, total=True):
|
||||||
|
latents: List[SaveNodeResult]
|
||||||
|
|
||||||
|
|
||||||
|
class UILatentsResult(TypedDict, total=True):
|
||||||
|
ui: UILatentsLatentsResult
|
||||||
|
|
||||||
|
|
||||||
|
ValidatedNodeResult = Union[Tuple, UIImagesResult, UILatentsResult, FunctionReturnsUIVariables]
|
||||||
|
|
||||||
|
|
||||||
class CustomNode(Protocol):
|
class CustomNode(Protocol):
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(cls) -> InputTypes: ...
|
def INPUT_TYPES(cls) -> InputTypes: ...
|
||||||
@ -52,9 +98,9 @@ class CustomNode(Protocol):
|
|||||||
# Optional method signature for VALIDATE_INPUTS
|
# Optional method signature for VALIDATE_INPUTS
|
||||||
VALIDATE_INPUTS: ClassVar[ValidateInputsMethod] = None
|
VALIDATE_INPUTS: ClassVar[ValidateInputsMethod] = None
|
||||||
|
|
||||||
RETURN_TYPES: ClassVar[Sequence[str]]
|
RETURN_TYPES: ClassVar[Tuple[CommonReturnTypes, ...]]
|
||||||
RETURN_NAMES: Optional[ClassVar[Tuple[str]]]
|
RETURN_NAMES: Optional[ClassVar[Tuple[str, ...]]]
|
||||||
OUTPUT_IS_LIST: Optional[ClassVar[Sequence[bool]]]
|
OUTPUT_IS_LIST: Optional[ClassVar[Tuple[bool, ...]]]
|
||||||
INPUT_IS_LIST: Optional[ClassVar[bool]]
|
INPUT_IS_LIST: Optional[ClassVar[bool]]
|
||||||
FUNCTION: ClassVar[str]
|
FUNCTION: ClassVar[str]
|
||||||
CATEGORY: ClassVar[str]
|
CATEGORY: ClassVar[str]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user