update installer usage

pull/4663/head
Vladimir Mandic 2026-02-19 12:21:46 +01:00
parent 76a20cf43d
commit 216558185b
34 changed files with 145 additions and 117 deletions

View File

@ -52,7 +52,6 @@ TBD
- refactor: reorganize `cli` scripts
- refactor: move tests to dedicated `/test/`
- refactor: all image handling to `modules/image/`
- refactor: captioning part-2, thanks @CalamitousFelicitousness
- refactor: remove face restoration, thanks @CalamitousFelicitousness
- refactor: unified command line parsing
- refactor: launch use threads to async execute non-critical tasks
@ -61,11 +60,13 @@ TBD
- refactor: improve `pydantic==2.x` compatibility
- refactor: entire logging into separate `modules/logger`
- refactor: replace `timestamp` based startup checks with state caching
- refactor: split monolithic `shared` module and introduce `ui_definitions`
- update `lint` rules, thanks @awsr
- refactor: split monolithic `shared` module and introduce `ui_definitions`
- use `threading` for deferable operatios
- use `threading` for io-independent parallel operations
- remove requirements: `clip`, `open-clip`
- remove `normalbae` pre-processor
- update `requirements`
- refactor: captioning part-2, thanks @CalamitousFelicitousness
- update `lint` rules, thanks @awsr
- **Fixes**
- handle `clip` installer doing unwanted `setuptools` update
- cleanup for `uv` installer fallback

View File

@ -1,4 +1,3 @@
from typing import overload
from functools import lru_cache
import os
import sys
@ -14,7 +13,7 @@ import cProfile
import importlib
import importlib.util
import importlib.metadata
from modules.logger import setup_logging, get_console, get_log, install_traceback, log, console
from modules.logger import setup_logging, log
class Dot(dict): # dot notation access to dictionary attributes
@ -141,7 +140,7 @@ def package_spec(package):
# check if package is installed
def installed(package, friendly: str = None, reload = False, quiet = False): # pylint: disable=redefined-outer-name
def installed(package, friendly: str = None, quiet = False): # pylint: disable=redefined-outer-name
t_start = time.time()
ok = True
try:
@ -275,7 +274,6 @@ def install(package, friendly: str = None, ignore: bool = False, reinstall: bool
isolation = '' if not no_build_isolation else '--no-build-isolation '
cmd = f"install{' --upgrade' if not args.uv else ''}{' --force-reinstall' if force else ''} {deps}{isolation}{package}"
res = pip(cmd, ignore=ignore, uv=package != "uv" and not package.startswith('git+'))
pass
ts('install', t_start)
return res
@ -1095,10 +1093,11 @@ def install_gradio():
# aiofiles-23.2.1 altair-5.5.0 annotated-types-0.7.0 anyio-4.9.0 attrs-25.3.0 certifi-2025.6.15 charset_normalizer-3.4.2 click-8.2.1 contourpy-1.3.2 cycler-0.12.1 fastapi-0.115.14 ffmpy-0.6.0 filelock-3.18.0 fonttools-4.58.4 fsspec-2025.5.1 gradio-3.43.2 gradio-client-0.5.0 h11-0.16.0 hf-xet-1.1.5 httpcore-1.0.9 httpx-0.28.1 huggingface-hub-0.33.1 idna-3.10 importlib-resources-6.5.2 jinja2-3.1.6 jsonschema-4.24.0 jsonschema-specifications-2025.4.1 kiwisolver-1.4.8 markupsafe-2.1.5 matplotlib-3.10.3 narwhals-1.45.0 numpy-1.26.4 orjson-3.10.18 packaging-25.0 pandas-2.3.0 pillow-10.4.0 pydantic-2.11.7 pydantic-core-2.33.2 pydub-0.25.1 pyparsing-3.2.3 python-dateutil-2.9.0.post0 python-multipart-0.0.20 pytz-2025.2 pyyaml-6.0.2 referencing-0.36.2 requests-2.32.4 rpds-py-0.25.1 semantic-version-2.10.0 six-1.17.0 sniffio-1.3.1 starlette-0.46.2 tqdm-4.67.1 typing-extensions-4.14.0 typing-inspection-0.4.1 tzdata-2025.2 urllib3-2.5.0 uvicorn-0.35.0 websockets-11.0.3
install('gradio==3.43.2', no_deps=True)
install('gradio-client==0.5.0', no_deps=True, quiet=True)
pkgs = ['fastapi', 'websockets', 'aiofiles', 'ffmpy', 'pydub', 'uvicorn', 'semantic-version', 'altair', 'python-multipart', 'matplotlib']
for pkg in pkgs:
if not installed(pkg, quiet=True):
install(pkg, quiet=True)
if not quick_allowed: # on quick path these are guaranteed installed by the state file
pkgs = ['fastapi', 'websockets', 'aiofiles', 'ffmpy', 'pydub', 'uvicorn', 'semantic-version', 'altair', 'python-multipart', 'matplotlib']
for pkg in pkgs:
if not installed(pkg, quiet=True):
install(pkg, quiet=True)
def install_pydantic():
@ -1178,7 +1177,6 @@ def install_requirements():
if args.optional:
quick_allowed = False
install_optional()
installed('torch', reload=True) # reload packages cache
log.info('Install: verifying requirements')
if args.new:
log.debug('Install: flag=new')
@ -1480,6 +1478,11 @@ def run_deferred_tasks():
t_start = time.time()
log.debug('Starting deferred tasks')
time.sleep(1.0) # wait for server to start
try:
from modules.sd_models import write_metadata
write_metadata()
except Exception as e:
log.error(f'Deferred task error: write_metadata {e}')
try:
check_version()
except Exception as e:
@ -1514,20 +1517,28 @@ def get_state():
except Exception:
pass
try:
from concurrent.futures import ThreadPoolExecutor
from modules.paths import extensions_builtin_dir, extensions_dir
extension_folders = [extensions_builtin_dir] if args.safe else [extensions_builtin_dir, extensions_dir]
ext_dirs = []
for folder in extension_folders:
if not os.path.isdir(folder):
continue
extensions = list_extensions_folder(folder, quiet=True)
for ext in extensions:
extension_dir = os.path.join(folder, ext)
try:
res = subprocess.run('git rev-parse HEAD', capture_output=True, shell=True, check=False, cwd=extension_dir)
commit = res.stdout.decode(encoding='utf8', errors='ignore').strip()
for ext in list_extensions_folder(folder, quiet=True):
ext_dirs.append((ext, os.path.join(folder, ext)))
def _get_commit(item):
ext, ext_dir = item
try:
res = subprocess.run('git rev-parse HEAD', capture_output=True, shell=True, check=False, cwd=ext_dir)
return ext, res.stdout.decode(encoding='utf8', errors='ignore').strip()
except Exception:
return ext, ''
with ThreadPoolExecutor(max_workers=min(len(ext_dirs), 8), thread_name_prefix='sdnext-git') as pool:
for ext, commit in pool.map(_get_commit, ext_dirs):
if commit:
state['extensions'][ext] = commit
except Exception:
pass
except Exception:
pass
return state

View File

@ -1,13 +1,13 @@
#!/usr/bin/env python
from modules.logger import log
from functools import lru_cache
import os
import sys
import time
import shlex
import subprocess
from functools import lru_cache
import installer
from modules.logger import log
debug_install = log.debug if os.environ.get('SD_INSTALL_DEBUG', None) is not None else lambda *args, **kwargs: None

View File

@ -49,7 +49,7 @@ def check_dependencies():
'mmpose==1.3.2',
'mmdet==3.3.0',
]
status = [installed(p, reload=False, quiet=True) for p in packages]
status = [installed(p, quiet=True) for p in packages]
debug(f'DWPose required={packages} status={status}')
if not all(status):
log.info(f'Installing dependencies: for=dwpose packages={packages}')

View File

@ -13,7 +13,7 @@ def check_dependencies():
from modules.logger import log
packages = [('mediapipe', 'mediapipe')]
for pkg in packages:
if not installed(pkg[1], reload=True, quiet=True):
if not installed(pkg[1], quiet=True):
install(pkg[0], pkg[1], ignore=False)
try:
import mediapipe as mp # pylint: disable=unused-import

View File

@ -12,7 +12,7 @@ from modules.control.units import lite # Kohya ControlLLLite
from modules.control.units import t2iadapter # TencentARC T2I-Adapter
from modules.control.units import reference # ControlNet-Reference
from modules.control.processor import preprocess_image
from modules import devices, shared, errors, processing, images, sd_models, sd_vae, scripts_manager, masking
from modules import devices, shared, errors, processing, images, video, sd_models, sd_vae, scripts_manager, masking
from modules.logger import log
from modules.processing_class import StableDiffusionProcessingControl
from modules.ui_common import infotext_to_html
@ -679,7 +679,7 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg
if video_type != 'None' and isinstance(output_images, list) and 'video' in p.ops:
p.do_not_save_grid = True # pylint: disable=attribute-defined-outside-init
output_filename = images.save_video(p, filename=None, images=output_images, video_type=video_type, duration=video_duration, loop=video_loop, pad=video_pad, interpolate=video_interpolate, sync=True)
output_filename = video.save_video(p, filename=None, images=output_images, video_type=video_type, duration=video_duration, loop=video_loop, pad=video_pad, interpolate=video_interpolate, sync=True)
if shared.opts.gradio_skip_video:
output_filename = ''
image_txt = f'| Frames {len(output_images)} | Size {output_images[0].width}x{output_images[0].height}'

View File

@ -11,9 +11,9 @@ def get_app(mp_name, threshold=0.5, resolution=640):
global insightface_app, instightface_mp # pylint: disable=global-statement
from installer import install, installed, install_insightface
if not installed('insightface', reload=False, quiet=True):
if not installed('insightface', quiet=True):
install_insightface()
if not installed('ip_adapter', reload=False, quiet=True):
if not installed('ip_adapter', quiet=True):
install('git+https://github.com/tencent-ailab/IP-Adapter.git', 'ip_adapter', ignore=False)
if insightface_app is None or mp_name != instightface_mp:

View File

@ -1,7 +1,8 @@
from modules.image.metadata import image_data, read_info_from_image
from modules.image.save import save_image, sanitize_filename_part
from modules.image.resize import resize_image
from modules.image.grid import image_grid, check_grid_size, get_grid_size, draw_grid_annotations, draw_prompt_matrix
from modules.image.namegen import FilenameGenerator
from modules.image.grid import image_grid, check_grid_size, get_grid_size, draw_grid_annotations, draw_prompt_matrix, combine_grid
__all__ = [
'check_grid_size',
@ -10,8 +11,10 @@ __all__ = [
'get_grid_size',
'image_data',
'image_grid',
'combine_grid',
'read_info_from_image',
'resize_image',
'sanitize_filename_part',
'save_image'
'save_image',
'FilenameGenerator',
]

View File

@ -19,7 +19,7 @@ from types import MappingProxyType
from hashlib import sha256
import functools
from modules import shared, devices, sd_models
from modules import shared, devices, sd_models, sd_models_utils
from modules.logger import log
@ -527,7 +527,7 @@ def openvino_fx(subgraph, example_inputs, options=None):
pass
else:
# Delete unused subgraphs
subgraph = subgraph.apply(sd_models.convert_to_faketensors)
subgraph = subgraph.apply(sd_models_utils.convert_to_faketensors)
devices.torch_gc(force=True, reason='openvino')
# Model is fully supported and already cached. Run the cached OV model directly.

View File

@ -1,7 +1,7 @@
import os
import enum
from collections import namedtuple
from modules import sd_models, hashes, shared
from modules import hashes, shared, sd_models, sd_checkpoint
NetworkWeights = namedtuple('NetworkWeights', ['network_key', 'sd_key', 'w', 'sd_module'])
@ -33,7 +33,7 @@ class NetworkOnDisk:
self.metadata = {}
self.is_safetensors = os.path.splitext(filename)[1].lower() == ".safetensors"
if self.is_safetensors:
self.metadata = sd_models.read_metadata_from_safetensors(filename)
self.metadata = sd_checkpoint.read_metadata_from_safetensors(filename)
if self.metadata:
m = {}
for k, v in sorted(self.metadata.items(), key=lambda x: metadata_tags_order.get(x[0], 999)):

View File

@ -55,7 +55,7 @@ class MemUsageMonitor:
return self.data
def summary(self):
from modules.shared import ram_stats
from modules.memstats import ram_stats
gpu = ''
cpu = ''
gpu = ''

View File

@ -99,7 +99,6 @@ def install_execution_provider(ep: ExecutionProvider):
from installer import installed, install, uninstall
res = "<br><pre>"
res += uninstall(["onnxruntime", "onnxruntime-directml", "onnxruntime-gpu", "onnxruntime-training", "onnxruntime-openvino"], quiet=True)
installed("onnxruntime", reload=True)
packages = ["onnxruntime"] # Failed to load olive: cannot import name '__version__' from 'onnxruntime'
if ep == ExecutionProvider.DirectML:
packages.append("onnxruntime-directml")

View File

@ -4,6 +4,7 @@ from PIL import Image
from rich.progress import Progress, TextColumn, BarColumn, TaskProgressColumn, TimeRemainingColumn, TimeElapsedColumn
import modules.postprocess.esrgan_model_arch as arch
from modules import images, devices, shared
from modules.images.grid import split_grid
from modules.logger import log, console
from modules.upscaler import Upscaler, UpscalerData, compile_upscaler
@ -193,7 +194,7 @@ def esrgan_upscale(model, img):
if shared.opts.upscaler_tile_size == 0:
return upscale_without_tiling(model, img)
grid = images.split_grid(img, shared.opts.upscaler_tile_size, shared.opts.upscaler_tile_size, shared.opts.upscaler_tile_overlap)
grid = split_grid(img, shared.opts.upscaler_tile_size, shared.opts.upscaler_tile_size, shared.opts.upscaler_tile_overlap)
newtiles = []
scale_factor = 1

View File

@ -2,7 +2,7 @@ import os
import time
import numpy as np
import torch
from modules import shared, devices, sd_models, sd_vae, errors
from modules import shared, devices, errors, sd_models, sd_models_utils, sd_vae
from modules.logger import log
from modules.vae import sd_vae_taesd
@ -71,7 +71,7 @@ def full_vqgan_decode(latents, model):
if 'VAE' in shared.opts.cuda_compile and shared.opts.cuda_compile_backend == "openvino_fx" and shared.compiled_model_state.first_pass_vae:
shared.compiled_model_state.first_pass_vae = False
if not shared.opts.openvino_disable_memory_cleanup and hasattr(shared.sd_model, "vqgan"):
model.vqgan.apply(sd_models.convert_to_faketensors)
model.vqgan.apply(sd_models_utils.convert_to_faketensors)
devices.torch_gc(force=True)
if shared.opts.diffusers_offload_mode == "balanced":
@ -166,7 +166,7 @@ def full_vae_decode(latents, model):
if 'VAE' in shared.opts.cuda_compile and shared.opts.cuda_compile_backend == "openvino_fx" and shared.compiled_model_state.first_pass_vae:
shared.compiled_model_state.first_pass_vae = False
if not shared.opts.openvino_disable_memory_cleanup and hasattr(shared.sd_model, "vae"):
model.vae.apply(sd_models.convert_to_faketensors)
model.vae.apply(sd_models_utils.convert_to_faketensors)
devices.torch_gc(force=True)
elif shared.opts.diffusers_move_unet and not getattr(model, 'has_accelerate', False) and base_device is not None:

View File

@ -1,7 +1,7 @@
import time
import logging
import torch
from modules import shared, devices, sd_models, errors
from modules import shared, errors, devices, sd_models, sd_models_utils
from modules.logger import log
from installer import setup_logging
@ -319,10 +319,10 @@ def openvino_post_compile(op="base"): # delete unet after OpenVINO compile
if shared.compiled_model_state.first_pass and op == "base":
shared.compiled_model_state.first_pass = False
if not shared.opts.openvino_disable_memory_cleanup and hasattr(shared.sd_model, "unet"):
shared.sd_model.unet.apply(sd_models.convert_to_faketensors)
shared.sd_model.unet.apply(sd_models_utils.convert_to_faketensors)
devices.torch_gc(force=True)
if shared.compiled_model_state.first_pass_refiner and op == "refiner":
shared.compiled_model_state.first_pass_refiner = False
if not shared.opts.openvino_disable_memory_cleanup and hasattr(shared.sd_refiner, "unet"):
shared.sd_refiner.unet.apply(sd_models.convert_to_faketensors)
shared.sd_refiner.unet.apply(sd_models_utils.convert_to_faketensors)
devices.torch_gc(force=True)

View File

@ -271,7 +271,8 @@ class State:
def do_set_current_image(self):
if (self.current_latent is None) or self.disable_preview or (self.preview_job == self.job_no):
return False
from modules import shared, sd_samplers
from modules import shared, sd_samplers, sd_samplers_common
from modules.sd_samplers_common import samples_to_image_grid, sample_to_image
self.preview_job = self.job_no
try:
sample = self.current_latent
@ -285,7 +286,7 @@ class State:
sample = self.current_noise_pred * (-self.current_sigma / (self.current_sigma**2 + 1) ** 0.5) + (original_sample / (self.current_sigma**2 + 1)) # pylint: disable=invalid-unary-operand-type
except Exception:
pass # ignore sigma errors
image = sd_samplers.samples_to_image_grid(sample) if shared.opts.show_progress_grid else sd_samplers.sample_to_image(sample)
image = samples_to_image_grid(sample) if shared.opts.show_progress_grid else sample_to_image(sample)
self.assign_current_image(image)
self.preview_job = -1
return True

View File

@ -3,6 +3,7 @@ import json
import gradio as gr
import modules.shared
import modules.extensions
from modules.logger import log
gradio_theme = gr.themes.Base()
@ -21,18 +22,18 @@ def refresh_themes(no_update=False):
with open(themes_file, encoding='utf8') as f:
res = json.load(f)
except Exception:
modules.log.error('Exception loading UI themes')
log.error('Exception loading UI themes')
if not no_update:
try:
modules.log.info('Refreshing UI themes')
log.info('Refreshing UI themes')
r = modules.shared.req('https://huggingface.co/datasets/freddyaboulton/gradio-theme-subdomains/resolve/main/subdomains.json')
if r.status_code == 200:
res = r.json()
modules.shared.writefile(res, themes_file)
else:
modules.log.error('Error refreshing UI themes')
log.error('Error refreshing UI themes')
except Exception:
modules.log.error('Exception refreshing UI themes')
log.error('Exception refreshing UI themes')
return res
@ -46,12 +47,12 @@ def list_themes():
themes = ['lobe']
modules.shared.opts.data['gradio_theme'] = themes[0]
modules.shared.opts.data['theme_type'] = 'None'
modules.log.info('UI theme: extension="lobe"')
log.info('UI theme: extension="lobe"')
elif 'Cozy-Nest' in extensions and modules.shared.opts.gradio_theme == 'cozy-nest':
themes = ['cozy-nest']
modules.shared.opts.data['gradio_theme'] = themes[0]
modules.shared.opts.data['theme_type'] = 'None'
modules.log.info('UI theme: extension="cozy-nest"')
log.info('UI theme: extension="cozy-nest"')
elif modules.shared.opts.theme_type == 'None':
gradio = ["gradio/default", "gradio/base", "gradio/glass", "gradio/monochrome", "gradio/soft"]
huggingface = refresh_themes(no_update=True)
@ -64,7 +65,7 @@ def list_themes():
elif modules.shared.opts.theme_type == 'Modern':
ext = next((e for e in modules.extensions.extensions if e.name == 'sdnext-modernui'), None)
if ext is None:
modules.log.error('UI themes: ModernUI not found')
log.error('UI themes: ModernUI not found')
builtin = list_builtin_themes()
themes = sorted(builtin)
modules.shared.opts.theme_type = 'Standard'
@ -79,7 +80,7 @@ def list_themes():
themes.append('modern/Default')
themes = sorted(themes)
else:
modules.log.error(f'UI themes: type={modules.shared.opts.theme_type} unknown')
log.error(f'UI themes: type={modules.shared.opts.theme_type} unknown')
themes = []
return themes
@ -94,7 +95,7 @@ def reload_gradio_theme():
gradio_theme = gr.themes.Base(**default_font_params)
available_themes = list_themes()
if theme_name not in available_themes:
# modules.log.error(f'UI theme invalid: type={modules.shared.opts.theme_type} theme="{theme_name}"')
# log.error(f'UI theme invalid: type={modules.shared.opts.theme_type} theme="{theme_name}"')
if modules.shared.opts.theme_type == 'Standard':
theme_name = 'black-teal'
elif modules.shared.opts.theme_type == 'Modern':
@ -106,22 +107,22 @@ def reload_gradio_theme():
theme_name = 'black-teal'
modules.shared.opts.data['gradio_theme'] = theme_name
modules.log.info(f'UI locale: name="{modules.shared.opts.ui_locale}"')
log.info(f'UI locale: name="{modules.shared.opts.ui_locale}"')
if theme_name.lower() in ['lobe', 'cozy-nest']:
modules.log.info(f'UI theme extension: name="{theme_name}"')
log.info(f'UI theme extension: name="{theme_name}"')
return None
elif modules.shared.opts.theme_type == 'Standard':
gradio_theme = gr.themes.Base(**default_font_params)
modules.log.info(f'UI theme: type={modules.shared.opts.theme_type} name="{theme_name}" available={len(available_themes)}')
log.info(f'UI theme: type={modules.shared.opts.theme_type} name="{theme_name}" available={len(available_themes)}')
return 'sdnext.css'
elif modules.shared.opts.theme_type == 'Modern':
gradio_theme = gr.themes.Base(**default_font_params)
modules.log.info(f'UI theme: type={modules.shared.opts.theme_type} name="{theme_name}" available={len(available_themes)}')
log.info(f'UI theme: type={modules.shared.opts.theme_type} name="{theme_name}" available={len(available_themes)}')
return 'base.css'
elif modules.shared.opts.theme_type == 'None':
if theme_name.startswith('gradio/'):
modules.log.warning('UI theme: using Gradio default theme which is not optimized for SD.Next')
log.warning('UI theme: using Gradio default theme which is not optimized for SD.Next')
if theme_name == "gradio/default":
gradio_theme = gr.themes.Default(**default_font_params)
elif theme_name == "gradio/base":
@ -133,18 +134,18 @@ def reload_gradio_theme():
elif theme_name == "gradio/soft":
gradio_theme = gr.themes.Soft(**default_font_params)
else:
modules.log.warning('UI theme: unknown Gradio theme')
log.warning('UI theme: unknown Gradio theme')
theme_name = "gradio/default"
gradio_theme = gr.themes.Default(**default_font_params)
elif theme_name.startswith('huggingface/'):
modules.log.warning('UI theme: using 3rd party theme which is not optimized for SD.Next')
log.warning('UI theme: using 3rd party theme which is not optimized for SD.Next')
try:
hf_theme_name = theme_name.replace('huggingface/', '')
gradio_theme = gr.themes.ThemeClass.from_hub(hf_theme_name)
except Exception as e:
modules.log.error(f"UI theme: download error accessing HuggingFace {e}")
log.error(f"UI theme: download error accessing HuggingFace {e}")
gradio_theme = gr.themes.Default(**default_font_params)
modules.log.info(f'UI theme: type={modules.shared.opts.theme_type} name="{theme_name}" style={modules.shared.opts.theme_style}')
log.info(f'UI theme: type={modules.shared.opts.theme_type} name="{theme_name}" style={modules.shared.opts.theme_style}')
return 'base.css'
modules.log.error(f'UI theme: type={modules.shared.opts.theme_type} unknown')
log.error(f'UI theme: type={modules.shared.opts.theme_type} unknown')
return None

View File

@ -18,6 +18,7 @@ from PIL import Image
from starlette.responses import FileResponse, JSONResponse
from modules import paths, shared, files_cache, errors, infotext, ui_symbols, ui_components, modelstats
from modules.logger import log
from modules.json_helpers import writefile
allowed_dirs = []
@ -838,7 +839,7 @@ def create_ui(container, button_parent, tabname, skip_indexing = False):
def fn_save_info(info):
fn = os.path.splitext(ui.last_item.filename)[0] + '.json'
shared.writefile(info, fn, silent=True)
writefile(info, fn, silent=True)
log.debug(f'Network save info: item="{ui.last_item.name}" filename="{fn}"')
return info
@ -851,7 +852,7 @@ def create_ui(container, button_parent, tabname, skip_indexing = False):
fn = os.path.splitext(ui.last_item.filename)[0] + '.json'
if hasattr(ui.last_item, 'type') and ui.last_item.type == 'Style':
info.update(**{ 'description': description, 'prompt': prompt, 'negative': negative, 'extra': extra, 'wildcards': wildcards })
shared.writefile(info, fn, silent=True)
writefile(info, fn, silent=True)
log.debug(f'Network save style: item="{ui.last_item.name}" filename="{fn}"')
return info
@ -1077,7 +1078,7 @@ def create_ui(container, button_parent, tabname, skip_indexing = False):
"negative": negative,
"extra": '',
}
shared.writefile(item, fn, silent=True)
writefile(item, fn, silent=True)
if len(prompt) > 0:
log.debug(f'Networks type=style quicksave style: item="{name}" filename="{fn}" prompt="{prompt}"')
else:

View File

@ -82,17 +82,17 @@ def html_css(css: list[str]):
themecss = os.path.join(script_path, "javascript", f"{modules.shared.opts.gradio_theme}.css")
if os.path.exists(themecss):
head += stylesheet(themecss)
modules.log.debug(f'UI theme: css="{themecss}" base="{css}" user="{usercss}"')
log.debug(f'UI theme: css="{themecss}" base="{css}" user="{usercss}"')
else:
modules.log.error(f'UI theme: css="{themecss}" not found')
log.error(f'UI theme: css="{themecss}" not found')
elif modules.shared.opts.theme_type == 'Modern':
theme_folder = next((e.path for e in modules.extensions.extensions if e.name == 'sdnext-modernui'), None)
themecss = os.path.join(theme_folder or '', 'themes', f'{modules.shared.opts.gradio_theme}.css')
if os.path.exists(themecss):
head += stylesheet(themecss)
modules.log.debug(f'UI theme: css="{themecss}" base="{css}" user="{usercss}"')
log.debug(f'UI theme: css="{themecss}" base="{css}" user="{usercss}"')
else:
modules.log.error(f'UI theme: css="{themecss}" not found')
log.error(f'UI theme: css="{themecss}" not found')
if usercss is not None:
head += stylesheet(usercss)
return head

View File

@ -263,7 +263,7 @@ class Script(scripts_manager.Script):
def after(self, p: processing.StableDiffusionProcessing, processed: processing.Processed, adapter_index, frames, lora_index, strength, latent_mode, video_type, duration, gif_loop, mp4_pad, mp4_interpolate, override_scheduler, fi_method, fi_iters, fi_order, fi_spatial, fi_temporal): # pylint: disable=arguments-differ, unused-argument
from modules.images import save_video
from modules.video import save_video
if video_type != 'None':
log.debug(f'AnimateDiff video: type={video_type} duration={duration} loop={gif_loop} pad={mp4_pad} interpolate={mp4_interpolate}')
save_video(p, filename=None, images=processed.images, video_type=video_type, duration=duration, loop=gif_loop, pad=mp4_pad, interpolate=mp4_interpolate)

View File

@ -1,7 +1,7 @@
import torch
import gradio as gr
import diffusers
from modules import scripts_manager, processing, shared, images, sd_models, devices
from modules import scripts_manager, processing, shared, images, video, sd_models, devices
from modules.logger import log
@ -110,5 +110,5 @@ class Script(scripts_manager.Script):
shared.sd_model = orig_pipeline
if video_type != 'None' and processed is not None:
images.save_video(p, filename=None, images=processed.images, video_type=video_type, duration=duration, loop=gif_loop, pad=mp4_pad, interpolate=mp4_interpolate)
video.save_video(p, filename=None, images=processed.images, video_type=video_type, duration=duration, loop=gif_loop, pad=mp4_pad, interpolate=mp4_interpolate)
return processed

View File

@ -15,7 +15,7 @@ orig_pipeline, orig_prompt_attention = None, None
def verify_insightface():
from installer import installed, install_insightface
if not installed('insightface', reload=False, quiet=True):
if not installed('insightface', quiet=True):
install_insightface()

View File

@ -14,7 +14,7 @@ def check_dependencies():
('ligo-segments', 'ligo-segments'),
]
for pkg in packages:
if not installed(pkg[1], reload=True, quiet=True):
if not installed(pkg[1], quiet=True):
install(pkg[0], pkg[1], ignore=False)
try:
from ligo.segments import segment # pylint: disable=unused-import

View File

@ -4,6 +4,7 @@ from PIL import Image, ImageDraw
from modules import images, devices, scripts_manager
from modules.processing import get_processed, process_images
from modules.shared import opts, state, log
from modules.images.grid import split_grid
class Script(scripts_manager.Script):
@ -64,9 +65,9 @@ class Script(scripts_manager.Script):
mask.height - down - (mask_blur//2 if down > 0 else 0)
), fill="black")
devices.torch_gc()
grid = images.split_grid(img, tile_w=p.width, tile_h=p.height, overlap=pixels)
grid_mask = images.split_grid(mask, tile_w=p.width, tile_h=p.height, overlap=pixels)
grid_latent_mask = images.split_grid(latent_mask, tile_w=p.width, tile_h=p.height, overlap=pixels)
grid = split_grid(img, tile_w=p.width, tile_h=p.height, overlap=pixels)
grid_mask = split_grid(mask, tile_w=p.width, tile_h=p.height, overlap=pixels)
grid_latent_mask = split_grid(latent_mask, tile_w=p.width, tile_h=p.height, overlap=pixels)
p.n_iter = 1
p.batch_size = 1
p.do_not_save_grid = True

View File

@ -1,6 +1,5 @@
import gradio as gr
import modules.images
from modules import scripts_postprocessing
from modules import video, scripts_postprocessing
class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing):
@ -47,4 +46,4 @@ class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing):
filename = filename.strip() if filename is not None else ''
if video_type == 'None' or len(filename) == 0 or images is None or len(images) < 2:
return
modules.images.save_video(p=None, filename=filename, images=images, video_type=video_type, duration=duration, loop=loop, pad=pad, interpolate=interpolate, scale=scale, change=change)
video.save_video(p=None, filename=filename, images=images, video_type=video_type, duration=duration, loop=loop, pad=pad, interpolate=interpolate, scale=scale, change=change)

View File

@ -30,7 +30,7 @@ class Script(scripts_manager.Script):
def dependencies(self):
from installer import installed, install, install_insightface
if not installed('insightface', reload=False, quiet=True):
if not installed('insightface', quiet=True):
install_insightface()
if not installed('torchdiffeq'):
install('torchdiffeq')

View File

@ -5,6 +5,7 @@ from modules import processing, shared, images, devices, scripts_manager
from modules.processing import get_processed
from modules.shared import opts, state, log
from modules.image.util import flatten
from modules.images.grid import split_grid
class Script(scripts_manager.Script):
@ -48,7 +49,7 @@ class Script(scripts_manager.Script):
else:
img = init_img
devices.torch_gc()
grid = images.split_grid(img, tile_w=init_img.width, tile_h=init_img.height, overlap=overlap)
grid = split_grid(img, tile_w=init_img.width, tile_h=init_img.height, overlap=overlap)
batch_size = p.batch_size
upscale_count = p.n_iter
p.n_iter = 1

View File

@ -5,7 +5,7 @@ Additional params for StableVideoDiffusion
import os
import torch
import gradio as gr
from modules import scripts_manager, processing, shared, sd_models, images, modelloader
from modules import scripts_manager, processing, shared, sd_models, images, modelloader, video
from modules.logger import log
@ -121,5 +121,5 @@ class Script(scripts_manager.Script):
# run processing
processed = processing.process_images(p)
if video_type != 'None':
images.save_video(p, filename=None, images=processed.images, video_type=video_type, duration=duration, loop=gif_loop, pad=mp4_pad, interpolate=mp4_interpolate)
video.save_video(p, filename=None, images=processed.images, video_type=video_type, duration=duration, loop=gif_loop, pad=mp4_pad, interpolate=mp4_interpolate)
return processed

View File

@ -7,7 +7,7 @@ TODO text2video items:
"""
import gradio as gr
from modules import scripts_manager, processing, shared, images, sd_models, modelloader
from modules import scripts_manager, processing, shared, images, video, sd_models, modelloader
from modules.logger import log
@ -92,5 +92,5 @@ class Script(scripts_manager.Script):
processed = processing.process_images(p)
if video_type != 'None':
images.save_video(p, filename=None, images=processed.images, video_type=video_type, duration=duration, loop=gif_loop, pad=mp4_pad, interpolate=mp4_interpolate)
video.save_video(p, filename=None, images=processed.images, video_type=video_type, duration=duration, loop=gif_loop, pad=mp4_pad, interpolate=mp4_interpolate)
return processed

View File

@ -248,8 +248,8 @@ axis_options = [
AxisOption("[Postprocess] Context", str, apply_context, choices=lambda: ["Add with forward", "Remove with forward", "Add with backward", "Remove with backward"]),
AxisOption("[Postprocess] Detailer", bool, apply_detailer, fmt=format_bool, choices=lambda: [False, True]),
AxisOption("[Postprocess] Detailer strength", str, apply_field("detailer_strength")),
AxisOption("[Quant] SDNQ quant mode", str, apply_sdnq_quant, cost=0.9, fmt=format_value_add_label, choices=lambda: ['none'] + sorted(shared.sdnq_quant_modes)),
AxisOption("[Quant] SDNQ quant mode TE", str, apply_sdnq_quant_te, cost=0.9, fmt=format_value_add_label, choices=lambda: ['none'] + sorted(shared.sdnq_quant_modes)),
AxisOption("[Quant] SDNQ quant mode", str, apply_sdnq_quant, cost=0.9, fmt=format_value_add_label, choices=lambda: ['none'] + sorted(shared_items.sdnq_quant_modes)),
AxisOption("[Quant] SDNQ quant mode TE", str, apply_sdnq_quant_te, cost=0.9, fmt=format_value_add_label, choices=lambda: ['none'] + sorted(shared_items.sdnq_quant_modes)),
AxisOption("[HDR] Mode", int, apply_field("hdr_mode")),
AxisOption("[HDR] Brightness", float, apply_field("hdr_brightness")),
AxisOption("[HDR] Color", float, apply_field("hdr_color")),

View File

@ -1,15 +1,16 @@
import time
from copy import copy
from PIL import Image
from modues.images.grid import GridAnnotation
from modules import shared, images, processing
from modules.logger import log
from modules.image.util import draw_text
def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend, include_lone_images, include_sub_grids, first_axes_processed, second_axes_processed, margin_size, no_grid: False, include_time: False, include_text: False): # pylint: disable=unused-argument
x_texts = [[images.GridAnnotation(x)] for x in x_labels]
y_texts = [[images.GridAnnotation(y)] for y in y_labels]
z_texts = [[images.GridAnnotation(z)] for z in z_labels]
x_texts = [[GridAnnotation(x)] for x in x_labels]
y_texts = [[GridAnnotation(y)] for y in y_labels]
z_texts = [[GridAnnotation(z)] for z in z_labels]
list_size = (len(xs) * len(ys) * len(zs))
processed_result = None

View File

@ -12,7 +12,7 @@ from scripts.xyz.xyz_grid_shared import str_permutations, list_to_csv_string, re
from scripts.xyz.xyz_grid_classes import axis_options, AxisOption, SharedSettingsStackHelper # pylint: disable=no-name-in-module
from scripts.xyz.xyz_grid_draw import draw_xyz_grid # pylint: disable=no-name-in-module
from scripts.xyz.xyz_grid_shared import apply_field, apply_task_args, apply_setting, apply_prompt, apply_order, apply_sampler, apply_hr_sampler_name, confirm_samplers, apply_checkpoint, apply_refiner, apply_unet, apply_clip_skip, apply_vae, list_lora, apply_lora, apply_lora_strength, apply_te, apply_styles, apply_upscaler, apply_context, apply_detailer, apply_override, apply_processing, apply_options, apply_seed, format_value_add_label, format_value, format_value_join_list, do_nothing, format_nothing # pylint: disable=no-name-in-module, unused-import
from modules import shared, errors, scripts_manager, images, processing
from modules import shared, errors, scripts_manager, images, video, processing
from modules.ui_components import ToolButton
from modules.ui_sections import create_video_inputs
import modules.ui_symbols as symbols
@ -412,7 +412,7 @@ class Script(scripts_manager.Script):
debug(f'XYZ grid remove subgrids: total={processed.images}')
if create_video and video_type != 'None' and not shared.state.interrupted:
images.save_video(p, filename=None, images=have_images, video_type=video_type, duration=video_duration, loop=video_loop, pad=video_pad, interpolate=video_interpolate)
video.save_video(p, filename=None, images=have_images, video_type=video_type, duration=video_duration, loop=video_loop, pad=video_pad, interpolate=video_interpolate)
shared.state.end(jobid)
return processed

View File

@ -11,7 +11,7 @@ import gradio as gr
from scripts.xyz.xyz_grid_shared import str_permutations, list_to_csv_string, restore_comma, re_range, re_plain_comma # pylint: disable=no-name-in-module
from scripts.xyz.xyz_grid_classes import axis_options, AxisOption, SharedSettingsStackHelper # pylint: disable=no-name-in-module
from scripts.xyz.xyz_grid_draw import draw_xyz_grid # pylint: disable=no-name-in-module
from modules import shared, errors, scripts_manager, images, processing
from modules import shared, errors, scripts_manager, images, video, processing
from modules.ui_components import ToolButton
from modules.ui_sections import create_video_inputs
import modules.ui_symbols as symbols
@ -440,7 +440,7 @@ class Script(scripts_manager.Script):
debug(f'XYZ grid remove subgrids: total={processed.images}')
if create_video and video_type != 'None' and not shared.state.interrupted:
images.save_video(p, filename=None, images=have_images, video_type=video_type, duration=video_duration, loop=video_loop, pad=video_pad, interpolate=video_interpolate)
video.save_video(p, filename=None, images=have_images, video_type=video_type, duration=video_duration, loop=video_loop, pad=video_pad, interpolate=video_interpolate)
p.do_not_save_grid = True
p.do_not_save_samples = True

View File

@ -74,6 +74,7 @@ fastapi_args = {
def initialize():
log.debug('Initializing: modules')
from concurrent.futures import ThreadPoolExecutor, as_completed
modules.sd_checkpoint.init_metadata()
modules.hashes.init_cache()
@ -81,22 +82,32 @@ def initialize():
modules.sd_samplers.list_samplers()
timer.startup.record("samplers")
modules.sd_vae.refresh_vae_list()
timer.startup.record("vae")
# run independent filesystem scans in parallel
def _scan_vae():
modules.sd_vae.refresh_vae_list()
def _scan_unet():
modules.sd_unet.refresh_unet_list()
def _scan_te():
modules.model_te.refresh_te_list()
def _scan_models():
modules.modelloader.cleanup_models()
modules.sd_checkpoint.setup_model()
def _scan_lora():
from modules.lora import lora_load
lora_load.list_available_networks()
def _scan_upscalers():
modules.modelloader.load_upscalers()
modules.sd_unet.refresh_unet_list()
timer.startup.record("unet")
modules.model_te.refresh_te_list()
timer.startup.record("te")
modules.modelloader.cleanup_models()
modules.sd_checkpoint.setup_model()
timer.startup.record("models")
from modules.lora import lora_load
lora_load.list_available_networks()
timer.startup.record("lora")
scans = [_scan_vae, _scan_unet, _scan_te, _scan_models, _scan_lora, _scan_upscalers]
with ThreadPoolExecutor(max_workers=len(scans), thread_name_prefix='sdnext-scan') as pool:
futures = {pool.submit(fn): fn.__name__ for fn in scans}
for future in as_completed(futures):
name = futures[future]
try:
future.result()
except Exception as e:
log.error(f'Scan error: {name} {e}')
timer.startup.record("scans")
shared.prompt_styles.reload()
timer.startup.record("styles")
@ -115,9 +126,6 @@ def initialize():
timer.startup.records["extensions"] = t_total # scripts can reset the time
log.debug(f'Extensions init time: {t_timer.summary()}')
modules.modelloader.load_upscalers()
timer.startup.record("upscalers")
modules.ui_extra_networks.initialize()
modules.ui_extra_networks.register_pages()
modules.extra_networks.initialize()
@ -128,6 +136,7 @@ def initialize():
hf_init()
hf_check_cache()
if shared.cmd_opts.tls_keyfile is not None and shared.cmd_opts.tls_certfile is not None:
try:
if not os.path.exists(shared.cmd_opts.tls_keyfile):
@ -374,7 +383,6 @@ def webui(restart=False):
start_common()
app = start_ui()
modules.script_callbacks.after_ui_callback()
modules.sd_models.write_metadata()
load_model()
mount_subpath(app)