mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2025-04-12 18:33:35 +00:00
Merge af6ce81f00
into 22ad513c72
This commit is contained in:
commit
b3f0019ddb
2
codebeaver.yml
Normal file
2
codebeaver.yml
Normal file
@ -0,0 +1,2 @@
|
||||
from:pytest
|
||||
# This file was generated automatically by CodeBeaver based on your repository. Learn how to customize it here: https://docs.codebeaver.ai/configuration
|
381
tests/test_cli_args.py
Normal file
381
tests/test_cli_args.py
Normal file
@ -0,0 +1,381 @@
|
||||
import os
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
import argparse
|
||||
import comfy.cli_args as cli_args
|
||||
import importlib
|
||||
import comfy.options
|
||||
|
||||
# No additional imports required since all necessary modules
|
||||
# (pytest, comfy.cli_args, etc.) are already imported in the test file.
|
||||
def test_is_valid_directory(tmp_path):
|
||||
"""
|
||||
Test the is_valid_directory function from comfy.cli_args.
|
||||
Verifies that:
|
||||
- Passing None returns None.
|
||||
- A valid directory returns the same path string.
|
||||
- An invalid directory path raises an argparse.ArgumentTypeError.
|
||||
"""
|
||||
assert cli_args.is_valid_directory(None) is None
|
||||
valid_dir = str(tmp_path)
|
||||
returned = cli_args.is_valid_directory(valid_dir)
|
||||
assert returned == valid_dir
|
||||
invalid_dir = os.path.join(valid_dir, "non_existing_dir")
|
||||
with pytest.raises(argparse.ArgumentTypeError) as excinfo:
|
||||
cli_args.is_valid_directory(invalid_dir)
|
||||
assert invalid_dir in str(excinfo.value)
|
||||
def test_listen_argument_no_value():
|
||||
"""
|
||||
Test that when the '--listen' argument is provided without a following value,
|
||||
the parser uses the const value "0.0.0.0,::" instead of the default.
|
||||
"""
|
||||
test_args = ["--listen"]
|
||||
args = cli_args.parser.parse_args(test_args)
|
||||
assert args.listen == "0.0.0.0,::"
|
||||
def test_preview_method_argument():
|
||||
"""
|
||||
Test that the '--preview-method' argument:
|
||||
- Correctly converts a valid value (e.g. "latent2rgb") to a LatentPreviewMethod enum instance.
|
||||
- Causes the parser to exit with an error (SystemExit) when provided an invalid value.
|
||||
"""
|
||||
valid_value = "latent2rgb"
|
||||
args = cli_args.parser.parse_args(["--preview-method", valid_value])
|
||||
assert args.preview_method == cli_args.LatentPreviewMethod.Latent2RGB
|
||||
with pytest.raises(SystemExit):
|
||||
cli_args.parser.parse_args(["--preview-method", "invalid_value"])
|
||||
def test_directml_argument():
|
||||
"""
|
||||
Test the '--directml' argument to ensure:
|
||||
- When provided without a value, the default const value (-1) is used.
|
||||
- When provided with an argument, the argument is correctly parsed as an integer.
|
||||
"""
|
||||
args = cli_args.parser.parse_args(["--directml"])
|
||||
assert args.directml == -1
|
||||
args = cli_args.parser.parse_args(["--directml", "5"])
|
||||
assert args.directml == 5
|
||||
def test_extra_model_paths_config_argument():
|
||||
"""
|
||||
Test that the '--extra-model-paths-config' argument is parsed correctly.
|
||||
Verifies that:
|
||||
- When not provided, the default value is None.
|
||||
- When provided once with multiple values, the result is a nested list containing one list.
|
||||
- When provided multiple times, each occurrence is stored as a separate sublist.
|
||||
"""
|
||||
args = cli_args.parser.parse_args([])
|
||||
assert args.extra_model_paths_config is None
|
||||
args = cli_args.parser.parse_args(["--extra-model-paths-config", "a.yaml", "b.yaml"])
|
||||
assert args.extra_model_paths_config == [["a.yaml", "b.yaml"]]
|
||||
args = cli_args.parser.parse_args([
|
||||
"--extra-model-paths-config", "a.yaml", "b.yaml",
|
||||
"--extra-model-paths-config", "c.yaml"
|
||||
])
|
||||
assert args.extra_model_paths_config == [["a.yaml", "b.yaml"], ["c.yaml"]]
|
||||
def test_windows_standalone_build_flag():
|
||||
"""
|
||||
Test that the '--windows-standalone-build' flag correctly sets auto_launch to True,
|
||||
and that when both '--windows-standalone-build' and '--disable-auto-launch' are provided,
|
||||
auto_launch becomes False. This test manually applies the module-level post-processing logic.
|
||||
"""
|
||||
def post_process_args(ns):
|
||||
if ns.windows_standalone_build:
|
||||
ns.auto_launch = True
|
||||
if ns.disable_auto_launch:
|
||||
ns.auto_launch = False
|
||||
return ns
|
||||
args = cli_args.parser.parse_args(["--windows-standalone-build"])
|
||||
args = post_process_args(args)
|
||||
assert args.auto_launch is True
|
||||
args = cli_args.parser.parse_args(["--windows-standalone-build", "--disable-auto-launch"])
|
||||
args = post_process_args(args)
|
||||
assert args.auto_launch is False
|
||||
def test_verbose_argument():
|
||||
"""
|
||||
Test that the '--verbose' argument works correctly:
|
||||
- When provided without a value, it should default to 'DEBUG' (using its const value).
|
||||
- When provided with an explicit value, the given value should be used.
|
||||
"""
|
||||
args = cli_args.parser.parse_args(["--verbose"])
|
||||
assert args.verbose == "DEBUG"
|
||||
args = cli_args.parser.parse_args(["--verbose", "WARNING"])
|
||||
assert args.verbose == "WARNING"
|
||||
def test_mutually_exclusive_cuda_malloc():
|
||||
"""
|
||||
Test that providing both mutually exclusive options '--cuda-malloc' and
|
||||
'--disable-cuda-malloc' raises a SystemExit due to the conflict.
|
||||
"""
|
||||
with pytest.raises(SystemExit):
|
||||
cli_args.parser.parse_args(["--cuda-malloc", "--disable-cuda-malloc"])
|
||||
def test_front_end_version_argument():
|
||||
"""
|
||||
Test that the '--front-end-version' argument:
|
||||
- Defaults to "comfyanonymous/ComfyUI@latest" when not provided.
|
||||
- Accepts and correctly parses a custom version string when provided.
|
||||
"""
|
||||
args = cli_args.parser.parse_args([])
|
||||
assert args.front_end_version == "comfyanonymous/ComfyUI@latest"
|
||||
custom_version = "user/custom@1.2.3"
|
||||
args = cli_args.parser.parse_args(["--front-end-version", custom_version])
|
||||
assert args.front_end_version == custom_version
|
||||
def test_mutually_exclusive_fpvae_group():
|
||||
"""
|
||||
Test that providing both mutually exclusive '--fp16-vae' and '--bf16-vae'
|
||||
arguments causes the parser to exit with an error.
|
||||
"""
|
||||
with pytest.raises(SystemExit):
|
||||
cli_args.parser.parse_args(["--fp16-vae", "--bf16-vae"])
|
||||
def test_default_values():
|
||||
"""
|
||||
Test that default values for all arguments are correctly set when no arguments are provided.
|
||||
This verifies the defaults for network settings, directory paths, various flags, and numeric options.
|
||||
"""
|
||||
args = cli_args.parser.parse_args([])
|
||||
assert args.listen == "127.0.0.1"
|
||||
assert args.port == 8188
|
||||
assert args.tls_keyfile is None
|
||||
assert args.tls_certfile is None
|
||||
assert args.enable_cors_header is None
|
||||
assert args.max_upload_size == 100
|
||||
assert args.base_directory is None
|
||||
assert args.output_directory is None
|
||||
assert args.temp_directory is None
|
||||
assert args.input_directory is None
|
||||
assert args.auto_launch is False
|
||||
assert args.disable_auto_launch is False
|
||||
assert args.cuda_device is None
|
||||
assert not getattr(args, 'cuda_malloc', False)
|
||||
assert not getattr(args, 'disable_cuda_malloc', False)
|
||||
assert not getattr(args, 'fp32_unet', False)
|
||||
assert not getattr(args, 'fp64_unet', False)
|
||||
assert not getattr(args, 'bf16_unet', False)
|
||||
assert not getattr(args, 'fp16_unet', False)
|
||||
assert not getattr(args, 'fp8_e4m3fn_unet', False)
|
||||
assert not getattr(args, 'fp8_e5m2_unet', False)
|
||||
assert not getattr(args, 'fp16_vae', False)
|
||||
assert not getattr(args, 'fp32_vae', False)
|
||||
assert not getattr(args, 'bf16_vae', False)
|
||||
assert not args.cpu_vae
|
||||
assert not getattr(args, 'fp8_e4m3fn_text_enc', False)
|
||||
assert not getattr(args, 'fp8_e5m2_text_enc', False)
|
||||
assert not getattr(args, 'fp16_text_enc', False)
|
||||
assert not getattr(args, 'fp32_text_enc', False)
|
||||
assert not getattr(args, 'force_upcast_attention', False)
|
||||
assert not getattr(args, 'dont_upcast_attention', False)
|
||||
assert not getattr(args, 'gpu_only', False)
|
||||
assert not getattr(args, 'highvram', False)
|
||||
assert not getattr(args, 'normalvram', False)
|
||||
assert not getattr(args, 'lowvram', False)
|
||||
assert not getattr(args, 'novram', False)
|
||||
assert not getattr(args, 'cpu', False)
|
||||
assert args.reserve_vram is None
|
||||
assert args.default_hashing_function == 'sha256'
|
||||
assert not args.disable_smart_memory
|
||||
assert not args.deterministic
|
||||
assert not args.fast
|
||||
assert args.verbose == 'INFO'
|
||||
assert not args.log_stdout
|
||||
assert args.front_end_version == "comfyanonymous/ComfyUI@latest"
|
||||
assert args.front_end_root is None
|
||||
assert args.user_directory is None
|
||||
assert not args.enable_compress_response_body
|
||||
def test_oneapi_device_selector_argument():
|
||||
"""
|
||||
Test that the '--oneapi-device-selector' argument is correctly parsed.
|
||||
Verifies that:
|
||||
- When not provided, the default value is None.
|
||||
- When provided with a specific string, the argument returns that string.
|
||||
"""
|
||||
args = cli_args.parser.parse_args([])
|
||||
assert args.oneapi_device_selector is None, "Default for oneapi-device-selector should be None"
|
||||
test_value = "GPU0,GPU1"
|
||||
args = cli_args.parser.parse_args(["--oneapi-device-selector", test_value])
|
||||
assert args.oneapi_device_selector == test_value, f"Expected oneapi-device-selector to be {test_value}"
|
||||
def test_tls_arguments():
|
||||
"""
|
||||
Test that TLS related arguments are correctly parsed.
|
||||
Verifies that:
|
||||
- When provided, the '--tls-keyfile' and '--tls-certfile' arguments are correctly stored.
|
||||
"""
|
||||
test_args = ["--tls-keyfile", "keyfile.pem", "--tls-certfile", "certfile.pem"]
|
||||
args = cli_args.parser.parse_args(test_args)
|
||||
assert args.tls_keyfile == "keyfile.pem"
|
||||
assert args.tls_certfile == "certfile.pem"
|
||||
def test_invalid_directml_argument():
|
||||
"""
|
||||
Test that providing a non-integer value for the '--directml' argument
|
||||
raises a SystemExit error due to the argparse type conversion failure.
|
||||
"""
|
||||
with pytest.raises(SystemExit):
|
||||
cli_args.parser.parse_args(["--directml", "not_a_number"])
|
||||
def test_mutually_exclusive_fpte_group():
|
||||
"""
|
||||
Test that providing mutually exclusive text encoder precision options
|
||||
(e.g. '--fp8_e4m3fn-text-enc' and '--fp16-text-enc') raises a SystemExit error.
|
||||
"""
|
||||
with pytest.raises(SystemExit):
|
||||
cli_args.parser.parse_args(["--fp8_e4m3fn-text-enc", "--fp16-text-enc"])
|
||||
def test_miscellaneous_flags():
|
||||
"""
|
||||
Test that miscellaneous boolean flags (disable-metadata, disable-all-custom-nodes, multi-user, and log-stdout)
|
||||
are correctly set when provided on the command line.
|
||||
"""
|
||||
args = cli_args.parser.parse_args([
|
||||
"--disable-metadata",
|
||||
"--disable-all-custom-nodes",
|
||||
"--multi-user",
|
||||
"--log-stdout"
|
||||
])
|
||||
assert args.disable_metadata is True, "Expected --disable-metadata to set disable_metadata to True"
|
||||
assert args.disable_all_custom_nodes is True, "Expected --disable-all-custom-nodes to set disable_all_custom_nodes to True"
|
||||
assert args.multi_user is True, "Expected --multi-user to set multi_user to True"
|
||||
assert args.log_stdout is True, "Expected --log-stdout to set log_stdout to True"
|
||||
def test_invalid_hashing_function_argument():
|
||||
"""
|
||||
Test that providing an invalid value for the '--default-hashing-function' argument
|
||||
raises a SystemExit error due to the invalid choice.
|
||||
"""
|
||||
with pytest.raises(SystemExit):
|
||||
cli_args.parser.parse_args(["--default-hashing-function", "invalid_hash"])
|
||||
def test_front_end_root_argument(tmp_path):
|
||||
"""
|
||||
Test that the '--front-end-root' argument correctly validates and returns
|
||||
the provided directory path as a string.
|
||||
"""
|
||||
valid_dir = str(tmp_path)
|
||||
args = cli_args.parser.parse_args(["--front-end-root", valid_dir])
|
||||
assert args.front_end_root == valid_dir
|
||||
def test_enable_cors_header_argument():
|
||||
"""
|
||||
Test that the '--enable-cors-header' argument is parsed correctly:
|
||||
- When provided without a value, it should use the const value "*"
|
||||
(indicating allow all origins).
|
||||
- When provided with an explicit value, it returns that value.
|
||||
"""
|
||||
args = cli_args.parser.parse_args(["--enable-cors-header"])
|
||||
assert args.enable_cors_header == "*", "Expected --enable-cors-header with no value to default to '*'"
|
||||
test_origin = "http://example.com"
|
||||
args = cli_args.parser.parse_args(["--enable-cors-header", test_origin])
|
||||
assert args.enable_cors_header == test_origin, "Expected --enable-cors-header to use the provided origin"
|
||||
def test_listen_argument_with_explicit_value():
|
||||
"""
|
||||
Test that providing an explicit IP address with '--listen' sets the value correctly.
|
||||
"""
|
||||
test_ip = "192.168.1.100"
|
||||
args = cli_args.parser.parse_args(["--listen", test_ip])
|
||||
assert args.listen == test_ip
|
||||
def test_cache_arguments():
|
||||
"""
|
||||
Test that the caching arguments are correctly parsed.
|
||||
Verifies that:
|
||||
- When provided with '--cache-lru' and an integer value, the cache_lru attribute is set accordingly and cache_classic is False.
|
||||
- When provided with '--cache-classic', the cache_classic flag is True and cache_lru remains at its default value (0).
|
||||
- Providing both options simultaneously raises a SystemExit error due to mutual exclusivity.
|
||||
"""
|
||||
args = cli_args.parser.parse_args(["--cache-lru", "15"])
|
||||
assert args.cache_lru == 15
|
||||
assert args.cache_classic is False
|
||||
args = cli_args.parser.parse_args(["--cache-classic"])
|
||||
assert args.cache_classic is True
|
||||
assert args.cache_lru == 0
|
||||
with pytest.raises(SystemExit):
|
||||
cli_args.parser.parse_args(["--cache-lru", "15", "--cache-classic"])
|
||||
def test_invalid_port_argument():
|
||||
"""
|
||||
Test that passing a non-integer value to the '--port' argument
|
||||
raises a SystemExit error due to type conversion failure.
|
||||
"""
|
||||
with pytest.raises(SystemExit):
|
||||
cli_args.parser.parse_args(["--port", "not_an_integer"])
|
||||
def test_mutually_exclusive_fpunet_group():
|
||||
"""
|
||||
Test that providing mutually exclusive unet precision options (e.g. '--fp32-unet' and '--fp16-unet')
|
||||
raises a SystemExit error due to the conflict in the fpunet group.
|
||||
"""
|
||||
with pytest.raises(SystemExit):
|
||||
cli_args.parser.parse_args(["--fp32-unet", "--fp16-unet"])
|
||||
def test_mutually_exclusive_upcast_arguments():
|
||||
"""
|
||||
Test the mutual exclusivity of the upcast arguments:
|
||||
--force-upcast-attention and --dont-upcast-attention.
|
||||
|
||||
This test verifies that:
|
||||
- Providing only --force-upcast-attention sets its flag to True while --dont-upcast-attention remains False.
|
||||
- Providing only --dont-upcast-attention sets its flag to True while --force-upcast-attention remains False.
|
||||
- Providing both flags simultaneously raises a SystemExit error.
|
||||
"""
|
||||
args = cli_args.parser.parse_args(["--force-upcast-attention"])
|
||||
assert getattr(args, "force_upcast_attention", False) is True
|
||||
assert getattr(args, "dont_upcast_attention", False) is False
|
||||
args = cli_args.parser.parse_args(["--dont-upcast-attention"])
|
||||
assert getattr(args, "dont_upcast_attention", False) is True
|
||||
assert getattr(args, "force_upcast_attention", False) is False
|
||||
with pytest.raises(SystemExit):
|
||||
cli_args.parser.parse_args(["--force-upcast-attention", "--dont-upcast-attention"])
|
||||
def test_disable_xformers_argument():
|
||||
"""
|
||||
Test that the '--disable-xformers' argument correctly sets the disable_xformers flag to True.
|
||||
"""
|
||||
args = cli_args.parser.parse_args(["--disable-xformers"])
|
||||
assert args.disable_xformers is True
|
||||
def test_module_args_parsing_behavior():
|
||||
"""
|
||||
Test the module-level args parsing behavior.
|
||||
This test temporarily sets comfy.options.args_parsing to False and reloads the cli_args module.
|
||||
When args_parsing is False, the parser should be forced to parse an empty list (using defaults).
|
||||
We verify that the globals in cli_args.args have the expected default values.
|
||||
"""
|
||||
# Save the original value
|
||||
original_args_parsing = comfy.options.args_parsing
|
||||
try:
|
||||
# Set args_parsing to False so that parser.parse_args([]) is used at the module level
|
||||
comfy.options.args_parsing = False
|
||||
reloaded_cli_args = importlib.reload(cli_args)
|
||||
# Since no arguments are provided by default, the defaults should be assigned.
|
||||
# For instance, 'listen' should be "127.0.0.1" and 'port' should be 8188.
|
||||
assert reloaded_cli_args.args.listen == "127.0.0.1", "Expected default listen to be 127.0.0.1"
|
||||
assert reloaded_cli_args.args.port == 8188, "Expected default port to be 8188"
|
||||
# Additionally, we want to check that a flag (like auto_launch) remains at its default (False)
|
||||
assert reloaded_cli_args.args.auto_launch is False, "Expected auto_launch to be False when no args provided"
|
||||
finally:
|
||||
# Restore the original args_parsing value and reload the module again to reset state.
|
||||
comfy.options.args_parsing = original_args_parsing
|
||||
importlib.reload(cli_args) # reset to original state
|
||||
def test_fpunet_valid_option():
|
||||
"""
|
||||
Test that providing the '--fp16-unet' argument correctly sets the fp16_unet flag,
|
||||
and does not set any other mutually exclusive fpunet options.
|
||||
"""
|
||||
args = cli_args.parser.parse_args(["--fp16-unet"])
|
||||
assert args.fp16_unet is True, "Expected --fp16-unet to set fp16_unet to True"
|
||||
assert not getattr(args, "fp32_unet", False), "Unexpected --fp32-unet flag when --fp16-unet is provided"
|
||||
assert not getattr(args, "fp64_unet", False), "Unexpected --fp64-unet flag when --fp16-unet is provided"
|
||||
assert not getattr(args, "bf16_unet", False), "Unexpected --bf16-unet flag when --fp16-unet is provided"
|
||||
assert not getattr(args, "fp8_e4m3fn_unet", False), "Unexpected --fp8_e4m3fn-unet flag when --fp16-unet is provided"
|
||||
assert not getattr(args, "fp8_e5m2_unet", False), "Unexpected --fp8_e5m2-unet flag when --fp16-unet is provided"
|
||||
def test_dont_print_server_and_quick_test_for_ci():
|
||||
"""
|
||||
Test that the '--dont-print-server' and '--quick-test-for-ci' flags are correctly parsed.
|
||||
Verifies that when not provided, their values default to False, and when provided,
|
||||
they are set to True.
|
||||
"""
|
||||
# Test with no flags provided (should use defaults)
|
||||
args = cli_args.parser.parse_args([])
|
||||
assert args.dont_print_server is False, "Expected default dont_print_server to be False"
|
||||
assert args.quick_test_for_ci is False, "Expected default quick_test_for_ci to be False"
|
||||
|
||||
# Test with both flags provided on the command line
|
||||
args = cli_args.parser.parse_args(["--dont-print-server", "--quick-test-for-ci"])
|
||||
assert args.dont_print_server is True, "Expected dont_print_server to be True when flag is provided"
|
||||
assert args.quick_test_for_ci is True, "Expected quick_test_for_ci to be True when flag is provided"
|
||||
def test_vram_group_lowvram_flag():
|
||||
"""
|
||||
Test that providing the '--lowvram' flag correctly sets the lowvram flag
|
||||
and ensures that all other mutually exclusive vram flags remain False.
|
||||
"""
|
||||
args = cli_args.parser.parse_args(["--lowvram"])
|
||||
assert args.lowvram is True
|
||||
# Ensure that no other mutually exclusive vram flags are set
|
||||
assert not getattr(args, "gpu_only", False)
|
||||
assert not getattr(args, "highvram", False)
|
||||
assert not getattr(args, "normalvram", False)
|
||||
assert not getattr(args, "novram", False)
|
||||
assert not getattr(args, "cpu", False)
|
Loading…
Reference in New Issue
Block a user