[pre-commit.ci] pre-commit autoupdate (#10869)

* [pre-commit.ci] pre-commit autoupdate

updates:
- [github.com/astral-sh/ruff-pre-commit: v0.12.12 → v0.13.0](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.12...v0.13.0)

* fix ruff errors

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Saugat Pachhai (सौगात) <[email protected]>
This commit is contained in:
pre-commit-ci[bot]
2025-09-20 10:22:37 +05:45
committed by GitHub
co-authored by Saugat Pachhai
parent 336c8695da
commit 6e896d396c
42 changed files with 150 additions and 114 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ repos:
- id: sort-simple-yaml
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.12.12'
rev: 'v0.13.0'
hooks:
- id: ruff-check
args: [--fix, --exit-non-zero-on-fix]
+1
View File
@@ -64,3 +64,4 @@ def get(name: str) -> Union[DatachainDataset, DVCDataset, URLDataset]:
for file in dataset.lock.files
]
return URLDataset(type="url", files=files, path=versioned_path)
raise AssertionError("unreachable")
+1 -1
View File
@@ -16,7 +16,7 @@ class CmdCheckIgnore(CmdBase):
def _show_results(self, result: "CheckIgnoreResult"):
if not result.match and not self.args.details:
return
return None
if self.args.details:
pattern_infos = result.pattern_infos
+2 -1
View File
@@ -83,7 +83,7 @@ class CmdDatasetUpdate(CmdBase):
return CmdDatasetAdd.display(name, new, action)
if dataset == new:
ui.write("[yellow]Nothing to update[/]", styled=True)
return
return None
assert new.lock
@@ -112,6 +112,7 @@ class CmdDatasetUpdate(CmdBase):
assert new.type == "url"
stats = diff_files(dataset.lock.files, new.lock.files)
log_changes(stats)
return None
def run(self):
from difflib import get_close_matches
+1
View File
@@ -139,6 +139,7 @@ class Config(dict):
return global_config_dir()
if level == "system":
return system_config_dir()
return None
@cached_property
def files(self) -> dict[str, str]:
+1 -1
View File
@@ -84,7 +84,7 @@ class Client:
except Exception as exc:
if callable(onerror):
onerror()
logger.exception(
logger.exception( # noqa: LOG007
"Could not connect to the database. "
"Check your database credentials and try again.",
exc_info=False,
+1 -1
View File
@@ -203,7 +203,7 @@ class SingleStageFile(FileMixin):
def dump_stages(self, stages, **kwargs) -> None:
if not stages:
return
return None
assert len(stages) == 1, "SingleStageFile can only dump one stage."
return self.dump(stages[0], **kwargs)
+1 -1
View File
@@ -9,7 +9,7 @@ if TYPE_CHECKING:
from dvc.stage import Stage
class DvcException(Exception):
class DvcException(Exception): # noqa: N818
"""Base class for all dvc exceptions."""
def __init__(self, msg, *args):
+1 -1
View File
@@ -55,7 +55,7 @@ def add_logging_level(level_name, level_num, method_name=None):
setattr(logging, method_name, log_to_root)
class LoggingException(Exception):
class LoggingException(Exception): # noqa: N818
def __init__(self, record):
msg = f"failed to log {record!s}"
super().__init__(msg)
+3 -2
View File
@@ -1473,12 +1473,13 @@ class Output:
):
"""Merge version meta for files which are unchanged from other."""
if not self.hash_info:
return
return None
if self.hash_info.isdir:
return self._merge_dir_version_meta(old_hi, old_obj)
if self.hash_info != old_hi:
return
return None
self.meta = old_meta
return None
def _merge_dir_version_meta(
self, old_hi: "HashInfo", old_obj: Optional[Union["HashFile", "Tree"]]
+3 -3
View File
@@ -66,7 +66,7 @@ class ParamsLoadError(ContextError):
pass
class KeyNotInContext(ContextError, KeyError):
class KeyNotInContext(ContextError, KeyError): # noqa: N818
def __init__(self, key: str) -> None:
self.key: str = key
super().__init__(f"Could not find '{key}'")
@@ -75,7 +75,7 @@ class KeyNotInContext(ContextError, KeyError):
return self.msg
class VarsAlreadyLoaded(ContextError):
class VarsAlreadyLoaded(ContextError): # noqa: N818
pass
@@ -272,7 +272,7 @@ class CtxDict(Container, MutableMapping):
if not isinstance(key, str):
# limitation for the interpolation
# ignore other kinds of keys
return
return None
return super().__setitem__(key, value)
def merge_update(self, other, overwrite=False):
+1
View File
@@ -202,6 +202,7 @@ def validate_value(value, key):
if isinstance(value, dict) and key == "cmd":
return True
raise ParseError(f"Cannot interpolate data of type '{type(value).__name__}'")
return None
def str_interpolate(
+1 -1
View File
@@ -167,7 +167,7 @@ class VegaConverter(Converter):
if isinstance(y, list):
return "y"
if not isinstance(y, dict):
return
return None
fields = {field for _, field in _file_field(y)}
if len(fields) == 1:
+1 -1
View File
@@ -50,7 +50,7 @@ class MultipleBranchError(DvcException):
self.ref_infos = ref_infos
class AmbiguousExpRefInfo(InvalidArgumentError):
class AmbiguousExpRefInfo(InvalidArgumentError): # noqa: N818
def __init__(self, exp_name: str, exp_ref_list: Iterable["ExpRefInfo"]):
msg = [
(
+1
View File
@@ -20,6 +20,7 @@ def _make_index_onerror(onerror, rev):
def _onerror(entry, exc):
if onerror:
return onerror(rev, entry, exc)
return None
return _onerror
+1 -1
View File
@@ -75,7 +75,7 @@ def install(self: "Repo", use_pre_commit_tool: bool = False) -> None:
scm = self.scm
if not isinstance(scm, Git):
return
return None
driver = "dvc git-hook merge-driver --ancestor %O --our %A --their %B "
scm.install_merge_driver("dvc", "DVC merge driver", driver)
+3 -1
View File
@@ -58,7 +58,7 @@ class SCMContext:
def track_changed_files(self) -> None:
"""Stage files that have changed."""
if not self.files_to_track:
return
return None
logger.debug("Staging files: %s", self.files_to_track)
return self.add(self.files_to_track)
@@ -76,6 +76,7 @@ class SCMContext:
logger.debug("Added '%s' to gitignore file.", path)
self.track_file(relpath(gitignore_file))
return self.ignored_paths.append(path)
return None
def ignore_remove(self, path: str) -> None:
from scmrepo.exceptions import FileNotInRepoError
@@ -90,6 +91,7 @@ class SCMContext:
if gitignore_file:
return self.track_file(relpath(gitignore_file))
return None
@contextmanager
def __call__(
+1 -1
View File
@@ -45,7 +45,7 @@ class NoSCMError(SCMError):
super().__init__(msg)
class InvalidRemoteSCMRepo(SCMError):
class InvalidRemoteSCMRepo(SCMError): # noqa: N818
pass
+1 -1
View File
@@ -121,7 +121,7 @@ def restore_fields(stage: "Stage") -> None:
old_outs = {out.def_path: out for out in old.outs}
for out in stage.outs:
old_out = old_outs.get(out.def_path, None)
old_out = old_outs.get(out.def_path)
if old_out is not None:
out.restore_fields(old_out)
+1 -1
View File
@@ -82,7 +82,7 @@ class DataSourceChanged(DvcException):
super().__init__(f"data source changed: {path}")
class StageNotFound(DvcException, KeyError):
class StageNotFound(DvcException, KeyError): # noqa: N818
def __init__(self, file, name):
self.file = file.relpath
self.name = name
+3 -3
View File
@@ -193,7 +193,7 @@ class Console:
sep = " " if sep is None else sep
end = "\n" if end is None else end
if not self._enabled and not force:
return
return None
file = file or (sys.stderr if stderr else sys.stdout)
with Tqdm.external_write_mode(file=file):
@@ -305,7 +305,7 @@ class Console:
from dvc.ui import table as t
if not data and not markdown:
return
return None
if not markdown and rich_table:
if force or self._enabled:
@@ -319,7 +319,7 @@ class Console:
borders=borders,
)
return
return None
return t.plain_table(
self,
+1 -1
View File
@@ -120,7 +120,7 @@ class Updater:
from dvc.ui import ui
if not ui.isatty():
return
return None
message = self._get_message(latest, pkg=pkg)
return ui.error_write(message, styled=True)
+11 -3
View File
@@ -265,8 +265,16 @@ show-fixes = true
[tool.ruff.lint]
ignore = [
"N818", "S101", "A005", "PT007", "RET502", "RET503", "SIM105", "SIM108", "SIM117",
"TRY003", "TRY300", "PERF203", "PLC0415", "PLR2004", "PLW2901", "LOG007",
"PERF203", # try-except-in-loop
"PLC0415", # import-outside-top-level
"PLR2004", # magic-value-comparison
"PLW2901", # redefined-loop-name
"S101", # assert
"SIM105", # suppressible-exception
"SIM108", # if-else-block-instead-of-if-exp
"SIM117", # multiple-with-statements
"TRY003", # raise-vanilla-args
"TRY300", # try-consider-else
]
select = [
"F", "E", "W", "C90", "I", "N", "UP", "YTT", "ASYNC", "S", "BLE", "B", "A", "C4", "DTZ", "T10",
@@ -304,4 +312,4 @@ max-args = 10
"dvc/commands/**" = ["N806"]
"dvc/testing/**" = ["ARG002"]
"dvc/testing/benchmarks/**" = ["ARG001"]
"tests/**" = ["S", "ARG001", "ARG002", "TRY002", "TRY301", "PERF"]
"tests/**" = ["S", "ARG001", "ARG002", "TRY002", "TRY301", "PERF", "PLR2004"]
+3 -1
View File
@@ -1,3 +1,5 @@
import re
import pytest
from dvc import api
@@ -13,7 +15,7 @@ def test_exp_save(tmp_dir, dvc, scm):
api.exp_save("foo")
with pytest.raises(
ExperimentExistsError,
match="Experiment conflicts with existing experiment 'foo'.",
match=re.escape("Experiment conflicts with existing experiment 'foo'."),
):
api.exp_save("foo")
api.exp_save("foo", force=True)
+12 -12
View File
@@ -204,10 +204,10 @@ def test_remove_multi_rev(tmp_dir, scm, dvc, exp_stage):
@pytest.mark.parametrize(
"keep, expected_removed",
[
[["exp1"], ["exp2", "exp3"]],
[["exp1", "exp2"], ["exp3"]],
[["exp1", "exp2", "exp3"], []],
[[], []], # remove does nothing if no experiments are specified
(["exp1"], ["exp2", "exp3"]),
(["exp1", "exp2"], ["exp3"]),
(["exp1", "exp2", "exp3"], []),
([], []), # remove does nothing if no experiments are specified
],
)
def test_keep_selected_by_name(tmp_dir, scm, dvc, exp_stage, keep, expected_removed):
@@ -239,14 +239,14 @@ def test_keep_selected_by_nonexistent_name(tmp_dir, scm, dvc, exp_stage):
@pytest.mark.parametrize(
"num_exps, rev, num, expected_removed",
[
[2, "exp1", 1, ["exp2"]],
[3, "exp3", 1, ["exp1", "exp2"]],
[3, "exp3", 2, ["exp1"]],
[3, "exp3", 3, []],
[3, "exp2", 2, ["exp3"]],
[4, "exp2", 2, ["exp3", "exp4"]],
[4, "exp4", 2, ["exp1", "exp2"]],
[1, None, 1, []], # remove does nothing if no experiments are specified
(2, "exp1", 1, ["exp2"]),
(3, "exp3", 1, ["exp1", "exp2"]),
(3, "exp3", 2, ["exp1"]),
(3, "exp3", 3, []),
(3, "exp2", 2, ["exp3"]),
(4, "exp2", 2, ["exp3", "exp4"]),
(4, "exp4", 2, ["exp1", "exp2"]),
(1, None, 1, []), # remove does nothing if no experiments are specified
],
)
def test_keep_selected_by_rev(
+3 -3
View File
@@ -18,7 +18,7 @@ def test_exp_save_unchanged(tmp_dir, dvc, scm):
dvc.experiments.save()
@pytest.mark.parametrize("name", (None, "test"))
@pytest.mark.parametrize("name", [None, "test"])
def test_exp_save(tmp_dir, dvc, scm, name):
setup_stage(tmp_dir, dvc, scm)
baseline = scm.get_rev()
@@ -47,13 +47,13 @@ def test_exp_save_overwrite_experiment(tmp_dir, dvc, scm):
@pytest.mark.parametrize(
"name",
(
[
"invalid/name",
"invalid..name",
"invalid~name",
"invalid?name",
"invalidname.",
),
],
)
def test_exp_save_invalid_name(tmp_dir, dvc, scm, name):
setup_stage(tmp_dir, dvc, scm)
+2 -2
View File
@@ -7,8 +7,8 @@ from tests.func.utils.test_hydra import hydra_setup
@pytest.mark.parametrize(
"changes, expected",
[
[["foo=baz"], "foo: baz\ngoo:\n bag: 3.0\nlorem: false"],
[["params.yaml:foo=baz"], "foo: baz\ngoo:\n bag: 3.0\nlorem: false"],
(["foo=baz"], "foo: baz\ngoo:\n bag: 3.0\nlorem: false"),
(["params.yaml:foo=baz"], "foo: baz\ngoo:\n bag: 3.0\nlorem: false"),
],
)
def test_modify_params(params_repo, dvc, changes, expected):
+2 -2
View File
@@ -289,14 +289,14 @@ def test_metrics_show_overlap(tmp_dir, dvc, run_copy_metrics, clear_before_run):
@pytest.mark.parametrize(
"file,error_path,err_type",
(
[
(PROJECT_FILE, ["workspace", "error", "type"], "YAMLSyntaxError"),
(
"metrics.yaml",
["workspace", "data", "metrics.yaml", "error", "type"],
"YAMLFileCorruptedError",
),
),
],
)
def test_log_errors(
tmp_dir, scm, dvc, capsys, run_copy_metrics, file, error_path, err_type
+2 -2
View File
@@ -300,13 +300,13 @@ def test_ignore_parsing_error(tmp_dir, dvc, run_copy_metrics):
@pytest.mark.parametrize(
"file,path_kwargs",
(
[
(PROJECT_FILE, {"revision": "workspace", "endkey": "error"}),
(
"plot.yaml",
{"revision": "workspace", "file": "plot.yaml", "endkey": "error"},
),
),
],
)
def test_log_errors(tmp_dir, scm, dvc, run_copy_metrics, file, path_kwargs, capsys):
metric = [{"val": 2}, {"val": 3}]
+1 -1
View File
@@ -628,7 +628,7 @@ def test_chained_import(tmp_dir, dvc, make_tmp_dir, erepo_dir, local_cloud):
assert (dst / "bar").read_text() == "bar"
@pytest.mark.parametrize("paths", ([], ["dir"]))
@pytest.mark.parametrize("paths", [[], ["dir"]])
def test_parameterized_repo(tmp_dir, dvc, scm, erepo_dir, paths):
path = erepo_dir.joinpath(*paths)
path.mkdir(parents=True, exist_ok=True)
+1 -1
View File
@@ -38,7 +38,7 @@ def load_data(file, output_format):
return pd.read_csv(file)
@pytest.mark.parametrize("output_format", ("csv", "json"))
@pytest.mark.parametrize("output_format", ["csv", "json"])
@pytest.mark.parametrize(
"args,file_name",
[
+2 -1
View File
@@ -1,4 +1,5 @@
import os
import re
import pytest
@@ -37,7 +38,7 @@ def test_remove_file_target(tmp_dir, dvc):
with pytest.raises(
StageFileIsNotDvcFileError,
match="'foo' is not a .dvc file. Do you mean 'foo.dvc'?",
match=re.escape("'foo' is not a .dvc file. Do you mean 'foo.dvc'?"),
):
dvc.remove("foo")
+5 -2
View File
@@ -1,4 +1,5 @@
import os
import re
import pytest
@@ -228,7 +229,7 @@ def test_parent_repo_collect_stages(tmp_dir, scm, dvc):
assert deep_subrepo_stages != []
@pytest.mark.parametrize("with_deps", (False, True))
@pytest.mark.parametrize("with_deps", [False, True])
def test_collect_symlink(tmp_dir, dvc, with_deps):
from dvc.exceptions import StageNotFoundError
@@ -339,6 +340,8 @@ def test_stage_add_duplicated_output(tmp_dir, dvc):
with pytest.raises(
OutputDuplicationError,
match="Use `dvc remove foo.dvc` to stop tracking the overlapping output.",
match=re.escape(
"Use `dvc remove foo.dvc` to stop tracking the overlapping output."
),
):
dvc.stage.add(name="duplicated", cmd="echo bar > foo", outs=["foo"])
+2 -2
View File
@@ -156,7 +156,7 @@ def test_update_unchanged(tmp_dir, dvc, erepo_dir, mocker):
assert not spy.called
@pytest.mark.parametrize("outs_exist", (False, True))
@pytest.mark.parametrize("outs_exist", [False, True])
def test_update_no_download(tmp_dir, dvc, erepo_dir, outs_exist, mocker):
with erepo_dir.chdir():
erepo_dir.dvc_gen("file", "file content", commit="add file")
@@ -204,7 +204,7 @@ def test_update_import_url(tmp_dir, dvc, workspace):
assert dst.read_text() == "updated file content"
@pytest.mark.parametrize("outs_exist", (False, True))
@pytest.mark.parametrize("outs_exist", [False, True])
def test_update_import_url_no_download(tmp_dir, dvc, workspace, outs_exist, mocker):
workspace.gen("file", "file content")
+4 -1
View File
@@ -1,3 +1,4 @@
import re
from contextlib import nullcontext as does_not_raise
import pytest
@@ -214,7 +215,9 @@ def hydra_setup_dir_basic(tmp_dir, config_subdir, config_name, config_content):
None,
pytest.raises(
ValueError,
match="Either `config_dir` or `config_module` should be provided.",
match=re.escape(
"Either `config_dir` or `config_module` should be provided."
),
),
),
],
+4 -4
View File
@@ -206,20 +206,20 @@ def test_diff_show_markdown_and_hash(mocker, show_hash, dvc):
@pytest.mark.parametrize(
"opts",
(
[
[],
["a_rev", "b_rev"],
["--targets", "."],
["--hide-missing"],
),
],
)
@pytest.mark.parametrize(
"show, expected",
(
[
([], ""),
(["--json"], "{}"),
(["--md"], "| Status | Path |\n|----------|--------|"),
),
],
)
def test_no_changes(mocker, capsys, opts, show, expected, dvc):
args = parse_args(["diff", *opts, *show])
+3 -3
View File
@@ -260,7 +260,7 @@ def test_should_pass_template_dir(tmp_dir, dvc, mocker, capsys):
)
@pytest.mark.parametrize("output", ("some_out", os.path.join("to", "subdir"), None))
@pytest.mark.parametrize("output", ["some_out", os.path.join("to", "subdir"), None])
def test_should_call_render(tmp_dir, mocker, capsys, plots_data, output):
cli_args = parse_args(["plots", "diff", "--targets", "plots.csv", "--out", output])
cmd = cli_args.func(cli_args)
@@ -322,7 +322,7 @@ def test_plots_diff_json(dvc, mocker, capsys):
@pytest.mark.parametrize(
"target,expected_out,expected_rtn",
(("t1", "\"{'t1'}\"", 0), (None, "t1\nt2", 0), ("t3", "", 1)),
[("t1", "\"{'t1'}\"", 0), (None, "t1\nt2", 0), ("t3", "", 1)],
)
def test_plots_templates(dvc, mocker, capsys, target, expected_out, expected_rtn):
t1 = mocker.Mock()
@@ -352,7 +352,7 @@ def test_plots_templates(dvc, mocker, capsys, target, expected_out, expected_rtn
assert rtn == expected_rtn
@pytest.mark.parametrize("split", (True, False))
@pytest.mark.parametrize("split", [True, False])
def test_show_json(split, mocker, capsys):
import dvc.commands.plots
+1 -1
View File
@@ -77,7 +77,7 @@ def test_scm_context_autostage_changed_files(scm_context):
def test_scm_context_clears_ignores_on_error(scm_context):
class CustomException(Exception):
class CustomException(Exception): # noqa: N818
pass
with pytest.raises(CustomException), scm_context(): # noqa: PT012
+8 -2
View File
@@ -1,3 +1,5 @@
import re
import pytest
from dvc import api
@@ -7,13 +9,17 @@ def test_open_raises_error_if_no_context(tmp_dir, dvc):
tmp_dir.dvc_gen("foo", "foo-text")
fd = api.open("foo")
with pytest.raises(AttributeError, match="should be used in a with statement."):
with pytest.raises(
AttributeError, match=re.escape("should be used in a with statement.")
):
fd.read()
def test_open_rev_raises_error_on_wrong_mode(tmp_dir, dvc):
tmp_dir.dvc_gen("foo", "foo-text")
with pytest.raises(ValueError, match="Only reading `mode` is supported."):
with pytest.raises(
ValueError, match=re.escape("Only reading `mode` is supported.")
):
with api.open("foo", mode="w"):
pass
+4 -2
View File
@@ -1,3 +1,5 @@
import re
import pytest
from dvc.compare import TabularData
@@ -365,12 +367,12 @@ def test_drop_duplicates_subset(axis, subset, expected):
def test_dropna_invalid_axis():
td = TabularData(["col-1", "col-2", "col-3"])
with pytest.raises(ValueError, match="Invalid 'axis' value foo."):
with pytest.raises(ValueError, match=re.escape("Invalid 'axis' value foo.")):
td.dropna("foo")
def test_drop_duplicates_invalid_axis():
td = TabularData(["col-1", "col-2", "col-3"])
with pytest.raises(ValueError, match="Invalid 'axis' value foo."):
with pytest.raises(ValueError, match=re.escape("Invalid 'axis' value foo.")):
td.drop_duplicates("foo")
+14 -14
View File
@@ -86,32 +86,32 @@ def test_to_omegaconf():
@pytest.mark.parametrize(
"changes, expected",
[
[{"foo": "baz"}, {"foo": "baz", "goo": {"bag": 3}, "lorem": False}],
[
({"foo": "baz"}, {"foo": "baz", "goo": {"bag": 3}, "lorem": False}),
(
{"foo": "baz", "goo": "bar"},
{"foo": "baz", "goo": "bar", "lorem": False},
],
[
),
(
{"goo": {"bag": 4}},
{"foo": {"bar": 1, "baz": 2}, "goo": {"bag": 4}, "lorem": False},
],
[
),
(
{"foo": {"bar": 1, "baz": 2, 0: "bar"}},
{
"foo": {"bar": 1, "baz": 2, 0: "bar"},
"goo": {"bag": 3},
"lorem": False,
},
],
[
),
(
{"lorem": {"ipsum": 3}},
{
"foo": {"bar": 1, "baz": 2},
"goo": {"bag": 3},
"lorem": {"ipsum": 3},
},
],
[{}, {"foo": {"bar": 1, "baz": 2}, "goo": {"bag": 3}, "lorem": False}],
),
({}, {"foo": {"bar": 1, "baz": 2}, "goo": {"bag": 3}, "lorem": False}),
],
)
def test_merge_dicts(changes, expected):
@@ -125,12 +125,12 @@ def test_merge_dicts(changes, expected):
@pytest.mark.parametrize(
"changes, expected",
[
[{"foo": "baz"}, {"foo": {"baz": 2}}],
[
({"foo": "baz"}, {"foo": {"baz": 2}}),
(
{"foo": "baz", "goo": "bag"},
{"foo": {"baz": 2}, "goo": {"bag": 3}},
],
[{}, {}],
),
({}, {}),
],
)
def test_remove_missing_keys(changes, expected):
+35 -32
View File
@@ -1,4 +1,5 @@
import os
import re
import pytest
@@ -52,19 +53,19 @@ def test_relpath_windows():
@pytest.mark.parametrize(
"inp,out,is_dir,expected",
[
["target", None, False, "target"],
["target", "dir", True, os.path.join("dir", "target")],
["target", "file_target", False, "file_target"],
[
("target", None, False, "target"),
("target", "dir", True, os.path.join("dir", "target")),
("target", "file_target", False, "file_target"),
(
"target",
os.path.join("dir", "subdir"),
True,
os.path.join("dir", "subdir", "target"),
],
["dir/", None, False, "dir"],
["dir", None, False, "dir"],
["dir", "other_dir", False, "other_dir"],
["dir", "other_dir", True, os.path.join("other_dir", "dir")],
),
("dir/", None, False, "dir"),
("dir", None, False, "dir"),
("dir", "other_dir", False, "other_dir"),
("dir", "other_dir", True, os.path.join("other_dir", "dir")),
],
)
def test_resolve_output(inp, out, is_dir, expected, mocker):
@@ -76,40 +77,40 @@ def test_resolve_output(inp, out, is_dir, expected, mocker):
@pytest.mark.parametrize(
"inp,out, default",
[
["dvc.yaml", ("dvc.yaml", None), None],
["dvc.yaml:name", ("dvc.yaml", "name"), None],
[":name", ("dvc.yaml", "name"), None],
["stage.dvc", ("stage.dvc", None), None],
["../models/stage.dvc", ("../models/stage.dvc", None), "def"],
[":name", ("default", "name"), "default"],
["something.dvc:name", ("something.dvc", "name"), None],
["../something.dvc:name", ("../something.dvc", "name"), None],
["file", (None, "file"), None],
["build@15", (None, "build@15"), None],
["build@{'level': 35}", (None, "build@{'level': 35}"), None],
[":build@15", ("dvc.yaml", "build@15"), None],
[":build@{'level': 35}", ("dvc.yaml", "build@{'level': 35}"), None],
["dvc.yaml:build@15", ("dvc.yaml", "build@15"), None],
[
("dvc.yaml", ("dvc.yaml", None), None),
("dvc.yaml:name", ("dvc.yaml", "name"), None),
(":name", ("dvc.yaml", "name"), None),
("stage.dvc", ("stage.dvc", None), None),
("../models/stage.dvc", ("../models/stage.dvc", None), "def"),
(":name", ("default", "name"), "default"),
("something.dvc:name", ("something.dvc", "name"), None),
("../something.dvc:name", ("../something.dvc", "name"), None),
("file", (None, "file"), None),
("build@15", (None, "build@15"), None),
("build@{'level': 35}", (None, "build@{'level': 35}"), None),
(":build@15", ("dvc.yaml", "build@15"), None),
(":build@{'level': 35}", ("dvc.yaml", "build@{'level': 35}"), None),
("dvc.yaml:build@15", ("dvc.yaml", "build@15"), None),
(
"dvc.yaml:build@{'level': 35}",
("dvc.yaml", "build@{'level': 35}"),
None,
],
[
),
(
"build2@{'level': [1, 2, 3]}",
(None, "build2@{'level': [1, 2, 3]}"),
None,
],
[
),
(
":build2@{'level': [1, 2, 3]}",
("dvc.yaml", "build2@{'level': [1, 2, 3]}"),
None,
],
[
),
(
"dvc.yaml:build2@{'level': [1, 2, 3]}",
("dvc.yaml", "build2@{'level': [1, 2, 3]}"),
None,
],
),
],
)
def test_parse_target(inp, out, default):
@@ -117,7 +118,9 @@ def test_parse_target(inp, out, default):
def test_hint_on_lockfile():
with pytest.raises(Exception, match="Did you mean: `dvc.yaml:name`?") as e:
with pytest.raises(
Exception, match=re.escape("Did you mean: `dvc.yaml:name`?")
) as e:
assert parse_target("dvc.lock:name")
assert "dvc.yaml:name" in str(e.value)