diff --git a/tests/conftest.py b/tests/conftest.py index 32fce7861..57bff6b00 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,6 +5,7 @@ import pytest from .dir_helpers import * # noqa, pylint: disable=wildcard-import from .remotes import * # noqa, pylint: disable=wildcard-import +from .utils.scriptify import scriptify # Prevent updater and analytics from running their processes os.environ["DVC_TEST"] = "true" @@ -164,3 +165,6 @@ def custom_template(tmp_dir, dvc): template = tmp_dir / "custom_template.json" shutil.copy(tmp_dir / ".dvc" / "plots" / "default.json", template) return template + + +scriptify_fixture = pytest.fixture(lambda: scriptify, name="scriptify") diff --git a/tests/func/test_repro_multistage.py b/tests/func/test_repro_multistage.py index c700115e7..8fab70eda 100644 --- a/tests/func/test_repro_multistage.py +++ b/tests/func/test_repro_multistage.py @@ -10,15 +10,16 @@ from dvc.exceptions import CyclicGraphError, ReproductionError from dvc.main import main from dvc.stage import PipelineStage from tests.func import test_repro +from tests.utils.scriptify import scriptify -COPY_SCRIPT_FORMAT = dedent( - """\ - import sys + +def copy_script(src, dest): import shutil - shutil.copyfile({}, {}) -""" -) -COPY_SCRIPT = COPY_SCRIPT_FORMAT.format("sys.argv[1]", "sys.argv[2]") + + shutil.copyfile(src, dest) + + +COPY_SCRIPT, _ = scriptify(copy_script) class MultiStageRun: @@ -357,7 +358,10 @@ def test_repro_when_new_deps_is_moved(tmp_dir, dvc): target = ":copy-file" assert not dvc.reproduce(target) - tmp_dir.gen("copy.py", COPY_SCRIPT_FORMAT.format("'bar'", "'foobar'")) + # hardcode values in source code, ignore sys.argv + tmp_dir.gen( + "copy.py", COPY_SCRIPT.replace("func(*argv)", 'func("bar", "foobar")') + ) from shutil import move move("foo", "bar") diff --git a/tests/utils/scriptify.py b/tests/utils/scriptify.py new file mode 100644 index 000000000..ee2d73f1d --- /dev/null +++ b/tests/utils/scriptify.py @@ -0,0 +1,36 @@ +import inspect +import sys +import textwrap +from pathlib import Path + +SCRIPT_TEMPLATE = """\ +#! {executable} +# AUTOGENERATED USING SCRIPTIFY FOR USE IN TESTS FOR DVC + + +{code} + + +if __name__ == "__main__": + import sys + + _, *argv = sys.argv + func = {func!s} + func(*argv) +""" + + +def scriptify(func, path=None): + # you can use `breakpoint()` inside functions too + # just remember to run the test in `-s` mode. + code = textwrap.dedent(inspect.getsource(func)) + executable = sys.executable + source = SCRIPT_TEMPLATE.format( + executable=executable, code=code, func=func.__name__ + ) + + if not path: + return source, None + + Path(path).write_text(source, encoding="utf-8") + return source, f"{executable} {path}"