From e29f99d041e73d27fa5d542fcdef3afd76db8af7 Mon Sep 17 00:00:00 2001 From: karajan1001 Date: Thu, 20 Aug 2020 19:57:05 +0800 Subject: [PATCH 1/4] Outputs as target supporting for `dvc status` fix #4191 1. Add a related test which would fail on current version. --- tests/func/test_status.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/func/test_status.py b/tests/func/test_status.py index 557f96719c..0398124218 100644 --- a/tests/func/test_status.py +++ b/tests/func/test_status.py @@ -118,3 +118,23 @@ def test_status_recursive(tmp_dir, dvc): } ], } + + +def test_status_outputs(tmp_dir, dvc, caplog): + dvc.run( + outs=["alice", "bob"], + cmd="echo alice>alice && echo bob>bob", + name="alice_bob", + ) + tmp_dir.gen("alice", "bob") + tmp_dir.gen("bob", "alice") + assert main(["status", "alice_bob"]) == 0 + assert "alice_bob:" in caplog.text + assert "changed outs:" in caplog.text + assert "modified: alice" in caplog.text + assert "modified: bob" in caplog.text + caplog.clear() + + assert main(["status", "alice"]) == 0 + assert "modified: alice" in caplog.text + assert "modified: bob" not in caplog.text From 6f63e66a49fac9508aaf3ca97561e9da034db539 Mon Sep 17 00:00:00 2001 From: karajan1001 Date: Mon, 24 Aug 2020 18:51:22 +0800 Subject: [PATCH 2/4] Pass the tests 1. add deps to the tests. 2. make change to pass the tests. --- dvc/repo/status.py | 25 +++++++++++++------------ dvc/stage/__init__.py | 8 ++++---- tests/func/test_status.py | 2 ++ 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/dvc/repo/status.py b/dvc/repo/status.py index d303ef35e7..1aa0c52676 100644 --- a/dvc/repo/status.py +++ b/dvc/repo/status.py @@ -10,31 +10,32 @@ logger = logging.getLogger(__name__) -def _joint_status(stages): +def _joint_status(pairs): status_info = {} - for stage in stages: + for stage, filter_info in pairs: if stage.frozen and not stage.is_repo_import: logger.warning( "{} is frozen. Its dependencies are" " not going to be shown in the status output.".format(stage) ) - - status_info.update(stage.status(check_updates=True)) + if not filter_info: + status_info.update(stage.status(check_updates=True)) + else: + for out in stage.filter_outs(filter_info): + status_info.update(out.status()) return status_info def _local_status(self, targets=None, with_deps=False, recursive=False): - if targets: - stages = cat( - self.collect(t, with_deps=with_deps, recursive=recursive) - for t in targets - ) - else: - stages = self.collect(None, with_deps=with_deps, recursive=recursive) + targets = targets or [None] + pairs = cat( + self.collect_granular(t, with_deps=with_deps, recursive=recursive) + for t in targets + ) - return _joint_status(stages) + return _joint_status(pairs) def _cloud_status( diff --git a/dvc/stage/__init__.py b/dvc/stage/__init__.py index 61f9c11914..a52a446275 100644 --- a/dvc/stage/__init__.py +++ b/dvc/stage/__init__.py @@ -442,7 +442,7 @@ def run(self, dry=False, no_commit=False, force=False, run_cache=True): if not no_commit: self.commit() - def _filter_outs(self, path_info): + def filter_outs(self, path_info): def _func(o): return path_info.isin_or_eq(o.path_info) @@ -451,7 +451,7 @@ def _func(o): @rwlocked(write=["outs"]) def checkout(self, **kwargs): stats = defaultdict(list) - for out in self._filter_outs(kwargs.get("filter_info")): + for out in self.filter_outs(kwargs.get("filter_info")): key, outs = self._checkout(out, **kwargs) if key: stats[key].extend(outs) @@ -526,14 +526,14 @@ def outs_cached(self): def get_all_files_number(self, filter_info=None): return sum( out.get_files_number(filter_info) - for out in self._filter_outs(filter_info) + for out in self.filter_outs(filter_info) ) def get_used_cache(self, *args, **kwargs): from dvc.cache import NamedCache cache = NamedCache() - for out in self._filter_outs(kwargs.get("filter_info")): + for out in self.filter_outs(kwargs.get("filter_info")): cache.update(out.get_used_cache(*args, **kwargs)) return cache diff --git a/tests/func/test_status.py b/tests/func/test_status.py index 0398124218..4ba64c15a2 100644 --- a/tests/func/test_status.py +++ b/tests/func/test_status.py @@ -121,8 +121,10 @@ def test_status_recursive(tmp_dir, dvc): def test_status_outputs(tmp_dir, dvc, caplog): + tmp_dir.dvc_gen({"foo": "foo", "bar": "bar"}) dvc.run( outs=["alice", "bob"], + deps=["foo", "bar"], cmd="echo alice>alice && echo bob>bob", name="alice_bob", ) From 1fcc1bfe2b79a3fdaf4e4693e0271752c8d1f73a Mon Sep 17 00:00:00 2001 From: karajan1001 Date: Tue, 25 Aug 2020 09:08:04 +0800 Subject: [PATCH 3/4] Update tests/func/test_status.py Co-authored-by: Saugat Pachhai --- tests/func/test_status.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/func/test_status.py b/tests/func/test_status.py index 4ba64c15a2..5125598aac 100644 --- a/tests/func/test_status.py +++ b/tests/func/test_status.py @@ -128,8 +128,7 @@ def test_status_outputs(tmp_dir, dvc, caplog): cmd="echo alice>alice && echo bob>bob", name="alice_bob", ) - tmp_dir.gen("alice", "bob") - tmp_dir.gen("bob", "alice") + tmp_dir.gen({"alice": "new alice", "bob": "new bob"}) assert main(["status", "alice_bob"]) == 0 assert "alice_bob:" in caplog.text assert "changed outs:" in caplog.text From ed07261b4fad71b4d5457b3750604606819b9c08 Mon Sep 17 00:00:00 2001 From: karajan1001 Date: Tue, 25 Aug 2020 09:40:07 +0800 Subject: [PATCH 4/4] Solve some change request. --- tests/func/test_status.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/tests/func/test_status.py b/tests/func/test_status.py index 5125598aac..f7184fe49b 100644 --- a/tests/func/test_status.py +++ b/tests/func/test_status.py @@ -120,7 +120,7 @@ def test_status_recursive(tmp_dir, dvc): } -def test_status_outputs(tmp_dir, dvc, caplog): +def test_status_outputs(tmp_dir, dvc): tmp_dir.dvc_gen({"foo": "foo", "bar": "bar"}) dvc.run( outs=["alice", "bob"], @@ -129,13 +129,11 @@ def test_status_outputs(tmp_dir, dvc, caplog): name="alice_bob", ) tmp_dir.gen({"alice": "new alice", "bob": "new bob"}) - assert main(["status", "alice_bob"]) == 0 - assert "alice_bob:" in caplog.text - assert "changed outs:" in caplog.text - assert "modified: alice" in caplog.text - assert "modified: bob" in caplog.text - caplog.clear() - - assert main(["status", "alice"]) == 0 - assert "modified: alice" in caplog.text - assert "modified: bob" not in caplog.text + + assert dvc.status(targets=["alice_bob"]) == { + "alice_bob": [ + {"changed outs": {"alice": "modified", "bob": "modified"}} + ] + } + + assert dvc.status(targets=["alice"]) == {"alice": "modified"}