From 5dcaaba614cf76005f66c2e9269361750440caf9 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Thu, 27 Apr 2023 09:42:41 -0400 Subject: [PATCH] reduce extra network exceptions --- TODO.md | 4 +- extensions-builtin/sd-webui-controlnet | 2 +- modules/lora | 2 +- modules/ui_extra_networks.py | 83 ++++---------------------- scripts/postprocessing_upscale.py | 7 +-- 5 files changed, 19 insertions(+), 79 deletions(-) diff --git a/TODO.md b/TODO.md index f67eeebfa..174c4b337 100644 --- a/TODO.md +++ b/TODO.md @@ -61,5 +61,5 @@ Tech that can be integrated as part of the core workflow... ### Pending Code Updates -- add optional models description shown in extra networks cards -- Add option to specify fallback sampler if primary sampler is not compatible with desired operation +- ability to view/add/edit model description shown in extra networks cards +- add option to specify fallback sampler if primary sampler is not compatible with desired operation diff --git a/extensions-builtin/sd-webui-controlnet b/extensions-builtin/sd-webui-controlnet index 93b0f9e1b..2bc440001 160000 --- a/extensions-builtin/sd-webui-controlnet +++ b/extensions-builtin/sd-webui-controlnet @@ -1 +1 @@ -Subproject commit 93b0f9e1b7cc246165666b7b307bc8243db2c3f4 +Subproject commit 2bc4400011b38ab7f1d3f27a95897a6cb0c28c2a diff --git a/modules/lora b/modules/lora index 18f171d88..d52c524fc 160000 --- a/modules/lora +++ b/modules/lora @@ -1 +1 @@ -Subproject commit 18f171d885d4c870bd1c0656f7247e9649df62fd +Subproject commit d52c524fc2942c053cf37c648188502a3a26df1b diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index a719bde33..a8e3851b1 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -20,37 +20,28 @@ close_symbol = '\U0000274C' # ❌ def register_page(page): """registers extra networks page for the UI; recommend doing it in on_before_ui() callback for extensions""" - extra_pages.append(page) allowed_dirs.clear() allowed_dirs.update(set(sum([x.allowed_directories_for_previews() for x in extra_pages], []))) def fetch_file(filename: str = ""): - from starlette.responses import FileResponse - + from starlette.responses import FileResponse, JSONResponse if not any([Path(x).absolute() in Path(filename).absolute().parents for x in allowed_dirs]): - raise ValueError(f"File cannot be fetched: {filename}. Must be in one of directories registered by extra pages.") - - ext = os.path.splitext(filename)[1].lower() - if ext not in (".png", ".jpg", ".webp"): - raise ValueError(f"File cannot be fetched: {filename}. Only png and jpg and webp.") - - # would profit from returning 304 + return JSONResponse({"error": f"File cannot be fetched: {filename}. Must be in one of directories registered by extra pages."}) + if os.path.splitext(filename)[1].lower() not in (".png", ".jpg", ".webp"): + return JSONResponse({"error": f"File cannot be fetched: {filename}. Only png and jpg and webp."}) return FileResponse(filename, headers={"Accept-Ranges": "bytes"}) def get_metadata(page: str = "", item: str = ""): from starlette.responses import JSONResponse - page = next(iter([x for x in extra_pages if x.name == page]), None) if page is None: return JSONResponse({}) - metadata = page.metadata.get(item) if metadata is None: return JSONResponse({}) - return JSONResponse({"metadata": metadata}) @@ -75,58 +66,44 @@ class ExtraNetworksPage: def search_terms_from_path(self, filename, possible_directories=None): abspath = os.path.abspath(filename) - for parentdir in (possible_directories if possible_directories is not None else self.allowed_directories_for_previews()): parentdir = os.path.abspath(parentdir) if abspath.startswith(parentdir): return abspath[len(parentdir):].replace('\\', '/') - return "" def create_html(self, tabname): view = shared.opts.extra_networks_default_view items_html = '' - self.metadata = {} - subdirs = {} for parentdir in [os.path.abspath(x) for x in self.allowed_directories_for_previews()]: for x in glob.glob(os.path.join(parentdir, '**/*'), recursive=True): if not os.path.isdir(x): continue - subdir = os.path.abspath(x)[len(parentdir):].replace("\\", "/") while subdir.startswith("/"): subdir = subdir[1:] - is_empty = len(os.listdir(x)) == 0 if not is_empty and not subdir.endswith("/"): subdir = subdir + "/" - subdirs[subdir] = 1 - if subdirs: subdirs = {"": 1, **subdirs} - subdirs_html = "".join([f""" """ for subdir in subdirs]) - for item in self.list_items(): metadata = item.get("metadata") if metadata: self.metadata[item["name"]] = metadata - items_html += self.create_html_for_item(item, tabname) - if items_html == '': dirs = "".join([f"
  • {x}
  • " for x in self.allowed_directories_for_previews()]) items_html = shared.html("extra-networks-no-cards.html").format(dirs=dirs) - self_name_id = self.name.replace(" ", "_") - res = f"""
    {subdirs_html} @@ -135,7 +112,6 @@ class ExtraNetworksPage: {items_html}
    """ - return res def list_items(self): @@ -146,11 +122,9 @@ class ExtraNetworksPage: def create_html_for_item(self, item, tabname): preview = item.get("preview", None) - onclick = item.get("onclick", None) if onclick is None: onclick = '"' + html.escape(f"""return cardClicked({json.dumps(tabname)}, {item["prompt"]}, {"true" if self.allow_negative_prompt else "false"})""") + '"' - height = f"height: {shared.opts.extra_networks_card_height}px;" if shared.opts.extra_networks_card_height else '' width = f"width: {shared.opts.extra_networks_card_width}px;" if shared.opts.extra_networks_card_width else '' background_image = f"background-image: url(\"{html.escape(preview)}\");" if preview else '' @@ -158,7 +132,6 @@ class ExtraNetworksPage: metadata = item.get("metadata") if metadata: metadata_button = f"
    " - args = { "style": f"'{height}{width}{background_image}'", "prompt": item.get("prompt", None), @@ -173,24 +146,19 @@ class ExtraNetworksPage: "search_term": item.get("search_term", ""), "metadata_button": metadata_button, } - return self.card_page.format(**args) def find_preview(self, path): """ Find a preview PNG for a given path (without extension) and call link_preview on it. """ - preview_extensions = ["png", "jpg", "webp"] if shared.opts.samples_format not in preview_extensions: preview_extensions.append(shared.opts.samples_format) - potential_files = sum([[path + "." + ext, path + ".preview." + ext] for ext in preview_extensions], []) - for file in potential_files: if os.path.isfile(file): return self.link_preview(file) - return None def find_description(self, path): @@ -214,31 +182,24 @@ class ExtraNetworksUi: def __init__(self): self.pages = None self.stored_extra_pages = None - self.button_save_preview = None self.preview_target_filename = None - self.button_save_description = None self.button_read_description = None self.description_target_filename = None self.description_input = None - self.tabname = None def pages_in_preferred_order(pages): tab_order = [x.lower().strip() for x in shared.opts.ui_extra_networks_tab_reorder.split(",")] - def tab_name_score(name): name = name.lower() for i, possible_match in enumerate(tab_order): if possible_match in name: return i - return len(pages) - tab_scores = {page.name: (tab_name_score(page.name), original_index) for original_index, page in enumerate(pages)} - return sorted(pages, key=lambda x: tab_scores[x.name]) @@ -247,54 +208,43 @@ def create_ui(container, button, tabname): ui.pages = [] ui.stored_extra_pages = pages_in_preferred_order(extra_pages.copy()) ui.tabname = tabname - - with gr.Tabs(elem_id=tabname+"_extra_tabs") as tabs: + with gr.Tabs(elem_id=tabname+"_extra_tabs"): for page in ui.stored_extra_pages: with gr.Tab(page.title): - page_elem = gr.HTML(page.create_html(ui.tabname)) ui.pages.append(page_elem) - - filter = gr.Textbox('', show_label=False, elem_id=tabname+"_extra_search", placeholder="Search...", visible=False) - + _filter = gr.Textbox('', show_label=False, elem_id=tabname+"_extra_search", placeholder="Search...", visible=False) ui.description_input = gr.TextArea('', show_label=False, elem_id=tabname+"_description_input", placeholder="Save/Replace Extra Network Description...", lines=2) button_refresh = ToolButton(refresh_symbol, elem_id=tabname+"_extra_refresh") button_close = ToolButton(close_symbol, elem_id=tabname+"_extra_close") - ui.button_save_preview = gr.Button('Save preview', elem_id=tabname+"_save_preview", visible=False) ui.preview_target_filename = gr.Textbox('Preview save filename', elem_id=tabname+"_preview_filename", visible=False) - ui.button_save_description = gr.Button('Save description', elem_id=tabname+"_save_description", visible=False) ui.button_read_description = gr.Button('Read description', elem_id=tabname+"_read_description", visible=False) ui.description_target_filename = gr.Textbox('Description save filename', elem_id=tabname+"_description_filename", visible=False) - def toggle_visibility(is_visible): is_visible = not is_visible return is_visible, gr.update(visible=is_visible), gr.update(variant=("secondary-down" if is_visible else "secondary")) - state_visible = gr.State(value=False) + state_visible = gr.State(value=False) # pylint: disable=abstract-class-instantiated button.click(fn=toggle_visibility, inputs=[state_visible], outputs=[state_visible, container, button]) button_close.click(fn=toggle_visibility, inputs=[state_visible], outputs=[state_visible, container]) def refresh(): res = [] - for pg in ui.stored_extra_pages: pg.refresh() res.append(pg.create_html(ui.tabname)) - return res button_refresh.click(fn=refresh, inputs=[], outputs=ui.pages) - return ui def path_is_parent(parent_path, child_path): parent_path = os.path.abspath(parent_path) child_path = os.path.abspath(child_path) - return child_path.startswith(parent_path) @@ -303,30 +253,24 @@ def setup_ui(ui, gallery): if len(images) == 0: print("There is no image in gallery to save as a preview.") return [page.create_html(ui.tabname) for page in ui.stored_extra_pages] - index = int(index) index = 0 if index < 0 else index index = len(images) - 1 if index >= len(images) else index - img_info = images[index if index >= 0 else 0] image = image_from_url_text(img_info) - geninfo, items = read_info_from_image(image) - + geninfo, _items = read_info_from_image(image) is_allowed = False for extra_page in ui.stored_extra_pages: if any([path_is_parent(x, filename) for x in extra_page.allowed_directories_for_previews()]): is_allowed = True break - assert is_allowed, f'writing to {filename} is not allowed' - if geninfo: pnginfo_data = PngImagePlugin.PngInfo() pnginfo_data.add_text('parameters', geninfo) image.save(filename, pnginfo=pnginfo_data) else: image.save(filename) - return [page.create_html(ui.tabname) for page in ui.stored_extra_pages] ui.button_save_preview.click( @@ -335,27 +279,24 @@ def setup_ui(ui, gallery): inputs=[ui.preview_target_filename, gallery, ui.preview_target_filename], outputs=[*ui.pages] ) - + # write description to a file def save_description(filename,descrip): lastDotIndex = filename.rindex('.') filename = filename[0:lastDotIndex]+".description.txt" if descrip != "": - try: - f = open(filename,'w') + try: + f = open(filename,'w', encoding='utf-8') except OSError: print ("Could not open file to write: " + filename) with f: f.write(descrip) f.close() return [page.create_html(ui.tabname) for page in ui.stored_extra_pages] - + ui.button_save_description.click( fn=save_description, _js="function(x,y){return [x,y]}", inputs=[ui.description_target_filename, ui.description_input], outputs=[*ui.pages] ) - - - diff --git a/scripts/postprocessing_upscale.py b/scripts/postprocessing_upscale.py index ef1186ac6..b2f9c7408 100644 --- a/scripts/postprocessing_upscale.py +++ b/scripts/postprocessing_upscale.py @@ -25,10 +25,9 @@ class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing): with gr.TabItem('Scale to', elem_id="extras_scale_to_tab") as tab_scale_to: with FormRow(): - with gr.Column(elem_id="upscaling_column_size", scale=4): - upscaling_resize_w = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="extras_upscaling_resize_w") - upscaling_resize_h = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="extras_upscaling_resize_h") - with gr.Column(elem_id="upscaling_dimensions_row", scale=1, elem_classes="dimensions-tools"): + with gr.Row(elem_id="upscaling_column_size", scale=4): + upscaling_resize_w = gr.Slider(minimum=64, maximum=4096, step=8, label="Width", value=512, elem_id="extras_upscaling_resize_w") + upscaling_resize_h = gr.Slider(minimum=64, maximum=4096, step=8, label="Height", value=512, elem_id="extras_upscaling_resize_h") upscaling_res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="upscaling_res_switch_btn") upscaling_crop = gr.Checkbox(label='Crop to fit', value=True, elem_id="extras_upscaling_crop")