119 lines
4.3 KiB
Python
119 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
import shutil
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from imagepipeline.core.pipeline import Pipeline
|
|
from imagepipeline.core.resume import materialize_external_outputs, step_outputs_complete
|
|
from imagepipeline.core.step import StepDefinition
|
|
from imagepipeline.modules.imagemagick_grayscale import ImageMagickGrayscale
|
|
from imagepipeline.modules.registry import get_module
|
|
from imagepipeline.utils.gmic import split_gmic_command
|
|
from tests.conftest import make_png
|
|
|
|
|
|
class TestGmicCommandSplit:
|
|
def test_splits_command_and_arguments(self) -> None:
|
|
assert split_gmic_command("-gcd_stereo_img 0,0,2.028,1,1.714,3.06,4,1,0") == [
|
|
"-gcd_stereo_img",
|
|
"0,0,2.028,1,1.714,3.06,4,1,0",
|
|
]
|
|
|
|
def test_preserves_quoted_empty_argument(self) -> None:
|
|
parts = split_gmic_command('-fx_custom_gradient 0,0,0,"",1,0')
|
|
assert parts == ["-fx_custom_gradient", "0,0,0,,1,0"]
|
|
|
|
|
|
class TestPipelineResume:
|
|
@pytest.mark.skipif(not shutil.which("magick"), reason="ImageMagick not installed")
|
|
def test_continue_skips_completed_steps(self, input_dir: Path, output_base: Path, capsys) -> None:
|
|
with Pipeline(
|
|
name="resume_test",
|
|
input_dir=input_dir,
|
|
output_base=output_base,
|
|
verbose=True,
|
|
) as p:
|
|
first = p.step("imagemagick_grayscale", inputs="input")
|
|
p.step("imagemagick_grayscale", inputs=first)
|
|
root = p.run()
|
|
|
|
capsys.readouterr()
|
|
|
|
with Pipeline(
|
|
name="resume_test",
|
|
input_dir=input_dir,
|
|
output_base=output_base,
|
|
verbose=True,
|
|
continue_from=root,
|
|
) as p:
|
|
step_a = p.step("imagemagick_grayscale", inputs="input")
|
|
p.step("imagemagick_grayscale", inputs=step_a)
|
|
resumed_root = p.run()
|
|
|
|
assert resumed_root == root
|
|
output = capsys.readouterr().out
|
|
assert "Skipped step imagemagick_grayscale_01" in output
|
|
assert "Skipped step imagemagick_grayscale_02" in output
|
|
|
|
@pytest.mark.skipif(not shutil.which("magick"), reason="ImageMagick not installed")
|
|
def test_existing_outputs_reuse_external_folder(
|
|
self, input_dir: Path, output_base: Path, tmp_path: Path, capsys
|
|
) -> None:
|
|
external = tmp_path / "external_rembg"
|
|
external.mkdir()
|
|
for src in input_dir.iterdir():
|
|
if src.is_file():
|
|
make_png(external / src.name, width=4, height=4, rgb=(10, 20, 30))
|
|
|
|
with Pipeline(
|
|
name="external_test",
|
|
input_dir=input_dir,
|
|
output_base=output_base,
|
|
verbose=True,
|
|
existing_outputs={"imagemagick_grayscale_01": external},
|
|
) as p:
|
|
reused = p.step("imagemagick_grayscale", inputs="input")
|
|
p.step("imagemagick_grayscale", inputs=reused)
|
|
root = p.run()
|
|
|
|
output = capsys.readouterr().out
|
|
assert "Reused external output for imagemagick_grayscale_01" in output
|
|
assert (root / "imagemagick_grayscale_01" / "photo_a.png").exists()
|
|
|
|
|
|
class TestMaterializeExternal:
|
|
def test_links_files_by_stem(self, tmp_path: Path) -> None:
|
|
external = tmp_path / "external"
|
|
external.mkdir()
|
|
make_png(external / "photo_a.png")
|
|
output_dir = tmp_path / "out"
|
|
step = StepDefinition(
|
|
step_id="imagemagick_grayscale_01",
|
|
module_name="imagemagick_grayscale",
|
|
module=ImageMagickGrayscale,
|
|
input_refs=["input"],
|
|
params={},
|
|
output_dir_name="imagemagick_grayscale_01",
|
|
)
|
|
input_paths = [tmp_path / "photo_a.png"]
|
|
paths = materialize_external_outputs(
|
|
external,
|
|
output_dir,
|
|
step,
|
|
matched_groups=[[path] for path in input_paths],
|
|
input_paths=input_paths,
|
|
params={},
|
|
)
|
|
assert len(paths) == 1
|
|
assert paths[0].name == "photo_a.png"
|
|
assert paths[0].is_symlink()
|
|
|
|
def test_step_outputs_complete(self, tmp_path: Path) -> None:
|
|
output_dir = tmp_path / "done"
|
|
output_dir.mkdir()
|
|
make_png(output_dir / "photo.png")
|
|
assert step_outputs_complete([output_dir / "photo.png"])
|
|
assert not step_outputs_complete([output_dir / "missing.png"])
|