dvc: rename dvc lock -> dvc freeze (#3915)

Fixes #3901
This commit is contained in:
Ruslan Kuprieiev
2020-05-31 03:38:21 +03:00
committed by GitHub
parent 516d82e411
commit 0bb49d2549
23 changed files with 156 additions and 145 deletions
+2 -2
View File
@@ -13,6 +13,7 @@ from .command import (
data_sync,
destroy,
diff,
freeze,
gc,
get,
get_url,
@@ -21,7 +22,6 @@ from .command import (
imp_url,
init,
install,
lock,
ls,
metrics,
move,
@@ -66,7 +66,7 @@ COMMANDS = [
install,
root,
ls,
lock,
freeze,
pipeline,
daemon,
commit,
+57
View File
@@ -0,0 +1,57 @@
import argparse
import logging
from dvc.command.base import CmdBase, append_doc_link
from dvc.exceptions import DvcException
logger = logging.getLogger(__name__)
class CmdFreezeBase(CmdBase):
def _run(self, func, name):
ret = 0
for target in self.args.targets:
try:
func(target)
except DvcException:
logger.exception(f"failed to {name} '{target}'")
ret = 1
return ret
class CmdFreeze(CmdFreezeBase):
def run(self):
return self._run(self.repo.freeze, "freeze")
class CmdUnfreeze(CmdFreezeBase):
def run(self):
return self._run(self.repo.unfreeze, "unfreeze")
def add_parser(subparsers, parent_parser):
FREEZE_HELP = "Freeze DVC-files."
freeze_parser = subparsers.add_parser(
"freeze",
parents=[parent_parser],
description=append_doc_link(FREEZE_HELP, "freeze"),
help=FREEZE_HELP,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
freeze_parser.add_argument(
"targets", nargs="+", help="DVC-files to freeze."
)
freeze_parser.set_defaults(func=CmdFreeze)
UNFREEZE_HELP = "Unfreeze DVC-files."
unfreeze_parser = subparsers.add_parser(
"unfreeze",
parents=[parent_parser],
description=append_doc_link(UNFREEZE_HELP, "unfreeze"),
help=UNFREEZE_HELP,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
unfreeze_parser.add_argument(
"targets", nargs="+", help="DVC-files to unfreeze."
)
unfreeze_parser.set_defaults(func=CmdUnfreeze)
-59
View File
@@ -1,59 +0,0 @@
import argparse
import logging
from dvc.command.base import CmdBase, append_doc_link
from dvc.exceptions import DvcException
logger = logging.getLogger(__name__)
class CmdLockBase(CmdBase):
def _run(self, unlock):
for target in self.args.targets:
try:
self.repo.lock_stage(target, unlock=unlock)
except DvcException:
logger.exception(
"failed to {}lock '{}'".format(
"un" if unlock else "", target
)
)
return 1
return 0
class CmdLock(CmdLockBase):
def run(self):
return self._run(False)
class CmdUnlock(CmdLockBase):
def run(self):
return self._run(True)
def add_parser(subparsers, parent_parser):
LOCK_HELP = "Lock DVC-files."
lock_parser = subparsers.add_parser(
"lock",
parents=[parent_parser],
description=append_doc_link(LOCK_HELP, "lock"),
help=LOCK_HELP,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
lock_parser.add_argument("targets", nargs="+", help="DVC-files to lock.")
lock_parser.set_defaults(func=CmdLock)
UNLOCK_HELP = "Unlock DVC-files."
unlock_parser = subparsers.add_parser(
"unlock",
parents=[parent_parser],
description=append_doc_link(UNLOCK_HELP, "unlock"),
help=UNLOCK_HELP,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
unlock_parser.add_argument(
"targets", nargs="+", help="DVC-files to unlock."
)
unlock_parser.set_defaults(func=CmdUnlock)
+1 -1
View File
@@ -17,7 +17,7 @@ class CmdPipelineShow(CmdBase):
G = self.repo.graph
stages = networkx.dfs_postorder_nodes(G, stage)
if locked:
stages = [s for s in stages if s.locked]
stages = [s for s in stages if s.frozen]
for stage in stages:
if commands:
+1 -1
View File
@@ -48,7 +48,7 @@ class Repo:
from dvc.repo.add import add
from dvc.repo.remove import remove
from dvc.repo.ls import ls
from dvc.repo.lock import lock as lock_stage
from dvc.repo.freeze import freeze, unfreeze
from dvc.repo.move import move
from dvc.repo.run import run
from dvc.repo.imp import imp
+21
View File
@@ -0,0 +1,21 @@
from . import locked
@locked
def _set(repo, target, frozen):
from dvc.utils import parse_target
path, name = parse_target(target)
stage = repo.get_stage(path, name)
stage.frozen = frozen
stage.dvcfile.dump(stage, update_pipeline=True)
return stage
def freeze(repo, target):
return _set(repo, target, True)
def unfreeze(repo, target):
return _set(repo, target, False)
+1 -1
View File
@@ -3,4 +3,4 @@ def imp(self, url, path, out=None, rev=None):
if rev is not None:
erepo["rev"] = rev
return self.imp_url(path, out=out, erepo=erepo, locked=True)
return self.imp_url(path, out=out, erepo=erepo, frozen=True)
+4 -4
View File
@@ -5,12 +5,12 @@ from dvc.utils import relpath, resolve_output, resolve_paths
from dvc.utils.fs import path_isin
from ..exceptions import OutputDuplicationError
from . import locked as locked_repo
from . import locked
@locked_repo
@locked
@scm_context
def imp_url(self, url, out=None, fname=None, erepo=None, locked=True):
def imp_url(self, url, out=None, fname=None, erepo=None, frozen=True):
from dvc.dvcfile import Dvcfile
from dvc.stage import Stage, create_stage
@@ -48,7 +48,7 @@ def imp_url(self, url, out=None, fname=None, erepo=None, locked=True):
stage.run()
stage.locked = locked
stage.frozen = frozen
dvcfile.dump(stage)
-13
View File
@@ -1,13 +0,0 @@
from . import locked
@locked
def lock(self, target, unlock=False):
from dvc.utils import parse_target
path, name = parse_target(target)
stage = self.get_stage(path, name)
stage.locked = False if unlock else True
stage.dvcfile.dump(stage, update_pipeline=True)
return stage
+3 -3
View File
@@ -10,9 +10,9 @@ logger = logging.getLogger(__name__)
def _reproduce_stage(stage, **kwargs):
if stage.locked and not stage.is_import:
if stage.frozen and not stage.is_import:
logger.warning(
"{} is locked. Its dependencies are"
"{} is frozen. Its dependencies are"
" not going to be reproduced.".format(stage)
)
@@ -34,7 +34,7 @@ def _get_active_graph(G):
active = G.copy()
for stage in G:
if not stage.locked:
if not stage.frozen:
continue
active.remove_edges_from(G.out_edges(stage))
for edge in G.out_edges(stage):
+2 -2
View File
@@ -14,9 +14,9 @@ def _joint_status(stages):
status = {}
for stage in stages:
if stage.locked and not stage.is_repo_import:
if stage.frozen and not stage.is_repo_import:
logger.warning(
"{} is locked. Its dependencies are"
"{} is frozen. Its dependencies are"
" not going to be shown in the status output.".format(stage)
)
+3 -2
View File
@@ -11,7 +11,8 @@ SINGLE_STAGE_SCHEMA = {
StageParams.PARAM_WDIR: Any(str, None),
StageParams.PARAM_DEPS: Any([dependency.SCHEMA], None),
StageParams.PARAM_OUTS: Any([output.SCHEMA], None),
StageParams.PARAM_LOCKED: bool,
StageParams.PARAM_LOCKED: bool, # backard compatibility
StageParams.PARAM_FROZEN: bool,
StageParams.PARAM_META: object,
StageParams.PARAM_ALWAYS_CHANGED: bool,
}
@@ -54,7 +55,7 @@ SINGLE_PIPELINE_STAGE_SCHEMA = {
Optional(StageParams.PARAM_PARAMS): [
Any(str, PARAM_PSTAGE_NON_DEFAULT_SCHEMA)
],
Optional(StageParams.PARAM_LOCKED): bool,
Optional(StageParams.PARAM_FROZEN): bool,
Optional(StageParams.PARAM_META): object,
Optional(StageParams.PARAM_ALWAYS_CHANGED): bool,
Optional(StageParams.PARAM_OUTS): [
+1 -1
View File
@@ -115,7 +115,7 @@ def to_pipeline_file(stage: "PipelineStage"):
stage.PARAM_PLOTS,
_get_outs([out for out in stage.outs if out.plot]),
),
(stage.PARAM_LOCKED, stage.locked),
(stage.PARAM_FROZEN, stage.frozen),
(stage.PARAM_ALWAYS_CHANGED, stage.always_changed),
]
return {
+10 -8
View File
@@ -42,6 +42,7 @@ def loads_from(cls, repo, path, wdir, data):
[
Stage.PARAM_CMD,
Stage.PARAM_LOCKED,
Stage.PARAM_FROZEN,
Stage.PARAM_ALWAYS_CHANGED,
Stage.PARAM_MD5,
"name",
@@ -93,7 +94,8 @@ class Stage(params.StageParams):
deps=None,
outs=None,
md5=None,
locked=False,
locked=False, # backward compatibility
frozen=False,
always_changed=False,
stage_text=None,
dvcfile=None,
@@ -110,7 +112,7 @@ class Stage(params.StageParams):
self.outs = outs
self.deps = deps
self.md5 = md5
self.locked = locked
self.frozen = locked or frozen
self.always_changed = always_changed
self._stage_text = stage_text
self._dvcfile = dvcfile
@@ -201,7 +203,7 @@ class Stage(params.StageParams):
return isinstance(self.deps[0], dependency.RepoDependency)
def changed_deps(self):
if self.locked:
if self.frozen:
return False
if self.is_callback:
@@ -401,16 +403,16 @@ class Stage(params.StageParams):
@rwlocked(read=["deps"], write=["outs"])
def run(self, dry=False, no_commit=False, force=False, run_cache=True):
if (self.cmd or self.is_import) and not self.locked and not dry:
if (self.cmd or self.is_import) and not self.frozen and not dry:
self.remove_outs(ignore_remove=False, force=False)
if not self.locked and self.is_import:
if not self.frozen and self.is_import:
sync_import(self, dry, force)
elif not self.locked and self.cmd:
elif not self.frozen and self.cmd:
run_stage(self, dry, force, run_cache)
else:
args = (
("outputs", "locked ") if self.locked else ("data sources", "")
("outputs", "frozen ") if self.frozen else ("data sources", "")
)
logger.info("Verifying %s in %s%s", *args, self)
if not dry:
@@ -452,7 +454,7 @@ class Stage(params.StageParams):
ret = []
show_import = self.is_repo_import and check_updates
if not self.locked or show_import:
if not self.frozen or show_import:
self._status_deps(ret)
self._status_outs(ret)
self._status_always_changed(ret)
+3 -3
View File
@@ -5,12 +5,12 @@ logger = logging.getLogger(__name__)
def update_import(stage, rev=None):
stage.deps[0].update(rev=rev)
locked = stage.locked
stage.locked = False
frozen = stage.frozen
stage.frozen = False
try:
stage.reproduce()
finally:
stage.locked = locked
stage.frozen = frozen
def sync_import(stage, dry=False, force=False):
+2 -1
View File
@@ -4,7 +4,8 @@ class StageParams:
PARAM_WDIR = "wdir"
PARAM_DEPS = "deps"
PARAM_OUTS = "outs"
PARAM_LOCKED = "locked"
PARAM_LOCKED = "locked" # backward compatibility
PARAM_FROZEN = "frozen"
PARAM_META = "meta"
PARAM_ALWAYS_CHANGED = "always_changed"
PARAM_PARAMS = "params"
+3 -2
View File
@@ -136,7 +136,8 @@ def compute_md5(stage):
return dict_md5(
d,
exclude=[
stage.PARAM_LOCKED,
stage.PARAM_LOCKED, # backward compatibility
stage.PARAM_FROZEN,
BaseOutput.PARAM_METRIC,
BaseOutput.PARAM_PERSIST,
],
@@ -155,7 +156,7 @@ def get_dump(stage):
stage.PARAM_MD5: stage.md5,
stage.PARAM_CMD: stage.cmd,
stage.PARAM_WDIR: resolve_wdir(stage.wdir, stage.path),
stage.PARAM_LOCKED: stage.locked,
stage.PARAM_FROZEN: stage.frozen,
stage.PARAM_DEPS: [d.dumpd() for d in stage.deps],
stage.PARAM_OUTS: [o.dumpd() for o in stage.outs],
stage.PARAM_ALWAYS_CHANGED: stage.always_changed,
+6 -6
View File
@@ -4,9 +4,9 @@
# - https://opensource.com/article/18/3/creating-bash-completion-script
# - https://stackoverflow.com/questions/12933362
_dvc_commands='add cache checkout commit config destroy diff fetch get-url get gc \
import-url import init install lock list metrics move params pipeline plots pull push \
remote remove repro root run status unlock unprotect update version'
_dvc_commands='add cache checkout commit config destroy diff fetch freeze get-url get gc \
import-url import init install list metrics move params pipeline plots pull push \
remote remove repro root run status unfreeze unprotect update version'
_dvc_options='-h --help -V --version'
_dvc_global_options='-h --help -q --quiet -v --verbose'
@@ -33,8 +33,8 @@ _dvc_init='--no-scm -f --force'
_dvc_install=''
_dvc_list='-R --recursive --dvc-only --rev'
_dvc_list_COMPGEN=_dvc_compgen_files
_dvc_lock=''
_dvc_lock_COMPGEN=_dvc_compgen_DVCFiles
_dvc_freeze=''
_dvc_freeze_COMPGEN=_dvc_compgen_DVCFiles
_dvc_metrics='add diff modify remove show'
_dvc_metrics_add='-t --type -x --xpath'
_dvc_metrics_add_COMPGEN=_dvc_compgen_files
@@ -76,7 +76,7 @@ _dvc_run='--no-exec -f --file -d --deps -o --outs -O --outs-no-cache --outs-pers
_dvc_run_COMPGEN=_dvc_compgen_DVCFiles
_dvc_status='-j --jobs -r --remote -a --all-branches -T --all-tags -d --with-deps -c --cloud'
_dvc_status_COMPGEN=_dvc_compgen_DVCFiles
_dvc_unlock_COMPGEN=_dvc_compgen_DVCFiles
_dvc_unfreeze_COMPGEN=_dvc_compgen_DVCFiles
_dvc_unprotect_COMPGEN=_dvc_compgen_files
_dvc_update='--rev'
_dvc_update_COMPGEN=_dvc_compgen_DVCFiles
+4 -4
View File
@@ -163,7 +163,7 @@ _dvc_init=(
_dvc_install=()
_dvc_lock=(
_dvc_freeze=(
"*:Stages:_files -g '(*.dvc|Dvcfile)'"
)
@@ -278,7 +278,7 @@ _dvc_status=(
"*:Stages:_files -g '(*.dvc|Dvcfile)'"
)
_dvc_unlock=(
_dvc_unfreeze=(
"*:Stages:_files -g '(*.dvc|Dvcfile)'"
)
@@ -308,6 +308,7 @@ case $words[1] in
destroy) _arguments $_dvc_global_options $_dvc_destroy ;;
diff) _arguments $_dvc_global_options $_dvc_diff ;;
fetch) _arguments $_dvc_global_options $_dvc_fetch ;;
freeze) _arguments $_dvc_global_options $_dvc_freeze ;;
get-url) _arguments $_dvc_global_options $_dvc_geturl ;;
get) _arguments $_dvc_global_options $_dvc_get ;;
gc) _arguments $_dvc_global_options $_dvc_gc ;;
@@ -315,7 +316,6 @@ case $words[1] in
import) _arguments $_dvc_global_options $_dvc_import ;;
init) _arguments $_dvc_global_options $_dvc_init ;;
install) _arguments $_dvc_global_options $_dvc_install ;;
lock) _arguments $_dvc_global_options $_dvc_lock ;;
list) _arguments $_dvc_global_options $_dvc_list ;;
metrics) _arguments $_dvc_global_options $_dvc_metrics ;;
move) _arguments $_dvc_global_options $_dvc_move ;;
@@ -330,7 +330,7 @@ case $words[1] in
root) _arguments $_dvc_global_options $_dvc_root ;;
run) _arguments $_dvc_global_options $_dvc_run ;;
status) _arguments $_dvc_global_options $_dvc_status ;;
unlock) _arguments $_dvc_global_options $_dvc_unlock ;;
unfreeze) _arguments $_dvc_global_options $_dvc_unfreeze ;;
unprotect) _arguments $_dvc_global_options $_dvc_unprotect ;;
update) _arguments $_dvc_global_options $_dvc_update ;;
esac
+2 -2
View File
@@ -134,7 +134,7 @@ def test_disconnected_stage(tmp_dir, dvc):
def test_print_locked_stages(tmp_dir, dvc, caplog):
tmp_dir.dvc_gen({"foo": "foo content", "bar": "bar content"})
dvc.lock_stage("foo.dvc")
dvc.freeze("foo.dvc")
caplog.clear()
with caplog.at_level(logging.INFO, logger="dvc"):
@@ -249,7 +249,7 @@ class TestDvcRepoPipeline(TestDvc):
def locked_stage(self):
self.dvc.add("foo")
self.dvc.lock_stage("foo.dvc")
self.dvc.freeze("foo.dvc")
pipelines = self.dvc.pipelines
self.assertEqual(len(pipelines), 0)
+21 -21
View File
@@ -554,7 +554,7 @@ class TestReproPipelines(SingleStageRun, TestDvc):
self.assertEqual(ret, 0)
class TestReproLocked(TestReproChangedData):
class TestReproFrozen(TestReproChangedData):
def test(self):
file2 = "file2"
file2_stage = self._run(
@@ -567,12 +567,12 @@ class TestReproLocked(TestReproChangedData):
self.swap_foo_with_bar()
ret = main(["lock", self._get_stage_target(file2_stage)])
ret = main(["freeze", self._get_stage_target(file2_stage)])
self.assertEqual(ret, 0)
stages = self.dvc.reproduce(self._get_stage_target(file2_stage))
self.assertEqual(len(stages), 0)
ret = main(["unlock", self._get_stage_target(file2_stage)])
ret = main(["unfreeze", self._get_stage_target(file2_stage)])
self.assertEqual(ret, 0)
stages = self.dvc.reproduce(self._get_stage_target(file2_stage))
self.assertTrue(filecmp.cmp(self.file1, self.BAR, shallow=False))
@@ -581,19 +581,19 @@ class TestReproLocked(TestReproChangedData):
def test_non_existing(self):
with self.assertRaises(StageFileDoesNotExistError):
self.dvc.lock_stage("Dvcfile")
self.dvc.lock_stage("pipelines.yaml")
self.dvc.lock_stage("pipelines.yaml:name")
self.dvc.lock_stage("Dvcfile:name")
self.dvc.lock_stage("stage.dvc")
self.dvc.lock_stage("stage.dvc:name")
self.dvc.lock_stage("not-existing-stage.json")
self.dvc.freeze("Dvcfile")
self.dvc.freeze("pipelines.yaml")
self.dvc.freeze("pipelines.yaml:name")
self.dvc.freeze("Dvcfile:name")
self.dvc.freeze("stage.dvc")
self.dvc.freeze("stage.dvc:name")
self.dvc.freeze("not-existing-stage.json")
ret = main(["lock", "non-existing-stage"])
ret = main(["freeze", "non-existing-stage"])
self.assertNotEqual(ret, 0)
class TestReproLockedCallback(SingleStageRun, TestDvc):
class TestReproFrozenCallback(SingleStageRun, TestDvc):
def test(self):
file1 = "file1"
file1_stage = file1 + ".dvc"
@@ -610,26 +610,26 @@ class TestReproLockedCallback(SingleStageRun, TestDvc):
stages = self.dvc.reproduce(self._get_stage_target(stage))
self.assertEqual(len(stages), 1)
self.dvc.lock_stage(self._get_stage_target(stage))
self.dvc.freeze(self._get_stage_target(stage))
stages = self.dvc.reproduce(self._get_stage_target(stage))
self.assertEqual(len(stages), 0)
self.dvc.lock_stage(self._get_stage_target(stage), unlock=True)
self.dvc.unfreeze(self._get_stage_target(stage))
stages = self.dvc.reproduce(self._get_stage_target(stage))
self.assertEqual(len(stages), 1)
class TestReproLockedUnchanged(TestRepro):
class TestReproFrozenUnchanged(TestRepro):
def test(self):
"""
Check that locking/unlocking doesn't affect stage state
Check that freezing/unfreezing doesn't affect stage state
"""
target = self._get_stage_target(self.stage)
self.dvc.lock_stage(target)
self.dvc.freeze(target)
stages = self.dvc.reproduce(target)
self.assertEqual(len(stages), 0)
self.dvc.lock_stage(target, unlock=True)
self.dvc.unfreeze(target)
stages = self.dvc.reproduce(target)
self.assertEqual(len(stages), 0)
@@ -879,9 +879,9 @@ class TestReproExternalBase(SingleStageRun, TestDvc):
with patch_download as mock_download:
with patch_checkout as mock_checkout:
with patch_run as mock_run:
stage.locked = False
stage.frozen = False
stage.run()
stage.locked = True
stage.frozen = True
mock_run.assert_not_called()
mock_download.assert_not_called()
@@ -1387,7 +1387,7 @@ class TestReproAlreadyCached(TestRepro):
with patch_download as mock_download:
with patch_checkout as mock_checkout:
assert main(["unlock", "bar.dvc"]) == 0
assert main(["unfreeze", "bar.dvc"]) == 0
ret = main(["repro", "--force", "bar.dvc"])
self.assertEqual(ret, 0)
self.assertEqual(mock_download.call_count, 1)
+7 -7
View File
@@ -101,18 +101,18 @@ class TestReproPipelinesMultiStage(
pass
class TestReproLockedMultiStage(MultiStageRun, test_repro.TestReproLocked):
class TestReproFrozenMultiStage(MultiStageRun, test_repro.TestReproFrozen):
pass
class TestReproLockedCallbackMultiStage(
MultiStageRun, test_repro.TestReproLockedCallback
class TestReproFrozenCallbackMultiStage(
MultiStageRun, test_repro.TestReproFrozenCallback
):
pass
class TestReproLockedUnchangedMultiStage(
MultiStageRun, test_repro.TestReproLockedUnchanged
class TestReproFrozenUnchangedMultiStage(
MultiStageRun, test_repro.TestReproFrozenUnchanged
):
pass
@@ -202,9 +202,9 @@ def test_non_existing_stage_name(tmp_dir, dvc, run_copy):
run_copy("file1", "file2", name="copy-file1-file2")
with pytest.raises(DvcException):
dvc.lock_stage(":copy-file1-file3")
dvc.freeze(":copy-file1-file3")
assert main(["lock", ":copy-file1-file3"]) != 0
assert main(["freeze", ":copy-file1-file3"]) != 0
def test_downstream(tmp_dir, dvc):
+2 -2
View File
@@ -15,7 +15,7 @@ def test_get_active_graph(tmp_dir, dvc):
single_stage=True, deps=["foo"], outs=["baz"], cmd="echo baz > baz"
)
dvc.lock_stage("bar.dvc")
dvc.freeze("bar.dvc")
graph = dvc.graph
active_graph = _get_active_graph(graph)
@@ -25,7 +25,7 @@ def test_get_active_graph(tmp_dir, dvc):
(baz_stage, foo_stage),
}
dvc.lock_stage("baz.dvc")
dvc.freeze("baz.dvc")
graph = dvc.graph
active_graph = _get_active_graph(graph)