diff --git a/modules/images.py b/modules/images.py index 4b0d198a2..23a6c4d13 100644 --- a/modules/images.py +++ b/modules/images.py @@ -298,7 +298,7 @@ class FilenameGenerator: 'model_name': lambda self: shared.sd_model.sd_checkpoint_info.model_name, 'model_hash': lambda self: shared.sd_model.sd_checkpoint_info.shorthash, - 'prompt': lambda self: self.prompt, + 'prompt': lambda self: self.prompt_full(), 'prompt_no_styles': lambda self: self.prompt_no_style(), 'prompt_words': lambda self: self.prompt_words(), 'prompt_hash': lambda self: hashlib.sha256(self.prompt.encode()).hexdigest()[0:8], @@ -350,6 +350,9 @@ class FilenameGenerator: shorthash = hashlib.sha256(img_str).hexdigest()[0:8] return shorthash + def prompt_full(self): + return self.sanitize(self.prompt) + def prompt_words(self): if self.prompt is None: return '' @@ -358,7 +361,7 @@ class FilenameGenerator: no_brackets = re_brackets.sub('', no_network) words = [x for x in re_nonletters.split(no_brackets or "") if len(x) > 0] prompt = " ".join(words[0:shared.opts.directories_max_prompt_words]) - return prompt + return self.sanitize(prompt) def prompt_no_style(self): if self.p is None or self.prompt is None: @@ -369,7 +372,7 @@ class FilenameGenerator: for part in style.split("{prompt}"): prompt_no_style = prompt_no_style.replace(part, "").replace(", ,", ",") prompt_no_style = prompt_no_style.replace(style, "") - return prompt_no_style + return self.sanitize(prompt_no_style) def datetime(self, *args): time_datetime = datetime.datetime.now() @@ -386,19 +389,21 @@ class FilenameGenerator: return formatted_time def sanitize(self, filename): - invalid_chars = '#<>:;"/\\|?*\n\t\r' + invalid_chars = '#<>.:;"/\\|?*\n\t\r' invalid_prefix = '' invalid_suffix = '.' - parts = Path(filename).parts + fn, ext = os.path.splitext(filename) + parts = Path(fn).parts + newparts = [] for part in parts: - part = part.translate({ord(x): '_' for x in invalid_chars}) + part = part.translate({ ord(x): '_' for x in invalid_chars }) part = part.lstrip(invalid_prefix) part = part.rstrip(invalid_suffix) - fn = Path(*parts) - max_length = os.statvfs(__file__).f_namemax if hasattr(os, 'statvfs') else 128 - fn, ext = os.path.splitext(fn) - fn = fn[:max_length-max(4, len(ext))] + ext - # shared.log.debug(f'Filename sanitize: input={filename} parts={parts} output={fn}') + newparts.append(part) + fn = Path(*newparts) + max_length = max(os.statvfs(__file__).f_namemax if hasattr(os, 'statvfs') else 128, 250) + fn = str(fn)[:max_length-max(4, len(ext))] + ext + shared.log.debug(f'Filename sanitize: input="{filename}" parts={parts} output={fn}') return fn def apply(self, x): @@ -563,20 +568,20 @@ def save_image(image, path, basename = '', seed=None, prompt=None, extension=sha if info is not None: pnginfo[pnginfo_section_name] = info params = script_callbacks.ImageSaveParams(image, p, filename, pnginfo) + params.filename = namegen.sanitize(filename) script_callbacks.before_image_saved_callback(params) exifinfo = params.pnginfo.get('UserComment', '') exifinfo = (exifinfo + ', ' if len(exifinfo) > 0 else '') + params.pnginfo.get(pnginfo_section_name, '') - filename = namegen.sanitize(params.filename) - dirname = os.path.dirname(filename) + dirname = os.path.dirname(params.filename) os.makedirs(dirname, exist_ok=True) - filename, extension = os.path.splitext(filename) + filename, extension = os.path.splitext(params.filename) filename_txt = f"{filename}.txt" if shared.opts.save_txt and len(exifinfo) > 0 else None save_queue.put((params.image, filename, extension, params, exifinfo, filename_txt)) # actual save is executed in a thread that polls data from queue save_queue.join() params.image.already_saved_as = params.filename script_callbacks.image_saved_callback(params) - return params.filename, filename_txt + return filename, filename_txt def safe_decode_string(s: bytes): diff --git a/modules/processing.py b/modules/processing.py index fffb93455..db1eeda12 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -845,6 +845,9 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: else: raise ValueError(f"Unknown backend {shared.backend}") + if not shared.opts.keep_incomplete and shared.state.interrupted: + x_samples_ddim = [] + if shared.cmd_opts.lowvram or shared.cmd_opts.medvram and shared.backend == shared.Backend.ORIGINAL: modules.lowvram.send_everything_to_cpu() devices.torch_gc() @@ -945,7 +948,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: index_of_first_image=index_of_first_image, infotexts=infotexts, ) - if p.scripts is not None and not shared.state.interrupted: + if p.scripts is not None and not (shared.state.interrupted or shared.state.skipped): p.scripts.postprocess(p, res) return res diff --git a/modules/sd_vae_approx.py b/modules/sd_vae_approx.py index 3e4b93ddd..bd09529e4 100644 --- a/modules/sd_vae_approx.py +++ b/modules/sd_vae_approx.py @@ -71,7 +71,7 @@ def cheap_approximation(sample): # Approximate simple ]).reshape(3, 4, 1, 1) simple_bias = None try: - x_sample = nn.functional.conv2d(sample, simple_weights.to(sample.device, sample.dtype), simple_bias.to(sample.device, sample.dtype)) # pylint: disable=not-callable + x_sample = nn.functional.conv2d(sample, simple_weights.to(sample.device, sample.dtype), simple_bias.to(sample.device, sample.dtype) if simple_bias is not None else None) # pylint: disable=not-callable return x_sample except Exception as e: shared.log.error(f'Decode simple: {e}') diff --git a/modules/ui_extensions.py b/modules/ui_extensions.py index a8e93e361..3f5e69b85 100644 --- a/modules/ui_extensions.py +++ b/modules/ui_extensions.py @@ -421,7 +421,6 @@ def create_ui(): update_extension_button = gr.Button(elem_id="update_extension_button", visible=False) with gr.Column(scale=4): search_text = gr.Text(label="Search") - info = gr.HTML('Note: After any operation such as install/uninstall or enable/disable, please restart the server') with gr.Column(scale=1): sort_column = gr.Dropdown(value="default", label="Sort by", choices=list(sort_ordering.keys()), multiselect=False) with gr.Column(scale=1): @@ -429,6 +428,9 @@ def create_ui(): check = gr.Button(value="Update all installed", variant="primary") apply = gr.Button(value="Apply changes", variant="primary") list_extensions() + gr.HTML('

Extension list

⯀ Refesh extension list to download latest list with status
⯀ Check status of an extension by looking at status icon before installing it
⯀ After any operation such as install/uninstall or enable/disable, please restart the server
') + gr.HTML('') + info = gr.HTML('') extensions_table = gr.HTML(create_html(search_text.value, sort_column.value)) check.click( fn=wrap_gradio_gpu_call(check_updates, extra_outputs=[gr.update()]), diff --git a/modules/ui_tempdir.py b/modules/ui_tempdir.py index 5b027fa98..1293ad6b6 100644 --- a/modules/ui_tempdir.py +++ b/modules/ui_tempdir.py @@ -58,9 +58,9 @@ def pil_to_temp_file(self, img, dir: str, format="png") -> str: # pylint: disabl if isinstance(key, str) and isinstance(value, str): metadata.add_text(key, value) use_metadata = True - with tempfile.NamedTemporaryFile(delete=False, suffix=".png", dir=dir) as file_obj: - img.save(file_obj, pnginfo=(metadata if use_metadata else None)) - name = file_obj.name + with tempfile.NamedTemporaryFile(delete=False, suffix=".png", dir=dir) as tmp: + img.save(tmp, pnginfo=(metadata if use_metadata else None)) + name = tmp.name shared.log.debug(f'Saving temp: image="{name}"') return name diff --git a/wiki b/wiki index 58e8d11f9..b9712d07c 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 58e8d11f94503d86f0b9b3f73046c5996a2fc000 +Subproject commit b9712d07cf931b8bca512ae4f083b88877062c77