From 9a3a16143aa5647e366bd304560d9cf3183f8335 Mon Sep 17 00:00:00 2001 From: Bernard Maltais Date: Tue, 12 Mar 2024 07:12:08 -0400 Subject: [PATCH 1/3] Fix issue with spaces in python path --- kohya_gui/basic_caption_gui.py | 2 +- kohya_gui/blip_caption_gui.py | 2 +- kohya_gui/convert_lcm_gui.py | 2 +- kohya_gui/convert_model_gui.py | 2 +- kohya_gui/extract_lora_from_dylora_gui.py | 2 +- kohya_gui/extract_lora_gui.py | 2 +- kohya_gui/extract_lycoris_locon_gui.py | 2 +- kohya_gui/finetune_gui.py | 4 +- kohya_gui/git_caption_gui.py | 2 +- kohya_gui/group_images_gui.py | 2 +- kohya_gui/merge_lora_gui.py | 4 +- kohya_gui/merge_lycoris_gui.py | 2 +- kohya_gui/resize_lora_gui.py | 2 +- kohya_gui/svd_merge_lora_gui.py | 2 +- kohya_gui/verify_lora_gui.py | 2 +- setup/setup_common.py | 50 +++++++++++++++++++---- 16 files changed, 58 insertions(+), 26 deletions(-) diff --git a/kohya_gui/basic_caption_gui.py b/kohya_gui/basic_caption_gui.py index d064ee646..8cb4094bc 100644 --- a/kohya_gui/basic_caption_gui.py +++ b/kohya_gui/basic_caption_gui.py @@ -38,7 +38,7 @@ def caption_images( log.info(f'Captioning files in {images_dir} with {caption_text}...') # Build the command to run caption.py - run_cmd = fr'{PYTHON} "{scriptdir}/tools/caption.py"' + run_cmd = fr'"{PYTHON}" "{scriptdir}/tools/caption.py"' run_cmd += f' --caption_text="{caption_text}"' # Add optional flags to the command diff --git a/kohya_gui/blip_caption_gui.py b/kohya_gui/blip_caption_gui.py index df1004a30..525c537ea 100644 --- a/kohya_gui/blip_caption_gui.py +++ b/kohya_gui/blip_caption_gui.py @@ -37,7 +37,7 @@ def caption_images( log.info(f"Captioning files in {train_data_dir}...") # Construct the command to run - run_cmd = rf'{PYTHON} "{scriptdir}/sd-scripts/finetune/make_captions.py"' + run_cmd = rf'"{PYTHON}" "{scriptdir}/sd-scripts/finetune/make_captions.py"' run_cmd += f' --batch_size="{int(batch_size)}"' run_cmd += f' --num_beams="{int(num_beams)}"' run_cmd += f' --top_p="{top_p}"' diff --git a/kohya_gui/convert_lcm_gui.py b/kohya_gui/convert_lcm_gui.py index 8073c1dfa..452a7045d 100644 --- a/kohya_gui/convert_lcm_gui.py +++ b/kohya_gui/convert_lcm_gui.py @@ -28,7 +28,7 @@ def convert_lcm( lora_scale, model_type ): - run_cmd = fr'{PYTHON} "{scriptdir}/tools/lcm_convert.py"' + run_cmd = fr'"{PYTHON}" "{scriptdir}/tools/lcm_convert.py"' # Check if source model exist if not os.path.isfile(model_path): diff --git a/kohya_gui/convert_model_gui.py b/kohya_gui/convert_model_gui.py index b457c5c68..0a4f615d5 100644 --- a/kohya_gui/convert_model_gui.py +++ b/kohya_gui/convert_model_gui.py @@ -49,7 +49,7 @@ def convert_model( msgbox('The provided target folder does not exist') return - run_cmd = fr'{PYTHON} "{scriptdir}/sd-scripts/tools/convert_diffusers20_original_sd.py"' + run_cmd = fr'"{PYTHON}" "{scriptdir}/sd-scripts/tools/convert_diffusers20_original_sd.py"' v1_models = [ 'runwayml/stable-diffusion-v1-5', diff --git a/kohya_gui/extract_lora_from_dylora_gui.py b/kohya_gui/extract_lora_from_dylora_gui.py index bbbce2402..2cc83fff0 100644 --- a/kohya_gui/extract_lora_from_dylora_gui.py +++ b/kohya_gui/extract_lora_from_dylora_gui.py @@ -51,7 +51,7 @@ def extract_dylora( save_to = f"{path}_tmp{ext}" run_cmd = ( - fr'{PYTHON} "{scriptdir}/sd-scripts/networks/extract_lora_from_dylora.py"' + fr'"{PYTHON}" "{scriptdir}/sd-scripts/networks/extract_lora_from_dylora.py"' ) run_cmd += fr' --save_to "{save_to}"' run_cmd += fr' --model "{model}"' diff --git a/kohya_gui/extract_lora_gui.py b/kohya_gui/extract_lora_gui.py index 561de5dce..b91cde7ee 100644 --- a/kohya_gui/extract_lora_gui.py +++ b/kohya_gui/extract_lora_gui.py @@ -74,7 +74,7 @@ def extract_lora( return run_cmd = ( - fr'{PYTHON} "{scriptdir}/sd-scripts/networks/extract_lora_from_models.py"' + fr'"{PYTHON}" "{scriptdir}/sd-scripts/networks/extract_lora_from_models.py"' ) run_cmd += f' --load_precision {load_precision}' run_cmd += f' --save_precision {save_precision}' diff --git a/kohya_gui/extract_lycoris_locon_gui.py b/kohya_gui/extract_lycoris_locon_gui.py index 1ad4b3ab6..647363a17 100644 --- a/kohya_gui/extract_lycoris_locon_gui.py +++ b/kohya_gui/extract_lycoris_locon_gui.py @@ -74,7 +74,7 @@ def extract_lycoris_locon( path, ext = os.path.splitext(output_name) output_name = f"{path}_tmp{ext}" - run_cmd = fr'{PYTHON} "{scriptdir}/sd-scripts/tools/lycoris_locon_extract.py"' + run_cmd = fr'"{PYTHON}" "{scriptdir}/sd-scripts/tools/lycoris_locon_extract.py"' if is_sdxl: run_cmd += f" --is_sdxl" if is_v2: diff --git a/kohya_gui/finetune_gui.py b/kohya_gui/finetune_gui.py index a1fa805e8..4fd3cc62e 100644 --- a/kohya_gui/finetune_gui.py +++ b/kohya_gui/finetune_gui.py @@ -453,7 +453,7 @@ def train_model( # create caption json file if generate_caption_database: - run_cmd = fr'{PYTHON} "{scriptdir}/sd-scripts/finetune/merge_captions_to_metadata.py"' + run_cmd = fr'"{PYTHON}" "{scriptdir}/sd-scripts/finetune/merge_captions_to_metadata.py"' if caption_extension == "": run_cmd += f' --caption_extension=".caption"' else: @@ -474,7 +474,7 @@ def train_model( # create images buckets if generate_image_buckets: - run_cmd = fr'{PYTHON} "{scriptdir}/sd-scripts/finetune/prepare_buckets_latents.py"' + run_cmd = fr'"{PYTHON}" "{scriptdir}/sd-scripts/finetune/prepare_buckets_latents.py"' run_cmd += fr' "{image_folder}"' run_cmd += fr' "{train_dir}/{caption_metadata_filename}"' run_cmd += fr' "{train_dir}/{latent_metadata_filename}"' diff --git a/kohya_gui/git_caption_gui.py b/kohya_gui/git_caption_gui.py index 701fb0e3e..268f1f3d3 100644 --- a/kohya_gui/git_caption_gui.py +++ b/kohya_gui/git_caption_gui.py @@ -33,7 +33,7 @@ def caption_images( return log.info(f'GIT captioning files in {train_data_dir}...') - run_cmd = fr'{PYTHON} "{scriptdir}/sd-scripts/finetune/make_captions_by_git.py"' + run_cmd = fr'"{PYTHON}" "{scriptdir}/sd-scripts/finetune/make_captions_by_git.py"' if not model_id == '': run_cmd += f' --model_id="{model_id}"' run_cmd += f' --batch_size="{int(batch_size)}"' diff --git a/kohya_gui/group_images_gui.py b/kohya_gui/group_images_gui.py index ae4a18757..f66d9f7f6 100644 --- a/kohya_gui/group_images_gui.py +++ b/kohya_gui/group_images_gui.py @@ -32,7 +32,7 @@ def group_images( log.info(f'Grouping images in {input_folder}...') - run_cmd = fr'{PYTHON} "{scriptdir}/tools/group_images.py"' + run_cmd = fr'"{PYTHON}" "{scriptdir}/tools/group_images.py"' run_cmd += f' "{input_folder}"' run_cmd += f' "{output_folder}"' run_cmd += f' {(group_size)}' diff --git a/kohya_gui/merge_lora_gui.py b/kohya_gui/merge_lora_gui.py index 85963de35..53f1baeb6 100644 --- a/kohya_gui/merge_lora_gui.py +++ b/kohya_gui/merge_lora_gui.py @@ -385,10 +385,10 @@ def merge_lora( return if not sdxl_model: - run_cmd = fr'{PYTHON} "{scriptdir}/sd-scripts/networks/merge_lora.py"' + run_cmd = fr'"{PYTHON}" "{scriptdir}/sd-scripts/networks/merge_lora.py"' else: run_cmd = ( - fr'{PYTHON} "{scriptdir}/sd-scripts/networks/sdxl_merge_lora.py"' + fr'"{PYTHON}" "{scriptdir}/sd-scripts/networks/sdxl_merge_lora.py"' ) if sd_model: run_cmd += fr' --sd_model "{sd_model}"' diff --git a/kohya_gui/merge_lycoris_gui.py b/kohya_gui/merge_lycoris_gui.py index 42cf28926..38978defa 100644 --- a/kohya_gui/merge_lycoris_gui.py +++ b/kohya_gui/merge_lycoris_gui.py @@ -36,7 +36,7 @@ def merge_lycoris( ): log.info('Merge model...') - run_cmd = fr'{PYTHON} "{scriptdir}/tools/merge_lycoris.py"' + run_cmd = fr'"{PYTHON}" "{scriptdir}/tools/merge_lycoris.py"' run_cmd += fr' "{base_model}"' run_cmd += fr' "{lycoris_model}"' run_cmd += fr' "{output_name}"' diff --git a/kohya_gui/resize_lora_gui.py b/kohya_gui/resize_lora_gui.py index 3ceb7ffcc..948fd0b25 100644 --- a/kohya_gui/resize_lora_gui.py +++ b/kohya_gui/resize_lora_gui.py @@ -59,7 +59,7 @@ def resize_lora( if device == '': device = 'cuda' - run_cmd = fr'{PYTHON} "{scriptdir}/sd-scripts/networks/resize_lora.py"' + run_cmd = fr'"{PYTHON}" "{scriptdir}/sd-scripts/networks/resize_lora.py"' run_cmd += f' --save_precision {save_precision}' run_cmd += fr' --save_to "{save_to}"' run_cmd += fr' --model "{model}"' diff --git a/kohya_gui/svd_merge_lora_gui.py b/kohya_gui/svd_merge_lora_gui.py index bf577777f..ed5059396 100644 --- a/kohya_gui/svd_merge_lora_gui.py +++ b/kohya_gui/svd_merge_lora_gui.py @@ -53,7 +53,7 @@ def svd_merge_lora( ratio_c /= total_ratio ratio_d /= total_ratio - run_cmd = fr'{PYTHON} "{scriptdir}/sd-scripts/networks/svd_merge_lora.py"' + run_cmd = fr'"{PYTHON}" "{scriptdir}/sd-scripts/networks/svd_merge_lora.py"' run_cmd += f' --save_precision {save_precision}' run_cmd += f' --precision {precision}' run_cmd += fr' --save_to "{save_to}"' diff --git a/kohya_gui/verify_lora_gui.py b/kohya_gui/verify_lora_gui.py index 7c8fdefa3..aa172739f 100644 --- a/kohya_gui/verify_lora_gui.py +++ b/kohya_gui/verify_lora_gui.py @@ -38,7 +38,7 @@ def verify_lora( msgbox('The provided model A is not a file') return - run_cmd = fr'{PYTHON} "{scriptdir}/sd-scripts/networks/check_lora_weights.py" "{lora_model}"' + run_cmd = fr'"{PYTHON}" "{scriptdir}/sd-scripts/networks/check_lora_weights.py" "{lora_model}"' log.info(run_cmd) diff --git a/setup/setup_common.py b/setup/setup_common.py index d9c50d485..812f3c130 100644 --- a/setup/setup_common.py +++ b/setup/setup_common.py @@ -423,36 +423,58 @@ def pip(arg: str, ignore: bool = False, quiet: bool = False, show_stdout: bool = return txt +import re +import pkg_resources +import logging + +log = logging.getLogger(__name__) + def installed(package, friendly: str = None): - # - # This function was adapted from code written by vladimandic: https://github.com/vladmandic/automatic/commits/master - # + """ + Checks if the specified package(s) are installed with the correct version. + This function can handle package specifications with or without version constraints, + and can also filter out command-line options and URLs when a 'friendly' string is provided. - # Remove brackets and their contents from the line using regular expressions - # e.g., diffusers[torch]==0.10.2 becomes diffusers==0.10.2 + Parameters: + - package: A string that specifies one or more packages with optional version constraints. + - friendly: An optional string used to provide a cleaner version of the package string + that excludes command-line options and URLs. + + Returns: + - True if all specified packages are installed with the correct versions, False otherwise. + + Note: + This function was adapted from code written by vladimandic. + """ + + # Remove any optional features specified in brackets (e.g., "package[option]==version" becomes "package==version") package = re.sub(r'\[.*?\]', '', package) try: if friendly: + # If a 'friendly' version of the package string is provided, split it into components pkgs = friendly.split() - # Exclude command-line options and URLs like "--index-url https://download.pytorch.org/whl/cu118" + # Filter out command-line options and URLs from the package specification pkgs = [ p for p in package.split() - if not p.startswith('--') and "://" not in p # Exclude command-line options and URLs + if not p.startswith('--') and "://" not in p ] else: + # Split the package string into components, excluding '-' and '=' prefixed items pkgs = [ p for p in package.split() if not p.startswith('-') and not p.startswith('=') ] + # For each package component, extract the package name, excluding any URLs pkgs = [ p.split('/')[-1] for p in pkgs - ] # get only package name if installing from URL - + ] + for pkg in pkgs: + # Parse the package name and version based on the version specifier used if '>=' in pkg: pkg_name, pkg_version = [x.strip() for x in pkg.split('>=')] elif '==' in pkg: @@ -460,35 +482,45 @@ def installed(package, friendly: str = None): else: pkg_name, pkg_version = pkg.strip(), None + # Attempt to find the installed package by its name spec = pkg_resources.working_set.by_key.get(pkg_name, None) if spec is None: + # Try again with lowercase name spec = pkg_resources.working_set.by_key.get(pkg_name.lower(), None) if spec is None: + # Try replacing underscores with dashes spec = pkg_resources.working_set.by_key.get(pkg_name.replace('_', '-'), None) if spec is not None: + # Package is found, check version version = pkg_resources.get_distribution(pkg_name).version log.debug(f'Package version found: {pkg_name} {version}') if pkg_version is not None: + # Verify if the installed version meets the specified constraints if '>=' in pkg: ok = version >= pkg_version else: ok = version == pkg_version if not ok: + # Version mismatch, log warning and return False log.warning(f'Package wrong version: {pkg_name} {version} required {pkg_version}') return False else: + # Package not found, log debug message and return False log.debug(f'Package version not found: {pkg_name}') return False + # All specified packages are installed with the correct versions return True except ModuleNotFoundError: + # One or more packages are not installed, log debug message and return False log.debug(f'Package not installed: {pkgs}') return False + # install package using pip if not already installed def install( # From 70d10e8cd80ba0770d50c0a2981fba6ffdb34cfb Mon Sep 17 00:00:00 2001 From: bmaltais Date: Tue, 12 Mar 2024 07:17:00 -0400 Subject: [PATCH 2/3] Fix issue with setup_common --- setup/setup_common.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/setup/setup_common.py b/setup/setup_common.py index 812f3c130..52f48943f 100644 --- a/setup/setup_common.py +++ b/setup/setup_common.py @@ -422,13 +422,6 @@ def pip(arg: str, ignore: bool = False, quiet: bool = False, show_stdout: bool = log.debug(f'Pip output: {txt}') return txt - -import re -import pkg_resources -import logging - -log = logging.getLogger(__name__) - def installed(package, friendly: str = None): """ Checks if the specified package(s) are installed with the correct version. From 6b10cb2c6f999f80ae7dafe35cfa7b23a85e467e Mon Sep 17 00:00:00 2001 From: bmaltais Date: Tue, 12 Mar 2024 07:38:57 -0400 Subject: [PATCH 3/3] New release --- .release | 2 +- README.md | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.release b/.release index fa6a39f15..0f75ce3fa 100644 --- a/.release +++ b/.release @@ -1 +1 @@ -v23.0.5 \ No newline at end of file +v23.0.6 \ No newline at end of file diff --git a/README.md b/README.md index d0ec16d7f..c1ce4299f 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ The GUI allows you to set the training parameters and generate and run the requi - [No module called tkinter](#no-module-called-tkinter) - [SDXL training](#sdxl-training) - [Change History](#change-history) + - [2024/03/11 (v23.0.6)](#20240311-v2306) + - [2024/03/11 (v23.0.5)](#20240311-v2305) - [2024/03/10 (v23.0.4)](#20240310-v2304) - [2024/03/10 (v23.0.3)](#20240310-v2303) - [2024/03/10 (v23.0.2)](#20240310-v2302) @@ -363,6 +365,10 @@ The documentation in this section will be moved to a separate document later. ## Change History +### 2024/03/11 (v23.0.6) + +- Fix issue with PYTHON path that have "spaces" in them + ### 2024/03/11 (v23.0.5) - Update python module verification