diff --git a/modules/img2img.py b/modules/img2img.py index 6b484db54..5a29b96c0 100644 --- a/modules/img2img.py +++ b/modules/img2img.py @@ -63,7 +63,7 @@ def process_batch(p, input_dir, output_dir, inpaint_mask_dir, args): shared.log.debug(f'Processed: {len(images)} Memory: {memory_stats()} batch') -def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_styles, init_img, sketch, init_img_with_mask, inpaint_color_sketch, inpaint_color_sketch_orig, init_img_inpaint, init_mask_inpaint, steps: int, sampler_index: int, latent_index: int, mask_blur: int, mask_alpha: float, inpainting_fill: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, diffusers_guidance_rescale: float, refiner_denoise_start: float, refiner_denoise_end: float, clip_skip: int, denoising_strength: float, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, seed_enable_extras: bool, selected_scale_tab: int, height: int, width: int, scale_by: float, resize_mode: int, inpaint_full_res: bool, inpaint_full_res_padding: int, inpainting_mask_invert: int, img2img_batch_input_dir: str, img2img_batch_output_dir: str, img2img_batch_inpaint_mask_dir: str, override_settings_texts, *args): # pylint: disable=unused-argument +def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_styles, init_img, sketch, init_img_with_mask, inpaint_color_sketch, inpaint_color_sketch_orig, init_img_inpaint, init_mask_inpaint, steps: int, sampler_index: int, latent_index: int, mask_blur: int, mask_alpha: float, inpainting_fill: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, diffusers_guidance_rescale: float, refiner_denoise_start: float, refiner_denoise_end: float, clip_skip: int, denoising_strength: float, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, selected_scale_tab: int, height: int, width: int, scale_by: float, resize_mode: int, inpaint_full_res: bool, inpaint_full_res_padding: int, inpainting_mask_invert: int, img2img_batch_input_dir: str, img2img_batch_output_dir: str, img2img_batch_inpaint_mask_dir: str, override_settings_texts, *args): # pylint: disable=unused-argument if shared.sd_model is None: shared.log.warning('Model not loaded') @@ -72,7 +72,7 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s if init_img is None: shared.log.debug('Init image not set') - shared.log.debug(f'img2img: id_task={id_task}|mode={mode}|prompt={prompt}|negative_prompt={negative_prompt}|prompt_styles={prompt_styles}|init_img={init_img}|sketch={sketch}|init_img_with_mask={init_img_with_mask}|inpaint_color_sketch={inpaint_color_sketch}|inpaint_color_sketch_orig={inpaint_color_sketch_orig}|init_img_inpaint={init_img_inpaint}|init_mask_inpaint={init_mask_inpaint}|steps={steps}|sampler_index={sampler_index}|latent_index={latent_index}|mask_blur={mask_blur}|mask_alpha={mask_alpha}|inpainting_fill={inpainting_fill}|restore_faces={restore_faces}|tiling={tiling}|n_iter={n_iter}|batch_size={batch_size}|cfg_scale={cfg_scale}|image_cfg_scale={image_cfg_scale}|clip_skip={clip_skip}|denoising_strength={denoising_strength}|seed={seed}|subseed{subseed}|subseed_strength={subseed_strength}|seed_resize_from_h={seed_resize_from_h}|seed_resize_from_w={seed_resize_from_w}|seed_enable_extras={seed_enable_extras}|selected_scale_tab={selected_scale_tab}|height={height}|width={width}|scale_by={scale_by}|resize_mode={resize_mode}|inpaint_full_res={inpaint_full_res}|inpaint_full_res_padding={inpaint_full_res_padding}|inpainting_mask_invert={inpainting_mask_invert}|img2img_batch_input_dir={img2img_batch_input_dir}|img2img_batch_output_dir={img2img_batch_output_dir}|img2img_batch_inpaint_mask_dir={img2img_batch_inpaint_mask_dir}|override_settings_texts={override_settings_texts}|args={args}') + shared.log.debug(f'img2img: id_task={id_task}|mode={mode}|prompt={prompt}|negative_prompt={negative_prompt}|prompt_styles={prompt_styles}|init_img={init_img}|sketch={sketch}|init_img_with_mask={init_img_with_mask}|inpaint_color_sketch={inpaint_color_sketch}|inpaint_color_sketch_orig={inpaint_color_sketch_orig}|init_img_inpaint={init_img_inpaint}|init_mask_inpaint={init_mask_inpaint}|steps={steps}|sampler_index={sampler_index}|latent_index={latent_index}|mask_blur={mask_blur}|mask_alpha={mask_alpha}|inpainting_fill={inpainting_fill}|restore_faces={restore_faces}|tiling={tiling}|n_iter={n_iter}|batch_size={batch_size}|cfg_scale={cfg_scale}|image_cfg_scale={image_cfg_scale}|clip_skip={clip_skip}|denoising_strength={denoising_strength}|seed={seed}|subseed{subseed}|subseed_strength={subseed_strength}|seed_resize_from_h={seed_resize_from_h}|seed_resize_from_w={seed_resize_from_w}|selected_scale_tab={selected_scale_tab}|height={height}|width={width}|scale_by={scale_by}|resize_mode={resize_mode}|inpaint_full_res={inpaint_full_res}|inpaint_full_res_padding={inpaint_full_res_padding}|inpainting_mask_invert={inpainting_mask_invert}|img2img_batch_input_dir={img2img_batch_input_dir}|img2img_batch_output_dir={img2img_batch_output_dir}|img2img_batch_inpaint_mask_dir={img2img_batch_inpaint_mask_dir}|override_settings_texts={override_settings_texts}|args={args}') if sampler_index is None: shared.log.warning('Selected sampler is not enabled') diff --git a/modules/processing.py b/modules/processing.py index 932748082..8d776cce4 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -443,7 +443,6 @@ def fix_seed(p): def create_infotext(p: StableDiffusionProcessing, all_prompts, all_seeds, all_subseeds, comments=None, iteration=0, position_in_batch=0): # pylint: disable=unused-argument index = position_in_batch + iteration * p.batch_size - enable_hr = getattr(p, 'enable_hr', False) token_merging_ratio = p.get_token_merging_ratio() token_merging_ratio_hr = p.get_token_merging_ratio(for_hr=True) uses_ensd = opts.eta_noise_seed_delta != 0 @@ -473,7 +472,7 @@ def create_infotext(p: StableDiffusionProcessing, all_prompts, all_seeds, all_su "Init image hash": getattr(p, 'init_img_hash', None), "Version": git_commit, "Token merging ratio": None if token_merging_ratio == 0 else token_merging_ratio, - "Token merging ratio hr": None if not enable_hr or token_merging_ratio_hr == 0 else token_merging_ratio_hr, + "Token merging ratio hr": None if not p.enable_hr or token_merging_ratio_hr == 0 else token_merging_ratio_hr, "Parser": opts.prompt_attention, } generation_params.update(p.extra_generation_params) @@ -974,7 +973,6 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): self.truncate_y = (self.hr_upscale_to_y - target_h) // opt_f # special case: the user has chosen to do nothing if self.hr_upscale_to_x == self.width and self.hr_upscale_to_y == self.height: - self.enable_hr = False self.denoising_strength = None self.extra_generation_params.pop("Hires upscale", None) self.extra_generation_params.pop("Hires resize", None) diff --git a/modules/shared.py b/modules/shared.py index 8fd6450ed..98d88e098 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -359,7 +359,7 @@ options_templates.update(options_section(('cuda', "Compute Settings"), { })) options_templates.update(options_section(('diffusers', "Diffusers Settings"), { - "diffusers_allow_safetensors": OptionInfo(False, 'Diffusers allow loading from safetensors files'), + "diffusers_allow_safetensors": OptionInfo(True, 'Diffusers allow loading from safetensors files'), "diffusers_pipeline": OptionInfo(pipelines[0], 'Select diffuser pipeline when loading from safetensors', gr.Dropdown, lambda: {"choices": pipelines}), "diffusers_move_base": OptionInfo(False, "Move base model to CPU when using refiner"), "diffusers_move_refiner": OptionInfo(True, "Move refiner model to CPU when not in use"), @@ -495,11 +495,11 @@ options_templates.update(options_section(('sampler-params', "Sampler Settings"), 'uni_pc_skip_type': OptionInfo("time_uniform", "UniPC skip type", gr.Radio, {"choices": ["time_uniform", "time_quadratic", "logSNR"]}), 'eta_noise_seed_delta': OptionInfo(0, "Noise seed delta (eta)", gr.Number, {"precision": 0}), "eta_ddim": OptionInfo(0.0, "Noise multiplier for DDIM (eta)", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}), + "schedulers_solver_order": OptionInfo(2, "Samplers solver order where applicable", gr.Slider, {"minimum": 1, "maximum": 5, "step": 1}), "schedulers_sep_diffusers": OptionInfo("

Diffusers specific config

", "", gr.HTML), "schedulers_prediction_type": OptionInfo("default", "Samplers override model prediction type", gr.Radio, lambda: {"choices": ['default', 'epsilon', 'sample', 'v-prediction']}), "schedulers_beta_schedule": OptionInfo("default", "Samplers override beta schedule", gr.Radio, lambda: {"choices": ['default', 'linear', 'scaled_linear', 'squaredcos_cap_v2']}), - "schedulers_solver_order": OptionInfo(2, "Samplers solver order where applicable", gr.Slider, {"minimum": 1, "maximum": 5, "step": 1}), "schedulers_use_karras": OptionInfo(True, "Samplers should use Karras sigmas where applicable"), "schedulers_use_loworder": OptionInfo(True, "Samplers should use use lower-order solvers in the final steps where applicable"), "schedulers_use_thresholding": OptionInfo(False, "Samplers should use dynamic thresholding where applicable"), @@ -740,6 +740,8 @@ if cmd_opts.backend is None: else: backend = Backend.DIFFUSERS if cmd_opts.backend.lower() == 'diffusers' else Backend.ORIGINAL opts.data['sd_backend'] = 'diffusers' if backend == Backend.DIFFUSERS else 'original' +opts.data['uni_pc_lower_order_final'] = opts.schedulers_use_loworder +opts.data['uni_pc_order'] = opts.schedulers_solver_order log.info(f'Pipeline: {backend}') diff --git a/modules/txt2img.py b/modules/txt2img.py index d06d60dae..098d5fcf8 100644 --- a/modules/txt2img.py +++ b/modules/txt2img.py @@ -5,9 +5,9 @@ from modules.ui import plaintext_to_html from modules.memstats import memory_stats -def txt2img(id_task: str, prompt: str, negative_prompt: str, prompt_styles, steps: int, sampler_index: int, latent_index: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, diffusers_guidance_rescale: float, clip_skip: int, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, seed_enable_extras: bool, height: int, width: int, enable_hr: bool, denoising_strength: float, hr_scale: float, hr_upscaler: str, hr_second_pass_steps: int, hr_resize_x: int, hr_resize_y: int, refiner_denoise_start: int, refiner_denoise_end: float, refiner_prompt: str, refiner_negative: str, override_settings_texts, *args): # pylint: disable=unused-argument +def txt2img(id_task: str, prompt: str, negative_prompt: str, prompt_styles, steps: int, sampler_index: int, latent_index: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, diffusers_guidance_rescale: float, clip_skip: int, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, height: int, width: int, enable_hr: bool, denoising_strength: float, hr_scale: float, hr_upscaler: str, hr_second_pass_steps: int, hr_resize_x: int, hr_resize_y: int, refiner_denoise_start: int, refiner_denoise_end: float, refiner_prompt: str, refiner_negative: str, override_settings_texts, *args): # pylint: disable=unused-argument - shared.log.debug(f'txt2img: id_task={id_task}|prompt={prompt}|negative_prompt={negative_prompt}|prompt_styles={prompt_styles}|steps={steps}|sampler_index={sampler_index}|latent_index={latent_index}|restore_faces={restore_faces}|tiling={tiling}|n_iter={n_iter}|batch_size={batch_size}|cfg_scale={cfg_scale}|clip_skip={clip_skip}|seed={seed}|subseed={subseed}|subseed_strength={subseed_strength}|seed_resize_from_h={seed_resize_from_h}|seed_resize_from_w={seed_resize_from_w}|seed_enable_extras={seed_enable_extras}|height={height}|width={width}|enable_hr={enable_hr}|denoising_strength={denoising_strength}|hr_scale={hr_scale}|hr_upscaler={hr_upscaler}|hr_second_pass_steps={hr_second_pass_steps}|hr_resize_x={hr_resize_x}|hr_resize_y={hr_resize_y}|image_cfg_scale={image_cfg_scale}|diffusers_guidance_rescale={diffusers_guidance_rescale}|refiner_denoise_start={refiner_denoise_start}|refiner_denoise_end={refiner_denoise_end}|refiner_prompt={refiner_prompt}|refiner_negative={refiner_negative}|override_settings_texts={override_settings_texts}args={args}') + shared.log.debug(f'txt2img: id_task={id_task}|prompt={prompt}|negative_prompt={negative_prompt}|prompt_styles={prompt_styles}|steps={steps}|sampler_index={sampler_index}|latent_index={latent_index}|restore_faces={restore_faces}|tiling={tiling}|n_iter={n_iter}|batch_size={batch_size}|cfg_scale={cfg_scale}|clip_skip={clip_skip}|seed={seed}|subseed={subseed}|subseed_strength={subseed_strength}|seed_resize_from_h={seed_resize_from_h}|seed_resize_from_w={seed_resize_from_w}||height={height}|width={width}|enable_hr={enable_hr}|denoising_strength={denoising_strength}|hr_scale={hr_scale}|hr_upscaler={hr_upscaler}|hr_second_pass_steps={hr_second_pass_steps}|hr_resize_x={hr_resize_x}|hr_resize_y={hr_resize_y}|image_cfg_scale={image_cfg_scale}|diffusers_guidance_rescale={diffusers_guidance_rescale}|refiner_denoise_start={refiner_denoise_start}|refiner_denoise_end={refiner_denoise_end}|refiner_prompt={refiner_prompt}|refiner_negative={refiner_negative}|override_settings_texts={override_settings_texts}args={args}') if sampler_index is None: shared.log.warning('Selected sampler is not enabled') sampler_index = 0 diff --git a/modules/ui.py b/modules/ui.py index 77e8b3620..e6fd1d6aa 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -148,7 +148,6 @@ def create_seed_inputs(target_interface): seed.style(container=False) random_seed = ToolButton(random_symbol, elem_id=f"{target_interface}_random_seed", label='Random seed') reuse_seed = ToolButton(reuse_symbol, elem_id=f"{target_interface}_reuse_seed", label='Reuse seed') - seed_checkbox = gr.Checkbox(label='Extra', elem_id=f"{target_interface}_subseed_show", value=False) # Ghost checkbox for compatibility with FormRow(visible=True, elem_id=f"{target_interface}_subseed_row"): subseed = gr.Number(label='Variation seed', value=-1, elem_id=f"{target_interface}_subseed") subseed.style(container=False) @@ -160,7 +159,7 @@ def create_seed_inputs(target_interface): seed_resize_from_h = gr.Slider(minimum=0, maximum=2048, step=8, label="Resize seed from height", value=0, elem_id=f"{target_interface}_seed_resize_from_h") random_seed.click(fn=lambda: [-1, -1], show_progress=False, inputs=[], outputs=[seed, subseed]) random_subseed.click(fn=lambda: -1, show_progress=False, inputs=[], outputs=[subseed]) - return seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox + return seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w def connect_clear_prompt(button): @@ -301,16 +300,16 @@ def create_refresh_button(refresh_component, refresh_method, refreshed_args, ele return ui_common.create_refresh_button(refresh_component, refresh_method, refreshed_args, elem_id) -def create_sampler_and_steps_selection(choices, tabname): - with FormRow(elem_id=f"sampler_selection_{tabname}"): +def create_sampler_and_steps_selection(choices, tabname, primary: bool = True): + with FormRow(elem_id=f"sampler_selection_{tabname}'_alt' if not primary else ''"): if 'UniPC' in [sampler.name for sampler in choices]: default_sampler_name = 'UniPC' elif 'Euler a' in [sampler.name for sampler in choices]: default_sampler_name = 'Euler a' else: default_sampler_name = modules.sd_samplers.samplers[0].name - sampler_index = gr.Dropdown(label='Sampling method', elem_id=f"{tabname}_sampling", choices=[x.name for x in choices], value=default_sampler_name, type="index") - steps = gr.Slider(minimum=0, maximum=99, step=1, elem_id=f"{tabname}_steps", label="Sampling steps", value=20) + sampler_index = gr.Dropdown(label='Sampling method', elem_id=f"{tabname}_sampling{'_alt' if not primary else ''}", choices=[x.name for x in choices], value=default_sampler_name, type="index") + steps = gr.Slider(minimum=0, maximum=99, step=1, elem_id=f"{tabname}_steps'_alt' if not primary else ''", label="Sampling steps", value=20) return steps, sampler_index @@ -356,7 +355,7 @@ def create_ui(startup_timer = None): for category in ordered_ui_categories(): if category == "sampler": modules.sd_samplers.set_samplers() - steps, sampler_index = create_sampler_and_steps_selection(modules.sd_samplers.samplers, "txt2img") + steps, sampler_index = create_sampler_and_steps_selection(modules.sd_samplers.samplers, "txt2img", True) elif category == "dimensions": with FormRow(): with gr.Column(elem_id="txt2img_column_size", scale=4): @@ -374,7 +373,7 @@ def create_ui(startup_timer = None): cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.1, label='CFG Scale', value=6.0, elem_id="txt2img_cfg_scale") clip_skip = gr.Slider(label='CLIP skip', value=1, minimum=1, maximum=14, step=1, elem_id='txt2img_clip_skip', interactive=True) elif category == "seed": - seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox = create_seed_inputs('txt2img') + seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w = create_seed_inputs('txt2img') elif category == "checkboxes": with FormRow(elem_classes="checkboxes-row", variant="compact"): second_pass = gr.Checkbox(label='Second pass', value=False, elem_id="txt2img_enable_hr") @@ -382,7 +381,7 @@ def create_ui(startup_timer = None): tiling = gr.Checkbox(label='Tiling', value=False, elem_id="txt2img_tiling") elif category == "second_pass": with FormGroup(visible=False, elem_id="txt2img_second_pass") as hr_options: - hr_second_pass_steps, latent_index = create_sampler_and_steps_selection(modules.sd_samplers.samplers, "txt2img") + hr_second_pass_steps, latent_index = create_sampler_and_steps_selection(modules.sd_samplers.samplers, "txt2img", False) with FormRow(elem_id="txt2img_hires_fix_row1", variant="compact"): denoising_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising strength', value=0.7, elem_id="txt2img_denoising_strength") @@ -432,36 +431,20 @@ def create_ui(startup_timer = None): _js="submit", inputs=[ dummy_component, - txt2img_prompt, - txt2img_negative_prompt, + txt2img_prompt, txt2img_negative_prompt, txt2img_prompt_styles, steps, - sampler_index, - latent_index, - restore_faces, - tiling, - batch_count, - batch_size, - cfg_scale, - image_cfg_scale, + sampler_index, latent_index, + restore_faces, tiling, + batch_count, batch_size, + cfg_scale, image_cfg_scale, diffusers_guidance_rescale, clip_skip, - seed, - subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, - seed_checkbox, - height, - width, - second_pass, - denoising_strength, - hr_scale, - hr_upscaler, - hr_second_pass_steps, - hr_resize_x, - hr_resize_y, - refiner_denoise_start, - refiner_denoise_end, - refiner_prompt, - refiner_negative, + seed, subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, + height, width, + second_pass, denoising_strength, + hr_scale, hr_upscaler, hr_second_pass_steps, hr_resize_x, hr_resize_y, + refiner_denoise_start, refiner_denoise_end, refiner_prompt, refiner_negative, override_settings, ] + custom_inputs, outputs=[ @@ -624,7 +607,7 @@ def create_ui(startup_timer = None): for category in ordered_ui_categories(): if category == "sampler": modules.sd_samplers.set_samplers() - steps, sampler_index = create_sampler_and_steps_selection(modules.sd_samplers.samplers_for_img2img, "img2img") + steps, sampler_index = create_sampler_and_steps_selection(modules.sd_samplers.samplers_for_img2img, "img2img", True) elif category == "dimensions": with FormRow(): @@ -688,7 +671,7 @@ def create_ui(startup_timer = None): refiner_denoise_end = gr.Slider(minimum=0.0, maximum=1.0, step=0.05, label='Denoise end', value=1.0, elem_id="txt2img_refiner_denoise_end") elif category == "seed": - seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox = create_seed_inputs('img2img') + seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w = create_seed_inputs('img2img') elif category == "checkboxes": with FormRow(elem_classes="checkboxes-row", variant="compact"): @@ -752,10 +735,8 @@ def create_ui(startup_timer = None): fn=wrap_gradio_gpu_call(modules.img2img.img2img, extra_outputs=[None, '', '']), _js="submit_img2img", inputs=[ - dummy_component, - dummy_component, - img2img_prompt, - img2img_negative_prompt, + dummy_component, dummy_component, + img2img_prompt, img2img_negative_prompt, img2img_prompt_styles, init_img, sketch, @@ -765,35 +746,23 @@ def create_ui(startup_timer = None): init_img_inpaint, init_mask_inpaint, steps, - sampler_index, - latent_index, - mask_blur, - mask_alpha, + sampler_index, latent_index, + mask_blur, mask_alpha, inpainting_fill, - restore_faces, - tiling, - batch_count, - batch_size, - cfg_scale, - image_cfg_scale, + restore_faces, tiling, + batch_count, batch_size, + cfg_scale, image_cfg_scale, diffusers_guidance_rescale, - refiner_denoise_start, - refiner_denoise_end, + refiner_denoise_start, refiner_denoise_end, clip_skip, denoising_strength, - seed, - subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox, + seed, subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, selected_scale_tab, - height, - width, + height, width, scale_by, resize_mode, - inpaint_full_res, - inpaint_full_res_padding, - inpainting_mask_invert, - img2img_batch_input_dir, - img2img_batch_output_dir, - img2img_batch_inpaint_mask_dir, + inpaint_full_res, inpaint_full_res_padding, inpainting_mask_invert, + img2img_batch_input_dir, img2img_batch_output_dir, img2img_batch_inpaint_mask_dir, override_settings, ] + custom_inputs, outputs=[