diff --git a/javascript/extensions.js b/javascript/extensions.js index aee52065f..67a4a0d53 100644 --- a/javascript/extensions.js +++ b/javascript/extensions.js @@ -1,4 +1,5 @@ function extensions_apply(extensions_disabled_list, extensions_update_list, disable_all) { + console.log('Extensions apply:', extensions_disabled_list, extensions_update_list, disable_all); const disable = []; const update = []; gradioApp().querySelectorAll('#extensions input[type="checkbox"]').forEach((x) => { @@ -10,6 +11,7 @@ function extensions_apply(extensions_disabled_list, extensions_update_list, disa } function extensions_check(info, extensions_disabled_list, search_text, sort_column) { + console.log('Extensions check:', info, extensions_disabled_list); const disable = []; gradioApp().querySelectorAll('#extensions input[type="checkbox"]').forEach((x) => { if (x.name.startsWith('enable_') && !x.checked) disable.push(x.name.substr(7)); @@ -23,8 +25,10 @@ function extensions_check(info, extensions_disabled_list, search_text, sort_colu } function install_extension(button, url) { + console.log('Extension install:', url); button.disabled = 'disabled'; button.value = 'Installing...'; + button.innerHTML = 'installing'; const textarea = gradioApp().querySelector('#extension_to_install textarea'); textarea.value = url; updateInput(textarea); @@ -32,10 +36,22 @@ function install_extension(button, url) { } function uninstall_extension(button, url) { + console.log('Extension uninstall:', url); button.disabled = 'disabled'; button.value = 'Uninstalling...'; + button.innerHTML = 'uninstalling'; const textarea = gradioApp().querySelector('#extension_to_install textarea'); textarea.value = url; updateInput(textarea); gradioApp().querySelector('#uninstall_extension_button').click(); } + +function update_extension(button, url) { + console.log('Extension update:', url); + button.value = 'Updating...'; + button.innerHTML = 'updating'; + const textarea = gradioApp().querySelector('#extension_to_install textarea'); + textarea.value = url; + updateInput(textarea); + gradioApp().querySelector('#update_extension_button').click(); +} diff --git a/javascript/style.css b/javascript/style.css index 04902104c..592e4260a 100644 --- a/javascript/style.css +++ b/javascript/style.css @@ -528,6 +528,11 @@ div#extras_scale_to_tab div.form{ font-size: 90%; } +.extension-button { + font-size: 95% !important; + width: 6em; +} + /* replace original footer with ours */ footer { diff --git a/modules/lora b/modules/lora index ee42c5cd4..cd984992c 160000 --- a/modules/lora +++ b/modules/lora @@ -1 +1 @@ -Subproject commit ee42c5cd425e318b13e443049d399b135995bd37 +Subproject commit cd984992cf6587dfc9582c45bcbe15c25f87bb89 diff --git a/modules/shared.py b/modules/shared.py index 4597204b8..8e627f19d 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -16,16 +16,37 @@ import modules.devices as devices import modules.paths_internal as paths from installer import log as central_logger # pylint: disable=E0611 + errors.install(gr) demo: gr.Blocks = None log = central_logger +progress_print_out = sys.stdout parser = cmd_args.parser url = 'https://github.com/vladmandic/automatic' -if os.environ.get('IGNORE_CMD_ARGS_ERRORS', None) is None: - cmd_opts = parser.parse_args() -else: - cmd_opts, _ = parser.parse_known_args() - +cmd_opts, _ = parser.parse_known_args() +hide_dirs = {"visible": not cmd_opts.hide_ui_dir_config} +is_device_dml = False +xformers_available = False +sd_model = None +clip_model = None +interrogator = modules.interrogate.InterrogateModels("interrogate") +sd_upscalers = [] +face_restorers = [] +tab_names = [] +options_templates = {} +hypernetworks = {} +loaded_hypernetworks = [] +gradio_theme = gr.themes.Base() +settings_components = None +latent_upscale_default_mode = "Latent" +latent_upscale_modes = { + "Latent": {"mode": "bilinear", "antialias": False}, + "Latent (antialiased)": {"mode": "bilinear", "antialias": True}, + "Latent (bicubic)": {"mode": "bicubic", "antialias": False}, + "Latent (bicubic antialiased)": {"mode": "bicubic", "antialias": True}, + "Latent (nearest)": {"mode": "nearest", "antialias": False}, + "Latent (nearest-exact)": {"mode": "nearest-exact", "antialias": False}, +} restricted_opts = { "samples_filename_pattern", "directories_filename_pattern", @@ -38,7 +59,6 @@ restricted_opts = { "outdir_save", "outdir_init_images" } - ui_reorder_categories = [ "inpaint", "sampler", @@ -52,20 +72,6 @@ ui_reorder_categories = [ "scripts", ] -cmd_opts.disable_extension_access = (cmd_opts.share or cmd_opts.listen or cmd_opts.server_name) and not cmd_opts.insecure -devices.device, devices.device_interrogate, devices.device_gfpgan, devices.device_esrgan, devices.device_codeformer = (devices.cpu if any(y in cmd_opts.use_cpu for y in [x, 'all']) else devices.get_optimal_device() for x in ['sd', 'interrogate', 'gfpgan', 'esrgan', 'codeformer']) -device = devices.device -is_device_dml = False -sd_upscalers = [] -sd_model = None -clip_model = None - - -if device.type == 'privateuseone': - import modules.dml # pylint: disable=ungrouped-imports - is_device_dml = True - - def reload_hypernetworks(): from modules.hypernetworks import hypernetwork global hypernetworks # pylint: disable=W0603 @@ -159,11 +165,8 @@ class State: self.current_image = image self.id_live_preview += 1 - state = State() state.server_start = time.time() -interrogator = modules.interrogate.InterrogateModels("interrogate") -face_restorers = [] class OptionInfo: @@ -187,6 +190,8 @@ def list_checkpoint_tiles(): import modules.sd_models # pylint: disable=W0621 return modules.sd_models.checkpoint_tiles() +default_checkpoint = list_checkpoint_tiles()[0] if len(list_checkpoint_tiles()) > 0 else "model.ckpt" + def refresh_checkpoints(): import modules.sd_models # pylint: disable=W0621 @@ -222,10 +227,6 @@ def refresh_themes(): except: log.error('Exception refreshing UI themes') -hide_dirs = {"visible": not cmd_opts.hide_ui_dir_config} -tab_names = [] -options_templates = {} -default_checkpoint = list_checkpoint_tiles()[0] if len(list_checkpoint_tiles()) > 0 else "model.ckpt" options_templates.update(options_section(('sd', "Stable Diffusion"), { "sd_model_checkpoint": OptionInfo(default_checkpoint, "Stable Diffusion checkpoint", gr.Dropdown, lambda: {"choices": list_checkpoint_tiles()}, refresh=refresh_checkpoints), @@ -577,50 +578,39 @@ class Options: """casts an arbitrary to the same type as this setting's value with key Example: cast_value("eta_noise_seed_delta", "12") -> returns 12 (an int rather than str) """ - if value is None: return None - default_value = self.data_labels[key].default if default_value is None: default_value = getattr(self, key, None) if default_value is None: return None - expected_type = type(default_value) if expected_type == bool and value == "False": value = False else: value = expected_type(value) - return value opts = Options() -batch_cond_uncond = opts.always_batch_cond_uncond or not (cmd_opts.lowvram or cmd_opts.medvram) -parallel_processing_allowed = not cmd_opts.lowvram and not cmd_opts.medvram -xformers_available = False +cmd_opts = cmd_args.compatibility_args(opts, cmd_opts) config_filename = cmd_opts.config -os.makedirs(opts.hypernetwork_dir, exist_ok=True) -hypernetworks = {} -loaded_hypernetworks = [] if os.path.exists(config_filename): opts.load(config_filename) -cmd_opts = cmd_args.compatibility_args(opts, cmd_opts) + +os.makedirs(opts.hypernetwork_dir, exist_ok=True) prompt_styles = modules.styles.StyleDatabase(opts.styles_dir) -settings_components = None -"""assinged from ui.py, a mapping on setting names to gradio components repsponsible for those settings""" -latent_upscale_default_mode = "Latent" -latent_upscale_modes = { - "Latent": {"mode": "bilinear", "antialias": False}, - "Latent (antialiased)": {"mode": "bilinear", "antialias": True}, - "Latent (bicubic)": {"mode": "bicubic", "antialias": False}, - "Latent (bicubic antialiased)": {"mode": "bicubic", "antialias": True}, - "Latent (nearest)": {"mode": "nearest", "antialias": False}, - "Latent (nearest-exact)": {"mode": "nearest-exact", "antialias": False}, -} -progress_print_out = sys.stdout -gradio_theme = gr.themes.Base() +cmd_opts.disable_extension_access = (cmd_opts.share or cmd_opts.listen or cmd_opts.server_name) and not cmd_opts.insecure +devices.device, devices.device_interrogate, devices.device_gfpgan, devices.device_esrgan, devices.device_codeformer = (devices.cpu if any(y in cmd_opts.use_cpu for y in [x, 'all']) else devices.get_optimal_device() for x in ['sd', 'interrogate', 'gfpgan', 'esrgan', 'codeformer']) +device = devices.device +batch_cond_uncond = opts.always_batch_cond_uncond or not (cmd_opts.lowvram or cmd_opts.medvram) +parallel_processing_allowed = not cmd_opts.lowvram and not cmd_opts.medvram +mem_mon = modules.memmon.MemUsageMonitor("MemMon", device, opts) +mem_mon.start() +if device.type == 'privateuseone': + import modules.dml # pylint: disable=ungrouped-imports + is_device_dml = True def reload_gradio_theme(theme_name=None): @@ -671,7 +661,6 @@ class TotalTQDM: desc="Total", total=state.job_count * state.sampling_steps, position=1, - file=progress_print_out ) def update(self): @@ -694,10 +683,7 @@ class TotalTQDM: self._tqdm.close() self._tqdm = None - total_tqdm = TotalTQDM() -mem_mon = modules.memmon.MemUsageMonitor("MemMon", device, opts) -mem_mon.start() def restart_server(restart=True): @@ -728,9 +714,7 @@ def html_path(filename): def html(filename): path = html_path(filename) - if os.path.exists(path): with open(path, encoding="utf8") as file: return file.read() - return "" diff --git a/modules/ui.py b/modules/ui.py index eae91ea73..0eb6b6759 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -1304,7 +1304,9 @@ def create_ui(): changed.append(key) try: opts.save(shared.config_filename) + shared.log.info(f'Settings changed: {len(changed)} {changed}') except RuntimeError: + shared.log.error(f'Settings change failed: {len(changed)} {changed}') return opts.dumpjson(), f'{len(changed)} Settings changed without save: {", ".join(changed)}' return opts.dumpjson(), f'{len(changed)} Settings changed{": " if len(changed) > 0 else ""}{", ".join(changed)}' @@ -1314,6 +1316,7 @@ def create_ui(): if not opts.set(key, value): return gr.update(value=getattr(opts, key)), opts.dumpjson() opts.save(shared.config_filename) + shared.log.debug(f'Setting changed: key={key}, value={value}') return get_value_for_setting(key), opts.dumpjson() with gr.Blocks(analytics_enabled=False) as settings_interface: diff --git a/modules/ui_extensions.py b/modules/ui_extensions.py index a993afd0b..ee56ac034 100644 --- a/modules/ui_extensions.py +++ b/modules/ui_extensions.py @@ -91,7 +91,7 @@ def check_updates(_id_task, disable_list, search_text, sort_column): except Exception: errors.display(e, f'extensions check update: {ext.name}') shared.state.nextjob() - return refresh_extensions_list_from_data(search_text, sort_column), "Update complete, please restart the server" + return refresh_extensions_list_from_data(search_text, sort_column), "Extension update complete | Restart required" def make_commit_link(commit_hash, remote, text=None): @@ -147,7 +147,7 @@ def install_extension_from_url(dirname, url, branch_name, search_text, sort_colu from launch import run_extension_installer run_extension_installer(target_dir) extensions.list_extensions() - return [refresh_extensions_list_from_data(search_text, sort_column), html.escape(f"Extension {url} installed into {target_dir}")] + return [refresh_extensions_list_from_data(search_text, sort_column), html.escape(f"Extension installed: {target_dir} | Restart required")] finally: shutil.rmtree(tmpdir, True) @@ -170,7 +170,25 @@ def uninstall_extension(extension_path, search_text, sort_column): update_extension_list() code = refresh_extensions_list_from_data(search_text, sort_column) # return code, ext_table, message - return code, f"Uninstalled {extension_path}" + return code, f"Extension uninstalled: {extension_path} | Restart required" + + +def update_extension(extension_path, search_text, sort_column): + exts = [extension for extension in extensions.extensions if extension.path == extension_path] + shared.log.info(f'Extension update: {extension_path}') + shared.state.job_count = len(exts) + for ext in exts: + shared.log.debug(f'Extensions update: {ext.name}') + shared.state.textinfo = ext.name + try: + ext.check_updates() + except FileNotFoundError as e: + if 'FETCH_HEAD' not in str(e): + raise + except Exception: + errors.display(e, f'extensions check update: {ext.name}') + shared.state.nextjob() + return refresh_extensions_list_from_data(search_text, sort_column), f"Extension updated: {extension_path} | Restart required" def refresh_extensions_list(search_text, sort_column): @@ -187,7 +205,7 @@ def refresh_extensions_list(search_text, sort_column): except Exception as e: shared.log.warning(f'Updated extensions list failed: {extensions_index} {e}') code = refresh_extensions_list_from_data(search_text, sort_column) - return code, f'Extensions list: {len(extensions.extensions)} registered | {len(extensions_list)} available' + return code, f'Extensions | {len(extensions.extensions)} registered | {len(extensions_list)} available' def search_extensions(search_text, sort_column): @@ -205,9 +223,9 @@ def refresh_extensions_list_from_data(search_text, sort_column):
Created {html.escape(created)} | Added {html.escape(added)} | Updated {html.escape(updated)}
+Created {html.escape(created)} | Added {html.escape(added)} | Pushed {html.escape(pushed)} | Updated {html.escape(updated)}
Stars {html.escape(str(stars))} | Size {html.escape(str(size))} | Commits {html.escape(str(commits))} | Issues {html.escape(str(issues))}