drawthings-py 0.2.1__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/PKG-INFO +1 -1
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/pyproject.toml +2 -2
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/__init__.py +2 -2
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/_dt_service.py +9 -1
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/cli_service.py +7 -1
- drawthings_py-0.3.0/src/drawthings_py/configs/_util.py +70 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/configs/config_dict.py +7 -1
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/configs/config_prop.py +33 -2
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/configs/configs.py +3 -24
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/configs/gen_config.py +17 -16
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/configs/presets.py +33 -1
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/configs/types.py +1 -1
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/drawthings.py +1 -1
- {drawthings_py-0.2.1/src/drawthings_py → drawthings_py-0.3.0/src/drawthings_py/grpc}/grpc_service.py +28 -9
- {drawthings_py-0.2.1/src/drawthings_py → drawthings_py-0.3.0/src/drawthings_py/image}/_metadata.py +1 -1
- {drawthings_py-0.2.1/src/drawthings_py → drawthings_py-0.3.0/src/drawthings_py/image}/_png_writer.py +1 -1
- {drawthings_py-0.2.1/src/drawthings_py → drawthings_py-0.3.0/src/drawthings_py/image}/_preview_decoders.py +1 -1
- {drawthings_py-0.2.1/src/drawthings_py → drawthings_py-0.3.0/src/drawthings_py/image}/image_buffer.py +2 -2
- drawthings_py-0.3.0/src/drawthings_py/models/__init__.py +6 -0
- drawthings_py-0.3.0/src/drawthings_py/models/grpc_models_source.py +46 -0
- drawthings_py-0.3.0/src/drawthings_py/models/types.py +121 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/request_builder.py +5 -5
- drawthings_py-0.3.0/src/drawthings_py/util/mixins.py +10 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/LICENSE +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/README.md +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/configs/__init__.py +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/configs/enums.py +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/configs/prop_schema.py +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/generated/dt_grpc/__init__.py +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/generated/dt_grpc/config_generated.py +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/generated/dt_grpc/config_generated.pyi +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/generated/dt_grpc/image_service/__init__.py +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/py.typed +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/config_props.yaml +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/anima_preview_3.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/chroma_hd.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/default.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/ernie_image_base.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/ernie_image_turbo.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/flux_1_dev.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/flux_1_fill_dev.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/flux_1_schnell.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/flux_2_dev_with_turbo.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/flux_2_klein_4b.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/flux_2_klein_4b_base.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/flux_2_klein_9b.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/flux_2_klein_9b_base.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/flux_2_klein_9b_kv.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/qwen_image_2512.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/qwen_image_2512_lightning.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/qwen_image_edit_2511.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/qwen_image_edit_2511_lightning.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/sdxl.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/stable_diffusion.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/z_image_base.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/z_image_turbo.json +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/enums.yaml +0 -0
- {drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/root_ca.crt +0 -0
- {drawthings_py-0.2.1/src/drawthings_py → drawthings_py-0.3.0/src/drawthings_py/util}/_errors.py +0 -0
- {drawthings_py-0.2.1/src/drawthings_py → drawthings_py-0.3.0/src/drawthings_py/util}/_util.py +0 -0
- {drawthings_py-0.2.1/src/drawthings_py → drawthings_py-0.3.0/src/drawthings_py/util}/filename_pattern.py +0 -0
- {drawthings_py-0.2.1/src/drawthings_py → drawthings_py-0.3.0/src/drawthings_py/util}/seed_provider.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "drawthings-py"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0"
|
|
4
4
|
description = "Python SDK for automating Draw Things image generation over gRPC."
|
|
5
5
|
authors = [{ name = "Kelly Jerrell", email = "kcjerrell@gmail.com" }]
|
|
6
6
|
readme = "README.md"
|
|
@@ -83,7 +83,7 @@ ignore_missing_imports = true
|
|
|
83
83
|
include = ["src"]
|
|
84
84
|
exclude = [
|
|
85
85
|
"src/drawthings_py/generated",
|
|
86
|
-
"src/drawthings_py/_metadata.py",
|
|
86
|
+
"src/drawthings_py/image/_metadata.py",
|
|
87
87
|
"src/drawthings_py/configs/gen_config_generated.py",
|
|
88
88
|
"scripts/gen"
|
|
89
89
|
]
|
|
@@ -4,8 +4,8 @@ Draw Things Python SDK
|
|
|
4
4
|
|
|
5
5
|
import drawthings_py.drawthings as DrawThings
|
|
6
6
|
from .configs import Configs, ConfigDict, Presets
|
|
7
|
-
from .filename_pattern import FilenamePattern
|
|
8
|
-
from .image_buffer import ImageBuffer
|
|
7
|
+
from .util.filename_pattern import FilenamePattern
|
|
8
|
+
from .image.image_buffer import ImageBuffer
|
|
9
9
|
from .request_builder import RequestBuilder
|
|
10
10
|
|
|
11
11
|
__all__ = [
|
|
@@ -6,7 +6,9 @@ from __future__ import annotations
|
|
|
6
6
|
from abc import ABC, abstractmethod
|
|
7
7
|
from types import TracebackType
|
|
8
8
|
|
|
9
|
-
from .
|
|
9
|
+
from drawthings_py.models.types import ModelsInfo
|
|
10
|
+
|
|
11
|
+
from .image.image_buffer import ImageBuffer
|
|
10
12
|
from .request_builder import RequestBuilder
|
|
11
13
|
|
|
12
14
|
|
|
@@ -21,6 +23,12 @@ class DrawThingsService(ABC):
|
|
|
21
23
|
Generate an image from the provided request builder
|
|
22
24
|
"""
|
|
23
25
|
|
|
26
|
+
@abstractmethod
|
|
27
|
+
async def get_models(self) -> ModelsInfo:
|
|
28
|
+
"""
|
|
29
|
+
Get models from the service
|
|
30
|
+
"""
|
|
31
|
+
|
|
24
32
|
@abstractmethod
|
|
25
33
|
def _dispose(self):
|
|
26
34
|
"""
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from typing_extensions import override
|
|
2
2
|
|
|
3
|
+
from drawthings_py.models.types import ModelsInfo
|
|
4
|
+
|
|
3
5
|
from ._dt_service import DrawThingsService
|
|
4
|
-
from .image_buffer import ImageBuffer
|
|
6
|
+
from .image.image_buffer import ImageBuffer
|
|
5
7
|
from .request_builder import RequestBuilder
|
|
6
8
|
|
|
7
9
|
|
|
@@ -16,6 +18,10 @@ class CliService(DrawThingsService):
|
|
|
16
18
|
"""
|
|
17
19
|
raise NotImplementedError("this is not implemented yet")
|
|
18
20
|
|
|
21
|
+
@override
|
|
22
|
+
async def get_models(self) -> ModelsInfo:
|
|
23
|
+
raise NotImplementedError("this is not implemented yet")
|
|
24
|
+
|
|
19
25
|
@override
|
|
20
26
|
async def generate_image(self, request: RequestBuilder) -> list[ImageBuffer]:
|
|
21
27
|
raise NotImplementedError("this is not implemented yet")
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from drawthings_py.configs.config_dict import ConfigDict
|
|
2
|
+
from drawthings_py.configs.gen_config import GenConfig
|
|
3
|
+
from drawthings_py.configs.enums import sampler_type_from_value
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def describe_config(config: GenConfig | ConfigDict) -> str:
|
|
7
|
+
cd = config._d if isinstance(config, GenConfig) else config # pyright: ignore[reportPrivateUsage]
|
|
8
|
+
|
|
9
|
+
# flux_klein.cktp, 1024x1024, Strength: 0.9, 20 steps.
|
|
10
|
+
# EulerA sampler, CFG: 2.5, Shift: auto, flux_turbo.ckpt and
|
|
11
|
+
# flux_boobs.skpt lora
|
|
12
|
+
|
|
13
|
+
leading: list[str] = []
|
|
14
|
+
if model := cd.get("model"):
|
|
15
|
+
leading.append(model)
|
|
16
|
+
if (width := cd.get("width")) and (height := cd.get("height")):
|
|
17
|
+
leading.append(f"{width}x{height}")
|
|
18
|
+
|
|
19
|
+
# Strength (omit when 1.0) and steps
|
|
20
|
+
mid: list[str] = []
|
|
21
|
+
if (strength := cd.get("strength")) is not None and float(strength) != 1.0:
|
|
22
|
+
mid.append(f"Strength: {strength}")
|
|
23
|
+
if steps := cd.get("steps"):
|
|
24
|
+
mid.append(f"{steps} steps")
|
|
25
|
+
|
|
26
|
+
# Sampler, CFG (guidance), shift, and loras
|
|
27
|
+
tail: list[str] = []
|
|
28
|
+
if (sampler := cd.get("sampler")) is not None:
|
|
29
|
+
tail.append(f"{sampler_type_from_value(sampler)} sampler")
|
|
30
|
+
if (guidance := cd.get("guidance")) is not None:
|
|
31
|
+
tail.append(f"CFG: {guidance}")
|
|
32
|
+
|
|
33
|
+
# Shift: "auto" when resolution_dependent_shift is True
|
|
34
|
+
if cd.get("resolution_dependent_shift"):
|
|
35
|
+
shift_val: str | float | None = "auto"
|
|
36
|
+
else:
|
|
37
|
+
shift_val = cd.get("shift")
|
|
38
|
+
if shift_val is not None:
|
|
39
|
+
tail.append(f"Shift: {shift_val}")
|
|
40
|
+
|
|
41
|
+
# Loras: list filenames
|
|
42
|
+
lora_files: list[str] = []
|
|
43
|
+
if loras := cd.get("loras"):
|
|
44
|
+
for lora in loras:
|
|
45
|
+
f = lora.get("file")
|
|
46
|
+
if f:
|
|
47
|
+
lora_files.append(f)
|
|
48
|
+
if lora_files:
|
|
49
|
+
if len(lora_files) == 1:
|
|
50
|
+
lf = lora_files[0]
|
|
51
|
+
elif len(lora_files) == 2:
|
|
52
|
+
lf = f"{lora_files[0]} and {lora_files[1]}"
|
|
53
|
+
else:
|
|
54
|
+
lf = ", ".join(lora_files[:-1]) + f", and {lora_files[-1]}"
|
|
55
|
+
tail.append(f"{lf} lora")
|
|
56
|
+
|
|
57
|
+
# Build the final description
|
|
58
|
+
parts: list[str] = []
|
|
59
|
+
if leading:
|
|
60
|
+
first = ", ".join(leading)
|
|
61
|
+
if mid:
|
|
62
|
+
first = f"{first}, {', '.join(mid)}."
|
|
63
|
+
else:
|
|
64
|
+
first = f"{first}."
|
|
65
|
+
parts.append(first)
|
|
66
|
+
|
|
67
|
+
if tail:
|
|
68
|
+
parts.append(", ".join(tail))
|
|
69
|
+
|
|
70
|
+
return " ".join(parts).strip()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import TypedDict, TypeAlias, Literal
|
|
1
|
+
from typing import TypeGuard, TypedDict, TypeAlias, Literal, get_args
|
|
2
2
|
from drawthings_py.configs.types import (
|
|
3
3
|
CompressionMethod,
|
|
4
4
|
ControlDict,
|
|
@@ -111,6 +111,12 @@ ConfigKey = Literal[
|
|
|
111
111
|
"compression_artifacts_quality",
|
|
112
112
|
]
|
|
113
113
|
|
|
114
|
+
_CONFIG_KEYS = frozenset(get_args(ConfigKey))
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def is_config_key(value: str) -> TypeGuard[ConfigKey]:
|
|
118
|
+
return value in _CONFIG_KEYS
|
|
119
|
+
|
|
114
120
|
|
|
115
121
|
class ConfigDict(TypedDict, total=False):
|
|
116
122
|
id: int
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
|
+
import json
|
|
2
3
|
from types import NoneType
|
|
3
4
|
from typing import Callable, Generic, Protocol, TypeVar, cast
|
|
4
5
|
|
|
@@ -19,14 +20,14 @@ from drawthings_py.generated.dt_grpc.config_generated import (
|
|
|
19
20
|
GenerationConfigurationT,
|
|
20
21
|
LoRAT,
|
|
21
22
|
)
|
|
22
|
-
from drawthings_py._util import (
|
|
23
|
+
from drawthings_py.util._util import (
|
|
23
24
|
ensure_str,
|
|
24
25
|
random_seed,
|
|
25
26
|
snake_to_camel,
|
|
26
27
|
try_parse_float,
|
|
27
28
|
try_parse_int,
|
|
28
29
|
)
|
|
29
|
-
from .config_dict import
|
|
30
|
+
from .config_dict import ConfigDict, ConfigKey, ConfigValue
|
|
30
31
|
from .types import (
|
|
31
32
|
ControlDict,
|
|
32
33
|
LoraDict,
|
|
@@ -524,7 +525,14 @@ class StrEnumProp(ConfigPropBase[str, int], Generic[V]):
|
|
|
524
525
|
return self._default
|
|
525
526
|
|
|
526
527
|
|
|
528
|
+
_config_props: dict[ConfigKey, ConfigProp] | None = None
|
|
529
|
+
|
|
530
|
+
|
|
527
531
|
def load_props() -> dict[ConfigKey, ConfigProp]:
|
|
532
|
+
global _config_props
|
|
533
|
+
if _config_props:
|
|
534
|
+
return _config_props
|
|
535
|
+
|
|
528
536
|
props: dict[ConfigKey, ConfigProp] = {}
|
|
529
537
|
|
|
530
538
|
definitions = cast(dict[ConfigKey, PropDefinition], load_definitions())
|
|
@@ -550,4 +558,27 @@ def load_props() -> dict[ConfigKey, ConfigProp]:
|
|
|
550
558
|
else:
|
|
551
559
|
print(f"Unknown config property type in YAML: {key}: {prop_type}")
|
|
552
560
|
|
|
561
|
+
_config_props = props
|
|
553
562
|
return props
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
def config_dict_from_json(json_data: str | dict[str, object]) -> ConfigDict:
|
|
566
|
+
if isinstance(json_data, str):
|
|
567
|
+
data = cast(dict[str, object], json.loads(json_data))
|
|
568
|
+
else:
|
|
569
|
+
data = json_data
|
|
570
|
+
config = ConfigDict()
|
|
571
|
+
for prop in load_props().values():
|
|
572
|
+
if value := prop.from_json(data):
|
|
573
|
+
config[prop.name] = value # pyright: ignore[reportGeneralTypeIssues]
|
|
574
|
+
return config
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
def config_dict_from_fbs(data: bytes) -> ConfigDict:
|
|
578
|
+
config_t = GenerationConfigurationT.InitFromPackedBuf(data)
|
|
579
|
+
config = ConfigDict()
|
|
580
|
+
for prop in load_props().values():
|
|
581
|
+
value = prop.from_fbs(config_t)
|
|
582
|
+
if value is not None:
|
|
583
|
+
config[prop.name] = value # pyright: ignore[reportGeneralTypeIssues]
|
|
584
|
+
return config
|
|
@@ -5,13 +5,11 @@ including JSON presets, JSON strings, and Python dictionaries.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import copy
|
|
8
|
-
import
|
|
9
|
-
from importlib.resources import files
|
|
10
|
-
from typing import Unpack, cast
|
|
8
|
+
from typing import Unpack
|
|
11
9
|
|
|
12
10
|
from .gen_config import GenConfig
|
|
13
11
|
from .config_dict import ConfigDict
|
|
14
|
-
from .presets import
|
|
12
|
+
from .presets import PresetName, Presets, load_preset_config
|
|
15
13
|
|
|
16
14
|
|
|
17
15
|
class Configs:
|
|
@@ -35,7 +33,7 @@ class Configs:
|
|
|
35
33
|
ValueError: If the preset file does not exist.
|
|
36
34
|
"""
|
|
37
35
|
try:
|
|
38
|
-
json_str =
|
|
36
|
+
json_str = load_preset_config(name)
|
|
39
37
|
return GenConfig.from_json(json_str)
|
|
40
38
|
except FileNotFoundError:
|
|
41
39
|
raise ValueError(f"Unknown preset: {name}")
|
|
@@ -89,22 +87,3 @@ class Configs:
|
|
|
89
87
|
for config_copy in reversed(copies):
|
|
90
88
|
d.update(config_copy)
|
|
91
89
|
return GenConfig(**d)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
def _load_preset_json(name: PresetName | Presets) -> str:
|
|
95
|
-
"""Get the JSON string for a named preset.
|
|
96
|
-
|
|
97
|
-
Args:
|
|
98
|
-
name: The name of the preset to get.
|
|
99
|
-
|
|
100
|
-
Returns:
|
|
101
|
-
A JSON string containing the preset data.
|
|
102
|
-
"""
|
|
103
|
-
filename = name + ".json"
|
|
104
|
-
path = files("drawthings_py.resources.configs") / filename
|
|
105
|
-
preset: PresetDefinition | None = None
|
|
106
|
-
with path.open("r", encoding="utf-8") as f:
|
|
107
|
-
preset = cast(PresetDefinition | None, json.load(f))
|
|
108
|
-
if preset is None:
|
|
109
|
-
raise ValueError(f"Unknown preset: {name}")
|
|
110
|
-
return json.dumps(preset["configuration"])
|
|
@@ -2,10 +2,18 @@ from __future__ import annotations
|
|
|
2
2
|
from collections.abc import MutableMapping, Iterator
|
|
3
3
|
from typing import Unpack, overload, Literal, cast
|
|
4
4
|
from typing_extensions import override
|
|
5
|
-
import json
|
|
6
5
|
import flatbuffers # pyright: ignore[reportMissingTypeStubs]
|
|
7
|
-
from drawthings_py.configs.config_dict import
|
|
8
|
-
|
|
6
|
+
from drawthings_py.configs.config_dict import (
|
|
7
|
+
ConfigDict,
|
|
8
|
+
ConfigKey,
|
|
9
|
+
ConfigValue,
|
|
10
|
+
is_config_key,
|
|
11
|
+
)
|
|
12
|
+
from drawthings_py.configs.config_prop import (
|
|
13
|
+
config_dict_from_fbs,
|
|
14
|
+
config_dict_from_json,
|
|
15
|
+
load_props,
|
|
16
|
+
)
|
|
9
17
|
from drawthings_py.generated.dt_grpc.config_generated import GenerationConfigurationT
|
|
10
18
|
from drawthings_py.configs.types import (
|
|
11
19
|
CompressionMethod,
|
|
@@ -203,7 +211,9 @@ class GenConfig(MutableMapping[ConfigKey, ConfigValue]):
|
|
|
203
211
|
config: A dictionary of configuration values to set.
|
|
204
212
|
**kwargs: Keyword arguments of configuration values to set.
|
|
205
213
|
"""
|
|
206
|
-
|
|
214
|
+
for key, value in (config or kwargs).items():
|
|
215
|
+
if is_config_key(key) and value is not None:
|
|
216
|
+
self._d[key] = cast(ConfigValue, value) # pyright: ignore[reportGeneralTypeIssues]
|
|
207
217
|
|
|
208
218
|
@overload
|
|
209
219
|
def set_hires_fix(self, value: None, /) -> None: ...
|
|
@@ -422,20 +432,11 @@ class GenConfig(MutableMapping[ConfigKey, ConfigValue]):
|
|
|
422
432
|
return bytes(builder.Output())
|
|
423
433
|
|
|
424
434
|
@classmethod
|
|
425
|
-
def from_json(cls,
|
|
426
|
-
|
|
427
|
-
config = ConfigDict()
|
|
428
|
-
for prop in CONFIG_PROPS.values():
|
|
429
|
-
if value := prop.from_json(data):
|
|
430
|
-
config[prop.name] = value # pyright: ignore[reportGeneralTypeIssues]
|
|
435
|
+
def from_json(cls, json_data: str | dict[str, object]) -> GenConfig:
|
|
436
|
+
config = config_dict_from_json(json_data)
|
|
431
437
|
return cls(**config)
|
|
432
438
|
|
|
433
439
|
@classmethod
|
|
434
440
|
def from_fbs(cls, data: bytes) -> GenConfig:
|
|
435
|
-
|
|
436
|
-
config = ConfigDict()
|
|
437
|
-
for prop in CONFIG_PROPS.values():
|
|
438
|
-
value = prop.from_fbs(config_t)
|
|
439
|
-
if value is not None:
|
|
440
|
-
config[prop.name] = value # pyright: ignore[reportGeneralTypeIssues]
|
|
441
|
+
config = config_dict_from_fbs(data)
|
|
441
442
|
return cls(**config)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from enum import StrEnum
|
|
2
|
-
from
|
|
2
|
+
from importlib.resources import files
|
|
3
|
+
import json
|
|
4
|
+
from typing import Literal, Required, TypedDict, cast
|
|
3
5
|
|
|
4
6
|
from .config_dict import ConfigDict
|
|
5
7
|
|
|
@@ -56,3 +58,33 @@ class PresetDefinition(TypedDict, total=False):
|
|
|
56
58
|
configuration: Required[ConfigDict]
|
|
57
59
|
name: Required[str]
|
|
58
60
|
version: str
|
|
61
|
+
|
|
62
|
+
def load_preset_data(name: PresetName | Presets | str) -> PresetDefinition:
|
|
63
|
+
"""Get the JSON string for a named preset.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
name: The name of the preset to get.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
A JSON string containing the preset data.
|
|
70
|
+
"""
|
|
71
|
+
filename = name + ".json"
|
|
72
|
+
path = files("drawthings_py.resources.configs") / filename
|
|
73
|
+
preset: PresetDefinition | None = None
|
|
74
|
+
with path.open("r", encoding="utf-8") as f:
|
|
75
|
+
preset = cast(PresetDefinition | None, json.load(f))
|
|
76
|
+
if preset is None:
|
|
77
|
+
raise ValueError(f"Unknown preset: {name}")
|
|
78
|
+
return preset
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def load_preset_config(name: PresetName | Presets) -> str:
|
|
82
|
+
"""Get the JSON string for a named preset.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
name: The name of the preset to get.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
A JSON string containing the preset data.
|
|
89
|
+
"""
|
|
90
|
+
return json.dumps(load_preset_data(name)["configuration"])
|
|
@@ -27,7 +27,7 @@ def grpc(
|
|
|
27
27
|
port: int - the port of the gRPC server
|
|
28
28
|
return: GrpcService - the gRPC service
|
|
29
29
|
"""
|
|
30
|
-
from .grpc_service import GrpcService # pylint: disable=import-outside-toplevel
|
|
30
|
+
from .grpc.grpc_service import GrpcService # pylint: disable=import-outside-toplevel
|
|
31
31
|
|
|
32
32
|
return GrpcService(
|
|
33
33
|
host=host, port=port, progressbar=progressbar, disable_messages=disable_messages
|
{drawthings_py-0.2.1/src/drawthings_py → drawthings_py-0.3.0/src/drawthings_py/grpc}/grpc_service.py
RENAMED
|
@@ -19,15 +19,22 @@ import tqdm
|
|
|
19
19
|
from grpclib import GRPCError
|
|
20
20
|
from grpclib.client import Channel
|
|
21
21
|
|
|
22
|
-
from .
|
|
23
|
-
from .
|
|
24
|
-
|
|
25
|
-
from .
|
|
26
|
-
from .
|
|
27
|
-
from .
|
|
28
|
-
from .
|
|
29
|
-
from .
|
|
30
|
-
from .
|
|
22
|
+
from drawthings_py.models import GrpcModelsSource
|
|
23
|
+
from drawthings_py.models.types import ModelsInfo
|
|
24
|
+
|
|
25
|
+
from drawthings_py._dt_service import DrawThingsService
|
|
26
|
+
from drawthings_py.util._errors import raise_grpc_error
|
|
27
|
+
from drawthings_py.image._metadata import ImageMetadata, copy_with_seed, create_metadata
|
|
28
|
+
from drawthings_py.image._preview_decoders import decode_preview
|
|
29
|
+
from drawthings_py.util._util import pluralize, seeds_from_batch
|
|
30
|
+
from drawthings_py.generated.dt_grpc.config_generated import GenerationConfiguration
|
|
31
|
+
from drawthings_py.generated.dt_grpc import image_service
|
|
32
|
+
from drawthings_py.image.image_buffer import ImageBuffer
|
|
33
|
+
from drawthings_py.request_builder import (
|
|
34
|
+
ProgressCallback,
|
|
35
|
+
RequestBuilder,
|
|
36
|
+
build_grpc_message,
|
|
37
|
+
)
|
|
31
38
|
|
|
32
39
|
cert_path = files("drawthings_py.resources").joinpath("root_ca.crt")
|
|
33
40
|
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
|
@@ -87,6 +94,7 @@ class GrpcService(DrawThingsService):
|
|
|
87
94
|
|
|
88
95
|
_channel: Channel
|
|
89
96
|
_service: image_service.ImageGenerationServiceStub
|
|
97
|
+
_models: GrpcModelsSource
|
|
90
98
|
|
|
91
99
|
_progressbar: bool
|
|
92
100
|
_disable_messages: bool
|
|
@@ -111,6 +119,12 @@ class GrpcService(DrawThingsService):
|
|
|
111
119
|
self._service = image_service.ImageGenerationServiceStub(self._channel)
|
|
112
120
|
self._progressbar = progressbar
|
|
113
121
|
self._disable_messages = disable_messages
|
|
122
|
+
self._models = GrpcModelsSource(self._service)
|
|
123
|
+
|
|
124
|
+
@override
|
|
125
|
+
async def get_models(self) -> ModelsInfo:
|
|
126
|
+
await self._models.load()
|
|
127
|
+
return self._models._models # pyright: ignore[reportPrivateUsage]
|
|
114
128
|
|
|
115
129
|
@override
|
|
116
130
|
async def generate_image(self, request: RequestBuilder) -> list[ImageBuffer]:
|
|
@@ -273,6 +287,7 @@ def _get_batch_metadata(
|
|
|
273
287
|
metadata_batch = [copy_with_seed(metadata, seed) for seed in seeds]
|
|
274
288
|
return metadata_batch
|
|
275
289
|
|
|
290
|
+
|
|
276
291
|
def _estimate_signposts(
|
|
277
292
|
config: GenerationConfiguration, request: image_service.ImageGenerationRequest
|
|
278
293
|
) -> int:
|
|
@@ -301,3 +316,7 @@ def _estimate_signposts(
|
|
|
301
316
|
est += 1
|
|
302
317
|
|
|
303
318
|
return est
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
# def _get_service_stub(host: str, port: int) -> image_service.ImageGenerationServiceStub:
|
|
322
|
+
# pass
|
{drawthings_py-0.2.1/src/drawthings_py → drawthings_py-0.3.0/src/drawthings_py/image}/_metadata.py
RENAMED
|
@@ -6,7 +6,7 @@ from collections.abc import Callable
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from typing import Any, Required, TypedDict, cast
|
|
8
8
|
|
|
9
|
-
from .generated.dt_grpc.config_generated import GenerationConfiguration
|
|
9
|
+
from drawthings_py.generated.dt_grpc.config_generated import GenerationConfiguration
|
|
10
10
|
|
|
11
11
|
SAMPLER_NAMES: dict[Any, str] = {
|
|
12
12
|
0: "DPM++ 2M Karras",
|
|
@@ -8,8 +8,8 @@ import fpzip
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
from PIL import Image
|
|
10
10
|
|
|
11
|
-
from ._metadata import ImageMetadata
|
|
12
|
-
from ._png_writer import write_png_with_usercomment
|
|
11
|
+
from drawthings_py.image._metadata import ImageMetadata
|
|
12
|
+
from drawthings_py.image._png_writer import write_png_with_usercomment
|
|
13
13
|
|
|
14
14
|
_TENSOR_HEADER_SIZE = 68
|
|
15
15
|
_FPZIP_MAGIC = 1012247
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
from typing_extensions import override
|
|
4
|
+
|
|
5
|
+
from drawthings_py.generated.dt_grpc import image_service
|
|
6
|
+
from drawthings_py.models.types import ModelsInfo
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ModelsSource(ABC): # noqa: F821
|
|
10
|
+
_models: ModelsInfo
|
|
11
|
+
_files: list[str]
|
|
12
|
+
|
|
13
|
+
def __init__(self):
|
|
14
|
+
self._models = ModelsInfo()
|
|
15
|
+
self._files = []
|
|
16
|
+
|
|
17
|
+
@abstractmethod
|
|
18
|
+
async def load(self) -> None:
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class GrpcModelsSource(ModelsSource):
|
|
25
|
+
_service: image_service.ImageGenerationServiceStub
|
|
26
|
+
|
|
27
|
+
def __init__(self, service: image_service.ImageGenerationServiceStub):
|
|
28
|
+
super().__init__()
|
|
29
|
+
self._service = service
|
|
30
|
+
|
|
31
|
+
@override
|
|
32
|
+
async def load(self) -> None:
|
|
33
|
+
req = image_service.EchoRequest(
|
|
34
|
+
"drawthings-py",
|
|
35
|
+
)
|
|
36
|
+
reply = await self._service.echo(req)
|
|
37
|
+
|
|
38
|
+
models = reply.override.models if reply.override is not None else None
|
|
39
|
+
print(f"{len(reply.files)} files. {len(models) if models else 0} models")
|
|
40
|
+
|
|
41
|
+
if reply.override is None:
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
self._models: ModelsInfo = ModelsInfo.from_echo_reply(reply)
|
|
45
|
+
self._files: list[str] = reply.files
|
|
46
|
+
return
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Any, Literal, TypeAlias, cast
|
|
3
|
+
|
|
4
|
+
from drawthings_py.generated.dt_grpc import image_service
|
|
5
|
+
from drawthings_py.util.mixins import ReprMixin
|
|
6
|
+
|
|
7
|
+
ModelTypes = Literal[
|
|
8
|
+
"models", "controlnets", "loras", "upscalers", "textual_inversions"
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ModelBase(ReprMixin):
|
|
13
|
+
file: str = ""
|
|
14
|
+
name: str = ""
|
|
15
|
+
|
|
16
|
+
def __init__(self, **kwargs: object):
|
|
17
|
+
for key, value in kwargs.items():
|
|
18
|
+
setattr(self, key, value)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ModelInfo(ModelBase):
|
|
22
|
+
prefix: str = ""
|
|
23
|
+
version: str = ""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ControlNetInfo(ModelBase):
|
|
27
|
+
modifier: str = ""
|
|
28
|
+
type: str = ""
|
|
29
|
+
global_average_pooling: bool = False
|
|
30
|
+
version: str = ""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class LoRAInfo(ModelBase):
|
|
34
|
+
prefix: str = ""
|
|
35
|
+
mode: str = ""
|
|
36
|
+
version: str = ""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class UpscalerInfo(ModelBase):
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class TextualInversionInfo(ModelBase):
|
|
44
|
+
keyword: str = ""
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
_jl: TypeAlias = list[dict[str, object]]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _cjl(data: Any) -> _jl: # pyright: ignore[reportExplicitAny, reportAny]
|
|
51
|
+
return cast(_jl, data)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ModelsInfo(ReprMixin):
|
|
55
|
+
models: list[ModelInfo]
|
|
56
|
+
controlNets: list[ControlNetInfo]
|
|
57
|
+
loras: list[LoRAInfo]
|
|
58
|
+
upscalers: list[UpscalerInfo]
|
|
59
|
+
textualInversions: list[TextualInversionInfo]
|
|
60
|
+
files: list[str]
|
|
61
|
+
|
|
62
|
+
def __init__(
|
|
63
|
+
self,
|
|
64
|
+
models: list[ModelInfo] | None = None,
|
|
65
|
+
controlNets: list[ControlNetInfo] | None = None,
|
|
66
|
+
loras: list[LoRAInfo] | None = None,
|
|
67
|
+
upscalers: list[UpscalerInfo] | None = None,
|
|
68
|
+
textualInversions: list[TextualInversionInfo] | None = None,
|
|
69
|
+
files: list[str] | None = None,
|
|
70
|
+
):
|
|
71
|
+
self.models = models or []
|
|
72
|
+
self.controlNets = controlNets or []
|
|
73
|
+
self.loras = loras or []
|
|
74
|
+
self.upscalers = upscalers or []
|
|
75
|
+
self.textualInversions = textualInversions or []
|
|
76
|
+
self.files = files or []
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def from_echo_reply(cls, reply: image_service.EchoReply) -> "ModelsInfo":
|
|
80
|
+
data = reply.override
|
|
81
|
+
files = reply.files or []
|
|
82
|
+
|
|
83
|
+
if data is None:
|
|
84
|
+
return cls(files=files)
|
|
85
|
+
|
|
86
|
+
models = (
|
|
87
|
+
[ModelInfo(**item) for item in _cjl(json.loads(data.models))]
|
|
88
|
+
if data.models
|
|
89
|
+
else []
|
|
90
|
+
)
|
|
91
|
+
control_nets = (
|
|
92
|
+
[ControlNetInfo(**item) for item in _cjl(json.loads(data.control_nets))]
|
|
93
|
+
if data.control_nets
|
|
94
|
+
else []
|
|
95
|
+
)
|
|
96
|
+
loras = (
|
|
97
|
+
[LoRAInfo(**item) for item in _cjl(json.loads(data.loras))]
|
|
98
|
+
if data.loras
|
|
99
|
+
else []
|
|
100
|
+
)
|
|
101
|
+
upscalers = (
|
|
102
|
+
[UpscalerInfo(**item) for item in _cjl(json.loads(data.upscalers))]
|
|
103
|
+
if data.upscalers
|
|
104
|
+
else []
|
|
105
|
+
)
|
|
106
|
+
textual_inversions = (
|
|
107
|
+
[
|
|
108
|
+
TextualInversionInfo(**item)
|
|
109
|
+
for item in _cjl(json.loads(data.textual_inversions))
|
|
110
|
+
]
|
|
111
|
+
if data.textual_inversions
|
|
112
|
+
else []
|
|
113
|
+
)
|
|
114
|
+
return cls(
|
|
115
|
+
models=models,
|
|
116
|
+
controlNets=control_nets,
|
|
117
|
+
loras=loras,
|
|
118
|
+
upscalers=upscalers,
|
|
119
|
+
textualInversions=textual_inversions,
|
|
120
|
+
files=reply.files,
|
|
121
|
+
)
|
|
@@ -9,11 +9,11 @@ import os
|
|
|
9
9
|
from dataclasses import dataclass
|
|
10
10
|
from typing import Callable, Literal, TypeAlias, cast
|
|
11
11
|
|
|
12
|
-
from .configs.config_dict import ConfigDict, ConfigKey, ConfigValue
|
|
13
|
-
from .configs.gen_config import GenConfig
|
|
14
|
-
from .generated.dt_grpc import image_service
|
|
15
|
-
from .image_buffer import ImageBuffer
|
|
16
|
-
from .seed_provider import SeedProvider
|
|
12
|
+
from drawthings_py.configs.config_dict import ConfigDict, ConfigKey, ConfigValue
|
|
13
|
+
from drawthings_py.configs.gen_config import GenConfig
|
|
14
|
+
from drawthings_py.generated.dt_grpc import image_service
|
|
15
|
+
from drawthings_py.image.image_buffer import ImageBuffer
|
|
16
|
+
from drawthings_py.util.seed_provider import SeedProvider
|
|
17
17
|
|
|
18
18
|
ImageSource: TypeAlias = str | os.PathLike[str] | ImageBuffer
|
|
19
19
|
"""Type alias for image sources, which can be file paths or ImageBuffer instances."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/generated/dt_grpc/config_generated.py
RENAMED
|
File without changes
|
{drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/generated/dt_grpc/config_generated.pyi
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/anima_preview_3.json
RENAMED
|
File without changes
|
{drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/chroma_hd.json
RENAMED
|
File without changes
|
{drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/default.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/flux_1_dev.json
RENAMED
|
File without changes
|
{drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/flux_1_fill_dev.json
RENAMED
|
File without changes
|
{drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/flux_1_schnell.json
RENAMED
|
File without changes
|
|
File without changes
|
{drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/flux_2_klein_4b.json
RENAMED
|
File without changes
|
|
File without changes
|
{drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/flux_2_klein_9b.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/qwen_image_2512.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/z_image_base.json
RENAMED
|
File without changes
|
{drawthings_py-0.2.1 → drawthings_py-0.3.0}/src/drawthings_py/resources/configs/z_image_turbo.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{drawthings_py-0.2.1/src/drawthings_py → drawthings_py-0.3.0/src/drawthings_py/util}/_errors.py
RENAMED
|
File without changes
|
{drawthings_py-0.2.1/src/drawthings_py → drawthings_py-0.3.0/src/drawthings_py/util}/_util.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|