From 457dddf7aa4476693f65b8022dee87958b06ba21 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Sun, 18 Jun 2023 11:38:42 -0400 Subject: [PATCH] refactor html-info and do some linting cleanups --- .pylintrc | 23 ++++++++++++++++------- cli/generate.py | 8 +------- cli/image-exif.py | 2 +- cli/image-palette.py | 2 +- cli/nvidia-smi.py | 3 +++ cli/process.py | 2 +- cli/sdapi.py | 8 ++++---- cli/torch-compile.py | 1 - cli/util.py | 8 ++++---- cli/video-extract.py | 2 +- modules/img2img.py | 7 ++++--- modules/postprocessing.py | 4 ++-- modules/sd_models.py | 13 +------------ modules/txt2img.py | 6 +++--- modules/ui.py | 27 ++++++++++++--------------- modules/ui_common.py | 25 +++++++++++++------------ modules/ui_postprocessing.py | 4 ++-- 17 files changed, 69 insertions(+), 76 deletions(-) diff --git a/.pylintrc b/.pylintrc index c7b088eb0..e552f6207 100644 --- a/.pylintrc +++ b/.pylintrc @@ -122,15 +122,21 @@ confidence=HIGH, INFERENCE_FAILURE, UNDEFINED # disable=C,R,W -disable=raw-checker-failed, - bad-inline-option, +disable=bad-inline-option, bare-except, broad-exception-caught, consider-iterating-dictionary, consider-using-dict-items, + consider-using-generator, + consider-using-enumerate, + consider-using-sys-exit, + consider-using-from-import, + consider-using-in, dangerous-default-value, deprecated-pragma, + duplicate-code, file-ignored, + import-error, import-outside-toplevel, invalid-name, line-too-long, @@ -139,16 +145,19 @@ disable=raw-checker-failed, missing-class-docstring, missing-function-docstring, missing-module-docstring, - duplicate-code, + no-else-return, + pointless-string-statement, + raw-checker-failed, + simplifiable-if-expression, suppressed-message, + too-many-nested-blocks, + too-few-public-methods, unnecessary-dunder-call, unnecessary-lambda, + use-dict-literal, use-symbolic-message-instead, - too-many-nested-blocks, useless-suppression, - wrong-import-position, - import-error, - simplifiable-if-expression + wrong-import-position enable=c-extension-no-member [METHOD_ARGS] diff --git a/cli/generate.py b/cli/generate.py index c5c3e1507..b8d5cac66 100755 --- a/cli/generate.py +++ b/cli/generate.py @@ -57,6 +57,7 @@ def grid(data): log.info({ 'grid': { 'name': f, 'size': image.size, 'images': len(data.image) } }) image.save(f, 'JPEG', exif = exif(data.info, None, 'grid'), optimize = True, quality = 70) return image + return data.image def exif(info, i = None, op = 'generate'): @@ -370,10 +371,3 @@ if __name__ == '__main__': log.info({ 'sampler performance': avg }) log.info({ 'stats' : stats }) asyncio.run(close()) -''' - except Exception as e: - log.info({ 'sampler performance': avg }) - log.info({ 'stats': stats }) - log.critical({ 'exception': e }) - exit() -''' diff --git a/cli/image-exif.py b/cli/image-exif.py index c6cdf69e9..bfd2ad7f2 100755 --- a/cli/image-exif.py +++ b/cli/image-exif.py @@ -14,7 +14,7 @@ from rich import print # pylint: disable=redefined-builtin class Exif: # pylint: disable=single-string-used-for-slots __slots__ = ('__dict__') # pylint: disable=superfluous-parens def __init__(self, image = None): - super(Exif, self).__setattr__('exif', Image.Exif()) + super(Exif, self).__setattr__('exif', Image.Exif()) # pylint: disable=super-with-arguments self.pnginfo = PngImagePlugin.PngInfo() self.tags = {**dict(ExifTags.TAGS.items()), **dict(ExifTags.GPSTAGS.items())} self.ids = {**{v: k for k, v in ExifTags.TAGS.items()}, **{v: k for k, v in ExifTags.GPSTAGS.items()}} diff --git a/cli/image-palette.py b/cli/image-palette.py index 77eb5e130..be49a7375 100755 --- a/cli/image-palette.py +++ b/cli/image-palette.py @@ -18,6 +18,7 @@ from PIL import Image from util import log grid = importlib.import_module('image-grid').grid + def color_to_df(param): colors_pre_list = str(param).replace('([(','').split(', (')[0:-1] df_rgb = [i.split('), ')[0] + ')' for i in colors_pre_list] @@ -87,7 +88,6 @@ def palette(img, params, output): log.info({ 'palette created': output }) plt.close() - return if __name__ == '__main__': diff --git a/cli/nvidia-smi.py b/cli/nvidia-smi.py index f7b11311a..37d6390c5 100755 --- a/cli/nvidia-smi.py +++ b/cli/nvidia-smi.py @@ -7,6 +7,7 @@ import xmltodict from rich import print # pylint: disable=redefined-builtin from util import log, Map + def get_nvidia_smi(output='dict'): smi = shutil.which('nvidia-smi') if smi is None: @@ -26,6 +27,8 @@ def get_nvidia_smi(output='dict'): return d elif output == 'json': return json.dumps(d, indent=4) + return None + if __name__ == "__main__": res = get_nvidia_smi(output='dict') diff --git a/cli/process.py b/cli/process.py index b134fc222..9f3582114 100644 --- a/cli/process.py +++ b/cli/process.py @@ -20,7 +20,7 @@ all_images = [] all_images_by_type = {} -class Result(object): +class Result(): def __init__(self, typ: str, fn: str, tag: str = None, requested: list = []): # noqa: B006 self.type = typ self.input = fn diff --git a/cli/sdapi.py b/cli/sdapi.py index 1f32eae25..4c66ad40b 100755 --- a/cli/sdapi.py +++ b/cli/sdapi.py @@ -62,7 +62,7 @@ async def result(req): return Map({ 'error': req.status, 'reason': req.reason, 'url': req.url }) else: json = await req.json() - if type(json) == list: + if isinstance(json, list): res = json elif json is None: res = {} @@ -79,7 +79,7 @@ def resultsync(req: requests.Response): return Map({ 'error': req.status_code, 'reason': req.reason, 'url': req.url }) else: json = req.json() - if type(json) == list: + if isinstance(json, list): res = json elif json is None: res = {} @@ -169,8 +169,8 @@ def progresssync(): def get_log(): res = getsync('/sdapi/v1/log') - for l in res: - log.debug(l) + for line in res: + log.debug(line) return res diff --git a/cli/torch-compile.py b/cli/torch-compile.py index 00d08b11c..891f27dc5 100755 --- a/cli/torch-compile.py +++ b/cli/torch-compile.py @@ -86,7 +86,6 @@ if __name__ == '__main__': # print stats print(json.dumps(results, indent = 4)) - """ Reference: Training & Inference backends: diff --git a/cli/util.py b/cli/util.py index a5ac0d37e..4fbecdc1e 100755 --- a/cli/util.py +++ b/cli/util.py @@ -71,9 +71,9 @@ def get_memory(): class Map(dict): # pylint: disable=C0205 - __slots__ = ('__dict__') # pylint: disable=C0325 + __slots__ = ('__dict__') # pylint: disable=superfluous-parens def __init__(self, *args, **kwargs): - super(Map, self).__init__(*args, **kwargs) + super(Map, self).__init__(*args, **kwargs) # pylint: disable=super-with-arguments for arg in args: if isinstance(arg, dict): for k, v in arg.items(): @@ -100,12 +100,12 @@ class Map(dict): # pylint: disable=C0205 def __setattr__(self, key, value): self.__setitem__(key, value) def __setitem__(self, key, value): - super(Map, self).__setitem__(key, value) + super(Map, self).__setitem__(key, value) # pylint: disable=super-with-arguments self.__dict__.update({key: value}) def __delattr__(self, item): self.__delitem__(item) def __delitem__(self, key): - super(Map, self).__delitem__(key) + super(Map, self).__delitem__(key) # pylint: disable=super-with-arguments del self.__dict__[key] diff --git a/cli/video-extract.py b/cli/video-extract.py index 9bc4544e6..106c5ada2 100755 --- a/cli/video-extract.py +++ b/cli/video-extract.py @@ -32,7 +32,7 @@ def extract(src: str, dst: str, rate: float = 0.015, fps: float = 0, start = 0, images = [] if not os.path.isfile(src) or not filetype.is_video(src): log.error({ 'extract': 'input is not movie file' }) - return + return 0 dst = dst if dst.endswith('/') else dst + '/' video = probe(src) diff --git a/modules/img2img.py b/modules/img2img.py index e1cb15483..b744c8281 100644 --- a/modules/img2img.py +++ b/modules/img2img.py @@ -4,7 +4,7 @@ from PIL import Image, ImageOps, ImageFilter, ImageEnhance, ImageChops, Unidenti import modules.scripts from modules import sd_samplers, shared, processing from modules.generation_parameters_copypaste import create_override_settings_dict -from modules.ui import plaintext_to_html, infotext_to_html +from modules.ui import plaintext_to_html from modules.memstats import memory_stats @@ -67,7 +67,8 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s if shared.sd_model is None: shared.log.warning('Model not loaded') - return + return [], '', '', 'Error: model not loaded' + if init_img is None: shared.log.debug('Init image not set') @@ -173,4 +174,4 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s p.close() generation_info_js = processed.js() shared.log.debug(f'Processed: {len(processed.images)} Memory: {memory_stats()} img') - return processed.images, generation_info_js, infotext_to_html(processed.info), plaintext_to_html(processed.comments) + return processed.images, generation_info_js, processed.info, plaintext_to_html(processed.comments) diff --git a/modules/postprocessing.py b/modules/postprocessing.py index 29c6bc204..5c87c3d0b 100644 --- a/modules/postprocessing.py +++ b/modules/postprocessing.py @@ -4,7 +4,7 @@ from typing import List from PIL import Image -from modules import shared, images, devices, scripts, scripts_postprocessing, ui_common, generation_parameters_copypaste +from modules import shared, images, devices, scripts, scripts_postprocessing, generation_parameters_copypaste from modules.shared import opts @@ -76,7 +76,7 @@ def run_postprocessing(extras_mode, image, image_folder: List[tempfile.NamedTemp outputs.append(pp.image) devices.torch_gc() - return outputs, ui_common.infotext_to_html(infotext), params + return outputs, infotext, params def run_extras(extras_mode, resize_mode, image, image_folder, input_dir, output_dir, show_extras_results, gfpgan_visibility, codeformer_visibility, codeformer_weight, upscaling_resize, upscaling_resize_w, upscaling_resize_h, upscaling_crop, extras_upscaler_1, extras_upscaler_2, extras_upscaler_2_visibility, upscale_first: bool, save_output: bool = True): #pylint: disable=unused-argument diff --git a/modules/sd_models.py b/modules/sd_models.py index fc3a51fb8..1d7bd8af5 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -667,14 +667,6 @@ def unload_model_weights(sd_model=None, _info=None): if shared.backend == shared.Backend.ORIGINAL: sd_hijack.model_hijack.undo_hijack(model_data.sd_model) sd_model = None - """ - if hasattr(model_data.sd_model, 'model'): - del model_data.sd_model.model - if hasattr(model_data.sd_model, 'first_stage_model'): - del model_data.sd_model.first_stage_model - if hasattr(model_data.sd_model, 'cond_stage_model'): - del model_data.sd_model.cond_stage_model - """ model_data.sd_model = None devices.torch_gc(force=True) shared.log.debug(f'Model weights unloaded: {memory_stats()}') @@ -682,11 +674,8 @@ def unload_model_weights(sd_model=None, _info=None): def apply_token_merging(sd_model, token_merging_ratio): - """ - Applies speed and memory optimizations from tomesd. - """ current_token_merging_ratio = getattr(sd_model, 'applied_token_merged_ratio', 0) - shared.log.debug(f'Appplying token merging: current={current_token_merging_ratio} target={token_merging_ratio}') + # shared.log.debug(f'Appplying token merging: current={current_token_merging_ratio} target={token_merging_ratio}') if current_token_merging_ratio == token_merging_ratio: return if current_token_merging_ratio > 0: diff --git a/modules/txt2img.py b/modules/txt2img.py index 25ff30fde..8ca3af5f9 100644 --- a/modules/txt2img.py +++ b/modules/txt2img.py @@ -1,7 +1,7 @@ import modules.scripts from modules import sd_samplers, shared, processing from modules.generation_parameters_copypaste import create_override_settings_dict -from modules.ui import plaintext_to_html, infotext_to_html +from modules.ui import plaintext_to_html from modules.memstats import memory_stats @@ -15,7 +15,7 @@ def txt2img(id_task: str, prompt: str, negative_prompt: str, prompt_styles, step if shared.sd_model is None: shared.log.warning('Model not loaded') - return + return [], '', '', 'Error: model not loaded' p = processing.StableDiffusionProcessingTxt2Img( sd_model=shared.sd_model, @@ -57,4 +57,4 @@ def txt2img(id_task: str, prompt: str, negative_prompt: str, prompt_styles, step p.close() generation_info_js = processed.js() shared.log.debug(f'Processed: {len(processed.images)} Memory: {memory_stats()} txt') - return processed.images, generation_info_js, infotext_to_html(processed.info), plaintext_to_html(processed.comments) + return processed.images, generation_info_js, processed.info, plaintext_to_html(processed.comments) diff --git a/modules/ui.py b/modules/ui.py index dc9a322e3..f0ec45cb2 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -59,11 +59,12 @@ extra_networks_symbol = '\U0001F310' # '\U0001F3B4' # 🎴 switch_values_symbol = '\U000021C5' # ⇅ -def plaintext_to_html(text): + +def plaintext_to_html(text): # may be referenced by extensions return ui_common.plaintext_to_html(text) -def infotext_to_html(text): +def infotext_to_html(text): # may be referenced by extensions return ui_common.infotext_to_html(text) @@ -109,9 +110,9 @@ def apply_styles(prompt, prompt_neg, styles): def process_interrogate(interrogation_function, mode, ii_input_dir, ii_output_dir, *ii_singles): if mode in {0, 1, 3, 4}: return [interrogation_function(ii_singles[mode]), None] - elif mode == 2: + if mode == 2: return [interrogation_function(ii_singles[mode]["image"]), None] - elif mode == 5: + if mode == 5: images = modules.shared.listfiles(ii_input_dir) if ii_output_dir != "": os.makedirs(ii_output_dir, exist_ok=True) @@ -121,9 +122,8 @@ def process_interrogate(interrogation_function, mode, ii_input_dir, ii_output_di img = Image.open(image) filename = os.path.basename(image) left, _ = os.path.splitext(filename) - print(interrogation_function(img), file=open(os.path.join(ii_output_dir, f"{left}.txt"), 'a', encoding='utf-8')) - - return [gr.update(), None] + print(interrogation_function(img), file=open(os.path.join(ii_output_dir, f"{left}.txt"), 'a', encoding='utf-8')) # pylint: disable=consider-using-with + return [gr.update(), None] def interrogate(image): @@ -273,7 +273,7 @@ def apply_setting(key, value): return gr.update() comp_args = opts.data_labels[key].component_args if comp_args and isinstance(comp_args, dict) and comp_args.get('visible') is False: - return + return gr.update() valtype = type(opts.data_labels[key].default) oldval = opts.data.get(key, None) opts.data[key] = valtype(value) if valtype != type(None) else value @@ -296,10 +296,6 @@ def create_refresh_button(refresh_component, refresh_method, refreshed_args, ele return refresh_button -def create_output_panel(tabname, outdir): - return ui_common.create_output_panel(tabname, outdir) - - def create_sampler_and_steps_selection(choices, tabname): with FormRow(elem_id=f"sampler_selection_{tabname}"): if 'UniPC' in [sampler.name for sampler in choices]: @@ -404,7 +400,7 @@ def create_ui(): show_progress=False, ) - txt2img_gallery, generation_info, html_info, html_log = create_output_panel("txt2img", opts.outdir_txt2img_samples) + txt2img_gallery, generation_info, html_info, _html_info_formatted, html_log = ui_common.create_output_panel("txt2img", opts.outdir_txt2img_samples) connect_reuse_seed(seed, reuse_seed, generation_info, dummy_component, is_subseed=False) connect_reuse_seed(subseed, reuse_subseed, generation_info, dummy_component, is_subseed=True) @@ -568,6 +564,7 @@ def create_ui(): has_exact_match = np.any(np.all(np.array(image) == np.array(state), axis=-1)) edited = same_size and has_exact_match return image if not edited or state is None else state + return state inpaint_color_sketch.change(update_orig, [inpaint_color_sketch, inpaint_color_sketch_orig], inpaint_color_sketch_orig) @@ -719,7 +716,7 @@ def create_ui(): outputs=[inpaint_controls, mask_alpha], ) - img2img_gallery, generation_info, html_info, html_log = create_output_panel("img2img", opts.outdir_img2img_samples) + img2img_gallery, generation_info, html_info, _html_info_formatted, html_log = ui_common.create_output_panel("img2img", opts.outdir_img2img_samples) connect_reuse_seed(seed, reuse_seed, generation_info, dummy_component, is_subseed=False) connect_reuse_seed(subseed, reuse_subseed, generation_info, dummy_component, is_subseed=True) @@ -1643,7 +1640,7 @@ def setup_ui_api(app): from pydantic import BaseModel, Field # pylint: disable=no-name-in-module from typing import List - class QuicksettingsHint(BaseModel): + class QuicksettingsHint(BaseModel): # pylint: disable=too-few-public-methods name: str = Field(title="Name of the quicksettings field") label: str = Field(title="Label of the quicksettings field") diff --git a/modules/ui_common.py b/modules/ui_common.py index 2c7287b57..efc6c04a9 100644 --- a/modules/ui_common.py +++ b/modules/ui_common.py @@ -19,11 +19,11 @@ def update_generation_info(generation_info, html_info, img_index): if img_index < 0 or img_index >= len(generation_info["infotexts"]): return html_info, generation_info infotext = generation_info["infotexts"][img_index] - html_text = infotext_to_html(infotext) - return html_text, infotext + html_info_formatted = infotext_to_html(infotext) + return html_info, html_info_formatted except Exception: pass - return html_info, generation_info + return html_info, html_info def plaintext_to_html(text): @@ -69,7 +69,7 @@ def delete_files(js_data, images, _html_info, _do_make_zip, index): def save_files(js_data, images, html_info, do_make_zip, index): os.makedirs(shared.opts.outdir_save, exist_ok=True) - class PObject: #quick dictionary to class object conversion. Its necessary due apply_filename_pattern requiring it + class PObject: # pylint: disable=too-few-public-methods def __init__(self, d=None): if d is not None: for key, value in d.items(): @@ -152,11 +152,11 @@ def create_output_panel(tabname, outdir): if platform.system() == "Windows": os.startfile(path) # pylint: disable=no-member elif platform.system() == "Darwin": - subprocess.Popen(["open", path]) + subprocess.Popen(["open", path]) # pylint: disable=consider-using-with elif "microsoft-standard-WSL2" in platform.uname().release: - subprocess.Popen(["wsl-open", path]) + subprocess.Popen(["wsl-open", path]) # pylint: disable=consider-using-with else: - subprocess.Popen(["xdg-open", path]) + subprocess.Popen(["xdg-open", path]) # pylint: disable=consider-using-with with gr.Column(variant='panel', elem_id=f"{tabname}_results"): with gr.Group(elem_id=f"{tabname}_gallery_container"): @@ -173,14 +173,15 @@ def create_output_panel(tabname, outdir): open_folder_button.click(fn=lambda: open_folder(shared.opts.outdir_samples or outdir), inputs=[], outputs=[]) download_files = gr.File(None, file_count="multiple", interactive=False, show_label=False, visible=False, elem_id=f'download_files_{tabname}') with gr.Group(): - html_info = gr.HTML(elem_id=f'html_info_{tabname}', elem_classes="infotext") - html_info_raw = gr.Text(elem_id=f'html_info_raw_{tabname}', visible=False) + html_info = gr.HTML(elem_id=f'html_info_{tabname}', elem_classes="infotext", visible=False) # contains raw infotext as returned by wrapped call + html_info_formatted = gr.HTML(elem_id=f'html_info_formatted_{tabname}', elem_classes="infotext", visible=True) # contains html formatted infotext + html_info.change(fn=infotext_to_html, inputs=[html_info], outputs=[html_info_formatted], show_progress=False) html_log = gr.HTML(elem_id=f'html_log_{tabname}') generation_info = gr.Textbox(visible=False, elem_id=f'generation_info_{tabname}') generation_info_button = gr.Button(visible=False, elem_id=f"{tabname}_generation_info_button") - generation_info_button.click(fn=update_generation_info, _js="(x, y, z) => [x, y, selected_gallery_index()]", show_progress=False, + generation_info_button.click(fn=update_generation_info, _js="(x, y, z) => [x, y, selected_gallery_index()]", show_progress=False, # triggered on gallery change from js inputs=[generation_info, html_info, html_info], - outputs=[html_info, html_info_raw], + outputs=[html_info, html_info_formatted], ) save.click(fn=call_queue.wrap_gradio_call(save_files), _js="(x, y, z, q1, q2) => [x, y, z, false, selected_gallery_index()]", show_progress=False, inputs=[generation_info, result_gallery, html_info, html_info, html_info], @@ -205,4 +206,4 @@ def create_output_panel(tabname, outdir): parameters_copypaste.register_paste_params_button(parameters_copypaste.ParamBinding( paste_button=paste_button, tabname=paste_tabname, source_tabname=("txt2img" if tabname == "txt2img" else None), source_image_component=result_gallery, paste_field_names=paste_field_names )) - return result_gallery, generation_info, html_info, html_log + return result_gallery, generation_info, html_info, html_info_formatted, html_log diff --git a/modules/ui_postprocessing.py b/modules/ui_postprocessing.py index d4e0b342e..8a52d0c2c 100644 --- a/modules/ui_postprocessing.py +++ b/modules/ui_postprocessing.py @@ -43,7 +43,7 @@ def create_ui(): interrupt.click(fn=lambda: shared.state.interrupt(), inputs=[], outputs=[]) skip = gr.Button('Skip', elem_id=f"{id_part}_skip", variant='secondary') skip.click(fn=lambda: shared.state.skip(), inputs=[], outputs=[]) - result_images, generation_info, html_info, html_log = ui_common.create_output_panel("extras", shared.opts.outdir_extras_samples) + result_images, generation_info, html_info, html_info_formatted, html_log = ui_common.create_output_panel("extras", shared.opts.outdir_extras_samples) gr.HTML('File metadata') exif_info = gr.HTML(elem_id="pnginfo_html_info") gen_info = gr.Text(elem_id="pnginfo_gen_info", visible=False) @@ -57,7 +57,7 @@ def create_ui(): extras_image.change( fn=wrap_gradio_call(wrap_pnginfo), inputs=[extras_image], - outputs=[_dummy, html_info, exif_info, gen_info], + outputs=[_dummy, html_info_formatted, exif_info, gen_info], ) submit.click( fn=call_queue.wrap_gradio_gpu_call(submit_click, extra_outputs=[None, '']),