Skip to content

Commit 0433565

Browse files
committed
api: add config support for open/read
Fixes #9610
1 parent b544950 commit 0433565

File tree

2 files changed

+57
-5
lines changed

2 files changed

+57
-5
lines changed

dvc/api/data.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ def open( # noqa, pylint: disable=redefined-builtin
7373
remote: Optional[str] = None,
7474
mode: str = "r",
7575
encoding: Optional[str] = None,
76+
config: Optional[Dict[str, Any]] = None,
7677
):
7778
"""
7879
Opens a file tracked in a DVC project.
@@ -114,6 +115,8 @@ def open( # noqa, pylint: disable=redefined-builtin
114115
Defaults to None.
115116
This should only be used in text mode.
116117
Mirrors the namesake parameter in builtin `open()`_.
118+
config(dict, optional): config to be passed to the DVC repository.
119+
Defaults to None.
117120
118121
Returns:
119122
_OpenContextManager: A context manager that generatse a corresponding
@@ -209,14 +212,24 @@ def open( # noqa, pylint: disable=redefined-builtin
209212
"rev": rev,
210213
"mode": mode,
211214
"encoding": encoding,
215+
"config": config,
212216
}
213217
return _OpenContextManager(_open, args, kwargs)
214218

215219

216-
def _open(path, repo=None, rev=None, remote=None, mode="r", encoding=None):
217-
repo_kwargs: Dict[str, Any] = {"subrepos": True, "uninitialized": True}
220+
def _open(path, repo=None, rev=None, remote=None, mode="r", encoding=None, config=None):
218221
if remote:
219-
repo_kwargs["config"] = {"core": {"remote": remote}}
222+
if config is not None:
223+
raise ValueError(
224+
"can't specify both `remote` and `config` at the same time"
225+
)
226+
config = {"core": {"remote": remote}}
227+
228+
repo_kwargs: Dict[str, Any] = {
229+
"subrepos": True,
230+
"uninitialized": True,
231+
"config": config,
232+
}
220233

221234
with Repo.open(repo, rev=rev, **repo_kwargs) as _repo:
222235
with _wrap_exceptions(_repo, path):
@@ -251,13 +264,19 @@ def _open(path, repo=None, rev=None, remote=None, mode="r", encoding=None):
251264
raise DvcIsADirectoryError(f"'{path}' is a directory") from exc
252265

253266

254-
def read(path, repo=None, rev=None, remote=None, mode="r", encoding=None):
267+
def read(path, repo=None, rev=None, remote=None, mode="r", encoding=None, config=None):
255268
"""
256269
Returns the contents of a tracked file (by DVC or Git). For Git repos, HEAD
257270
is used unless a rev argument is supplied. The default remote is tried
258271
unless a remote argument is supplied.
259272
"""
260273
with open(
261-
path, repo=repo, rev=rev, remote=remote, mode=mode, encoding=encoding
274+
path,
275+
repo=repo,
276+
rev=rev,
277+
remote=remote,
278+
mode=mode,
279+
encoding=encoding,
280+
config=config,
262281
) as fd:
263282
return fd.read()

tests/func/api/test_data.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,36 @@ def test_open_from_remote(tmp_dir, erepo_dir, cloud, local_cloud):
218218
remote="other",
219219
) as fd:
220220
assert fd.read() == "foo content"
221+
222+
with api.open(
223+
os.path.join("dir", "foo"),
224+
repo=f"file://{erepo_dir.as_posix()}",
225+
config={"core": {"remote": "other"}},
226+
) as fd:
227+
assert fd.read() == "foo content"
228+
229+
230+
def test_read_from_remote(tmp_dir, erepo_dir, cloud, local_cloud):
231+
erepo_dir.add_remote(config=cloud.config, name="other")
232+
erepo_dir.add_remote(config=local_cloud.config, default=True)
233+
erepo_dir.dvc_gen({"dir": {"foo": "foo content"}}, commit="create file")
234+
erepo_dir.dvc.push(remote="other")
235+
remove(erepo_dir.dvc.cache.local.path)
236+
237+
assert (
238+
api.read(
239+
os.path.join("dir", "foo"),
240+
repo=f"file://{erepo_dir.as_posix()}",
241+
remote="other",
242+
)
243+
== "foo content"
244+
)
245+
246+
assert (
247+
api.read(
248+
os.path.join("dir", "foo"),
249+
repo=f"file://{erepo_dir.as_posix()}",
250+
config={"core": {"remote": "other"}},
251+
)
252+
== "foo content"
253+
)

0 commit comments

Comments
 (0)