import json import os.path import sys import time import traceback import git import gradio as gr import html import shutil import errno from modules import extensions, shared, paths from modules.call_queue import wrap_gradio_gpu_call available_extensions = {"extensions": []} def check_access(): assert not shared.cmd_opts.disable_extension_access, "extension access disabled because of command line flags" def apply_and_restart(disable_list, update_list): check_access() disabled = json.loads(disable_list) assert type(disabled) == list, f"wrong disable_list data for apply_and_restart: {disable_list}" update = json.loads(update_list) assert type(update) == list, f"wrong update_list data for apply_and_restart: {update_list}" update = set(update) for ext in extensions.extensions: if ext.name not in update: continue try: ext.fetch_and_reset_hard() except Exception: print(f"Error getting updates for {ext.name}:", file=sys.stderr) print(traceback.format_exc(), file=sys.stderr) shared.opts.disabled_extensions = disabled shared.opts.save(shared.config_filename) shared.state.interrupt() shared.state.need_restart = True def check_updates(id_task, disable_list): check_access() disabled = json.loads(disable_list) assert type(disabled) == list, f"wrong disable_list data for apply_and_restart: {disable_list}" exts = [ext for ext in extensions.extensions if ext.remote is not None and ext.name not in disabled] shared.state.job_count = len(exts) for ext in exts: shared.state.textinfo = ext.name try: ext.check_updates() except FileNotFoundError as e: if 'FETCH_HEAD' not in str(e): raise except Exception: print(f"Error checking updates for {ext.name}:", file=sys.stderr) print(traceback.format_exc(), file=sys.stderr) shared.state.nextjob() return extension_table(), "" def extension_table(): code = f"""
Extension | URL | Version | Update |
---|---|---|---|
{remote} | {ext.version} | {ext_status} |
Extension | Description | Action |
---|---|---|
{html.escape(name)} {tags_text} |
{html.escape(description)} Added: {html.escape(added)} |
{install_code} |
Extension hidden: {hidden}
" return code, list(tags) def create_ui(): import modules.ui with gr.Blocks(analytics_enabled=False) as ui: with gr.Tabs(elem_id="tabs_extensions") as tabs: with gr.TabItem("Installed"): with gr.Row(elem_id="extensions_installed_top"): apply = gr.Button(value="Apply and restart UI", variant="primary") check = gr.Button(value="Check for updates") extensions_disabled_list = gr.Text(elem_id="extensions_disabled_list", visible=False).style(container=False) extensions_update_list = gr.Text(elem_id="extensions_update_list", visible=False).style(container=False) info = gr.HTML() extensions_table = gr.HTML(lambda: extension_table()) apply.click( fn=apply_and_restart, _js="extensions_apply", inputs=[extensions_disabled_list, extensions_update_list], outputs=[], ) check.click( fn=wrap_gradio_gpu_call(check_updates, extra_outputs=[gr.update()]), _js="extensions_check", inputs=[info, extensions_disabled_list], outputs=[extensions_table, info], ) with gr.TabItem("Available"): with gr.Row(): refresh_available_extensions_button = gr.Button(value="Load from:", variant="primary") available_extensions_index = gr.Text(value="https://raw.githubusercontent.com/AUTOMATIC1111/stable-diffusion-webui-extensions/master/index.json", label="Extension index URL").style(container=False) extension_to_install = gr.Text(elem_id="extension_to_install", visible=False) install_extension_button = gr.Button(elem_id="install_extension_button", visible=False) with gr.Row(): hide_tags = gr.CheckboxGroup(value=["ads", "localization", "installed"], label="Hide extensions with tags", choices=["script", "ads", "localization", "installed"]) sort_column = gr.Radio(value="newest first", label="Order", choices=["newest first", "oldest first", "a-z", "z-a", "internal order", ], type="index") with gr.Row(): search_extensions_text = gr.Text(label="Search").style(container=False) install_result = gr.HTML() available_extensions_table = gr.HTML() refresh_available_extensions_button.click( fn=modules.ui.wrap_gradio_call(refresh_available_extensions, extra_outputs=[gr.update(), gr.update(), gr.update()]), inputs=[available_extensions_index, hide_tags, sort_column], outputs=[available_extensions_index, available_extensions_table, hide_tags, install_result, search_extensions_text], ) install_extension_button.click( fn=modules.ui.wrap_gradio_call(install_extension_from_index, extra_outputs=[gr.update(), gr.update()]), inputs=[extension_to_install, hide_tags, sort_column, search_extensions_text], outputs=[available_extensions_table, extensions_table, install_result], ) search_extensions_text.change( fn=modules.ui.wrap_gradio_call(search_extensions, extra_outputs=[gr.update()]), inputs=[search_extensions_text, hide_tags, sort_column], outputs=[available_extensions_table, install_result], ) hide_tags.change( fn=modules.ui.wrap_gradio_call(refresh_available_extensions_for_tags, extra_outputs=[gr.update()]), inputs=[hide_tags, sort_column, search_extensions_text], outputs=[available_extensions_table, install_result] ) sort_column.change( fn=modules.ui.wrap_gradio_call(refresh_available_extensions_for_tags, extra_outputs=[gr.update()]), inputs=[hide_tags, sort_column, search_extensions_text], outputs=[available_extensions_table, install_result] ) with gr.TabItem("Install from URL"): install_url = gr.Text(label="URL for extension's git repository") install_dirname = gr.Text(label="Local directory name", placeholder="Leave empty for auto") install_button = gr.Button(value="Install", variant="primary") install_result = gr.HTML(elem_id="extension_install_result") install_button.click( fn=modules.ui.wrap_gradio_call(install_extension_from_url, extra_outputs=[gr.update()]), inputs=[install_dirname, install_url], outputs=[extensions_table, install_result], ) return ui