From 0d6b2239bdb55d4c1a59605d5bea65f722c899c8 Mon Sep 17 00:00:00 2001 From: Jorge Orpinel Date: Mon, 17 Feb 2020 20:53:19 -0600 Subject: [PATCH 01/11] api: update to latest definitions to match iterative/dvc.org/pull/908 --- dvc/api.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/dvc/api.py b/dvc/api.py index def9e8cf5b..ed3a77e16e 100644 --- a/dvc/api.py +++ b/dvc/api.py @@ -18,10 +18,10 @@ def __init__(self, url): def get_url(path, repo=None, rev=None, remote=None): - """ - Returns the full URL to the data artifact specified by its `path` in a - `repo`. - NOTE: There is no guarantee that the file actually exists in that location. + """Returns URL to the storage location of a data artifact tracked + by DVC, specified by its path in a repo. + + NOTE: There's no guarantee that the file actually exists in that location. """ with _make_repo(repo, rev=rev) as _repo: _require_dvc(_repo) @@ -31,7 +31,7 @@ def get_url(path, repo=None, rev=None, remote=None): def open(path, repo=None, rev=None, remote=None, mode="r", encoding=None): - """Context manager to open a file artifact as a file object.""" + """Context manager to open a tracked file as a file object.""" args = (path,) kwargs = { "repo": repo, @@ -63,7 +63,7 @@ def _open(path, repo=None, rev=None, remote=None, mode="r", encoding=None): def read(path, repo=None, rev=None, remote=None, mode="r", encoding=None): - """Returns the contents of a file artifact.""" + """Returns the contents of a tracked file.""" with open( path, repo=repo, rev=rev, remote=remote, mode=mode, encoding=encoding ) as fd: @@ -84,5 +84,6 @@ def _make_repo(repo_url=None, rev=None): def _require_dvc(repo): + """Raises UrlNotDvcRepoError if repo is not a DVC repository.""" if not isinstance(repo, Repo): raise UrlNotDvcRepoError(repo.url) From 6b14cef8327dc46be4721825aeceae52dfa9f259 Mon Sep 17 00:00:00 2001 From: Ruslan Kuprieiev Date: Sun, 23 Feb 2020 06:34:04 +0200 Subject: [PATCH 02/11] Update dvc/api.py --- dvc/api.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dvc/api.py b/dvc/api.py index ed3a77e16e..d1312baaf3 100644 --- a/dvc/api.py +++ b/dvc/api.py @@ -84,6 +84,5 @@ def _make_repo(repo_url=None, rev=None): def _require_dvc(repo): - """Raises UrlNotDvcRepoError if repo is not a DVC repository.""" if not isinstance(repo, Repo): raise UrlNotDvcRepoError(repo.url) From 8b2dca09dcfda081b449202ed6a749319ed84206 Mon Sep 17 00:00:00 2001 From: Jorge Orpinel Date: Fri, 28 Feb 2020 00:49:05 -0600 Subject: [PATCH 03/11] metrics show: update -h output to match docs per https://github.com/iterative/dvc.org/pull/1014/commits/2c3452119545987f77b764e4aa6fc94d051092a7 --- dvc/command/metrics.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dvc/command/metrics.py b/dvc/command/metrics.py index 6cb3887fd7..038e2f2669 100644 --- a/dvc/command/metrics.py +++ b/dvc/command/metrics.py @@ -187,8 +187,7 @@ def add_parser(subparsers, parent_parser): metrics_show_parser.add_argument( "targets", nargs="*", - help="Metric files or directories (see -R) to show " - "(leave empty to display all)", + help="Metric files or directories (see -R) to show", ) metrics_show_parser.add_argument( "-t", From bc613c6ab7f33cf7aa6c251ae5f6100b6fe05034 Mon Sep 17 00:00:00 2001 From: Jorge Orpinel Date: Sun, 1 Mar 2020 19:14:12 -0600 Subject: [PATCH 04/11] api: update docstrings to match iterative/dvc.org/pull/908 --- dvc/api.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/dvc/api.py b/dvc/api.py index d1312baaf3..3ce8b9df69 100644 --- a/dvc/api.py +++ b/dvc/api.py @@ -7,21 +7,21 @@ class UrlNotDvcRepoError(DvcException): - """Thrown if given URL is not a DVC repository. - - Args: - url (str): URL to the repository - """ + """Thrown if the given URL is not a DVC repository.""" def __init__(self, url): super().__init__("'{}' is not a DVC repository.".format(url)) def get_url(path, repo=None, rev=None, remote=None): - """Returns URL to the storage location of a data artifact tracked - by DVC, specified by its path in a repo. + """ + Returns the URL to the storage location of a data file or directory tracked + in a DVC repo. Its formed by reading the remote configuration, and the + DVC-file where the given path is an output. For Git repos, HEAD is used + unless a rev argument is supplied. - NOTE: There's no guarantee that the file actually exists in that location. + NOTE: This function does not check for the actual existence of the file or + directory in the remote storage. """ with _make_repo(repo, rev=rev) as _repo: _require_dvc(_repo) @@ -31,7 +31,11 @@ def get_url(path, repo=None, rev=None, remote=None): def open(path, repo=None, rev=None, remote=None, mode="r", encoding=None): - """Context manager to open a tracked file as a file object.""" + """ + Open file or model (path) tracked in a repo (by DVC or Git), and and return + a file object. For Git repos, HEAD is used unless a rev argument is + supplied. The default remote is tried unless a remote argument is supplied. + """ args = (path,) kwargs = { "repo": repo, @@ -63,7 +67,7 @@ def _open(path, repo=None, rev=None, remote=None, mode="r", encoding=None): def read(path, repo=None, rev=None, remote=None, mode="r", encoding=None): - """Returns the contents of a tracked file.""" + """Returns the contents of a tracked file (by DVC or Git). Wraps open()""" with open( path, repo=repo, rev=rev, remote=remote, mode=mode, encoding=encoding ) as fd: From 1b09308389e86eb863ac182ee10c40b9cd2ff3c2 Mon Sep 17 00:00:00 2001 From: Jorge Orpinel Date: Sun, 1 Mar 2020 19:35:04 -0600 Subject: [PATCH 05/11] api: refactor DVC repo check in get_url, and document it --- dvc/api.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/dvc/api.py b/dvc/api.py index 3ce8b9df69..8d48d1c4b6 100644 --- a/dvc/api.py +++ b/dvc/api.py @@ -20,11 +20,14 @@ def get_url(path, repo=None, rev=None, remote=None): DVC-file where the given path is an output. For Git repos, HEAD is used unless a rev argument is supplied. + Raises UrlNotDvcRepoError if repo is not a DVC project. + NOTE: This function does not check for the actual existence of the file or directory in the remote storage. """ with _make_repo(repo, rev=rev) as _repo: - _require_dvc(_repo) + if not isinstance(_repo, Repo): + raise UrlNotDvcRepoError(_repo.url) out = _repo.find_out_by_relpath(path) remote_obj = _repo.cloud.get_remote(remote) return str(remote_obj.checksum_to_path_info(out.checksum)) @@ -85,8 +88,3 @@ def _make_repo(repo_url=None, rev=None): pass # fallthrough to external_repo with external_repo(url=repo_url, rev=rev) as repo: yield repo - - -def _require_dvc(repo): - if not isinstance(repo, Repo): - raise UrlNotDvcRepoError(repo.url) From 8257c807705eeb58bd326e2722e5ea9fcfce57ff Mon Sep 17 00:00:00 2001 From: Jorge Orpinel Date: Sun, 1 Mar 2020 23:36:10 -0600 Subject: [PATCH 06/11] dvc: cosmetic edits as I explored exceptions that api functions may raise --- dvc/config.py | 7 +++---- dvc/scm/__init__.py | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/dvc/config.py b/dvc/config.py index 1d6118ec45..6d16181051 100644 --- a/dvc/config.py +++ b/dvc/config.py @@ -201,9 +201,8 @@ class Config(dict): validate (bool): optional flag to tell dvc if it should validate the config or just load it as is. 'True' by default. - Raises: - ConfigError: thrown when config has an invalid format. + ConfigError: thrown if config has an invalid format. """ APPNAME = "dvc" @@ -272,7 +271,7 @@ def load(self, validate=True): """Loads config from all the config files. Raises: - dvc.config.ConfigError: thrown if config has invalid format. + ConfigError: thrown if config has an invalid format. """ conf = {} for level in self.LEVELS: @@ -332,7 +331,7 @@ def _map_dirs(conf, func): @contextmanager def edit(self, level="repo"): if level in {"repo", "local"} and self.dvc_dir is None: - raise ConfigError("Not inside a dvc repo") + raise ConfigError("Not inside a DVC repo") conf = self.load_one(level) yield conf diff --git a/dvc/scm/__init__.py b/dvc/scm/__init__.py index 62f106314d..15a75796ff 100644 --- a/dvc/scm/__init__.py +++ b/dvc/scm/__init__.py @@ -4,8 +4,8 @@ from dvc.scm.git import Git -# just a sugar to point that this is an actual implementation for a dvc -# project under no SCM control +# Syntactic sugar to signal that this is an actual implementation for a DVC +# project under no SCM control. class NoSCM(Base): pass From f29e5ecb01c4492f7a01a98419a2b38ac7f90b32 Mon Sep 17 00:00:00 2001 From: Jorge Orpinel Date: Tue, 3 Mar 2020 01:19:45 -0600 Subject: [PATCH 07/11] api: copy default info to read() docstring from open() per https://github.com/iterative/dvc/pull/3426#pullrequestreview-366949501 --- dvc/api.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dvc/api.py b/dvc/api.py index 8d48d1c4b6..e8842123eb 100644 --- a/dvc/api.py +++ b/dvc/api.py @@ -70,7 +70,11 @@ def _open(path, repo=None, rev=None, remote=None, mode="r", encoding=None): def read(path, repo=None, rev=None, remote=None, mode="r", encoding=None): - """Returns the contents of a tracked file (by DVC or Git). Wraps open()""" + """ + Returns the contents of a tracked file (by DVC or Git). For Git repos, HEAD + is used unless a rev argument is supplied. The default remote is tried + unless a remote argument is supplied. + """ with open( path, repo=repo, rev=rev, remote=remote, mode=mode, encoding=encoding ) as fd: From 197d9e8c788a6b9f1085111f2fe222d52494ae54 Mon Sep 17 00:00:00 2001 From: Jorge Orpinel Date: Tue, 3 Mar 2020 01:41:54 -0600 Subject: [PATCH 08/11] api: improve open() docstring for clarity and add example per https://github.com/iterative/dvc/pull/3426#pullrequestreview-366956856 --- dvc/api.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/dvc/api.py b/dvc/api.py index e8842123eb..26515b3443 100644 --- a/dvc/api.py +++ b/dvc/api.py @@ -35,9 +35,18 @@ def get_url(path, repo=None, rev=None, remote=None): def open(path, repo=None, rev=None, remote=None, mode="r", encoding=None): """ - Open file or model (path) tracked in a repo (by DVC or Git), and and return - a file object. For Git repos, HEAD is used unless a rev argument is + Open file or model in the supplied path tracked in a repo (both DVC + projects and plain Git repos are supported), and produces a file object + (see example below). For Git repos, HEAD is used unless a rev argument is supplied. The default remote is tried unless a remote argument is supplied. + + Example: + + with dvc.api.open( + 'path/to/tracked.dat', + repo='https://example.com/url/to/repo' + ) as fd: + # ... Handle file object fd """ args = (path,) kwargs = { From 7f083979252a8b10ab58c893ab5920846b8420e1 Mon Sep 17 00:00:00 2001 From: Jorge Orpinel Date: Tue, 3 Mar 2020 01:46:33 -0600 Subject: [PATCH 09/11] api: remove unnecessary info from get_url docstring per https://github.com/iterative/dvc/pull/3426#discussion_r386203064 --- dvc/api.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dvc/api.py b/dvc/api.py index 26515b3443..eb3225d754 100644 --- a/dvc/api.py +++ b/dvc/api.py @@ -16,9 +16,8 @@ def __init__(self, url): def get_url(path, repo=None, rev=None, remote=None): """ Returns the URL to the storage location of a data file or directory tracked - in a DVC repo. Its formed by reading the remote configuration, and the - DVC-file where the given path is an output. For Git repos, HEAD is used - unless a rev argument is supplied. + in a DVC repo. For Git repos, HEAD is used unless a rev argument is + supplied. The default remote is tried unless a remote argument is supplied. Raises UrlNotDvcRepoError if repo is not a DVC project. From 2e3a34d4423c1ec5e3add12ffc9f73330248de1a Mon Sep 17 00:00:00 2001 From: Jorge Orpinel Date: Wed, 4 Mar 2020 18:33:26 -0600 Subject: [PATCH 10/11] api: produces->generated in open() docstring --- dvc/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dvc/api.py b/dvc/api.py index eb3225d754..bf474368cc 100644 --- a/dvc/api.py +++ b/dvc/api.py @@ -35,7 +35,7 @@ def get_url(path, repo=None, rev=None, remote=None): def open(path, repo=None, rev=None, remote=None, mode="r", encoding=None): """ Open file or model in the supplied path tracked in a repo (both DVC - projects and plain Git repos are supported), and produces a file object + projects and plain Git repos are supported), and generated a file object (see example below). For Git repos, HEAD is used unless a rev argument is supplied. The default remote is tried unless a remote argument is supplied. From 7daf8b009a4b4fa63134009f4e2ef4c1608ed84a Mon Sep 17 00:00:00 2001 From: Jorge Orpinel Date: Thu, 5 Mar 2020 15:19:40 -0600 Subject: [PATCH 11/11] api: simplify open docstring per https://github.com/iterative/dvc/pull/3426#discussion_r388218147 --- dvc/api.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/dvc/api.py b/dvc/api.py index bf474368cc..98763d16a7 100644 --- a/dvc/api.py +++ b/dvc/api.py @@ -34,15 +34,13 @@ def get_url(path, repo=None, rev=None, remote=None): def open(path, repo=None, rev=None, remote=None, mode="r", encoding=None): """ - Open file or model in the supplied path tracked in a repo (both DVC - projects and plain Git repos are supported), and generated a file object - (see example below). For Git repos, HEAD is used unless a rev argument is - supplied. The default remote is tried unless a remote argument is supplied. - - Example: + Open file in the supplied path tracked in a repo (both DVC projects and + plain Git repos are supported). For Git repos, HEAD is used unless a rev + argument is supplied. The default remote is tried unless a remote argument + is supplied. It may only be used as a context manager: with dvc.api.open( - 'path/to/tracked.dat', + 'path/to/file', repo='https://example.com/url/to/repo' ) as fd: # ... Handle file object fd