Merge pull request #5036 from vladmandic/fix/scripts-empty-arg-vector

Fix/scripts empty arg vector
This commit is contained in:
Vladimir Mandic
2026-08-18 17:35:05 +02:00
committed by GitHub
2 changed files with 333 additions and 24 deletions
+47 -24
View File
@@ -340,6 +340,27 @@ def wrap_call(func: Callable, filename: str, funcname: str, *args, default=None,
return default
def resolve_script_args(script, args, per_script_args=None):
"""Positional args for one script hook, None when the vector cannot fill the script's slot.
A caller-supplied override wins outright. Otherwise the declared range has to fit the vector,
since a truncated slice would splat fewer positionals than the hook signature takes. A script
that declares no args still runs: its empty slice is complete rather than truncated.
"""
if not hasattr(script, 'args_from') or not hasattr(script, 'args_to'):
return None
if per_script_args:
override = per_script_args.get(script.title(), None)
if override is not None:
return override
if (script.args_to <= 0) or (script.args_to < script.args_from):
return None
if (script.args_to > len(args)) and (script.args_to > script.args_from):
debug(f'Script: title="{script.title()}" op=skip args={len(args)} required={script.args_to}')
return None
return args[script.args_from:script.args_to]
class ScriptSummary:
def __init__(self, op: str):
self.start = time.time()
@@ -621,9 +642,10 @@ class ScriptRunner:
if 'upscale' in script.title():
if not hasattr(p, 'init_images') and p.task_args.get('image', None) is not None:
p.init_images = p.task_args['image']
parsed = []
if hasattr(script, 'args_to') and hasattr(script, 'args_from'):
parsed = p.per_script_args.get(script.title(), args[script.args_from:script.args_to])
parsed = resolve_script_args(script, args, p.per_script_args)
if parsed is None: # the script was selected by hand, so a vector that cannot drive it is worth saying out loud
log.error(f'Script: title="{script.title()}" args={len(args)} required={getattr(script, "args_to", None)} not run')
return None
if hasattr(script, 'run'):
processed = script.run(p, *parsed)
else:
@@ -644,9 +666,10 @@ class ScriptRunner:
script = None
if script is None or not hasattr(script, 'after'):
return processed
parsed = []
if hasattr(script, 'args_to') and hasattr(script, 'args_from'):
parsed = p.per_script_args.get(script.title(), args[script.args_from:script.args_to])
parsed = resolve_script_args(script, args, p.per_script_args)
if parsed is None:
log.error(f'Script: title="{script.title()}" args={len(args)} required={getattr(script, "args_to", None)} not run')
return processed
after_processed = script.after(p, processed, *parsed)
if after_processed is not None:
processed = after_processed
@@ -658,8 +681,8 @@ class ScriptRunner:
s = ScriptSummary('before-process')
for script in self.alwayson_scripts:
try:
if hasattr(script, 'args_to') and hasattr(script, 'args_from') and (script.args_to > 0) and (script.args_to >= script.args_from):
args = p.per_script_args.get(script.title(), p.script_args[script.args_from:script.args_to])
args = resolve_script_args(script, p.script_args, p.per_script_args)
if args is not None:
script.before_process(p, *args, **kwargs)
except Exception as e:
errors.display(e, f"Error running before process: {script.filename}")
@@ -670,8 +693,8 @@ class ScriptRunner:
s = ScriptSummary('process')
for script in self.alwayson_scripts:
try:
if hasattr(script, 'args_to') and hasattr(script, 'args_from') and (script.args_to > 0) and (script.args_to >= script.args_from):
args = p.per_script_args.get(script.title(), p.script_args[script.args_from:script.args_to])
args = resolve_script_args(script, p.script_args, p.per_script_args)
if args is not None:
script.process(p, *args, **kwargs)
except Exception as e:
errors.display(e, f'Running script process: {script.filename}')
@@ -683,8 +706,8 @@ class ScriptRunner:
processed = None
for script in self.alwayson_scripts:
try:
if hasattr(script, 'args_to') and hasattr(script, 'args_from') and (script.args_to > 0) and (script.args_to >= script.args_from):
args = p.per_script_args.get(script.title(), p.script_args[script.args_from:script.args_to])
args = resolve_script_args(script, p.script_args, p.per_script_args)
if args is not None:
_processed = script.process_images(p, *args, **kwargs)
if _processed is not None:
processed = _processed
@@ -698,8 +721,8 @@ class ScriptRunner:
s = ScriptSummary('before-process-batch')
for script in self.alwayson_scripts:
try:
if hasattr(script, 'args_to') and hasattr(script, 'args_from') and (script.args_to > 0) and (script.args_to >= script.args_from):
args = p.per_script_args.get(script.title(), p.script_args[script.args_from:script.args_to])
args = resolve_script_args(script, p.script_args, p.per_script_args)
if args is not None:
script.before_process_batch(p, *args, **kwargs)
except Exception as e:
errors.display(e, f'Running script before process batch: {script.filename}')
@@ -710,8 +733,8 @@ class ScriptRunner:
s = ScriptSummary('process-batch')
for script in self.alwayson_scripts:
try:
if hasattr(script, 'args_to') and hasattr(script, 'args_from') and (script.args_to > 0) and (script.args_to >= script.args_from):
args = p.per_script_args.get(script.title(), p.script_args[script.args_from:script.args_to])
args = resolve_script_args(script, p.script_args, p.per_script_args)
if args is not None:
script.process_batch(p, *args, **kwargs)
except Exception as e:
errors.display(e, f'Running script process batch: {script.filename}')
@@ -722,8 +745,8 @@ class ScriptRunner:
s = ScriptSummary('postprocess')
for script in self.alwayson_scripts:
try:
if hasattr(script, 'args_to') and hasattr(script, 'args_from') and (script.args_to > 0) and (script.args_to >= script.args_from):
args = p.per_script_args.get(script.title(), p.script_args[script.args_from:script.args_to])
args = resolve_script_args(script, p.script_args, p.per_script_args)
if args is not None:
script.postprocess(p, processed, *args)
except Exception as e:
errors.display(e, f'Running script postprocess: {script.filename}')
@@ -734,8 +757,8 @@ class ScriptRunner:
s = ScriptSummary('postprocess-batch')
for script in self.alwayson_scripts:
try:
if hasattr(script, 'args_to') and hasattr(script, 'args_from') and (script.args_to > 0) and (script.args_to >= script.args_from):
args = p.per_script_args.get(script.title(), p.script_args[script.args_from:script.args_to])
args = resolve_script_args(script, p.script_args, p.per_script_args)
if args is not None:
script.postprocess_batch(p, *args, images=images, **kwargs)
except Exception as e:
errors.display(e, f'Running script before postprocess batch: {script.filename}')
@@ -746,8 +769,8 @@ class ScriptRunner:
s = ScriptSummary('postprocess-batch-list')
for script in self.alwayson_scripts:
try:
if hasattr(script, 'args_to') and hasattr(script, 'args_from') and (script.args_to > 0) and (script.args_to >= script.args_from):
args = p.per_script_args.get(script.title(), p.script_args[script.args_from:script.args_to])
args = resolve_script_args(script, p.script_args, p.per_script_args)
if args is not None:
script.postprocess_batch_list(p, pp, *args, **kwargs)
except Exception as e:
errors.display(e, f'Running script before postprocess batch list: {script.filename}')
@@ -758,8 +781,8 @@ class ScriptRunner:
s = ScriptSummary('postprocess-image')
for script in self.alwayson_scripts:
try:
if hasattr(script, 'args_to') and hasattr(script, 'args_from') and (script.args_to > 0) and (script.args_to >= script.args_from):
args = p.per_script_args.get(script.title(), p.script_args[script.args_from:script.args_to])
args = resolve_script_args(script, p.script_args, p.per_script_args)
if args is not None:
script.postprocess_image(p, pp, *args)
except Exception as e:
errors.display(e, f'Running script postprocess image: {script.filename}')