mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 01:04:32 +02:00
+8
-2
@@ -127,8 +127,8 @@ def env_flag(name: str, default: bool = False) -> bool:
|
||||
|
||||
def print_profile(profiler: cProfile.Profile, msg: str):
|
||||
profiler.disable()
|
||||
from modules.errors import profile
|
||||
profile(profiler, msg)
|
||||
from modules.errors import profile_print
|
||||
profile_print(msg, local_profiler=profiler)
|
||||
|
||||
|
||||
def package_version(package):
|
||||
@@ -942,6 +942,12 @@ def check_torch():
|
||||
install(torch_command, 'torch torchvision', quiet=False)
|
||||
|
||||
try:
|
||||
try:
|
||||
# import torch pulls torch.distributed immediately which is slow and unnecessary
|
||||
import torch.distributed.tensor._ops as dtensor_ops
|
||||
dtensor_ops.single_dim_strategy._resolve_foreach_elementwise_overload = lambda *a, **kw: None # pylint: disable=protected-access
|
||||
except Exception:
|
||||
pass
|
||||
import torch
|
||||
try:
|
||||
import intel_extension_for_pytorch as ipex # pylint: disable=import-error, unused-import
|
||||
|
||||
@@ -196,8 +196,8 @@ def clean_server():
|
||||
def start_server(immediate=True, server=None):
|
||||
if args.profile:
|
||||
import cProfile
|
||||
pr = cProfile.Profile()
|
||||
pr.enable()
|
||||
profiler = cProfile.Profile()
|
||||
profiler.enable()
|
||||
import gc
|
||||
import importlib.util
|
||||
collected = 0
|
||||
@@ -221,10 +221,12 @@ def start_server(immediate=True, server=None):
|
||||
server.wants_restart = False
|
||||
uvicorn = server.webui(restart=not immediate, _exit=True)
|
||||
else:
|
||||
uvicorn = server.webui(restart=not immediate)
|
||||
uvicorn = server.webui(restart=not immediate, profiler=profiler if args.profile else None)
|
||||
if args.profile:
|
||||
pr.disable()
|
||||
installer.print_profile(pr, 'WebUI')
|
||||
profiler.disable()
|
||||
installer.print_profile(profiler, 'WebUI')
|
||||
profiler.clear()
|
||||
profiler.enable()
|
||||
rec('server')
|
||||
return uvicorn, server
|
||||
|
||||
@@ -343,10 +345,12 @@ def main():
|
||||
if uv is not None and uv.wants_restart:
|
||||
clean_server()
|
||||
log.info('Server restarting...')
|
||||
# uv, instance = start_server(immediate=False, server=instance)
|
||||
os.execv(sys.executable, ['python'] + sys.argv)
|
||||
else:
|
||||
log.info('Exiting...')
|
||||
from modules import errors
|
||||
errors.profile_stop()
|
||||
errors.profile_print('Shutdown')
|
||||
break
|
||||
time.sleep(1.0)
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ import sys
|
||||
import html
|
||||
import threading
|
||||
import time
|
||||
import cProfile
|
||||
from modules import shared, progress, errors, timer
|
||||
from modules.logger import log
|
||||
|
||||
@@ -65,8 +64,9 @@ def wrap_gradio_call(func, extra_outputs=None, add_stats=False, name=None):
|
||||
jobid = shared.state.begin(job_name, task_id=task_id)
|
||||
try:
|
||||
if shared.cmd_opts.profile:
|
||||
pr = cProfile.Profile()
|
||||
pr.enable()
|
||||
errors.profile_stop()
|
||||
errors.profile_print('BeforeWrapGradioCall')
|
||||
errors.profile_start()
|
||||
res = func(*args, **kwargs)
|
||||
if res is None:
|
||||
msg = "No result returned from function"
|
||||
@@ -76,8 +76,9 @@ def wrap_gradio_call(func, extra_outputs=None, add_stats=False, name=None):
|
||||
else:
|
||||
res = list(res)
|
||||
if shared.cmd_opts.profile:
|
||||
pr.disable()
|
||||
errors.profile(pr, 'Wrap')
|
||||
errors.profile_stop()
|
||||
errors.profile_print('AfterWrapGradioCall')
|
||||
errors.profile_start()
|
||||
except Exception as e:
|
||||
errors.display(e, 'gradio call')
|
||||
res = extra_outputs_array or []
|
||||
|
||||
+24
-4
@@ -8,6 +8,7 @@ log = get_log()
|
||||
setup_logging()
|
||||
install_traceback()
|
||||
already_displayed = {}
|
||||
_profiler = None
|
||||
|
||||
|
||||
class ValidationError(ValueError):
|
||||
@@ -63,19 +64,21 @@ def exception(suppress=None):
|
||||
console.print_exception(show_locals=False, max_frames=16, extra_lines=2, suppress=suppress, theme="ansi_dark", word_wrap=False, width=min([console.width, 200]))
|
||||
|
||||
|
||||
def profile(profiler, msg: str, n: int = 16):
|
||||
profiler.disable()
|
||||
def profile_print(msg: str='', n: int = 16, local_profiler=None):
|
||||
if local_profiler is None:
|
||||
local_profiler = _profiler
|
||||
if local_profiler is None:
|
||||
return
|
||||
import io
|
||||
import pstats
|
||||
stream = io.StringIO() # pylint: disable=abstract-class-instantiated
|
||||
p = pstats.Stats(profiler, stream=stream)
|
||||
p = pstats.Stats(local_profiler, stream=stream)
|
||||
p.sort_stats(pstats.SortKey.CUMULATIVE)
|
||||
p.print_stats(200)
|
||||
# p.print_title()
|
||||
# p.print_call_heading(10, 'time')
|
||||
# p.print_callees(10)
|
||||
# p.print_callers(10)
|
||||
profiler = None
|
||||
lines = stream.getvalue().split('\n')
|
||||
lines = [x for x in lines if '<frozen' not in x
|
||||
and '{built-in' not in x
|
||||
@@ -92,6 +95,23 @@ def profile(profiler, msg: str, n: int = 16):
|
||||
log.debug(f'Profile {msg}: {txt}')
|
||||
|
||||
|
||||
def profile_start():
|
||||
global _profiler # pylint: disable=global-statement
|
||||
if _profiler is not None:
|
||||
_profiler.disable()
|
||||
_profiler.clear()
|
||||
_profiler.enable()
|
||||
else:
|
||||
import cProfile
|
||||
_profiler = cProfile.Profile()
|
||||
_profiler.enable()
|
||||
|
||||
|
||||
def profile_stop():
|
||||
if _profiler is not None:
|
||||
_profiler.disable()
|
||||
|
||||
|
||||
def profile_torch(profiler, msg: str):
|
||||
profiler.stop()
|
||||
lines = profiler.key_averages().table(sort_by="cpu_time_total", row_limit=12)
|
||||
|
||||
+150
-131
@@ -1,13 +1,13 @@
|
||||
from typing import Union
|
||||
import itertools
|
||||
import os
|
||||
from collections import UserDict
|
||||
from collections.abc import Callable, Iterator
|
||||
from dataclasses import dataclass, field
|
||||
from functools import lru_cache
|
||||
from modules.logger import log
|
||||
|
||||
|
||||
do_cache_folders = os.environ.get('SD_NO_CACHE', None) is None
|
||||
|
||||
class Directory: # forward declaration
|
||||
...
|
||||
|
||||
@@ -20,34 +20,34 @@ DirectoryIterator = Iterator[Directory]
|
||||
DirectoryCollection = dict[str, Directory]
|
||||
ExtensionFilter = Callable
|
||||
ExtensionList = list[str]
|
||||
RecursiveType = Union[bool,Callable]
|
||||
RecursiveType = Union[bool, Callable]
|
||||
|
||||
|
||||
def real_path(directory_path:str) -> str | None:
|
||||
@lru_cache(maxsize=1024)
|
||||
def real_path(directory_path: str) -> str | None:
|
||||
"""Cached real_path resolution to avoid repeated abspath/expanduser calls."""
|
||||
if not directory_path:
|
||||
return None
|
||||
try:
|
||||
return os.path.abspath(os.path.expanduser(directory_path))
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
return None
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Directory(Directory): # pylint: disable=E0102
|
||||
path: str = field(default_factory=str)
|
||||
mtime: float = field(default_factory=float, init=False)
|
||||
files: FilePathList = field(default_factory=list)
|
||||
directories: DirectoryPathList = field(default_factory=list)
|
||||
|
||||
def __post_init__(self):
|
||||
object.__setattr__(self, 'mtime', self.live_mtime)
|
||||
mtime: float = 0.0
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, dict_object: dict) -> Directory:
|
||||
directory = cls.__new__(cls)
|
||||
object.__setattr__(directory, 'path', dict_object.get('path'))
|
||||
object.__setattr__(directory, 'mtime', dict_object.get('mtime'))
|
||||
object.__setattr__(directory, 'files', dict_object.get('files'))
|
||||
object.__setattr__(directory, 'directories', dict_object.get('directories'))
|
||||
object.__setattr__(directory, 'mtime', dict_object.get('mtime', 0.0))
|
||||
object.__setattr__(directory, 'files', dict_object.get('files', []))
|
||||
object.__setattr__(directory, 'directories', dict_object.get('directories', []))
|
||||
return directory
|
||||
|
||||
def clear(self) -> None:
|
||||
@@ -59,12 +59,15 @@ class Directory(Directory): # pylint: disable=E0102
|
||||
}))
|
||||
|
||||
def update(self, source_directory: Directory) -> Directory:
|
||||
if source_directory is not self:
|
||||
if source_directory is not self and source_directory is not None:
|
||||
self._update(source_directory)
|
||||
return self
|
||||
|
||||
def _update(self, source:Directory) -> None:
|
||||
assert not source.path or source.path == self.path, f'When updating a directory, the paths must match. Attempted to update Directory `{self.path}` with `{source.path}`'
|
||||
def _update(self, source: Directory) -> None:
|
||||
assert not source.path or source.path == self.path, (
|
||||
f'When updating a directory, the paths must match. '
|
||||
f'Attempted to update Directory `{self.path}` with `{source.path}`'
|
||||
)
|
||||
for dead_path in self.directories:
|
||||
if dead_path not in source.directories:
|
||||
delete_cached_directory(dead_path)
|
||||
@@ -74,105 +77,115 @@ class Directory(Directory): # pylint: disable=E0102
|
||||
|
||||
@property
|
||||
def exists(self) -> bool:
|
||||
return self.path and os.path.exists(self.path)
|
||||
return bool(self.path and os.path.exists(self.path))
|
||||
|
||||
@property
|
||||
def is_directory(self) -> bool:
|
||||
return self.exists and os.path.isdir(self.path)
|
||||
return bool(self.path and os.path.isdir(self.path))
|
||||
|
||||
@property
|
||||
def live_mtime(self) -> float:
|
||||
return os.path.getmtime(self.path) if self.is_directory else 0
|
||||
try:
|
||||
return os.path.getmtime(self.path) if self.path else 0.0
|
||||
except OSError:
|
||||
return 0.0
|
||||
|
||||
@property
|
||||
def is_stale(self) -> bool:
|
||||
return not self.is_directory or self.mtime != self.live_mtime
|
||||
return self.mtime != self.live_mtime
|
||||
|
||||
|
||||
class DirectoryCache(UserDict, DirectoryCollection):
|
||||
def __delattr__(self, directory_path: str) -> None:
|
||||
directory: Directory = get_directory(directory_path, fetch=False)
|
||||
if directory:
|
||||
map(delete_cached_directory, directory.directories)
|
||||
for child in directory.directories:
|
||||
delete_cached_directory(child)
|
||||
directory.clear()
|
||||
del self.data[directory_path]
|
||||
self.data.pop(directory_path, None)
|
||||
|
||||
|
||||
def clean_directory(directory: Directory, /, recursive: RecursiveType=False) -> bool:
|
||||
def clean_directory(directory: Directory, /, recursive: RecursiveType = False) -> bool:
|
||||
if not directory.is_directory:
|
||||
is_clean = False
|
||||
delete_cached_directory(directory.path)
|
||||
else:
|
||||
is_clean = not directory.is_stale
|
||||
if not is_clean:
|
||||
directory.update(fetch_directory(directory.path))
|
||||
else:
|
||||
for directory_path in directory.directories[:]:
|
||||
try:
|
||||
recurse = recursive and (not callable(recursive) or recursive(directory.path))
|
||||
directory = get_directory(directory_path, fetch=recurse)
|
||||
if directory:
|
||||
if directory.is_directory:
|
||||
if recurse:
|
||||
is_clean = clean_directory(directory, recursive=recurse) and is_clean
|
||||
continue
|
||||
delete_cached_directory(directory_path)
|
||||
# If we had intended to fetch this directory, but didn't, that means it doesn't exist. Purge.
|
||||
if recurse:
|
||||
directory.directories.remove(directory_path)
|
||||
is_clean = False
|
||||
except Exception:
|
||||
pass
|
||||
return False
|
||||
|
||||
is_clean = not directory.is_stale
|
||||
if not is_clean:
|
||||
fetched = fetch_directory(directory.path)
|
||||
if fetched:
|
||||
directory.update(fetched)
|
||||
elif recursive:
|
||||
for directory_path in list(directory.directories):
|
||||
try:
|
||||
recurse = recursive and (not callable(recursive) or recursive(directory.path))
|
||||
child_dir = get_directory(directory_path, fetch=recurse)
|
||||
if child_dir:
|
||||
if child_dir.is_directory:
|
||||
if recurse:
|
||||
is_clean = clean_directory(child_dir, recursive=recurse) and is_clean
|
||||
continue
|
||||
delete_cached_directory(directory_path)
|
||||
if recurse:
|
||||
directory.directories.remove(directory_path)
|
||||
is_clean = False
|
||||
except Exception:
|
||||
pass
|
||||
return is_clean
|
||||
|
||||
|
||||
def get_directory(directory_or_path: str, /, fetch: bool=True) -> Directory | None:
|
||||
def get_directory(directory_or_path: str | Directory, /, fetch: bool = True) -> Directory | None:
|
||||
if isinstance(directory_or_path, Directory):
|
||||
if directory_or_path.is_directory:
|
||||
return directory_or_path
|
||||
else:
|
||||
directory_or_path = directory_or_path.path
|
||||
directory_or_path = real_path(directory_or_path)
|
||||
if not cache_folders.get(directory_or_path, None):
|
||||
directory_or_path = directory_or_path.path
|
||||
|
||||
resolved_path = real_path(directory_or_path)
|
||||
if not resolved_path:
|
||||
return None
|
||||
|
||||
if resolved_path not in cache_folders:
|
||||
if fetch:
|
||||
directory = fetch_directory(directory_path=directory_or_path)
|
||||
directory = fetch_directory(directory_path=resolved_path)
|
||||
if directory and do_cache_folders:
|
||||
cache_folders[directory_or_path] = directory
|
||||
cache_folders[resolved_path] = directory
|
||||
return directory
|
||||
else:
|
||||
clean_directory(cache_folders[directory_or_path])
|
||||
return cache_folders[directory_or_path] if directory_or_path in cache_folders else None
|
||||
return None
|
||||
|
||||
cached = cache_folders[resolved_path]
|
||||
clean_directory(cached)
|
||||
return cache_folders.get(resolved_path)
|
||||
|
||||
|
||||
def fetch_directory(directory_path: str) -> Directory | None:
|
||||
directory: Directory
|
||||
for directory in _walk(directory_path, recurse=False):
|
||||
return directory # The return is intentional, we get a generator, we only need the one
|
||||
return directory
|
||||
return None
|
||||
|
||||
|
||||
def _walk(top, recurse:RecursiveType=True) -> Directory:
|
||||
# reimplemented `path.walk()`
|
||||
def _walk(top: str, recurse: RecursiveType = True) -> Iterator[Directory]:
|
||||
nondirs = []
|
||||
walk_dirs = []
|
||||
top_mtime = 0.0
|
||||
|
||||
try:
|
||||
top_mtime = os.path.getmtime(top)
|
||||
scandir_it = os.scandir(top)
|
||||
except OSError:
|
||||
return
|
||||
|
||||
with scandir_it:
|
||||
while True:
|
||||
try:
|
||||
entry = next(scandir_it)
|
||||
except StopIteration:
|
||||
break
|
||||
if not entry.is_dir():
|
||||
for entry in scandir_it:
|
||||
if not entry.is_dir(follow_symlinks=True):
|
||||
nondirs.append(entry.path)
|
||||
else:
|
||||
if entry.is_symlink() and not os.path.exists(entry.path):
|
||||
log.error(f'Files broken symlink: {entry.path}')
|
||||
else:
|
||||
walk_dirs.append(entry.path)
|
||||
yield Directory(top, nondirs, walk_dirs)
|
||||
|
||||
yield Directory(path=top, files=nondirs, directories=walk_dirs, mtime=top_mtime)
|
||||
|
||||
if recurse:
|
||||
for new_path in walk_dirs:
|
||||
if callable(recurse) and not recurse(new_path):
|
||||
@@ -180,13 +193,13 @@ def _walk(top, recurse:RecursiveType=True) -> Directory:
|
||||
yield from _walk(new_path, recurse=recurse)
|
||||
|
||||
|
||||
def _cached_walk(top, recurse:RecursiveType=True) -> Directory:
|
||||
top = get_directory(top)
|
||||
if not top:
|
||||
def _cached_walk(top: str, recurse: RecursiveType = True) -> Iterator[Directory]:
|
||||
top_dir = get_directory(top)
|
||||
if not top_dir:
|
||||
return
|
||||
yield top
|
||||
yield top_dir
|
||||
if recurse:
|
||||
for child_directory in top.directories:
|
||||
for child_directory in top_dir.directories:
|
||||
if os.path.basename(child_directory).startswith('models--'):
|
||||
continue
|
||||
if callable(recurse) and not recurse(child_directory):
|
||||
@@ -194,28 +207,27 @@ def _cached_walk(top, recurse:RecursiveType=True) -> Directory:
|
||||
yield from _cached_walk(child_directory, recurse=recurse)
|
||||
|
||||
|
||||
def walk(top, recurse:RecursiveType=True, cached=True) -> Directory:
|
||||
def walk(top: str, recurse: RecursiveType = True, cached: bool = True) -> Iterator[Directory]:
|
||||
yield from _cached_walk(top, recurse=recurse) if cached else _walk(top, recurse=recurse)
|
||||
|
||||
|
||||
def delete_cached_directory(directory_path:str) -> bool:
|
||||
global cache_folders # pylint: disable=W0602
|
||||
def delete_cached_directory(directory_path: str) -> bool:
|
||||
if directory_path in cache_folders:
|
||||
del cache_folders[directory_path]
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def is_directory(dir_path:str) -> bool:
|
||||
return dir_path and os.path.exists(dir_path) and os.path.isdir(dir_path)
|
||||
def is_directory(dir_path: str) -> bool:
|
||||
return bool(dir_path and os.path.isdir(dir_path))
|
||||
|
||||
|
||||
def directory_mtime(directory_path:str, /, recursive:RecursiveType=True) -> float:
|
||||
return float(max(0, *[directory.mtime for directory in get_directories(directory_path, recursive=recursive)]))
|
||||
def directory_mtime(directory_path: str, /, recursive: RecursiveType = True) -> float:
|
||||
dirs = get_directories(directory_path, recursive=recursive)
|
||||
return max((d.mtime for d in dirs), default=0.0)
|
||||
|
||||
|
||||
def unique_directories(directories:DirectoryPathList, /, recursive:RecursiveType=True) -> DirectoryPathIterator:
|
||||
'''Ensure no empty, or duplicates'''
|
||||
'''If we are going recursive, then directories that are children of other directories are redundant'''
|
||||
''' @todo this is incredibly inneficient. the hit is small, but it is ugly, no? '''
|
||||
def unique_directories(directories: DirectoryPathList, /, recursive: RecursiveType = True) -> DirectoryPathIterator:
|
||||
directories = sorted(unique_paths(directories), reverse=True)
|
||||
while directories:
|
||||
directory = directories.pop()
|
||||
@@ -231,74 +243,81 @@ def unique_directories(directories:DirectoryPathList, /, recursive:RecursiveType
|
||||
child_directory = directories[-1][len(directory):]
|
||||
if child_directory:
|
||||
next_directory = _directory
|
||||
if not callable(recursive):
|
||||
_remove_directory = next_directory
|
||||
else:
|
||||
for sub_directory in child_directory.split(os.path.sep):
|
||||
next_directory = os.path.join(next_directory, sub_directory)
|
||||
if recursive(next_directory):
|
||||
_remove_directory = os.path.join(next_directory, '')
|
||||
break
|
||||
_remove_directory = None
|
||||
for sub_directory in child_directory.split(os.path.sep):
|
||||
next_directory = os.path.join(next_directory, sub_directory)
|
||||
if recursive(next_directory):
|
||||
_remove_directory = os.path.join(next_directory, '')
|
||||
break
|
||||
while _remove_directory and directories:
|
||||
_d = directories.pop()
|
||||
if not directories[-1].startswith(_remove_directory):
|
||||
del _remove_directory
|
||||
break
|
||||
directories.pop()
|
||||
|
||||
|
||||
def unique_paths(directory_paths:DirectoryPathList) -> DirectoryPathIterator:
|
||||
realpaths = (real_path(directory_path) for directory_path in filter(bool, directory_paths))
|
||||
return {real_directory_path: True for real_directory_path in filter(bool, realpaths)}.keys()
|
||||
def unique_paths(directory_paths: DirectoryPathList) -> DirectoryPathIterator:
|
||||
seen = set()
|
||||
for path in directory_paths:
|
||||
if path:
|
||||
r = real_path(path)
|
||||
if r and r not in seen:
|
||||
seen.add(r)
|
||||
yield r
|
||||
|
||||
|
||||
def get_directories(*directory_paths: DirectoryPathList, fetch:bool=True, recursive:RecursiveType=True) -> DirectoryCollection:
|
||||
directory_paths = unique_directories(directory_paths, recursive=recursive)
|
||||
directories = (get_directory(directory_path, fetch=fetch) for directory_path in directory_paths)
|
||||
return filter(bool, directories)
|
||||
def get_directories(*directory_paths: DirectoryPathList, fetch: bool = True, recursive: RecursiveType = True) -> DirectoryCollection:
|
||||
dirs = unique_directories(directory_paths, recursive=recursive)
|
||||
return [d for d in (get_directory(p, fetch=fetch) for p in dirs) if d]
|
||||
|
||||
|
||||
def directory_files(*directories_or_paths: DirectoryPathList | DirectoryList, recursive: RecursiveType=True) -> FilePathIterator:
|
||||
return itertools.chain.from_iterable(
|
||||
itertools.chain(
|
||||
directory_object.files,
|
||||
[]
|
||||
if not recursive
|
||||
else itertools.chain.from_iterable(
|
||||
directory_files(directory, recursive=recursive)
|
||||
for directory
|
||||
in filter(
|
||||
bool,
|
||||
map(get_directory, filter(((bool if recursive else False) if not callable(recursive) else recursive), directory_object.directories))
|
||||
)
|
||||
)
|
||||
)
|
||||
for directory_object
|
||||
in filter(bool, map(get_directory, directories_or_paths))
|
||||
)
|
||||
def directory_files(*directories_or_paths: DirectoryPathList | DirectoryList, recursive: RecursiveType = True) -> FilePathIterator:
|
||||
"""Iterative directory file gatherer avoiding deeply nested generator recursion."""
|
||||
visited = set()
|
||||
stack = list(directories_or_paths)
|
||||
|
||||
while stack:
|
||||
item = stack.pop()
|
||||
dir_obj = get_directory(item) if not isinstance(item, Directory) else item
|
||||
if not dir_obj or dir_obj.path in visited:
|
||||
continue
|
||||
|
||||
visited.add(dir_obj.path)
|
||||
yield from dir_obj.files
|
||||
|
||||
if recursive:
|
||||
for child_path in dir_obj.directories:
|
||||
if callable(recursive) and not recursive(child_path):
|
||||
continue
|
||||
stack.append(child_path)
|
||||
|
||||
|
||||
def extension_filter(ext_filter: ExtensionList | None=None, ext_blacklist: ExtensionList | None=None) -> ExtensionFilter:
|
||||
if ext_filter:
|
||||
ext_filter = [*map(str.upper, ext_filter)]
|
||||
if ext_blacklist:
|
||||
ext_blacklist = [*map(str.upper, ext_blacklist)]
|
||||
def filter_functon(fp:str):
|
||||
return (not ext_filter or any(fp.upper().endswith(ew) for ew in ext_filter)) and (not ext_blacklist or not any(fp.upper().endswith(ew) for ew in ext_blacklist))
|
||||
return filter_functon
|
||||
def extension_filter(ext_filter: ExtensionList | None = None, ext_blacklist: ExtensionList | None = None) -> ExtensionFilter:
|
||||
"""Fast C-level tuple.endswith checks."""
|
||||
valid_exts = tuple(ext.lower() if ext.startswith('.') else f'.{ext.lower()}' for ext in ext_filter) if ext_filter else None
|
||||
black_exts = tuple(ext.lower() if ext.startswith('.') else f'.{ext.lower()}' for ext in ext_blacklist) if ext_blacklist else None
|
||||
|
||||
def filter_function(fp: str) -> bool:
|
||||
fp_lower = fp.lower()
|
||||
if valid_exts and not fp_lower.endswith(valid_exts):
|
||||
return False
|
||||
if black_exts and fp_lower.endswith(black_exts):
|
||||
return False
|
||||
return True
|
||||
|
||||
return filter_function
|
||||
|
||||
|
||||
def not_hidden(filepath: str) -> bool:
|
||||
return not os.path.basename(filepath).startswith('.')
|
||||
|
||||
|
||||
def filter_files(file_paths: FilePathList, ext_filter: ExtensionList | None=None, ext_blacklist: ExtensionList | None=None) -> FilePathIterator:
|
||||
def filter_files(file_paths: FilePathList, ext_filter: ExtensionList | None = None, ext_blacklist: ExtensionList | None = None) -> FilePathIterator:
|
||||
return filter(extension_filter(ext_filter, ext_blacklist), file_paths)
|
||||
|
||||
|
||||
def list_files(*directory_paths:DirectoryPathList, ext_filter: ExtensionList | None=None, ext_blacklist: ExtensionList | None=None, recursive:RecursiveType=True) -> FilePathIterator:
|
||||
return filter_files(itertools.chain.from_iterable(
|
||||
directory_files(directory, recursive=recursive)
|
||||
for directory in get_directories(*directory_paths, recursive=recursive)
|
||||
), ext_filter, ext_blacklist)
|
||||
def list_files(*directory_paths: DirectoryPathList, ext_filter: ExtensionList | None = None, ext_blacklist: ExtensionList | None = None, recursive: RecursiveType = True) -> FilePathIterator:
|
||||
raw_files = directory_files(*directory_paths, recursive=recursive)
|
||||
return filter_files(raw_files, ext_filter, ext_blacklist)
|
||||
|
||||
|
||||
cache_folders = DirectoryCache({})
|
||||
|
||||
+5
-1
@@ -78,6 +78,9 @@ except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
# del torch._C._c10d_init
|
||||
import torch.distributed # pylint: disable=ungrouped-imports
|
||||
torch.distributed.is_available = lambda: False
|
||||
import torch.distributed.distributed_c10d as _c10d # pylint: disable=unused-import,ungrouped-imports
|
||||
except Exception:
|
||||
log.warning('Loader: torch is not built with distributed support')
|
||||
@@ -98,8 +101,9 @@ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
warnings.filterwarnings(action="ignore", category=UserWarning, module="torchvision")
|
||||
torchvision = None
|
||||
try:
|
||||
sys.modules['torchvision.samples'] = types.ModuleType("torchvision.samples") # monkey-patch to avoid torchvision sample download
|
||||
import torchvision # pylint: disable=W0611,C0411
|
||||
import pytorch_lightning # pytorch_lightning should be imported after torch, but it re-enables warnings on import so import once to disable them # pylint: disable=W0611,C0411
|
||||
# import pytorch_lightning # pytorch_lightning should be imported after torch, but it re-enables warnings on import so import once to disable them # pylint: disable=W0611,C0411
|
||||
except Exception as e:
|
||||
report(f'torchvision=={torchvision.__version__ if torchvision is not None else None}', e)
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import os
|
||||
import io
|
||||
from functools import lru_cache
|
||||
import random
|
||||
import re
|
||||
import time
|
||||
@@ -196,8 +197,12 @@ class ExtraNetworksPage:
|
||||
errors.display(e, 'Network version')
|
||||
return all_versions[0]
|
||||
|
||||
@lru_cache(maxsize=2048, typed=False)
|
||||
def link_preview(self, filename: str):
|
||||
if not os.path.exists(filename):
|
||||
if filename == 'ui/assets/missing.png':
|
||||
return f"{shared.opts.subpath}/sdapi/v1/network/thumb?filename={filename}"
|
||||
just_file = not bool(os.path.dirname(filename))
|
||||
if just_file or not os.path.exists(filename):
|
||||
ref = os.path.join(paths.reference_path, filename)
|
||||
if os.path.exists(ref):
|
||||
filename = ref
|
||||
@@ -456,6 +461,7 @@ class ExtraNetworksPage:
|
||||
errors.display(e, 'Networks')
|
||||
return ""
|
||||
|
||||
@lru_cache(maxsize=2048, typed=False)
|
||||
def find_preview_file(self, path: str | None):
|
||||
if path is None:
|
||||
return 'ui/assets/missing.png'
|
||||
@@ -477,6 +483,7 @@ class ExtraNetworksPage:
|
||||
return file
|
||||
return 'ui/assets/missing.png'
|
||||
|
||||
@lru_cache(maxsize=2048, typed=False)
|
||||
def find_preview(self, filename: str):
|
||||
t0 = time.time()
|
||||
preview_file = self.find_preview_file(filename)
|
||||
|
||||
@@ -63,6 +63,7 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage):
|
||||
v['tags'].append(f'Size: {size} GB')
|
||||
shared.reference_models[k] = v
|
||||
|
||||
models = []
|
||||
for k, v in shared.reference_models.items():
|
||||
count['total'] += 1
|
||||
url = v['path']
|
||||
@@ -126,14 +127,14 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage):
|
||||
if ready:
|
||||
count['ready'] += 1
|
||||
|
||||
yield {
|
||||
model = {
|
||||
"type": 'Model',
|
||||
"name": name,
|
||||
"title": name,
|
||||
"filename": url,
|
||||
"preview": self.find_preview(os.path.join(paths.reference_path, preview)),
|
||||
"local_preview": preview_file,
|
||||
"onclick": '"' + html.escape(f"selectReference({json.dumps(path)})") + '"',
|
||||
"onclick": '"' + html.escape(f"selectReference({path})") + '"',
|
||||
"hash": None,
|
||||
"mtime": mtime,
|
||||
"size": size,
|
||||
@@ -143,7 +144,10 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage):
|
||||
"version": version,
|
||||
"tags": v.get('tags', []),
|
||||
}
|
||||
models.append(model)
|
||||
# yield model
|
||||
log.debug(f'Networks: type="reference" {count}')
|
||||
return models
|
||||
|
||||
def create_item(self, name):
|
||||
record = None
|
||||
@@ -190,8 +194,7 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage):
|
||||
item = future.result()
|
||||
if item is not None:
|
||||
items.append(item)
|
||||
for record in self.list_reference():
|
||||
items.append(record)
|
||||
items += self.list_reference()
|
||||
self.update_all_previews(items)
|
||||
return items
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import os
|
||||
import json
|
||||
from modules import shared, ui_extra_networks, modelstats, files_cache
|
||||
from modules.logger import log
|
||||
|
||||
@@ -44,22 +43,25 @@ class ExtraNetworksPageWildcards(ui_extra_networks.ExtraNetworksPage):
|
||||
relname = os.path.relpath(filename, shared.opts.wildcards_dir)
|
||||
name = os.path.splitext(relname)[0]
|
||||
size, mtime = modelstats.stat(filename)
|
||||
records = []
|
||||
try:
|
||||
record = {
|
||||
"type": 'Wildcard',
|
||||
"name": name,
|
||||
"filename": filename,
|
||||
"preview": self.find_preview(filename),
|
||||
# "preview": self.find_preview(filename),
|
||||
"preview": None,
|
||||
"local_preview": f"{os.path.splitext(filename)[0]}.{shared.opts.samples_format}",
|
||||
"prompt": json.dumps(f" __{name}__"),
|
||||
"prompt": f" __{name}__",
|
||||
"mtime": mtime,
|
||||
"size": size,
|
||||
"description": '',
|
||||
"info": {},
|
||||
}
|
||||
yield record
|
||||
records.append(record)
|
||||
except Exception as e:
|
||||
log.debug(f'Networks error: type=wildcard file="{filename}" {e}')
|
||||
return records
|
||||
|
||||
def allowed_directories_for_previews(self):
|
||||
return [v for v in [shared.opts.wildcards_dir] if v is not None]
|
||||
|
||||
@@ -12,6 +12,7 @@ from threading import Thread
|
||||
from installer import git_commit, custom_excepthook, version
|
||||
from modules.logger import log
|
||||
from modules import timer
|
||||
import modules.errors
|
||||
import modules.loader
|
||||
import modules.hashes
|
||||
import modules.paths
|
||||
@@ -155,6 +156,8 @@ def initialize():
|
||||
# make the program just exit at ctrl+c without waiting for anything
|
||||
def sigint_handler(_sig, _frame):
|
||||
log.trace(f'State history: uptime={round(time.time() - shared.state.server_start)} jobs={shared.state.job_history} tasks={shared.state.task_history} latents={shared.state.latent_history} images={shared.state.image_history}')
|
||||
if modules.errors._profiler is not None: # pylint: disable=protected-access
|
||||
modules.errors.profile_print('SIGINT')
|
||||
log.info('Exiting')
|
||||
try:
|
||||
for f in glob.glob("*.lock"):
|
||||
@@ -393,7 +396,7 @@ def start_ui():
|
||||
return app
|
||||
|
||||
|
||||
def webui(restart=False, _exit=False):
|
||||
def webui(restart=False, _exit=False, profiler=None):
|
||||
if restart:
|
||||
modules.script_callbacks.app_reload_callback()
|
||||
modules.script_callbacks.script_unloaded_callback()
|
||||
@@ -422,6 +425,7 @@ def webui(restart=False, _exit=False):
|
||||
log.info(f"Launch time: {timer.launch.summary(min_time=0)}")
|
||||
log.info(f"Installer time: {timer.init.summary(min_time=0)}")
|
||||
log.info(f"Startup time: {timer.startup.summary(min_time=0)}")
|
||||
modules.errors._profiler = profiler # pylint: disable=protected-access
|
||||
else:
|
||||
timer.startup.add('launch', timer.launch.get_total())
|
||||
timer.startup.add('installer', timer.init.get_total())
|
||||
|
||||
Reference in New Issue
Block a user