mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-02 15:28:30 +01:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd1e228e55 | ||
|
|
3b2e031e60 | ||
|
|
e5ee82bc99 | ||
|
|
bc95b650a4 | ||
|
|
257ea5f4cb | ||
|
|
5f7acd4cbe | ||
|
|
13325ea89b | ||
|
|
fd71434df5 | ||
|
|
2ff4ff2daa | ||
|
|
0ee6d6eba8 | ||
|
|
7c34370464 | ||
|
|
b67b254287 | ||
|
|
212928a1fa | ||
|
|
5be23cfd4e | ||
|
|
4d3a631e60 | ||
|
|
491155cdb0 | ||
|
|
9bb4501bf0 | ||
|
|
4cb658f96c | ||
|
|
9f66897bf7 | ||
|
|
84a1750013 | ||
|
|
6cb37ac27b | ||
|
|
f38490c897 | ||
|
|
34d80fbfce | ||
|
|
89537a77b5 | ||
|
|
c72e1fb0b8 | ||
|
|
9fbe5d929d | ||
|
|
0635b0ca15 | ||
|
|
06abf73c22 | ||
|
|
5e2c441d28 | ||
|
|
6efd699267 | ||
|
|
f639ab50ab | ||
|
|
953ae56536 | ||
|
|
ac0397e536 | ||
|
|
b243ccab1f | ||
|
|
c31a5d9df9 | ||
|
|
44b78b81b9 | ||
|
|
d25cb79e0a | ||
|
|
79238fd2a3 | ||
|
|
2bf7bd990a | ||
|
|
68b9ecb95c | ||
|
|
594716ec79 | ||
|
|
84b2e685e2 | ||
|
|
0bb2f3d10c | ||
|
|
f42468bcaf | ||
|
|
28545c0cc5 | ||
|
|
0ee752d464 | ||
|
|
9a1bcd7f1d | ||
|
|
422caa13c4 | ||
|
|
3b56c40add | ||
|
|
b647475a64 | ||
|
|
966adec21c | ||
|
|
4eb073868c | ||
|
|
196c1c7a17 | ||
|
|
df5b582c3f | ||
|
|
20edd72a43 | ||
|
|
ba06c0504a | ||
|
|
18a9fea4af | ||
|
|
bfb65870a4 | ||
|
|
a122b80d52 | ||
|
|
71afff6db3 | ||
|
|
48ec86de28 | ||
|
|
78ab929ad1 | ||
|
|
5c31189a91 | ||
|
|
b46bd9ca65 | ||
|
|
d711ecda04 | ||
|
|
e3b0f190ab | ||
|
|
eae4fe21ce | ||
|
|
1c06302a47 | ||
|
|
71669225c5 | ||
|
|
60c5f202a1 | ||
|
|
426a7149a4 | ||
|
|
0100c14d6a | ||
|
|
f1de712710 | ||
|
|
bf5fe95c30 | ||
|
|
fe008d9748 | ||
|
|
dad464285e | ||
|
|
d218b6ac2b | ||
|
|
041ea17233 | ||
|
|
987b1c4213 | ||
|
|
f2e479422f | ||
|
|
73820cc596 | ||
|
|
e7b695dbef | ||
|
|
27a8222e2a | ||
|
|
5850639a97 | ||
|
|
f2b56bbb8a | ||
|
|
cf8195c829 | ||
|
|
402c107823 | ||
|
|
b73754edd1 | ||
|
|
333f2f04f0 | ||
|
|
470c50a22b | ||
|
|
01f49b7f24 | ||
|
|
19f2246bee | ||
|
|
6a44783d72 | ||
|
|
98a286d88d | ||
|
|
499c2dda01 | ||
|
|
5f2615ff53 | ||
|
|
457d615a51 | ||
|
|
827f9a7f03 | ||
|
|
7821e126fe | ||
|
|
72ab5a12df | ||
|
|
abcd70b9cf | ||
|
|
3e4e143bee | ||
|
|
766b43bc2d | ||
|
|
92c66b2331 | ||
|
|
b1211366cd | ||
|
|
92823f1d84 | ||
|
|
f3fa67440d | ||
|
|
3275f1ebf5 | ||
|
|
4392af6d95 | ||
|
|
a02c5a7405 | ||
|
|
dec1ac7346 | ||
|
|
8ccae0a086 | ||
|
|
3c31234151 | ||
|
|
77b451d118 | ||
|
|
1d47b03cd5 | ||
|
|
7c898cfad7 | ||
|
|
1f07023d17 | ||
|
|
1e6b0242aa | ||
|
|
3c1e9ee9be | ||
|
|
9622157565 | ||
|
|
6ff4342f02 | ||
|
|
5bb72b36cb | ||
|
|
1aed230cd0 | ||
|
|
c50b2e1e71 | ||
|
|
34bc410075 | ||
|
|
47ff40da0c | ||
|
|
ee35ec10a2 | ||
|
|
e18fd34b2c | ||
|
|
c0b64b0a10 | ||
|
|
3927e75ef1 | ||
|
|
e5ae5ef24b | ||
|
|
e187508f40 | ||
|
|
8768b50aed | ||
|
|
7c61463d2d | ||
|
|
b0d0315689 | ||
|
|
7edcb6b1e5 | ||
|
|
b6d231f9cf | ||
|
|
322fcec5ca | ||
|
|
1e5b3603cc | ||
|
|
ffa630e8d5 | ||
|
|
1e9b60dc48 | ||
|
|
83dd2b2a7b | ||
|
|
d238350a2d | ||
|
|
06b9196371 | ||
|
|
b4f42242c9 | ||
|
|
fbdb566079 | ||
|
|
3d7bbb8492 | ||
|
|
fd7c891217 | ||
|
|
2b3b15f767 | ||
|
|
8c9358957c | ||
|
|
86dd0785a0 | ||
|
|
a8aec51c35 |
@@ -10,7 +10,7 @@ jobs:
|
||||
name: run benchmarks
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- uses: iterative/dvc-bench@main
|
||||
|
||||
@@ -23,9 +23,9 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.8
|
||||
python-version: 3.12
|
||||
|
||||
- run: python -m pip install --upgrade pip setuptools_scm build twine
|
||||
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
SETUPTOOLS_SCM_PRETEND_VERSION_FOR_DVC: ${{ env.version }}
|
||||
- run: twine check --strict dist/*
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Packages
|
||||
path: dist/
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: Packages
|
||||
path: dist
|
||||
@@ -83,7 +83,7 @@ jobs:
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: Packages
|
||||
path: dist
|
||||
|
||||
@@ -31,9 +31,10 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: security-extended
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
path: ${{ matrix.plugin }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.pyv }}
|
||||
cache: pip
|
||||
|
||||
@@ -23,14 +23,14 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, windows-latest, macos-latest]
|
||||
pyv: ["3.8", "3.9", "3.10", "3.11"]
|
||||
pyv: ["3.9", "3.10", "3.11", "3.12"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.pyv }}
|
||||
cache: pip
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
run: |
|
||||
pip install --upgrade pip wheel
|
||||
pip install -e ".[dev]"
|
||||
- uses: pre-commit/[email protected].0
|
||||
- uses: pre-commit/[email protected].1
|
||||
- name: run tests
|
||||
timeout-minutes: 40
|
||||
env:
|
||||
|
||||
@@ -22,7 +22,7 @@ repos:
|
||||
- id: sort-simple-yaml
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: 'v0.1.5'
|
||||
rev: 'v0.2.2'
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [--fix, --exit-non-zero-on-fix]
|
||||
|
||||
@@ -5,10 +5,7 @@ from PyInstaller.utils.hooks import collect_submodules, is_module_or_submodule
|
||||
# Celery dynamically imports most celery internals at runtime
|
||||
# pyinstaller hook must expose all modules loaded by
|
||||
# kombu.utils.imports:symbol_by_name()
|
||||
_EXCLUDES = (
|
||||
"celery.bin",
|
||||
"celery.contrib",
|
||||
)
|
||||
_EXCLUDES = ("celery.bin", "celery.contrib")
|
||||
hiddenimports = collect_submodules(
|
||||
"celery",
|
||||
filter=lambda name: not any(
|
||||
|
||||
+45
-39
@@ -23,10 +23,11 @@ def viztracer_profile(
|
||||
tracer = viztracer.VizTracer(max_stack_depth=depth, log_async=log_async)
|
||||
|
||||
tracer.start()
|
||||
yield
|
||||
tracer.stop()
|
||||
|
||||
tracer.save(path() if callable(path) else path)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
tracer.stop()
|
||||
tracer.save(path() if callable(path) else path)
|
||||
|
||||
|
||||
@contextmanager
|
||||
@@ -45,31 +46,33 @@ def yappi_profile(
|
||||
yappi.set_clock_type("wall" if wall_clock else "cpu")
|
||||
|
||||
yappi.start()
|
||||
yield
|
||||
yappi.stop()
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
yappi.stop()
|
||||
|
||||
threads = yappi.get_thread_stats()
|
||||
stats = {}
|
||||
if separate_threads:
|
||||
for thread in threads:
|
||||
ctx_id = thread.id
|
||||
stats[ctx_id] = yappi.get_func_stats(ctx_id=ctx_id)
|
||||
else:
|
||||
stats[None] = yappi.get_func_stats()
|
||||
|
||||
fpath = path() if callable(path) else path
|
||||
for ctx_id, st in stats.items():
|
||||
if fpath:
|
||||
out = f"{fpath}-{ctx_id}" if ctx_id is not None else fpath
|
||||
st.save(out, type="callgrind")
|
||||
threads = yappi.get_thread_stats()
|
||||
stats = {}
|
||||
if separate_threads:
|
||||
for thread in threads:
|
||||
ctx_id = thread.id
|
||||
stats[ctx_id] = yappi.get_func_stats(ctx_id=ctx_id)
|
||||
else:
|
||||
if ctx_id is not None:
|
||||
print(f"\nThread {ctx_id}") # noqa: T201
|
||||
st.print_all()
|
||||
if ctx_id is None:
|
||||
threads.print_all()
|
||||
stats[None] = yappi.get_func_stats()
|
||||
|
||||
yappi.clear_stats()
|
||||
fpath = path() if callable(path) else path
|
||||
for ctx_id, st in stats.items():
|
||||
if fpath:
|
||||
out = f"{fpath}-{ctx_id}" if ctx_id is not None else fpath
|
||||
st.save(out, type="callgrind")
|
||||
else:
|
||||
if ctx_id is not None:
|
||||
print(f"\nThread {ctx_id}") # noqa: T201
|
||||
st.print_all()
|
||||
if ctx_id is None:
|
||||
threads.print_all()
|
||||
|
||||
yappi.clear_stats()
|
||||
|
||||
|
||||
@contextmanager
|
||||
@@ -85,13 +88,15 @@ def instrument(html_output=False):
|
||||
profiler = Profiler()
|
||||
|
||||
profiler.start()
|
||||
yield
|
||||
profiler.stop()
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
profiler.stop()
|
||||
|
||||
if html_output:
|
||||
profiler.open_in_browser()
|
||||
return
|
||||
print(profiler.output_text(unicode=True, color=True)) # noqa: T201
|
||||
if html_output:
|
||||
profiler.open_in_browser()
|
||||
else:
|
||||
print(profiler.output_text(unicode=True, color=True)) # noqa: T201
|
||||
|
||||
|
||||
@contextmanager
|
||||
@@ -102,13 +107,14 @@ def profile(dump_path: Optional[str] = None):
|
||||
prof = cProfile.Profile()
|
||||
prof.enable()
|
||||
|
||||
yield
|
||||
|
||||
prof.disable()
|
||||
if not dump_path:
|
||||
prof.print_stats(sort="cumtime")
|
||||
return
|
||||
prof.dump_stats(dump_path)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
prof.disable()
|
||||
if dump_path:
|
||||
prof.dump_stats(dump_path)
|
||||
else:
|
||||
prof.print_stats(sort="cumtime")
|
||||
|
||||
|
||||
@contextmanager
|
||||
|
||||
+10
-10
@@ -1,5 +1,5 @@
|
||||
from dataclasses import asdict, dataclass, field, fields
|
||||
from typing import Any, ClassVar, Dict, List, Optional
|
||||
from typing import Any, ClassVar, Optional
|
||||
|
||||
from funcy import compact
|
||||
from voluptuous import Required
|
||||
@@ -13,11 +13,11 @@ class Annotation:
|
||||
PARAM_META: ClassVar[str] = "meta"
|
||||
|
||||
desc: Optional[str] = None
|
||||
type: Optional[str] = None # noqa: A003
|
||||
labels: List[str] = field(default_factory=list)
|
||||
meta: Dict[str, Any] = field(default_factory=dict)
|
||||
type: Optional[str] = None
|
||||
labels: list[str] = field(default_factory=list)
|
||||
meta: dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
def to_dict(self) -> Dict[str, str]:
|
||||
def to_dict(self) -> dict[str, str]:
|
||||
return compact(asdict(self))
|
||||
|
||||
|
||||
@@ -31,11 +31,11 @@ class Artifact:
|
||||
|
||||
path: str
|
||||
desc: Optional[str] = None
|
||||
type: Optional[str] = None # noqa: A003
|
||||
labels: List[str] = field(default_factory=list)
|
||||
meta: Dict[str, Any] = field(default_factory=dict)
|
||||
type: Optional[str] = None
|
||||
labels: list[str] = field(default_factory=list)
|
||||
meta: dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
def to_dict(self) -> Dict[str, str]:
|
||||
def to_dict(self) -> dict[str, str]:
|
||||
return compact(asdict(self))
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ ANNOTATION_SCHEMA = {
|
||||
Annotation.PARAM_LABELS: [str],
|
||||
Annotation.PARAM_META: object,
|
||||
}
|
||||
ARTIFACT_SCHEMA: Dict[Any, Any] = {
|
||||
ARTIFACT_SCHEMA: dict[Any, Any] = {
|
||||
Required(Artifact.PARAM_PATH): str,
|
||||
**ANNOTATION_SCHEMA, # type: ignore[arg-type]
|
||||
}
|
||||
|
||||
+4
-2
@@ -2,21 +2,23 @@ from dvc.fs.dvc import _DVCFileSystem as DVCFileSystem
|
||||
|
||||
from .artifacts import artifacts_show
|
||||
from .data import get_url, open, read
|
||||
from .dataset import get as get_dataset
|
||||
from .experiments import exp_save, exp_show
|
||||
from .scm import all_branches, all_commits, all_tags
|
||||
from .show import metrics_show, params_show
|
||||
|
||||
__all__ = [
|
||||
"DVCFileSystem",
|
||||
"all_branches",
|
||||
"all_commits",
|
||||
"all_tags",
|
||||
"artifacts_show",
|
||||
"exp_save",
|
||||
"exp_show",
|
||||
"get_dataset",
|
||||
"get_url",
|
||||
"metrics_show",
|
||||
"open",
|
||||
"params_show",
|
||||
"metrics_show",
|
||||
"read",
|
||||
"DVCFileSystem",
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Dict, Optional
|
||||
from typing import Any, Optional
|
||||
|
||||
from dvc.repo import Repo
|
||||
|
||||
@@ -8,7 +8,7 @@ def artifacts_show(
|
||||
version: Optional[str] = None,
|
||||
stage: Optional[str] = None,
|
||||
repo: Optional[str] = None,
|
||||
) -> Dict[str, str]:
|
||||
) -> dict[str, str]:
|
||||
"""
|
||||
Return path and Git revision for an artifact in a DVC project.
|
||||
|
||||
@@ -36,7 +36,7 @@ def artifacts_show(
|
||||
if version and stage:
|
||||
raise ValueError("Artifact version and stage are mutually exclusive.")
|
||||
|
||||
repo_kwargs: Dict[str, Any] = {
|
||||
repo_kwargs: dict[str, Any] = {
|
||||
"subrepos": True,
|
||||
"uninitialized": True,
|
||||
}
|
||||
|
||||
+7
-15
@@ -1,6 +1,6 @@
|
||||
from contextlib import _GeneratorContextManager as GCM
|
||||
from contextlib import contextmanager
|
||||
from typing import Any, Dict, Optional
|
||||
from typing import Any, Optional
|
||||
|
||||
from funcy import reraise
|
||||
|
||||
@@ -39,7 +39,7 @@ def get_url(path, repo=None, rev=None, remote=None):
|
||||
from dvc.config import NoRemoteError
|
||||
from dvc_data.index import StorageKeyError
|
||||
|
||||
repo_kwargs: Dict[str, Any] = {}
|
||||
repo_kwargs: dict[str, Any] = {}
|
||||
if remote:
|
||||
repo_kwargs["config"] = {"core": {"remote": remote}}
|
||||
with Repo.open(
|
||||
@@ -57,11 +57,7 @@ def get_url(path, repo=None, rev=None, remote=None):
|
||||
class _OpenContextManager(GCM):
|
||||
def __init__(self, func, args, kwds):
|
||||
self.gen = func(*args, **kwds)
|
||||
self.func, self.args, self.kwds = ( # type: ignore[assignment]
|
||||
func,
|
||||
args,
|
||||
kwds,
|
||||
)
|
||||
self.func, self.args, self.kwds = (func, args, kwds) # type: ignore[assignment]
|
||||
|
||||
def __getattr__(self, name):
|
||||
raise AttributeError("dvc.api.open() should be used in a with statement.")
|
||||
@@ -74,8 +70,8 @@ def open( # noqa: A001
|
||||
remote: Optional[str] = None,
|
||||
mode: str = "r",
|
||||
encoding: Optional[str] = None,
|
||||
config: Optional[Dict[str, Any]] = None,
|
||||
remote_config: Optional[Dict[str, Any]] = None,
|
||||
config: Optional[dict[str, Any]] = None,
|
||||
remote_config: Optional[dict[str, Any]] = None,
|
||||
):
|
||||
"""
|
||||
Opens a file tracked in a DVC project.
|
||||
@@ -233,7 +229,7 @@ def _open(
|
||||
config=None,
|
||||
remote_config=None,
|
||||
):
|
||||
repo_kwargs: Dict[str, Any] = {
|
||||
repo_kwargs: dict[str, Any] = {
|
||||
"subrepos": True,
|
||||
"uninitialized": True,
|
||||
"remote": remote,
|
||||
@@ -262,11 +258,7 @@ def _open(
|
||||
fs_path = fs.from_os_path(path)
|
||||
|
||||
try:
|
||||
with fs.open(
|
||||
fs_path,
|
||||
mode=mode,
|
||||
encoding=encoding,
|
||||
) as fobj:
|
||||
with fs.open(fs_path, mode=mode, encoding=encoding) as fobj:
|
||||
yield fobj
|
||||
except FileNotFoundError as exc:
|
||||
raise FileMissingError(path) from exc
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
from typing import Literal, TypedDict, Union
|
||||
|
||||
|
||||
class DVCXDataset(TypedDict):
|
||||
type: Literal["dvcx"]
|
||||
name: str
|
||||
version: int
|
||||
|
||||
|
||||
class DVCDataset(TypedDict):
|
||||
type: Literal["dvc"]
|
||||
url: str
|
||||
path: str
|
||||
sha: str
|
||||
|
||||
|
||||
class URLDataset(TypedDict):
|
||||
type: Literal["url"]
|
||||
files: list[str]
|
||||
path: str
|
||||
|
||||
|
||||
def get(name: str) -> Union[DVCXDataset, DVCDataset, URLDataset]:
|
||||
from difflib import get_close_matches
|
||||
|
||||
from dvc.fs import get_cloud_fs
|
||||
from dvc.repo import Repo, datasets
|
||||
|
||||
repo = Repo()
|
||||
try:
|
||||
dataset = repo.datasets[name]
|
||||
except datasets.DatasetNotFoundError as e:
|
||||
add_note = getattr(e, "add_note", lambda _: None)
|
||||
if matches := get_close_matches(name, repo.datasets):
|
||||
add_note(f"Did you mean: {matches[0]!r}?")
|
||||
raise
|
||||
|
||||
if dataset._invalidated:
|
||||
raise ValueError(f"dataset not in sync. Sync with 'dvc ds update {name}'.")
|
||||
if not dataset.lock:
|
||||
raise ValueError("missing lock information")
|
||||
if dataset.type == "dvc":
|
||||
return DVCDataset(
|
||||
type="dvc",
|
||||
url=dataset.lock.url,
|
||||
path=dataset.lock.path,
|
||||
sha=dataset.lock.rev_lock,
|
||||
)
|
||||
if dataset.type == "dvcx":
|
||||
return DVCXDataset(
|
||||
type="dvcx", name=dataset.name_version[0], version=dataset.lock.version
|
||||
)
|
||||
if dataset.type == "url":
|
||||
fs_cls, _, path = get_cloud_fs(repo.config, url=dataset.lock.url)
|
||||
assert fs_cls
|
||||
join_version = getattr(fs_cls, "join_version", lambda path, _: path)
|
||||
protocol = fs_cls.protocol
|
||||
versioned_path = join_version(path, dataset.lock.meta.version_id)
|
||||
versioned_path = f"{protocol}://{versioned_path}"
|
||||
files = [
|
||||
join_version(
|
||||
fs_cls.join(versioned_path, file.relpath), file.meta.version_id
|
||||
)
|
||||
for file in dataset.lock.files
|
||||
]
|
||||
return URLDataset(type="url", files=files, path=versioned_path)
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Dict, List, Optional, Union
|
||||
from typing import Optional, Union
|
||||
|
||||
from rich.text import Text
|
||||
|
||||
@@ -9,7 +9,7 @@ from dvc.repo.experiments.show import tabulate
|
||||
def exp_save(
|
||||
name: Optional[str] = None,
|
||||
force: bool = False,
|
||||
include_untracked: Optional[List[str]] = None,
|
||||
include_untracked: Optional[list[str]] = None,
|
||||
):
|
||||
"""
|
||||
Create a new DVC experiment using `exp save`.
|
||||
@@ -61,12 +61,12 @@ def _postprocess(exp_rows):
|
||||
|
||||
def exp_show(
|
||||
repo: Optional[str] = None,
|
||||
revs: Optional[Union[str, List[str]]] = None,
|
||||
revs: Optional[Union[str, list[str]]] = None,
|
||||
num: int = 1,
|
||||
param_deps: bool = False,
|
||||
force: bool = False,
|
||||
config: Optional[Dict] = None,
|
||||
) -> List[Dict]:
|
||||
config: Optional[dict] = None,
|
||||
) -> list[dict]:
|
||||
"""Get DVC experiments tracked in `repo`.
|
||||
|
||||
Without arguments, this function will retrieve all experiments derived from
|
||||
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
from typing import List, Optional
|
||||
from typing import Optional
|
||||
|
||||
from dvc.repo import Repo
|
||||
|
||||
|
||||
def all_branches(repo: Optional[str] = None) -> List[str]:
|
||||
def all_branches(repo: Optional[str] = None) -> list[str]:
|
||||
"""Get all Git branches in a DVC repository.
|
||||
|
||||
Args:
|
||||
@@ -20,7 +20,7 @@ def all_branches(repo: Optional[str] = None) -> List[str]:
|
||||
return _repo.scm.list_branches()
|
||||
|
||||
|
||||
def all_commits(repo: Optional[str] = None) -> List[str]:
|
||||
def all_commits(repo: Optional[str] = None) -> list[str]:
|
||||
"""Get all Git commits in a DVC repository.
|
||||
|
||||
Args:
|
||||
@@ -37,7 +37,7 @@ def all_commits(repo: Optional[str] = None) -> List[str]:
|
||||
return _repo.scm.list_all_commits()
|
||||
|
||||
|
||||
def all_tags(repo: Optional[str] = None) -> List[str]:
|
||||
def all_tags(repo: Optional[str] = None) -> list[str]:
|
||||
"""Get all Git tags in a DVC repository.
|
||||
|
||||
Args:
|
||||
|
||||
+8
-7
@@ -1,6 +1,7 @@
|
||||
import typing
|
||||
from collections import Counter
|
||||
from typing import Dict, Iterable, Optional, Union
|
||||
from collections.abc import Iterable
|
||||
from typing import Optional, Union
|
||||
|
||||
from funcy import first
|
||||
|
||||
@@ -8,7 +9,7 @@ from dvc.repo import Repo
|
||||
|
||||
|
||||
def _postprocess(results):
|
||||
processed: Dict[str, Dict] = {}
|
||||
processed: dict[str, dict] = {}
|
||||
for rev, rev_data in results.items():
|
||||
if not rev_data:
|
||||
continue
|
||||
@@ -24,7 +25,7 @@ def _postprocess(results):
|
||||
(k if counts[k] == 1 else f"{file_name}:{k}"): v
|
||||
for k, v in file_data["data"].items()
|
||||
}
|
||||
processed[rev] = {**processed[rev], **to_merge}
|
||||
processed[rev] = processed[rev] | to_merge
|
||||
|
||||
if "workspace" in processed:
|
||||
del processed["workspace"]
|
||||
@@ -36,8 +37,8 @@ def metrics_show(
|
||||
*targets: str,
|
||||
repo: Optional[str] = None,
|
||||
rev: Optional[str] = None,
|
||||
config: Optional[Dict] = None,
|
||||
) -> Dict:
|
||||
config: Optional[dict] = None,
|
||||
) -> dict:
|
||||
"""Get metrics tracked in `repo`.
|
||||
|
||||
Without arguments, this function will retrieve all metrics from all tracked
|
||||
@@ -159,8 +160,8 @@ def params_show(
|
||||
stages: Optional[Union[str, Iterable[str]]] = None,
|
||||
rev: Optional[str] = None,
|
||||
deps: bool = False,
|
||||
config: Optional[Dict] = None,
|
||||
) -> Dict:
|
||||
config: Optional[dict] = None,
|
||||
) -> dict:
|
||||
"""Get parameters tracked in `repo`.
|
||||
|
||||
Without arguments, this function will retrieve all params from all tracked
|
||||
|
||||
+6
-12
@@ -1,5 +1,5 @@
|
||||
import os
|
||||
from typing import TYPE_CHECKING, Optional, Tuple
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from dvc.fs import GitFileSystem, Schemes
|
||||
from dvc_data.hashfile.db import get_odb
|
||||
@@ -15,7 +15,7 @@ def _get_odb(
|
||||
repo,
|
||||
settings,
|
||||
fs=None,
|
||||
prefix: Optional[Tuple[str, ...]] = None,
|
||||
prefix: Optional[tuple[str, ...]] = None,
|
||||
hash_name: Optional[str] = None,
|
||||
**kwargs,
|
||||
):
|
||||
@@ -27,7 +27,7 @@ def _get_odb(
|
||||
cls, config, fs_path = get_cloud_fs(repo.config, **settings)
|
||||
fs = fs or cls(**config)
|
||||
if prefix:
|
||||
fs_path = fs.path.join(fs_path, *prefix)
|
||||
fs_path = fs.join(fs_path, *prefix)
|
||||
if hash_name:
|
||||
config["hash_name"] = hash_name
|
||||
return get_odb(fs, fs_path, state=repo.state, **config)
|
||||
@@ -86,7 +86,7 @@ class CacheManager:
|
||||
return FileStorage(
|
||||
key=(),
|
||||
fs=self.local.fs,
|
||||
path=self.local.fs.path.join(self.default_local_cache_dir, self.FS_DIR),
|
||||
path=self.local.fs.join(self.default_local_cache_dir, self.FS_DIR),
|
||||
)
|
||||
|
||||
def _init_odb(self, schemes):
|
||||
@@ -144,15 +144,9 @@ def migrate_2_to_3(repo: "Repo", dry: bool = False):
|
||||
)
|
||||
return
|
||||
|
||||
with TqdmCallback(
|
||||
desc="Computing DVC 3.0 hashes",
|
||||
unit="files",
|
||||
) as cb:
|
||||
with TqdmCallback(desc="Computing DVC 3.0 hashes", unit="files") as cb:
|
||||
migration = prepare(src, dest, callback=cb)
|
||||
|
||||
with TqdmCallback(
|
||||
desc="Migrating to DVC 3.0 cache",
|
||||
unit="files",
|
||||
) as cb:
|
||||
with TqdmCallback(desc="Migrating to DVC 3.0 cache", unit="files") as cb:
|
||||
count = migrate(migration, callback=cb)
|
||||
ui.write(f"Migrated {count} files to DVC 3.0 cache location.")
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import argparse
|
||||
|
||||
|
||||
class HelpFormatter(argparse.HelpFormatter):
|
||||
def _get_default_metavar_for_optional(self, action: argparse.Action) -> str:
|
||||
return action.dest
|
||||
|
||||
|
||||
class RawTextHelpFormatter(HelpFormatter, argparse.RawTextHelpFormatter):
|
||||
pass
|
||||
|
||||
|
||||
class RawDescriptionHelpFormatter(HelpFormatter, argparse.RawDescriptionHelpFormatter):
|
||||
pass
|
||||
+47
-42
@@ -17,8 +17,10 @@ from dvc.commands import (
|
||||
dag,
|
||||
data,
|
||||
data_sync,
|
||||
dataset,
|
||||
destroy,
|
||||
diff,
|
||||
du,
|
||||
experiments,
|
||||
freeze,
|
||||
gc,
|
||||
@@ -26,6 +28,7 @@ from dvc.commands import (
|
||||
get_url,
|
||||
git_hook,
|
||||
imp,
|
||||
imp_db,
|
||||
imp_url,
|
||||
init,
|
||||
install,
|
||||
@@ -41,56 +44,61 @@ from dvc.commands import (
|
||||
repro,
|
||||
root,
|
||||
stage,
|
||||
studio,
|
||||
unprotect,
|
||||
update,
|
||||
version,
|
||||
)
|
||||
from dvc.log import logger
|
||||
|
||||
from . import DvcParserError
|
||||
from . import DvcParserError, formatter
|
||||
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
COMMANDS = [
|
||||
init,
|
||||
queue,
|
||||
get,
|
||||
get_url,
|
||||
destroy,
|
||||
add,
|
||||
remove,
|
||||
move,
|
||||
unprotect,
|
||||
repro,
|
||||
data_sync,
|
||||
gc,
|
||||
imp,
|
||||
imp_url,
|
||||
config,
|
||||
checkout,
|
||||
remote,
|
||||
artifacts,
|
||||
cache,
|
||||
metrics,
|
||||
params,
|
||||
install,
|
||||
root,
|
||||
ls,
|
||||
ls_url,
|
||||
freeze,
|
||||
dag,
|
||||
daemon,
|
||||
check_ignore,
|
||||
checkout,
|
||||
commit,
|
||||
completion,
|
||||
diff,
|
||||
version,
|
||||
update,
|
||||
git_hook,
|
||||
plots,
|
||||
stage,
|
||||
experiments,
|
||||
check_ignore,
|
||||
config,
|
||||
daemon,
|
||||
dag,
|
||||
data,
|
||||
artifacts,
|
||||
data_sync,
|
||||
dataset,
|
||||
destroy,
|
||||
diff,
|
||||
du,
|
||||
experiments,
|
||||
freeze,
|
||||
gc,
|
||||
get,
|
||||
get_url,
|
||||
git_hook,
|
||||
imp,
|
||||
imp_db,
|
||||
imp_url,
|
||||
init,
|
||||
install,
|
||||
ls,
|
||||
ls_url,
|
||||
metrics,
|
||||
move,
|
||||
params,
|
||||
plots,
|
||||
queue,
|
||||
remote,
|
||||
remove,
|
||||
repro,
|
||||
root,
|
||||
stage,
|
||||
studio,
|
||||
unprotect,
|
||||
update,
|
||||
version,
|
||||
]
|
||||
|
||||
|
||||
@@ -159,7 +167,7 @@ def get_main_parser():
|
||||
prog="dvc",
|
||||
description=desc,
|
||||
parents=[parent_parser],
|
||||
formatter_class=argparse.RawTextHelpFormatter,
|
||||
formatter_class=formatter.RawTextHelpFormatter,
|
||||
add_help=False,
|
||||
)
|
||||
|
||||
@@ -194,15 +202,12 @@ def get_main_parser():
|
||||
# Sub commands
|
||||
subparsers = parser.add_subparsers(
|
||||
title="Available Commands",
|
||||
metavar="COMMAND",
|
||||
metavar="command",
|
||||
dest="cmd",
|
||||
help="Use `dvc COMMAND --help` for command-specific help.",
|
||||
help="Use `dvc command --help` for command-specific help.",
|
||||
required=True,
|
||||
)
|
||||
|
||||
from .utils import fix_subparsers
|
||||
|
||||
fix_subparsers(subparsers)
|
||||
|
||||
for cmd in COMMANDS:
|
||||
cmd.add_parser(subparsers, parent_parser)
|
||||
|
||||
|
||||
@@ -26,18 +26,6 @@ class DictAction(argparse.Action):
|
||||
setattr(args, self.dest, d)
|
||||
|
||||
|
||||
def fix_subparsers(subparsers):
|
||||
"""Workaround for bug in Python 3. See more info at:
|
||||
https://bugs.python.org/issue16308
|
||||
https://github.com/iterative/dvc/issues/769
|
||||
|
||||
Args:
|
||||
subparsers: subparsers to fix.
|
||||
"""
|
||||
subparsers.required = True
|
||||
subparsers.dest = "cmd"
|
||||
|
||||
|
||||
def append_doc_link(help_message, path):
|
||||
from dvc.utils import format_link
|
||||
|
||||
|
||||
+2
-4
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -71,7 +69,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(ADD_HELP, "add"),
|
||||
help=ADD_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-commit",
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import DictAction, append_doc_link, fix_subparsers
|
||||
from dvc.cli.utils import DictAction, append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
|
||||
@@ -47,13 +45,13 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(ARTIFACTS_HELP, "artifacts"),
|
||||
help=ARTIFACTS_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
artifacts_subparsers = artifacts_parser.add_subparsers(
|
||||
dest="cmd",
|
||||
help="Use `dvc artifacts CMD --help` to display command-specific help.",
|
||||
required=True,
|
||||
)
|
||||
fix_subparsers(artifacts_subparsers)
|
||||
|
||||
ARTIFACTS_GET_HELP = "Download an artifact from a DVC project."
|
||||
get_parser = artifacts_subparsers.add_parser(
|
||||
@@ -61,7 +59,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(ARTIFACTS_GET_HELP, "artifacts/get"),
|
||||
help=ARTIFACTS_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
get_parser.add_argument("url", help="Location of DVC repository to download from")
|
||||
get_parser.add_argument(
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import argparse
|
||||
import os
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link, fix_subparsers
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.commands.config import CmdConfig
|
||||
from dvc.ui import ui
|
||||
|
||||
@@ -58,12 +58,13 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(CACHE_HELP, "cache"),
|
||||
help=CACHE_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
|
||||
cache_subparsers = cache_parser.add_subparsers(
|
||||
dest="cmd",
|
||||
help="Use `dvc cache CMD --help` for command-specific help.",
|
||||
required=True,
|
||||
)
|
||||
|
||||
parent_cache_config_parser = argparse.ArgumentParser(
|
||||
@@ -76,7 +77,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser, parent_cache_config_parser],
|
||||
description=append_doc_link(CACHE_HELP, "cache/dir"),
|
||||
help=CACHE_DIR_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
cache_dir_parser.add_argument(
|
||||
"-u",
|
||||
@@ -103,7 +104,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(CACHE_HELP, "cache/migrate"),
|
||||
help=CACHE_MIGRATE_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
cache_migrate_parser.add_argument(
|
||||
"--dvc-files",
|
||||
@@ -122,5 +123,3 @@ def add_parser(subparsers, parent_parser):
|
||||
action="store_true",
|
||||
)
|
||||
cache_migrate_parser.set_defaults(func=CmdCacheMigrate)
|
||||
|
||||
fix_subparsers(cache_subparsers)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.ui import ui
|
||||
@@ -85,7 +83,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(ADD_HELP, "check-ignore"),
|
||||
help=ADD_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-d",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import argparse
|
||||
import operator
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import CheckoutError
|
||||
@@ -67,7 +66,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(CHECKOUT_HELP, "checkout"),
|
||||
help=CHECKOUT_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
checkout_parser.add_argument(
|
||||
"--summary",
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -40,7 +38,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(COMMIT_HELP, "commit"),
|
||||
help=COMMIT_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
commit_parser.add_argument(
|
||||
"-f",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.completion import PREAMBLE
|
||||
from dvc.cli.utils import append_doc_link
|
||||
@@ -31,7 +30,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(COMPLETION_DESCRIPTION, "completion"),
|
||||
help=COMPLETION_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
completion_parser.add_argument(
|
||||
"-s",
|
||||
|
||||
+23
-20
@@ -1,6 +1,9 @@
|
||||
import argparse
|
||||
import os
|
||||
|
||||
from funcy import set_in
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -8,7 +11,7 @@ from dvc.ui import ui
|
||||
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
NAME_REGEX = r"^(?P<remote>remote\.)?(?P<section>[^\.]*)\.(?P<option>[^\.]*)$"
|
||||
NAME_REGEX = r"^(?P<top>(remote|db)\.)?(?P<section>[^\.]*)\.(?P<option>[^\.]*)$"
|
||||
|
||||
|
||||
def _name_type(value):
|
||||
@@ -17,10 +20,12 @@ def _name_type(value):
|
||||
match = re.match(NAME_REGEX, value)
|
||||
if not match:
|
||||
raise argparse.ArgumentTypeError(
|
||||
"name argument should look like remote.name.option or section.option"
|
||||
"name argument should look like remote.name.option or "
|
||||
"db.name.option or section.option"
|
||||
)
|
||||
top = match.group("top")
|
||||
return (
|
||||
bool(match.group("remote")),
|
||||
top.strip(".") if top else None,
|
||||
match.group("section").lower(),
|
||||
match.group("option").lower(),
|
||||
)
|
||||
@@ -49,12 +54,11 @@ class CmdConfig(CmdBaseNoRepo):
|
||||
logger.error("name argument is required")
|
||||
return 1
|
||||
|
||||
remote, section, opt = self.args.name
|
||||
remote_or_db, section, opt = self.args.name
|
||||
|
||||
if self.args.value is None and not self.args.unset:
|
||||
return self._get(remote, section, opt)
|
||||
|
||||
return self._set(remote, section, opt)
|
||||
return self._get(remote_or_db, section, opt)
|
||||
return self._set(remote_or_db, section, opt)
|
||||
|
||||
def _list(self):
|
||||
if any((self.args.name, self.args.value, self.args.unset)):
|
||||
@@ -75,18 +79,18 @@ class CmdConfig(CmdBaseNoRepo):
|
||||
|
||||
return 0
|
||||
|
||||
def _get(self, remote, section, opt):
|
||||
def _get(self, remote_or_db, section, opt):
|
||||
from dvc.config import ConfigError
|
||||
|
||||
levels = self._get_appropriate_levels(self.args.level)[::-1]
|
||||
|
||||
for level in levels:
|
||||
conf = self.config.read(level)
|
||||
if remote:
|
||||
conf = conf["remote"]
|
||||
if remote_or_db:
|
||||
conf = conf[remote_or_db]
|
||||
|
||||
try:
|
||||
self._check(conf, remote, section, opt)
|
||||
self._check(conf, remote_or_db, section, opt)
|
||||
except ConfigError:
|
||||
if self.args.level:
|
||||
raise
|
||||
@@ -99,16 +103,15 @@ class CmdConfig(CmdBaseNoRepo):
|
||||
|
||||
return 0
|
||||
|
||||
def _set(self, remote, section, opt):
|
||||
def _set(self, remote_or_db, section, opt):
|
||||
with self.config.edit(self.args.level) as conf:
|
||||
if remote:
|
||||
conf = conf["remote"]
|
||||
if remote_or_db:
|
||||
conf = conf[remote_or_db]
|
||||
if self.args.unset:
|
||||
self._check(conf, remote, section, opt)
|
||||
self._check(conf, remote_or_db, section, opt)
|
||||
del conf[section][opt]
|
||||
else:
|
||||
self._check(conf, remote, section)
|
||||
conf[section][opt] = self.args.value
|
||||
conf.update(set_in(conf, [section, opt], self.args.value))
|
||||
|
||||
if self.args.name == "cache.type":
|
||||
logger.warning(
|
||||
@@ -119,10 +122,10 @@ class CmdConfig(CmdBaseNoRepo):
|
||||
|
||||
return 0
|
||||
|
||||
def _check(self, conf, remote, section, opt=None):
|
||||
def _check(self, conf, remote_or_db, section, opt=None):
|
||||
from dvc.config import ConfigError
|
||||
|
||||
name = "remote" if remote else "section"
|
||||
name = remote_or_db or "section"
|
||||
if section not in conf:
|
||||
raise ConfigError(f"{name} '{section}' doesn't exist")
|
||||
|
||||
@@ -207,7 +210,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_config_parser, parent_parser],
|
||||
description=append_doc_link(CONFIG_HELP, "config"),
|
||||
help=CONFIG_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
config_parser.add_argument(
|
||||
"-u",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import fix_subparsers
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logger.getChild(__name__)
|
||||
@@ -53,10 +52,9 @@ def add_parser(subparsers, parent_parser):
|
||||
daemon_subparsers = daemon_parser.add_subparsers(
|
||||
dest="cmd",
|
||||
help="Use `dvc daemon CMD --help` for command-specific help.",
|
||||
required=True,
|
||||
)
|
||||
|
||||
fix_subparsers(daemon_subparsers)
|
||||
|
||||
DAEMON_UPDATER_HELP = "Fetch latest available version."
|
||||
daemon_updater_parser = daemon_subparsers.add_parser(
|
||||
"updater",
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
import argparse
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.ui import ui
|
||||
@@ -86,7 +86,7 @@ def _collect_targets(repo, target, outs):
|
||||
targets.extend([str(out) for out in stage.outs])
|
||||
continue
|
||||
|
||||
for out in outs_trie.itervalues(prefix=repo.fs.path.parts(path)):
|
||||
for out in outs_trie.itervalues(prefix=repo.fs.parts(path)):
|
||||
targets.extend(str(out))
|
||||
|
||||
return targets
|
||||
@@ -160,7 +160,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(DAG_HELP, "dag"),
|
||||
help=DAG_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
dag_parser.add_argument(
|
||||
"--dot",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import argparse
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, ClassVar
|
||||
|
||||
from funcy import chunks, compact, log_durations
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link, fix_subparsers
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
from dvc.utils import colorize
|
||||
@@ -17,14 +17,14 @@ logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdDataStatus(CmdBase):
|
||||
COLORS = {
|
||||
COLORS: ClassVar[dict[str, str]] = {
|
||||
"not_in_remote": "red",
|
||||
"not_in_cache": "red",
|
||||
"committed": "green",
|
||||
"uncommitted": "yellow",
|
||||
"untracked": "cyan",
|
||||
}
|
||||
LABELS = {
|
||||
LABELS: ClassVar[dict[str, str]] = {
|
||||
"not_in_remote": "Not in remote",
|
||||
"not_in_cache": "Not in cache",
|
||||
"committed": "DVC committed changes",
|
||||
@@ -32,7 +32,7 @@ class CmdDataStatus(CmdBase):
|
||||
"untracked": "Untracked files",
|
||||
"unchanged": "DVC unchanged files",
|
||||
}
|
||||
HINTS = {
|
||||
HINTS: ClassVar[dict[str, tuple[str, ...]]] = {
|
||||
"not_in_remote": ('use "dvc push <file>..." to upload files',),
|
||||
"not_in_cache": ('use "dvc fetch <file>..." to download files',),
|
||||
"committed": ("git commit the corresponding dvc files to update the repo",),
|
||||
@@ -129,13 +129,13 @@ def add_parser(subparsers, parent_parser):
|
||||
data_parser = subparsers.add_parser(
|
||||
"data",
|
||||
parents=[parent_parser],
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
data_subparsers = data_parser.add_subparsers(
|
||||
dest="cmd",
|
||||
help="Use `dvc data CMD --help` to display command-specific help.",
|
||||
required=True,
|
||||
)
|
||||
fix_subparsers(data_subparsers)
|
||||
|
||||
DATA_STATUS_HELP = (
|
||||
"Show changes between the last git commit, the dvcfiles and the workspace."
|
||||
@@ -144,7 +144,7 @@ def add_parser(subparsers, parent_parser):
|
||||
"status",
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(DATA_STATUS_HELP, "data/status"),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
help=DATA_STATUS_HELP,
|
||||
)
|
||||
data_status_parser.add_argument(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -145,7 +145,7 @@ def add_parser(subparsers, _parent_parser):
|
||||
parents=[shared_parent_parser()],
|
||||
description=append_doc_link(PULL_HELP, "pull"),
|
||||
help=PULL_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
pull_parser.add_argument(
|
||||
"-r", "--remote", help="Remote storage to pull from", metavar="<name>"
|
||||
@@ -220,7 +220,7 @@ def add_parser(subparsers, _parent_parser):
|
||||
parents=[shared_parent_parser()],
|
||||
description=append_doc_link(PUSH_HELP, "push"),
|
||||
help=PUSH_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
push_parser.add_argument(
|
||||
"-r", "--remote", help="Remote storage to push to", metavar="<name>"
|
||||
@@ -282,7 +282,7 @@ def add_parser(subparsers, _parent_parser):
|
||||
parents=[shared_parent_parser()],
|
||||
description=append_doc_link(FETCH_HELP, "fetch"),
|
||||
help=FETCH_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
fetch_parser.add_argument(
|
||||
"-r", "--remote", help="Remote storage to fetch from", metavar="<name>"
|
||||
@@ -355,7 +355,7 @@ def add_parser(subparsers, _parent_parser):
|
||||
description=append_doc_link(STATUS_HELP, "status"),
|
||||
help=STATUS_HELP,
|
||||
conflict_handler="resolve",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
status_parser.add_argument(
|
||||
"-q",
|
||||
@@ -429,5 +429,11 @@ def add_parser(subparsers, _parent_parser):
|
||||
default=False,
|
||||
help="Show status in JSON format.",
|
||||
)
|
||||
status_parser.add_argument(
|
||||
"--no-updates",
|
||||
dest="check_updates",
|
||||
action="store_false",
|
||||
help="Ignore updates to imported data.",
|
||||
)
|
||||
|
||||
status_parser.set_defaults(func=CmdDataStatus)
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from rich.text import Text
|
||||
|
||||
from dvc.repo.datasets import Dataset, FileInfo
|
||||
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
def diff_files(old: list["FileInfo"], new: list["FileInfo"]) -> dict[str, list[str]]:
|
||||
old_files = {d.relpath: d for d in old}
|
||||
new_files = {d.relpath: d for d in new}
|
||||
rest = old_files.keys() & new_files.keys()
|
||||
return {
|
||||
"added": list(new_files.keys() - old_files.keys()),
|
||||
"deleted": list(old_files.keys() - new_files.keys()),
|
||||
"modified": [p for p in rest if new_files[p] != old_files[p]],
|
||||
}
|
||||
|
||||
|
||||
class CmdDatasetAdd(CmdBase):
|
||||
@classmethod
|
||||
def display(cls, name: str, dataset: "Dataset", action: str = "Adding"):
|
||||
from dvc.ui import ui
|
||||
|
||||
assert dataset.lock
|
||||
|
||||
url = dataset.spec.url
|
||||
ver: str = ""
|
||||
if dataset.type == "dvcx":
|
||||
ver = f"v{dataset.lock.version}"
|
||||
if dataset.type == "dvc":
|
||||
if dataset.lock.path:
|
||||
url = f"{url}:/{dataset.lock.path.lstrip('/')}"
|
||||
if rev := dataset.lock.rev:
|
||||
ver = rev
|
||||
|
||||
ver_part: Optional["Text"] = None
|
||||
if ver:
|
||||
ver_part = ui.rich_text.assemble(" @ ", (ver, "repr.number"))
|
||||
text = ui.rich_text.assemble("(", (url, "repr.url"), ver_part or "", ")")
|
||||
ui.write(action, ui.rich_text(name, "cyan"), text, styled=True)
|
||||
|
||||
def run(self):
|
||||
if not self.args.dvc and self.args.rev:
|
||||
raise DvcException("--rev can't be used without --dvc")
|
||||
if not self.args.dvc and self.args.path:
|
||||
raise DvcException("--path can't be used without --dvc")
|
||||
|
||||
d = vars(self.args)
|
||||
for key in ["dvc", "dvcx", "url"]:
|
||||
if url := d.pop(key, None):
|
||||
d.update({"type": key, "url": url})
|
||||
break
|
||||
|
||||
existing = self.repo.datasets.get(self.args.name)
|
||||
with self.repo.scm_context:
|
||||
if not self.args.force and existing:
|
||||
path = self.repo.fs.relpath(existing.manifest_path)
|
||||
raise DvcException(
|
||||
f"{self.args.name} already exists in {path}, "
|
||||
"use the --force to overwrite"
|
||||
)
|
||||
dataset = self.repo.datasets.add(**d)
|
||||
self.display(self.args.name, dataset)
|
||||
return 0
|
||||
|
||||
|
||||
class CmdDatasetUpdate(CmdBase):
|
||||
def display(self, name: str, dataset: "Dataset", new: "Dataset"):
|
||||
from dvc.commands.checkout import log_changes
|
||||
from dvc.ui import ui
|
||||
|
||||
action = "Updating"
|
||||
if not dataset.lock:
|
||||
return CmdDatasetAdd.display(name, new, action)
|
||||
if dataset == new:
|
||||
ui.write("[yellow]Nothing to update[/]", styled=True)
|
||||
return
|
||||
|
||||
assert new.lock
|
||||
|
||||
v: Optional[tuple[str, str]] = None
|
||||
if dataset.type == "dvcx":
|
||||
assert new.type == "dvcx"
|
||||
if new.lock.version < dataset.lock.version:
|
||||
action = "Downgrading"
|
||||
|
||||
v = (f"v{dataset.lock.version}", f"v{new.lock.version}")
|
||||
if dataset.type == "dvc":
|
||||
assert new.type == "dvc"
|
||||
v = (f"{dataset.lock.rev_lock[:9]}", f"{new.lock.rev_lock[:9]}")
|
||||
|
||||
if v:
|
||||
part = ui.rich_text.assemble(
|
||||
(v[0], "repr.number"),
|
||||
" -> ",
|
||||
(v[1], "repr.number"),
|
||||
)
|
||||
else:
|
||||
part = ui.rich_text(dataset.spec.url, "repr.url")
|
||||
changes = ui.rich_text.assemble("(", part, ")")
|
||||
ui.write(action, ui.rich_text(name, "cyan"), changes, styled=True)
|
||||
if dataset.type == "url":
|
||||
assert new.type == "url"
|
||||
stats = diff_files(dataset.lock.files, new.lock.files)
|
||||
log_changes(stats)
|
||||
|
||||
def run(self):
|
||||
from difflib import get_close_matches
|
||||
|
||||
from dvc.repo.datasets import DatasetNotFoundError
|
||||
from dvc.ui import ui
|
||||
|
||||
version = None
|
||||
if self.args.rev:
|
||||
try:
|
||||
version = int(self.args.rev.lstrip("v"))
|
||||
except ValueError:
|
||||
version = self.args.rev
|
||||
|
||||
d = vars(self.args) | {"version": version}
|
||||
with self.repo.scm_context:
|
||||
try:
|
||||
dataset, new = self.repo.datasets.update(**d)
|
||||
except DatasetNotFoundError:
|
||||
logger.exception("")
|
||||
if matches := get_close_matches(self.args.name, self.repo.datasets):
|
||||
ui.write(
|
||||
"did you mean?",
|
||||
ui.rich_text(matches[0], "cyan"),
|
||||
stderr=True,
|
||||
styled=True,
|
||||
)
|
||||
return 1
|
||||
self.display(self.args.name, dataset, new)
|
||||
return 0
|
||||
|
||||
|
||||
def add_parser(subparsers, parent_parser):
|
||||
ds_parser = subparsers.add_parser(
|
||||
"dataset",
|
||||
aliases=["ds"],
|
||||
parents=[parent_parser],
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
ds_subparsers = ds_parser.add_subparsers(
|
||||
dest="cmd",
|
||||
help="Use `dvc dataset CMD --help` to display command-specific help.",
|
||||
required=True,
|
||||
)
|
||||
|
||||
dataset_add_help = "Add a dataset."
|
||||
ds_add_parser = ds_subparsers.add_parser(
|
||||
"add",
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(dataset_add_help, "dataset/add"),
|
||||
formatter_class=formatter.RawTextHelpFormatter,
|
||||
help=dataset_add_help,
|
||||
)
|
||||
|
||||
url_exclusive_group = ds_add_parser.add_mutually_exclusive_group(required=True)
|
||||
url_exclusive_group.add_argument(
|
||||
"--dvcx", metavar="name", help="Name of the dvcx dataset to track"
|
||||
)
|
||||
url_exclusive_group.add_argument(
|
||||
"--dvc",
|
||||
help="Path or URL to a Git/DVC repository to track",
|
||||
metavar="url",
|
||||
)
|
||||
url_exclusive_group.add_argument(
|
||||
"--url",
|
||||
help="""\
|
||||
URL of a cloud-versioned remote to track. Supported URLs:
|
||||
|
||||
s3://bucket/key/path
|
||||
gs://bucket/path/to/file/or/dir
|
||||
azure://mycontainer/path
|
||||
remote://remote_name/path/to/file/or/dir (see `dvc remote`)
|
||||
""",
|
||||
)
|
||||
ds_add_parser.add_argument("name", help="Name of the dataset to add")
|
||||
ds_add_parser.add_argument(
|
||||
"--rev",
|
||||
help="Git revision, e.g. SHA, branch, tag (only applicable with --dvc)",
|
||||
metavar="<commit>",
|
||||
)
|
||||
ds_add_parser.add_argument(
|
||||
"--path",
|
||||
help="Path to a file or a directory within a git repository "
|
||||
"(only applicable with --dvc)",
|
||||
)
|
||||
ds_add_parser.add_argument(
|
||||
"-f",
|
||||
"--force",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Overwrite existing dataset",
|
||||
)
|
||||
ds_add_parser.set_defaults(func=CmdDatasetAdd)
|
||||
|
||||
dataset_update_help = "Update a dataset."
|
||||
ds_update_parser = ds_subparsers.add_parser(
|
||||
"update",
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(dataset_update_help, "dataset/update"),
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
help=dataset_update_help,
|
||||
)
|
||||
ds_update_parser.add_argument("name", help="Name of the dataset to update")
|
||||
ds_update_parser.add_argument(
|
||||
"--rev",
|
||||
"--version",
|
||||
nargs="?",
|
||||
help="DVCX dataset version or Git revision (e.g. SHA, branch, tag)",
|
||||
metavar="<version>",
|
||||
)
|
||||
ds_update_parser.set_defaults(func=CmdDatasetUpdate)
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -41,7 +40,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(DESTROY_HELP, "destroy"),
|
||||
help=DESTROY_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
destroy_parser.add_argument(
|
||||
"-f",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import argparse
|
||||
import os
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -163,7 +162,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(DIFF_DESCRIPTION, "diff"),
|
||||
help=DIFF_DESCRIPTION,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
diff_parser.add_argument(
|
||||
"--targets",
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import DictAction, append_doc_link
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CmdDU(CmdBaseNoRepo):
|
||||
def run(self):
|
||||
from dvc.repo import Repo
|
||||
from dvc.utils.humanize import naturalsize
|
||||
|
||||
entries = Repo.du(
|
||||
self.args.url,
|
||||
self.args.path,
|
||||
rev=self.args.rev,
|
||||
summarize=self.args.summarize,
|
||||
config=self.args.config,
|
||||
remote=self.args.remote,
|
||||
remote_config=self.args.remote_config,
|
||||
)
|
||||
ui.table([(naturalsize(size), path) for path, size in entries])
|
||||
return 0
|
||||
|
||||
|
||||
def add_parser(subparsers, parent_parser):
|
||||
DU_HELP = "Show disk usage."
|
||||
du_parser = subparsers.add_parser(
|
||||
"du",
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(DU_HELP, "du"),
|
||||
help=DU_HELP,
|
||||
formatter_class=formatter.RawTextHelpFormatter,
|
||||
)
|
||||
du_parser.add_argument("url", help="Location of DVC repository")
|
||||
du_parser.add_argument(
|
||||
"--rev",
|
||||
nargs="?",
|
||||
help="Git revision (e.g. SHA, branch, tag)",
|
||||
metavar="<commit>",
|
||||
)
|
||||
du_parser.add_argument(
|
||||
"-s",
|
||||
"--summarize",
|
||||
action="store_true",
|
||||
help="Show total disk usage.",
|
||||
)
|
||||
du_parser.add_argument(
|
||||
"--config",
|
||||
type=str,
|
||||
help=(
|
||||
"Path to a config file that will be merged with the config "
|
||||
"in the target repository."
|
||||
),
|
||||
)
|
||||
du_parser.add_argument(
|
||||
"--remote",
|
||||
type=str,
|
||||
help="Remote name to set as a default in the target repository.",
|
||||
)
|
||||
du_parser.add_argument(
|
||||
"--remote-config",
|
||||
type=str,
|
||||
nargs="*",
|
||||
action=DictAction,
|
||||
help=(
|
||||
"Remote config options to merge with a remote's config (default or one "
|
||||
"specified by '--remote') in the target repository."
|
||||
),
|
||||
)
|
||||
du_parser.add_argument(
|
||||
"path",
|
||||
nargs="?",
|
||||
help="Path to directory within the repository",
|
||||
).complete = completion.DIR
|
||||
du_parser.set_defaults(func=CmdDU)
|
||||
@@ -1,6 +1,5 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli.utils import append_doc_link, fix_subparsers, hide_subparsers_from_help
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.utils import append_doc_link, hide_subparsers_from_help
|
||||
from dvc.commands.experiments import (
|
||||
apply,
|
||||
branch,
|
||||
@@ -44,16 +43,16 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
aliases=["exp"],
|
||||
description=append_doc_link(EXPERIMENTS_HELP, "exp"),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
help=EXPERIMENTS_HELP,
|
||||
)
|
||||
|
||||
experiments_subparsers = experiments_parser.add_subparsers(
|
||||
dest="cmd",
|
||||
help="Use `dvc experiments CMD --help` to display command-specific help.",
|
||||
required=True,
|
||||
)
|
||||
|
||||
fix_subparsers(experiments_subparsers)
|
||||
for cmd in SUB_COMMANDS:
|
||||
cmd.add_parser(experiments_subparsers, parent_parser)
|
||||
hide_subparsers_from_help(experiments_subparsers)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -30,7 +28,7 @@ def add_parser(experiments_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(EXPERIMENTS_APPLY_HELP, "exp/apply"),
|
||||
help=EXPERIMENTS_APPLY_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
experiments_apply_parser.add_argument(
|
||||
"--no-force",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -21,7 +20,7 @@ def add_parser(experiments_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(EXPERIMENTS_BRANCH_HELP, "exp/branch"),
|
||||
help=EXPERIMENTS_BRANCH_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
experiments_branch_parser.add_argument(
|
||||
"experiment", help="Experiment to be promoted."
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -20,6 +19,6 @@ def add_parser(experiments_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(EXPERIMENTS_CLEAN_HELP, "exp/clean"),
|
||||
help=EXPERIMENTS_CLEAN_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
experiments_clean_parser.set_defaults(func=CmdExperimentsClean)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.commands.metrics import DEFAULT_PRECISION
|
||||
@@ -59,7 +57,7 @@ def add_parser(experiments_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(EXPERIMENTS_DIFF_HELP, "exp/diff"),
|
||||
help=EXPERIMENTS_DIFF_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
experiments_diff_parser.add_argument(
|
||||
"a_rev", nargs="?", help="Old experiment to compare (defaults to HEAD)"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import InvalidArgumentError
|
||||
@@ -63,7 +62,7 @@ def add_parser(experiments_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(EXPERIMENTS_LIST_HELP, "exp/list"),
|
||||
help=EXPERIMENTS_LIST_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
add_rev_selection_flags(experiments_list_parser, "List")
|
||||
display_group = experiments_list_parser.add_mutually_exclusive_group()
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -49,7 +48,7 @@ def add_parser(experiments_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(EXPERIMENTS_PULL_HELP, "exp/pull"),
|
||||
help=EXPERIMENTS_PULL_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
add_rev_selection_flags(experiments_pull_parser, "Pull", True)
|
||||
experiments_pull_parser.add_argument(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import argparse
|
||||
from typing import Any, Dict
|
||||
from typing import Any
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -12,7 +11,7 @@ logger = logger.getChild(__name__)
|
||||
|
||||
class CmdExperimentsPush(CmdBase):
|
||||
@staticmethod
|
||||
def log_result(result: Dict[str, Any], remote: str):
|
||||
def log_result(result: dict[str, Any], remote: str):
|
||||
from dvc.utils import humanize
|
||||
|
||||
def join_exps(exps):
|
||||
@@ -90,7 +89,7 @@ def add_parser(experiments_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(EXPERIMENTS_PUSH_HELP, "exp/push"),
|
||||
help=EXPERIMENTS_PUSH_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
add_rev_selection_flags(experiments_push_parser, "Push", True)
|
||||
experiments_push_parser.add_argument(
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import InvalidArgumentError
|
||||
@@ -54,7 +53,7 @@ def add_parser(experiments_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(EXPERIMENTS_REMOVE_HELP, "exp/remove"),
|
||||
help=EXPERIMENTS_REMOVE_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
remove_group = experiments_remove_parser.add_mutually_exclusive_group()
|
||||
add_rev_selection_flags(experiments_remove_parser, "Remove", False)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import InvalidArgumentError
|
||||
@@ -38,7 +37,7 @@ def add_parser(experiments_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(EXPERIMENTS_RENAME_HELP, "exp/rename"),
|
||||
help=EXPERIMENTS_RENAME_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
rename_group = experiments_rename_parser.add_mutually_exclusive_group()
|
||||
rename_group.add_argument(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.commands.repro import CmdRepro
|
||||
from dvc.commands.repro import add_arguments as add_repro_arguments
|
||||
@@ -32,7 +33,7 @@ def add_parser(experiments_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(EXPERIMENTS_RUN_HELP, "exp/run"),
|
||||
help=EXPERIMENTS_RUN_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
_add_run_common(experiments_run_parser)
|
||||
experiments_run_parser.set_defaults(func=CmdExperimentsRun)
|
||||
@@ -106,8 +107,4 @@ def _add_run_common(parser):
|
||||
default=None,
|
||||
help="Custom commit message to use when committing the experiment.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-M", # obsolete
|
||||
dest="message",
|
||||
help=argparse.SUPPRESS,
|
||||
)
|
||||
parser.add_argument("-M", dest="message", help=argparse.SUPPRESS) # obsolete
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
@@ -13,7 +14,9 @@ class CmdExperimentsSave(CmdBase):
|
||||
def run(self):
|
||||
try:
|
||||
ref = self.repo.experiments.save(
|
||||
targets=self.args.targets,
|
||||
name=self.args.name,
|
||||
recursive=self.args.recursive,
|
||||
force=self.args.force,
|
||||
include_untracked=self.args.include_untracked,
|
||||
message=self.args.message,
|
||||
@@ -38,7 +41,19 @@ def add_parser(experiments_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(EXPERIMENTS_SAVE_HELP, "exp/save"),
|
||||
help=EXPERIMENTS_SAVE_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
save_parser.add_argument(
|
||||
"targets",
|
||||
nargs="*",
|
||||
help=("Limit DVC caching to these .dvc files and stage names."),
|
||||
).complete = completion.DVCFILES_AND_STAGE
|
||||
save_parser.add_argument(
|
||||
"-R",
|
||||
"--recursive",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Cache subdirectories of the specified directory.",
|
||||
)
|
||||
save_parser.add_argument(
|
||||
"-f",
|
||||
@@ -78,9 +93,5 @@ def add_parser(experiments_subparsers, parent_parser):
|
||||
default=None,
|
||||
help="Custom commit message to use when committing the experiment.",
|
||||
)
|
||||
save_parser.add_argument(
|
||||
"-M", # obsolete
|
||||
dest="message",
|
||||
help=argparse.SUPPRESS,
|
||||
)
|
||||
save_parser.add_argument("-M", dest="message", help=argparse.SUPPRESS) # obsolete
|
||||
save_parser.set_defaults(func=CmdExperimentsSave)
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import argparse
|
||||
import re
|
||||
from collections.abc import Iterable
|
||||
from datetime import date, datetime
|
||||
from typing import TYPE_CHECKING, Dict, Iterable
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from funcy import lmap
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.commands.metrics import DEFAULT_PRECISION
|
||||
@@ -56,7 +58,7 @@ def baseline_styler(typ):
|
||||
|
||||
def show_experiments(
|
||||
td: "TabularData",
|
||||
headers: Dict[str, Iterable[str]],
|
||||
headers: dict[str, Iterable[str]],
|
||||
keep=None,
|
||||
drop=None,
|
||||
pager=True,
|
||||
@@ -200,7 +202,7 @@ def add_parser(experiments_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(EXPERIMENTS_SHOW_HELP, "exp/show"),
|
||||
help=EXPERIMENTS_SHOW_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
add_rev_selection_flags(experiments_show_parser, "Show")
|
||||
experiments_show_parser.add_argument(
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
@@ -38,7 +36,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(FREEZE_HELP, "freeze"),
|
||||
help=FREEZE_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
freeze_parser.add_argument(
|
||||
"targets", nargs="+", help="Stages or .dvc files to freeze"
|
||||
@@ -51,7 +49,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(UNFREEZE_HELP, "unfreeze"),
|
||||
help=UNFREEZE_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
unfreeze_parser.add_argument(
|
||||
"targets", nargs="+", help="Stages or .dvc files to unfreeze"
|
||||
|
||||
+11
-4
@@ -1,6 +1,6 @@
|
||||
import argparse
|
||||
import os
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -86,6 +86,7 @@ class CmdGC(CmdBase):
|
||||
num=self.args.num,
|
||||
not_in_remote=self.args.not_in_remote,
|
||||
dry=self.args.dry,
|
||||
skip_failed=self.args.skip_failed,
|
||||
)
|
||||
return 0
|
||||
|
||||
@@ -101,7 +102,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(GC_DESCRIPTION, "gc"),
|
||||
help=GC_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
gc_parser.add_argument(
|
||||
"-w",
|
||||
@@ -155,12 +156,12 @@ def add_parser(subparsers, parent_parser):
|
||||
"--date",
|
||||
type=str,
|
||||
dest="commit_date",
|
||||
metavar="<YYYY-MM-DD>",
|
||||
metavar="<yyyy-mm-dd>",
|
||||
default=None,
|
||||
help=(
|
||||
"Keep cached data referenced in the commits after ( inclusive )"
|
||||
" a certain time. Date must match the extended ISO 8601 format "
|
||||
"(YYYY-MM-DD)."
|
||||
"(yyyy-mm-dd)."
|
||||
),
|
||||
)
|
||||
gc_parser.add_argument(
|
||||
@@ -188,6 +189,12 @@ def add_parser(subparsers, parent_parser):
|
||||
help="Remote storage to collect garbage in",
|
||||
metavar="<name>",
|
||||
)
|
||||
gc_parser.add_argument(
|
||||
"--skip-failed",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Skip revisions that fail when collected.",
|
||||
)
|
||||
gc_parser.add_argument(
|
||||
"-f",
|
||||
"--force",
|
||||
|
||||
+2
-4
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import DictAction, append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
@@ -59,7 +57,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(GET_HELP, "get"),
|
||||
help=GET_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
get_parser.add_argument(
|
||||
"url", help="Location of DVC or Git repository to download from"
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import DictAction, append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
@@ -36,7 +34,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(GET_HELP, "get-url"),
|
||||
help=GET_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
get_parser.add_argument(
|
||||
"url", help="See `dvc import-url -h` for full list of supported URLs."
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import fix_subparsers
|
||||
from dvc.exceptions import NotDvcRepoError
|
||||
from dvc.log import logger
|
||||
|
||||
@@ -94,10 +94,9 @@ def add_parser(subparsers, parent_parser):
|
||||
git_hook_subparsers = git_hook_parser.add_subparsers(
|
||||
dest="cmd",
|
||||
help="Use `dvc daemon CMD --help` for command-specific help.",
|
||||
required=True,
|
||||
)
|
||||
|
||||
fix_subparsers(git_hook_subparsers)
|
||||
|
||||
PRE_COMMIT_HELP = "Run pre-commit GIT hook."
|
||||
pre_commit_parser = git_hook_subparsers.add_parser(
|
||||
"pre-commit",
|
||||
@@ -140,6 +139,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=MERGE_DRIVER_HELP,
|
||||
help=MERGE_DRIVER_HELP,
|
||||
formatter_class=formatter.HelpFormatter,
|
||||
)
|
||||
merge_driver_parser.add_argument(
|
||||
"--ancestor",
|
||||
|
||||
+2
-4
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import DictAction, append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
@@ -51,7 +49,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(IMPORT_HELP, "import"),
|
||||
help=IMPORT_HELP,
|
||||
formatter_class=argparse.RawTextHelpFormatter,
|
||||
formatter_class=formatter.RawTextHelpFormatter,
|
||||
)
|
||||
import_parser.add_argument(
|
||||
"url", help="Location of DVC or Git repository to download from"
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase, CmdBaseNoRepo
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdTestDb(CmdBaseNoRepo):
|
||||
def run(self):
|
||||
from dvc.config import Config
|
||||
from dvc.database import client
|
||||
from dvc.exceptions import DvcException
|
||||
|
||||
connection = self.args.conn
|
||||
db_config = Config.from_cwd().get("db", {})
|
||||
if connection not in db_config:
|
||||
raise DvcException(f"connection {connection} not found in config")
|
||||
|
||||
config = db_config.get(connection, {})
|
||||
if self.args.url:
|
||||
config["url"] = self.args.url
|
||||
if self.args.username:
|
||||
config["username"] = self.args.username
|
||||
if self.args.password:
|
||||
config["password"] = self.args.password
|
||||
with client(config) as db:
|
||||
ui.write(f"Testing with {db}", styled=True)
|
||||
db.test_connection()
|
||||
ui.write("Connection successful", styled=True)
|
||||
|
||||
|
||||
class CmdImportDb(CmdBase):
|
||||
def run(self):
|
||||
self.repo.imp_db(
|
||||
sql=self.args.sql,
|
||||
table=self.args.table,
|
||||
output_format=self.args.output_format,
|
||||
out=self.args.out,
|
||||
force=self.args.force,
|
||||
connection=self.args.conn,
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
def add_parser(subparsers, parent_parser):
|
||||
IMPORT_HELP = "Snapshot a table or a SQL query result to a CSV/JSON format"
|
||||
import_parser = subparsers.add_parser(
|
||||
"import-db",
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(IMPORT_HELP, "import-db"),
|
||||
help=IMPORT_HELP,
|
||||
formatter_class=formatter.RawTextHelpFormatter,
|
||||
)
|
||||
group = import_parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument("--sql", help="SQL query to snapshot")
|
||||
group.add_argument("--table", help="Table to snapshot")
|
||||
import_parser.add_argument(
|
||||
"--output-format",
|
||||
default="csv",
|
||||
const="csv",
|
||||
nargs="?",
|
||||
choices=["csv", "json"],
|
||||
help="Export format",
|
||||
)
|
||||
import_parser.add_argument(
|
||||
"-o",
|
||||
"--out",
|
||||
nargs="?",
|
||||
help="Destination path to download files to",
|
||||
metavar="<path>",
|
||||
).complete = completion.FILE
|
||||
import_parser.add_argument(
|
||||
"-f",
|
||||
"--force",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Override destination file or folder if exists.",
|
||||
)
|
||||
import_parser.add_argument(
|
||||
"--conn",
|
||||
required=True,
|
||||
help="Database connection to use, needs to be set in config",
|
||||
)
|
||||
|
||||
import_parser.set_defaults(func=CmdImportDb)
|
||||
|
||||
TEST_DB_HELP = "Test the database connection"
|
||||
test_db_parser = subparsers.add_parser(
|
||||
"test-db",
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(TEST_DB_HELP, "test-db"),
|
||||
add_help=False,
|
||||
)
|
||||
test_db_parser.add_argument("--conn", required=True)
|
||||
test_db_parser.add_argument("--url")
|
||||
test_db_parser.add_argument("--password")
|
||||
test_db_parser.add_argument("--username")
|
||||
test_db_parser.set_defaults(func=CmdTestDb)
|
||||
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import DictAction, append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
@@ -44,7 +42,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(IMPORT_HELP, "import-url"),
|
||||
help=IMPORT_HELP,
|
||||
formatter_class=argparse.RawTextHelpFormatter,
|
||||
formatter_class=formatter.RawTextHelpFormatter,
|
||||
)
|
||||
import_parser.add_argument(
|
||||
"url",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import argparse
|
||||
|
||||
import colorama
|
||||
|
||||
from dvc import analytics
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -69,7 +68,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(INIT_DESCRIPTION, "init"),
|
||||
help=INIT_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
init_parser.add_argument(
|
||||
"--no-scm",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
@@ -25,7 +24,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(INSTALL_HELP, "install"),
|
||||
help=INSTALL_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
install_parser.add_argument(
|
||||
"--use-pre-commit-tool",
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import DictAction, append_doc_link
|
||||
from dvc.commands.ls.ls_colors import LsColors
|
||||
@@ -59,6 +57,9 @@ class CmdList(CmdBaseNoRepo):
|
||||
elif entries:
|
||||
show_entries(entries, with_color=True, with_size=self.args.size)
|
||||
return 0
|
||||
except FileNotFoundError:
|
||||
logger.exception("")
|
||||
return 1
|
||||
except DvcException:
|
||||
logger.exception("failed to list '%s'", self.args.url)
|
||||
return 1
|
||||
@@ -75,7 +76,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(LIST_HELP, "list"),
|
||||
help=LIST_HELP,
|
||||
formatter_class=argparse.RawTextHelpFormatter,
|
||||
formatter_class=formatter.RawTextHelpFormatter,
|
||||
)
|
||||
list_parser.add_argument("url", help="Location of DVC repository to list")
|
||||
list_parser.add_argument(
|
||||
@@ -121,11 +122,7 @@ def add_parser(subparsers, parent_parser):
|
||||
"specified by '--remote') in the target repository."
|
||||
),
|
||||
)
|
||||
list_parser.add_argument(
|
||||
"--size",
|
||||
action="store_true",
|
||||
help="Show sizes.",
|
||||
)
|
||||
list_parser.add_argument("--size", action="store_true", help="Show sizes.")
|
||||
list_parser.add_argument(
|
||||
"path",
|
||||
nargs="?",
|
||||
|
||||
@@ -20,7 +20,7 @@ class LsColors:
|
||||
else:
|
||||
self._codes[code] = color
|
||||
|
||||
def format(self, entry): # noqa: A003
|
||||
def format(self, entry):
|
||||
text = entry["path"]
|
||||
|
||||
if entry.get("isout", False) and "out" in self._codes:
|
||||
|
||||
+4
-12
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import DictAction, append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -33,22 +32,15 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(LS_HELP, "list-url"),
|
||||
help=LS_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
lsurl_parser.add_argument(
|
||||
"url", help="See `dvc import-url -h` for full list of supported URLs."
|
||||
)
|
||||
lsurl_parser.add_argument(
|
||||
"-R",
|
||||
"--recursive",
|
||||
action="store_true",
|
||||
help="Recursively list files.",
|
||||
)
|
||||
lsurl_parser.add_argument(
|
||||
"--size",
|
||||
action="store_true",
|
||||
help="Show sizes.",
|
||||
"-R", "--recursive", action="store_true", help="Recursively list files."
|
||||
)
|
||||
lsurl_parser.add_argument("--size", action="store_true", help="Show sizes.")
|
||||
lsurl_parser.add_argument(
|
||||
"--fs-config",
|
||||
type=str,
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link, fix_subparsers
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
from dvc.utils.serialize import encode_exception
|
||||
@@ -107,23 +105,22 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(METRICS_HELP, "metrics"),
|
||||
help=METRICS_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
|
||||
metrics_subparsers = metrics_parser.add_subparsers(
|
||||
dest="cmd",
|
||||
help="Use `dvc metrics CMD --help` to display command-specific help.",
|
||||
required=True,
|
||||
)
|
||||
|
||||
fix_subparsers(metrics_subparsers)
|
||||
|
||||
METRICS_SHOW_HELP = "Print metrics, with optional formatting."
|
||||
metrics_show_parser = metrics_subparsers.add_parser(
|
||||
"show",
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(METRICS_SHOW_HELP, "metrics/show"),
|
||||
help=METRICS_SHOW_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
metrics_show_parser.add_argument(
|
||||
"targets",
|
||||
@@ -197,7 +194,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(METRICS_DIFF_HELP, "metrics/diff"),
|
||||
help=METRICS_DIFF_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
metrics_diff_parser.add_argument(
|
||||
"a_rev",
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
@@ -34,7 +32,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(MOVE_DESCRIPTION, "move"),
|
||||
help=MOVE_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
move_parser.add_argument(
|
||||
"src", help="Source path to a data file or directory."
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link, fix_subparsers
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
@@ -61,16 +59,15 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(PARAMS_HELP, "params"),
|
||||
help=PARAMS_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
|
||||
params_subparsers = params_parser.add_subparsers(
|
||||
dest="cmd",
|
||||
help="Use `dvc params CMD --help` to display command-specific help.",
|
||||
required=True,
|
||||
)
|
||||
|
||||
fix_subparsers(params_subparsers)
|
||||
|
||||
PARAMS_DIFF_HELP = (
|
||||
"Show changes in params between commits in the DVC repository, or "
|
||||
"between a commit and the workspace."
|
||||
@@ -80,7 +77,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(PARAMS_DIFF_HELP, "params/diff"),
|
||||
help=PARAMS_DIFF_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
params_diff_parser.add_argument(
|
||||
"a_rev",
|
||||
|
||||
+16
-73
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import os
|
||||
from typing import TYPE_CHECKING, Dict, List, Optional
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from funcy import compact, first, get_in
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link, fix_subparsers
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
@@ -20,35 +20,26 @@ logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
def _show_json(
|
||||
renderers_with_errors: List["RendererWithErrors"],
|
||||
renderers_with_errors: list["RendererWithErrors"],
|
||||
split=False,
|
||||
errors: Optional[Dict[str, Exception]] = None,
|
||||
errors: Optional[dict[str, Exception]] = None,
|
||||
):
|
||||
from dvc.render.convert import to_json
|
||||
from dvc.utils.serialize import encode_exception
|
||||
|
||||
all_errors: List[Dict] = []
|
||||
all_errors: list[dict] = []
|
||||
data = {}
|
||||
|
||||
for renderer, src_errors, def_errors in renderers_with_errors:
|
||||
name = renderer.name
|
||||
data[name] = to_json(renderer, split)
|
||||
all_errors.extend(
|
||||
{
|
||||
"name": name,
|
||||
"rev": rev,
|
||||
"source": source,
|
||||
**encode_exception(e),
|
||||
}
|
||||
{"name": name, "rev": rev, "source": source, **encode_exception(e)}
|
||||
for rev, per_rev_src_errors in src_errors.items()
|
||||
for source, e in per_rev_src_errors.items()
|
||||
)
|
||||
all_errors.extend(
|
||||
{
|
||||
"name": name,
|
||||
"rev": rev,
|
||||
**encode_exception(e),
|
||||
}
|
||||
{"name": name, "rev": rev, **encode_exception(e)}
|
||||
for rev, e in def_errors.items()
|
||||
)
|
||||
|
||||
@@ -59,49 +50,6 @@ def _show_json(
|
||||
ui.write_json(compact({"errors": all_errors, "data": data}), highlight=False)
|
||||
|
||||
|
||||
def _adjust_vega_renderers(renderers):
|
||||
from dvc.render import REVISION_FIELD, VERSION_FIELD
|
||||
from dvc_render import VegaRenderer
|
||||
|
||||
for r in renderers:
|
||||
if isinstance(r, VegaRenderer):
|
||||
if _data_versions_count(r) > 1:
|
||||
summary = _summarize_version_infos(r)
|
||||
for dp in r.datapoints:
|
||||
vi = dp.pop(VERSION_FIELD, {})
|
||||
keys = list(vi.keys())
|
||||
for key in keys:
|
||||
if not (len(summary.get(key, set())) > 1):
|
||||
vi.pop(key)
|
||||
if vi:
|
||||
dp["rev"] = "::".join(vi.values())
|
||||
else:
|
||||
for dp in r.datapoints:
|
||||
dp[REVISION_FIELD] = dp[VERSION_FIELD]["revision"]
|
||||
dp.pop(VERSION_FIELD, {})
|
||||
|
||||
|
||||
def _summarize_version_infos(renderer):
|
||||
from collections import defaultdict
|
||||
|
||||
from dvc.render import VERSION_FIELD
|
||||
|
||||
result = defaultdict(set)
|
||||
|
||||
for dp in renderer.datapoints:
|
||||
for key, value in dp.get(VERSION_FIELD, {}).items():
|
||||
result[key].add(value)
|
||||
return dict(result)
|
||||
|
||||
|
||||
def _data_versions_count(renderer):
|
||||
from itertools import product
|
||||
|
||||
summary = _summarize_version_infos(renderer)
|
||||
x = product(summary.get("filename", {None}), summary.get("field", {None}))
|
||||
return len(set(x))
|
||||
|
||||
|
||||
class CmdPlots(CmdBase):
|
||||
def _func(self, *args, **kwargs):
|
||||
raise NotImplementedError
|
||||
@@ -144,10 +92,7 @@ class CmdPlots(CmdBase):
|
||||
return 1
|
||||
|
||||
try:
|
||||
plots_data = self._func(
|
||||
targets=self.args.targets,
|
||||
props=self._props(),
|
||||
)
|
||||
plots_data = self._func(targets=self.args.targets, props=self._props())
|
||||
|
||||
if not plots_data and not self.args.json:
|
||||
ui.error_write(
|
||||
@@ -175,11 +120,10 @@ class CmdPlots(CmdBase):
|
||||
return 0
|
||||
|
||||
renderers = [r.renderer for r in renderers_with_errors]
|
||||
_adjust_vega_renderers(renderers)
|
||||
if self.args.show_vega:
|
||||
renderer = first(filter(lambda r: r.TYPE == "vega", renderers))
|
||||
if renderer:
|
||||
ui.write_json(renderer.get_filled_template(as_string=False))
|
||||
ui.write_json(renderer.get_filled_template())
|
||||
return 0
|
||||
|
||||
output_file: Path = (Path.cwd() / out).resolve() / "index.html"
|
||||
@@ -267,15 +211,14 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(PLOTS_HELP, "plots"),
|
||||
help=PLOTS_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
plots_subparsers = plots_parser.add_subparsers(
|
||||
dest="cmd",
|
||||
help="Use `dvc plots CMD --help` to display command-specific help.",
|
||||
required=True,
|
||||
)
|
||||
|
||||
fix_subparsers(plots_subparsers)
|
||||
|
||||
SHOW_HELP = (
|
||||
"Generate plots from target files or from `plots` definitions in `dvc.yaml`."
|
||||
)
|
||||
@@ -284,7 +227,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(SHOW_HELP, "plots/show"),
|
||||
help=SHOW_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
plots_show_parser.add_argument(
|
||||
"targets",
|
||||
@@ -307,7 +250,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(PLOTS_DIFF_HELP, "plots/diff"),
|
||||
help=PLOTS_DIFF_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
plots_diff_parser.add_argument(
|
||||
"--targets",
|
||||
@@ -343,7 +286,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(PLOTS_MODIFY_HELP, "plots/modify"),
|
||||
help=PLOTS_MODIFY_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
plots_modify_parser.add_argument(
|
||||
"target",
|
||||
@@ -364,7 +307,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(TEMPLATES_HELP, "plots/templates"),
|
||||
help=TEMPLATES_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
plots_templates_parser.add_argument(
|
||||
"template",
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli.utils import append_doc_link, fix_subparsers
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.commands.queue import kill, logs, remove, start, status, stop
|
||||
|
||||
SUB_COMMANDS = [
|
||||
start,
|
||||
stop,
|
||||
status,
|
||||
logs,
|
||||
remove,
|
||||
kill,
|
||||
]
|
||||
SUB_COMMANDS = [start, stop, status, logs, remove, kill]
|
||||
|
||||
|
||||
def add_parser(subparsers, parent_parser):
|
||||
@@ -20,15 +12,15 @@ def add_parser(subparsers, parent_parser):
|
||||
"queue",
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(QUEUE_HELP, "queue"),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
help=QUEUE_HELP,
|
||||
)
|
||||
|
||||
queue_subparsers = queue_parser.add_subparsers(
|
||||
dest="cmd",
|
||||
help="Use `dvc queue CMD --help` to display command-specific help.",
|
||||
required=True,
|
||||
)
|
||||
|
||||
fix_subparsers(queue_subparsers)
|
||||
for cmd in SUB_COMMANDS:
|
||||
cmd.add_parser(queue_subparsers, parent_parser)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -27,7 +26,7 @@ def add_parser(queue_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(QUEUE_KILL_HELP, "queue/kill"),
|
||||
help=QUEUE_KILL_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
queue_kill_parser.add_argument(
|
||||
"-f",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -29,7 +28,7 @@ def add_parser(queue_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(QUEUE_LOGS_HELP, "queue/logs"),
|
||||
help=QUEUE_LOGS_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
queue_logs_parser.add_argument(
|
||||
"-e",
|
||||
@@ -46,9 +45,5 @@ def add_parser(queue_subparsers, parent_parser):
|
||||
),
|
||||
action="store_true",
|
||||
)
|
||||
queue_logs_parser.add_argument(
|
||||
"task",
|
||||
help="Task to show.",
|
||||
metavar="<task>",
|
||||
)
|
||||
queue_logs_parser.add_argument("task", help="Task to show.", metavar="<task>")
|
||||
queue_logs_parser.set_defaults(func=CmdQueueLogs)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import InvalidArgumentError
|
||||
@@ -62,7 +61,7 @@ def add_parser(queue_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(QUEUE_REMOVE_HELP, "queue/remove"),
|
||||
help=QUEUE_REMOVE_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
queue_remove_parser.add_argument(
|
||||
"--all",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -27,7 +26,7 @@ def add_parser(queue_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(QUEUE_START_HELP, "queue/start"),
|
||||
help=QUEUE_START_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
queue_start_parser.add_argument(
|
||||
"-j",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.compare import TabularData
|
||||
@@ -52,6 +51,6 @@ def add_parser(queue_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(QUEUE_STATUS_HELP, "queue/status"),
|
||||
help=QUEUE_STATUS_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
queue_status_parser.set_defaults(func=CmdQueueStatus)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -32,7 +31,7 @@ def add_parser(queue_subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(QUEUE_STOP_HELP, "queue/stop"),
|
||||
help=QUEUE_STOP_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
queue_stop_parser.add_argument(
|
||||
"--kill",
|
||||
|
||||
+10
-12
@@ -1,6 +1,5 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli.utils import append_doc_link, fix_subparsers
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.commands.config import CmdConfig
|
||||
from dvc.ui import ui
|
||||
from dvc.utils import format_link
|
||||
@@ -155,23 +154,22 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(REMOTE_HELP, "remote"),
|
||||
help=REMOTE_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
|
||||
remote_subparsers = remote_parser.add_subparsers(
|
||||
dest="cmd",
|
||||
help="Use `dvc remote CMD --help` for command-specific help.",
|
||||
required=True,
|
||||
)
|
||||
|
||||
fix_subparsers(remote_subparsers)
|
||||
|
||||
REMOTE_ADD_HELP = "Add a new data remote."
|
||||
remote_add_parser = remote_subparsers.add_parser(
|
||||
"add",
|
||||
parents=[parent_config_parser, parent_parser],
|
||||
description=append_doc_link(REMOTE_ADD_HELP, "remote/add"),
|
||||
help=REMOTE_ADD_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
remote_add_parser.add_argument("name", help="Name of the remote")
|
||||
remote_add_parser.add_argument(
|
||||
@@ -202,7 +200,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_config_parser, parent_parser],
|
||||
description=append_doc_link(REMOTE_DEFAULT_HELP, "remote/default"),
|
||||
help=REMOTE_DEFAULT_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
remote_default_parser.add_argument("name", nargs="?", help="Name of the remote")
|
||||
remote_default_parser.add_argument(
|
||||
@@ -220,7 +218,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_config_parser, parent_parser],
|
||||
description=append_doc_link(REMOTE_MODIFY_HELP, "remote/modify"),
|
||||
help=REMOTE_MODIFY_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
remote_modify_parser.add_argument("name", help="Name of the remote")
|
||||
remote_modify_parser.add_argument("option", help="Name of the option to modify.")
|
||||
@@ -242,7 +240,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_config_parser, parent_parser],
|
||||
description=append_doc_link(REMOTE_LIST_HELP, "remote/list"),
|
||||
help=REMOTE_LIST_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
remote_list_parser.set_defaults(func=CmdRemoteList)
|
||||
|
||||
@@ -252,7 +250,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_config_parser, parent_parser],
|
||||
description=append_doc_link(REMOTE_REMOVE_HELP, "remote/remove"),
|
||||
help=REMOTE_REMOVE_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
remote_remove_parser.add_argument("name", help="Name of the remote to remove.")
|
||||
remote_remove_parser.set_defaults(func=CmdRemoteRemove)
|
||||
@@ -262,7 +260,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_config_parser, parent_parser],
|
||||
description=append_doc_link(REMOTE_RENAME_HELP, "remote/rename"),
|
||||
help=REMOTE_RENAME_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
remote_rename_parser.add_argument("name", help="Remote to be renamed")
|
||||
remote_rename_parser.add_argument("new", help="New name of the remote")
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
@@ -30,7 +28,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(REMOVE_HELP, "remove"),
|
||||
help=REMOVE_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
remove_parser.add_argument(
|
||||
"--outs",
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.commands.status import CmdDataStatus
|
||||
@@ -167,7 +165,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(REPRO_HELP, "repro"),
|
||||
help=REPRO_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
# repro/exp run shared args
|
||||
add_arguments(repro_parser)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -24,6 +23,6 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(ROOT_HELP, "root"),
|
||||
help=ROOT_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
root_parser.set_defaults(func=CmdRoot)
|
||||
|
||||
+12
-12
@@ -1,12 +1,13 @@
|
||||
import argparse
|
||||
import logging
|
||||
from collections.abc import Iterable
|
||||
from contextlib import contextmanager
|
||||
from itertools import chain, filterfalse
|
||||
from typing import TYPE_CHECKING, Dict, Iterable, List
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link, fix_subparsers
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.utils.cli_parse import parse_params
|
||||
from dvc.utils.humanize import truncate_text
|
||||
@@ -33,7 +34,7 @@ def generate_description(stage: "Stage") -> str:
|
||||
def is_plot_or_metric(out: "Output"):
|
||||
return bool(out.plot) or bool(out.metric)
|
||||
|
||||
desc: List[str] = []
|
||||
desc: list[str] = []
|
||||
|
||||
outs = list(filterfalse(is_plot_or_metric, stage.outs))
|
||||
if outs:
|
||||
@@ -55,7 +56,7 @@ def prepare_stages_data(
|
||||
stages: Iterable["Stage"],
|
||||
description: bool = True,
|
||||
max_length: int = MAX_TEXT_LENGTH,
|
||||
) -> Dict[str, str]:
|
||||
) -> dict[str, str]:
|
||||
return {
|
||||
stage.addressing: (
|
||||
prepare_description(stage, max_length=max_length) if description else ""
|
||||
@@ -67,7 +68,7 @@ def prepare_stages_data(
|
||||
class CmdStageList(CmdBase):
|
||||
def _get_stages(self) -> Iterable["Stage"]:
|
||||
if self.args.all:
|
||||
stages: List["Stage"] = self.repo.index.stages
|
||||
stages: list["Stage"] = self.repo.index.stages
|
||||
logger.trace("%d no. of stages found", len(stages))
|
||||
return stages
|
||||
|
||||
@@ -96,7 +97,7 @@ class CmdStageList(CmdBase):
|
||||
return 0
|
||||
|
||||
|
||||
def parse_cmd(commands: List[str]) -> str:
|
||||
def parse_cmd(commands: list[str]) -> str:
|
||||
"""
|
||||
We need to take into account two cases:
|
||||
|
||||
@@ -284,23 +285,22 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(STAGES_HELP, "stage"),
|
||||
help=STAGES_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
|
||||
stage_subparsers = stage_parser.add_subparsers(
|
||||
dest="cmd",
|
||||
help="Use `dvc stage CMD --help` to display command-specific help.",
|
||||
required=True,
|
||||
)
|
||||
|
||||
fix_subparsers(stage_subparsers)
|
||||
|
||||
STAGE_ADD_HELP = "Create stage"
|
||||
stage_add_parser = stage_subparsers.add_parser(
|
||||
"add",
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(STAGE_ADD_HELP, "stage/add"),
|
||||
help=STAGE_ADD_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
stage_add_parser.add_argument(
|
||||
"-n", "--name", help="Name of the stage to add", required=True
|
||||
@@ -314,7 +314,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(STAGE_LIST_HELP, "stage/list"),
|
||||
help=STAGE_LIST_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
stage_list_parser.add_argument(
|
||||
"targets",
|
||||
|
||||
@@ -60,18 +60,19 @@ class CmdDataStatus(CmdDataBase):
|
||||
all_commits=self.args.all_commits,
|
||||
with_deps=self.args.with_deps,
|
||||
recursive=self.args.recursive,
|
||||
check_updates=self.args.check_updates,
|
||||
)
|
||||
except DvcException:
|
||||
logger.exception("")
|
||||
return 1
|
||||
|
||||
if self.args.quiet:
|
||||
return bool(st)
|
||||
|
||||
if self.args.json:
|
||||
ui.write_json(st)
|
||||
return 0
|
||||
|
||||
if self.args.quiet:
|
||||
return bool(st)
|
||||
|
||||
if st:
|
||||
self._show(st, indent)
|
||||
return 0
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
import os
|
||||
|
||||
from funcy import get_in
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.commands.config import CmdConfig
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdStudioLogin(CmdConfig):
|
||||
def run(self):
|
||||
from dvc_studio_client.auth import StudioAuthError, get_access_token
|
||||
|
||||
from dvc.env import DVC_STUDIO_URL
|
||||
from dvc.ui import ui
|
||||
from dvc.utils.studio import STUDIO_URL
|
||||
|
||||
name = self.args.name
|
||||
hostname = self.args.hostname or os.environ.get(DVC_STUDIO_URL) or STUDIO_URL
|
||||
scopes = self.args.scopes
|
||||
|
||||
studio = self.config.get("studio", {})
|
||||
if studio.get("url", hostname) == hostname and "token" in studio:
|
||||
raise DvcException(
|
||||
"Token already exists. "
|
||||
"To login with a different token, "
|
||||
"logout using 'dvc studio logout'."
|
||||
)
|
||||
|
||||
open_browser = not self.args.no_open
|
||||
try:
|
||||
_, access_token = get_access_token(
|
||||
token_name=name,
|
||||
hostname=hostname,
|
||||
scopes=scopes,
|
||||
open_browser=open_browser,
|
||||
client_name="DVC",
|
||||
)
|
||||
except StudioAuthError as e:
|
||||
ui.error_write(str(e))
|
||||
return 1
|
||||
|
||||
self.save_config(hostname, access_token)
|
||||
|
||||
config_path = self.config.files["global"]
|
||||
ui.write(f"Authentication complete. Saved token to {config_path}.")
|
||||
return 0
|
||||
|
||||
def save_config(self, hostname, token):
|
||||
with self.config.edit("global") as conf:
|
||||
conf["studio"]["token"] = token
|
||||
conf["studio"]["url"] = hostname
|
||||
|
||||
|
||||
class CmdStudioLogout(CmdConfig):
|
||||
def run(self):
|
||||
from dvc.ui import ui
|
||||
|
||||
with self.config.edit("global") as conf:
|
||||
if not get_in(conf, ["studio", "token"]):
|
||||
ui.error_write(
|
||||
"Not logged in to Studio. Log in with 'dvc studio login'."
|
||||
)
|
||||
return 1
|
||||
|
||||
del conf["studio"]["token"]
|
||||
|
||||
ui.write("Logged out from Studio (you can log back in with 'dvc studio login')")
|
||||
return 0
|
||||
|
||||
|
||||
class CmdStudioToken(CmdConfig):
|
||||
def run(self):
|
||||
from dvc.ui import ui
|
||||
|
||||
conf = self.config.read("global")
|
||||
token = get_in(conf, ["studio", "token"])
|
||||
if not token:
|
||||
ui.error_write("Not logged in to Studio.")
|
||||
return 1
|
||||
|
||||
ui.write(token)
|
||||
return 0
|
||||
|
||||
|
||||
def add_parser(subparsers, parent_parser):
|
||||
STUDIO_HELP = "Commands to authenticate DVC with Iterative Studio"
|
||||
STUDIO_DESCRIPTION = (
|
||||
"Authenticate DVC with Studio and set the token."
|
||||
" Once this token has been properly configured,\n"
|
||||
" DVC will utilize it for seamlessly sharing live experiments\n"
|
||||
" and sending notifications to Studio regarding any experiments"
|
||||
" that have been pushed."
|
||||
)
|
||||
|
||||
studio_parser = subparsers.add_parser(
|
||||
"studio",
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(STUDIO_DESCRIPTION, "studio"),
|
||||
help=STUDIO_HELP,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
studio_subparser = studio_parser.add_subparsers(
|
||||
dest="cmd",
|
||||
help="Use `DVC studio CMD --help` to display command-specific help.",
|
||||
required=True,
|
||||
)
|
||||
|
||||
STUDIO_LOGIN_HELP = "Authenticate DVC with Studio host"
|
||||
STUDIO_LOGIN_DESCRIPTION = (
|
||||
"By default, this command authenticates the DVC with Studio\n"
|
||||
" using default scopes and assigns a random name as the token name."
|
||||
)
|
||||
login_parser = studio_subparser.add_parser(
|
||||
"login",
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(STUDIO_LOGIN_DESCRIPTION, "studio/login"),
|
||||
help=STUDIO_LOGIN_HELP,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
|
||||
login_parser.add_argument(
|
||||
"-H",
|
||||
"--hostname",
|
||||
action="store",
|
||||
default=None,
|
||||
help="The hostname of the Studio instance to authenticate with.",
|
||||
)
|
||||
login_parser.add_argument(
|
||||
"-s",
|
||||
"--scopes",
|
||||
action="store",
|
||||
default=None,
|
||||
help="The scopes for the authentication token. ",
|
||||
)
|
||||
|
||||
login_parser.add_argument(
|
||||
"-n",
|
||||
"--name",
|
||||
action="store",
|
||||
default=None,
|
||||
help="The name of the authentication token. It will be used to\n"
|
||||
"identify token shown in Studio profile.",
|
||||
)
|
||||
|
||||
login_parser.add_argument(
|
||||
"--no-open",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Use authentication flow based on user code.\n"
|
||||
"You will be presented with user code to enter in browser.\n"
|
||||
"DVC will also use this if it cannot launch browser on your behalf.",
|
||||
)
|
||||
login_parser.set_defaults(func=CmdStudioLogin)
|
||||
|
||||
STUDIO_LOGOUT_HELP = "Logout user from Studio"
|
||||
STUDIO_LOGOUT_DESCRIPTION = (
|
||||
"This removes the studio token from your global config.\n"
|
||||
)
|
||||
|
||||
logout_parser = studio_subparser.add_parser(
|
||||
"logout",
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(STUDIO_LOGOUT_DESCRIPTION, "studio/logout"),
|
||||
help=STUDIO_LOGOUT_HELP,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
|
||||
logout_parser.set_defaults(func=CmdStudioLogout)
|
||||
|
||||
STUDIO_TOKEN_HELP = "View the token dvc uses to contact Studio" # noqa: S105 # nosec B105
|
||||
|
||||
logout_parser = studio_subparser.add_parser(
|
||||
"token",
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(STUDIO_TOKEN_HELP, "studio/token"),
|
||||
help=STUDIO_TOKEN_HELP,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
|
||||
logout_parser.set_defaults(func=CmdStudioToken)
|
||||
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
@@ -31,7 +29,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(UNPROTECT_HELP, "unprotect"),
|
||||
help=UNPROTECT_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
unprotect_parser.add_argument(
|
||||
"targets", nargs="+", help="Data files/directories to unprotect."
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli import completion, formatter
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
@@ -38,7 +36,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(UPDATE_HELP, "update"),
|
||||
help=UPDATE_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
update_parser.add_argument(
|
||||
"targets", nargs="+", help=".dvc files to update."
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import formatter
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
@@ -27,7 +26,7 @@ def add_parser(subparsers, parent_parser):
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(VERSION_HELP, "version"),
|
||||
help=VERSION_HELP,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
aliases=["doctor"],
|
||||
)
|
||||
version_parser.set_defaults(func=CmdVersion)
|
||||
|
||||
+20
-28
@@ -1,23 +1,15 @@
|
||||
from collections import abc
|
||||
from itertools import chain, repeat, zip_longest
|
||||
from operator import itemgetter
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
Dict,
|
||||
from collections.abc import (
|
||||
ItemsView,
|
||||
Iterable,
|
||||
Iterator,
|
||||
List,
|
||||
Mapping,
|
||||
MutableSequence,
|
||||
Optional,
|
||||
Sequence,
|
||||
Set,
|
||||
Tuple,
|
||||
Union,
|
||||
overload,
|
||||
)
|
||||
from itertools import chain, repeat, zip_longest
|
||||
from operator import itemgetter
|
||||
from typing import TYPE_CHECKING, Any, Optional, Union, overload
|
||||
|
||||
from funcy import reraise
|
||||
|
||||
@@ -25,7 +17,7 @@ if TYPE_CHECKING:
|
||||
from dvc.ui.table import CellT
|
||||
|
||||
|
||||
class Column(List["CellT"]):
|
||||
class Column(list["CellT"]):
|
||||
pass
|
||||
|
||||
|
||||
@@ -35,13 +27,13 @@ def with_value(value, default):
|
||||
|
||||
class TabularData(MutableSequence[Sequence["CellT"]]):
|
||||
def __init__(self, columns: Sequence[str], fill_value: Optional[str] = ""):
|
||||
self._columns: Dict[str, Column] = {name: Column() for name in columns}
|
||||
self._keys: List[str] = list(columns)
|
||||
self._columns: dict[str, Column] = {name: Column() for name in columns}
|
||||
self._keys: list[str] = list(columns)
|
||||
self._fill_value = fill_value
|
||||
self._protected: Set[str] = set()
|
||||
self._protected: set[str] = set()
|
||||
|
||||
@property
|
||||
def columns(self) -> List[Column]:
|
||||
def columns(self) -> list[Column]:
|
||||
return list(map(self.column, self.keys()))
|
||||
|
||||
def is_protected(self, col_name) -> bool:
|
||||
@@ -60,10 +52,10 @@ class TabularData(MutableSequence[Sequence["CellT"]]):
|
||||
projection = {k: self.column(k) for k in self.keys()}
|
||||
return projection.items()
|
||||
|
||||
def keys(self) -> List[str]:
|
||||
def keys(self) -> list[str]:
|
||||
return self._keys
|
||||
|
||||
def _iter_col_row(self, row: Sequence["CellT"]) -> Iterator[Tuple["CellT", Column]]:
|
||||
def _iter_col_row(self, row: Sequence["CellT"]) -> Iterator[tuple["CellT", Column]]:
|
||||
for val, col in zip_longest(row, self.columns):
|
||||
if col is None:
|
||||
break
|
||||
@@ -81,7 +73,7 @@ class TabularData(MutableSequence[Sequence["CellT"]]):
|
||||
for val, col in self._iter_col_row(value):
|
||||
col.insert(index, val)
|
||||
|
||||
def __iter__(self) -> Iterator[List["CellT"]]:
|
||||
def __iter__(self) -> Iterator[list["CellT"]]:
|
||||
return map(list, zip(*self.columns))
|
||||
|
||||
def __getattr__(self, item: str) -> Column:
|
||||
@@ -127,7 +119,7 @@ class TabularData(MutableSequence[Sequence["CellT"]]):
|
||||
return len(self.columns[0])
|
||||
|
||||
@property
|
||||
def shape(self) -> Tuple[int, int]:
|
||||
def shape(self) -> tuple[int, int]:
|
||||
return len(self.columns), len(self)
|
||||
|
||||
def drop(self, *col_names: str) -> None:
|
||||
@@ -170,7 +162,7 @@ class TabularData(MutableSequence[Sequence["CellT"]]):
|
||||
if key not in keys:
|
||||
self.add_column(key)
|
||||
|
||||
row: List["CellT"] = [
|
||||
row: list["CellT"] = [
|
||||
with_value(d.get(key), self._fill_value) for key in self.keys()
|
||||
]
|
||||
self.append(row)
|
||||
@@ -185,7 +177,7 @@ class TabularData(MutableSequence[Sequence["CellT"]]):
|
||||
|
||||
def as_dict(
|
||||
self, cols: Optional[Iterable[str]] = None
|
||||
) -> Iterable[Dict[str, "CellT"]]:
|
||||
) -> Iterable[dict[str, "CellT"]]:
|
||||
keys = self.keys() if cols is None else set(cols)
|
||||
return [{k: self._columns[k][i] for k in keys} for i in range(len(self))]
|
||||
|
||||
@@ -202,7 +194,7 @@ class TabularData(MutableSequence[Sequence["CellT"]]):
|
||||
if how not in ["any", "all"]:
|
||||
raise ValueError(f"Invalid 'how' value {how}. Choose one of ['any', 'all']")
|
||||
|
||||
match_line: Set = set()
|
||||
match_line: set = set()
|
||||
match_any = True
|
||||
if how == "all":
|
||||
match_any = False
|
||||
@@ -245,7 +237,7 @@ class TabularData(MutableSequence[Sequence["CellT"]]):
|
||||
)
|
||||
|
||||
if axis == "cols":
|
||||
cols_to_drop: List[str] = []
|
||||
cols_to_drop: list[str] = []
|
||||
for n_col, col in enumerate(self.columns):
|
||||
if subset and self.keys()[n_col] not in subset:
|
||||
continue
|
||||
@@ -259,7 +251,7 @@ class TabularData(MutableSequence[Sequence["CellT"]]):
|
||||
|
||||
elif axis == "rows":
|
||||
unique_rows = []
|
||||
rows_to_drop: List[int] = []
|
||||
rows_to_drop: list[int] = []
|
||||
for n_row, row in enumerate(self):
|
||||
if subset:
|
||||
row = [
|
||||
@@ -319,7 +311,7 @@ def diff_table(
|
||||
) -> TabularData:
|
||||
a_rev = a_rev or "HEAD"
|
||||
b_rev = b_rev or "workspace"
|
||||
headers: List[str] = ["Path", title, a_rev, b_rev, "Change"]
|
||||
headers: list[str] = ["Path", title, a_rev, b_rev, "Change"]
|
||||
fill_value = "-"
|
||||
td = TabularData(headers, fill_value=fill_value)
|
||||
|
||||
@@ -394,7 +386,7 @@ def metrics_table(
|
||||
|
||||
for branch, val in metrics.items():
|
||||
for fname, metric in val.get("data", {}).items():
|
||||
row_data: Dict[str, str] = {"Revision": branch, "Path": fname}
|
||||
row_data: dict[str, str] = {"Revision": branch, "Path": fname}
|
||||
metric = metric.get("data", {})
|
||||
flattened = (
|
||||
flatten(format_dict(metric))
|
||||
|
||||
+14
-14
@@ -3,7 +3,7 @@ import os
|
||||
import re
|
||||
from contextlib import contextmanager
|
||||
from functools import partial
|
||||
from typing import TYPE_CHECKING, Dict, Optional
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from funcy import compact, memoize, re_find
|
||||
|
||||
@@ -14,7 +14,7 @@ from .utils.objects import cached_property
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from dvc.fs import FileSystem
|
||||
from dvc.types import DictStrAny, StrPath
|
||||
from dvc.types import DictStrAny
|
||||
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
@@ -89,8 +89,8 @@ class Config(dict):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
dvc_dir: Optional["StrPath"] = None,
|
||||
local_dvc_dir: Optional["StrPath"] = None,
|
||||
dvc_dir: Optional[str] = None,
|
||||
local_dvc_dir: Optional[str] = None,
|
||||
validate: bool = True,
|
||||
fs: Optional["FileSystem"] = None,
|
||||
config: Optional["DictStrAny"] = None,
|
||||
@@ -105,7 +105,7 @@ class Config(dict):
|
||||
self.fs = fs or self.wfs
|
||||
|
||||
if dvc_dir:
|
||||
self.dvc_dir = self.fs.path.abspath(dvc_dir)
|
||||
self.dvc_dir = self.fs.abspath(dvc_dir)
|
||||
|
||||
self.local_dvc_dir = local_dvc_dir
|
||||
if not fs and not local_dvc_dir:
|
||||
@@ -138,17 +138,17 @@ class Config(dict):
|
||||
return system_config_dir()
|
||||
|
||||
@cached_property
|
||||
def files(self) -> Dict[str, str]:
|
||||
def files(self) -> dict[str, str]:
|
||||
files = {
|
||||
level: os.path.join(self.get_dir(level), self.CONFIG)
|
||||
for level in ("system", "global")
|
||||
}
|
||||
|
||||
if self.dvc_dir is not None:
|
||||
files["repo"] = self.fs.path.join(self.dvc_dir, self.CONFIG)
|
||||
files["repo"] = self.fs.join(self.dvc_dir, self.CONFIG)
|
||||
|
||||
if self.local_dvc_dir is not None:
|
||||
files["local"] = self.wfs.path.join(self.local_dvc_dir, self.CONFIG_LOCAL)
|
||||
files["local"] = self.wfs.join(self.local_dvc_dir, self.CONFIG_LOCAL)
|
||||
|
||||
return files
|
||||
|
||||
@@ -302,11 +302,11 @@ class Config(dict):
|
||||
return path.def_path
|
||||
|
||||
if os.path.expanduser(path) != path:
|
||||
return localfs.path.as_posix(path)
|
||||
return localfs.as_posix(path)
|
||||
|
||||
if isinstance(path, RelPath) or not os.path.isabs(path):
|
||||
path = relpath(path, conf_dir)
|
||||
return localfs.path.as_posix(path)
|
||||
return localfs.as_posix(path)
|
||||
|
||||
return path
|
||||
|
||||
@@ -344,7 +344,7 @@ class Config(dict):
|
||||
return Schema(dirs_schema, extra=ALLOW_EXTRA)(conf)
|
||||
|
||||
def load_config_to_level(self, level=None):
|
||||
merged_conf: Dict = {}
|
||||
merged_conf: dict = {}
|
||||
for merge_level in self.LEVELS:
|
||||
if merge_level == level:
|
||||
break
|
||||
@@ -390,10 +390,10 @@ class Config(dict):
|
||||
|
||||
|
||||
def _parse_named(conf):
|
||||
result: Dict[str, Dict] = {"remote": {}, "machine": {}}
|
||||
result: dict[str, dict] = {"remote": {}, "machine": {}, "db": {}}
|
||||
|
||||
for section, val in conf.items():
|
||||
match = re_find(r'^\s*(remote|machine)\s*"(.*)"\s*$', section)
|
||||
match = re_find(r'^\s*(remote|machine|db)\s*"(.*)"\s*$', section)
|
||||
if match:
|
||||
key, name = match
|
||||
result[key][name] = val
|
||||
@@ -408,7 +408,7 @@ def _pack_named(conf):
|
||||
result = compact(conf)
|
||||
|
||||
# Transform remote.name -> 'remote "name"'
|
||||
for key in ("remote", "machine"):
|
||||
for key in ("remote", "machine", "db"):
|
||||
for name, val in conf[key].items():
|
||||
result[f'{key} "{name}"'] = val
|
||||
result.pop(key, None)
|
||||
|
||||
+21
-8
@@ -181,7 +181,7 @@ SCHEMA = {
|
||||
"remote": {
|
||||
str: ByUrl(
|
||||
{
|
||||
"": {**LOCAL_COMMON, **REMOTE_COMMON},
|
||||
"": LOCAL_COMMON | REMOTE_COMMON,
|
||||
"s3": {
|
||||
"region": str,
|
||||
"profile": str,
|
||||
@@ -240,6 +240,9 @@ SCHEMA = {
|
||||
"ssl_verify": Any(Bool, str),
|
||||
"token": str,
|
||||
"use_https": Bool,
|
||||
"user": str,
|
||||
"password": str,
|
||||
"data_proxy_target": str,
|
||||
Optional("verify", default=False): Bool,
|
||||
**REMOTE_COMMON,
|
||||
},
|
||||
@@ -257,9 +260,9 @@ SCHEMA = {
|
||||
"exclude_shared_token_cache_credential": Bool,
|
||||
"exclude_managed_identity_credential": Bool,
|
||||
Optional("verify", default=False): Bool,
|
||||
"timeout": int,
|
||||
"read_timeout": int,
|
||||
"connection_timeout": int,
|
||||
"timeout": Coerce(int),
|
||||
"read_timeout": Coerce(int),
|
||||
"connection_timeout": Coerce(int),
|
||||
**REMOTE_COMMON,
|
||||
},
|
||||
"oss": {
|
||||
@@ -282,10 +285,10 @@ SCHEMA = {
|
||||
Optional("verify", default=True): Bool,
|
||||
**REMOTE_COMMON,
|
||||
},
|
||||
"http": {**HTTP_COMMON, **REMOTE_COMMON},
|
||||
"https": {**HTTP_COMMON, **REMOTE_COMMON},
|
||||
"webdav": {**WEBDAV_COMMON, **REMOTE_COMMON},
|
||||
"webdavs": {**WEBDAV_COMMON, **REMOTE_COMMON},
|
||||
"http": HTTP_COMMON | REMOTE_COMMON,
|
||||
"https": HTTP_COMMON | REMOTE_COMMON,
|
||||
"webdav": WEBDAV_COMMON | REMOTE_COMMON,
|
||||
"webdavs": WEBDAV_COMMON | REMOTE_COMMON,
|
||||
"remote": {str: object}, # Any of the above options are valid
|
||||
}
|
||||
)
|
||||
@@ -333,6 +336,8 @@ SCHEMA = {
|
||||
"params": str,
|
||||
"plots": str,
|
||||
"live": str,
|
||||
"auto_push": Bool,
|
||||
"git_remote": str,
|
||||
},
|
||||
"parsing": {
|
||||
"bool": All(Lower, Choices("store_true", "boolean_optional")),
|
||||
@@ -343,6 +348,7 @@ SCHEMA = {
|
||||
Exclusive("config_dir", "config_source"): str,
|
||||
Exclusive("config_module", "config_source"): str,
|
||||
"config_name": str,
|
||||
"plugins_path": str,
|
||||
},
|
||||
"studio": {
|
||||
"token": str,
|
||||
@@ -350,4 +356,11 @@ SCHEMA = {
|
||||
"repo_url": str,
|
||||
Optional("offline", default=False): Bool,
|
||||
},
|
||||
"db": {
|
||||
str: {
|
||||
"url": str,
|
||||
"username": str,
|
||||
"password": str,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
+11
-15
@@ -5,13 +5,14 @@ import logging
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from collections.abc import Mapping, Sequence
|
||||
from contextlib import nullcontext
|
||||
from typing import TYPE_CHECKING, Any, List, Mapping, Optional, Sequence, Union
|
||||
from typing import TYPE_CHECKING, Any, Optional, Union
|
||||
|
||||
from dvc.log import logger
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import ContextManager
|
||||
from contextlib import AbstractContextManager
|
||||
|
||||
from dvc.env import DVC_DAEMON, DVC_DAEMON_LOGFILE
|
||||
from dvc.utils import fix_env, is_binary
|
||||
@@ -55,7 +56,7 @@ def _win_detached_subprocess(args: Sequence[str], **kwargs) -> int:
|
||||
return popen.pid
|
||||
|
||||
|
||||
def _get_dvc_args() -> List[str]:
|
||||
def _get_dvc_args() -> list[str]:
|
||||
args = [sys.executable]
|
||||
if not is_binary():
|
||||
root_dir = os.path.abspath(os.path.dirname(__file__))
|
||||
@@ -106,12 +107,7 @@ def _posix_detached_subprocess(args: Sequence[str], **kwargs) -> int:
|
||||
os.close(read_end)
|
||||
return int(pid_str)
|
||||
|
||||
proc = subprocess.Popen(
|
||||
args,
|
||||
shell=False, # noqa: S603
|
||||
close_fds=True,
|
||||
**kwargs,
|
||||
)
|
||||
proc = subprocess.Popen(args, shell=False, close_fds=True, **kwargs) # noqa: S603
|
||||
os.close(read_end)
|
||||
os.write(write_end, str(proc.pid).encode("utf8"))
|
||||
os.close(write_end)
|
||||
@@ -136,7 +132,7 @@ def _map_log_level_to_flag() -> Optional[str]:
|
||||
return flags.get(logger.getEffectiveLevel())
|
||||
|
||||
|
||||
def daemon(args: List[str]) -> None:
|
||||
def daemon(args: list[str]) -> None:
|
||||
"""Launch a `dvc daemon` command in a detached process.
|
||||
|
||||
Args:
|
||||
@@ -148,12 +144,12 @@ def daemon(args: List[str]) -> None:
|
||||
|
||||
|
||||
def _spawn(
|
||||
args: List[str],
|
||||
executable: Optional[Union[str, List[str]]] = None,
|
||||
args: list[str],
|
||||
executable: Optional[Union[str, list[str]]] = None,
|
||||
env: Optional[Mapping[str, str]] = None,
|
||||
output_file: Optional[str] = None,
|
||||
) -> int:
|
||||
file: "ContextManager[Any]" = nullcontext()
|
||||
file: "AbstractContextManager[Any]" = nullcontext()
|
||||
kwargs = {}
|
||||
if output_file:
|
||||
file = open(output_file, "ab") # noqa: SIM115
|
||||
@@ -168,9 +164,9 @@ def _spawn(
|
||||
return _detached_subprocess(executable + args, env=env, **kwargs)
|
||||
|
||||
|
||||
def daemonize(args: List[str], executable: Union[None, str, List[str]] = None) -> None:
|
||||
def daemonize(args: list[str], executable: Union[None, str, list[str]] = None) -> None:
|
||||
if os.name not in ("posix", "nt"):
|
||||
return None
|
||||
return
|
||||
|
||||
if os.environ.get(DVC_DAEMON):
|
||||
logger.debug("skipping launching a new daemon.")
|
||||
|
||||
+11
-9
@@ -1,9 +1,9 @@
|
||||
"""Manages dvc remotes that user can use with push/pull/status commands."""
|
||||
|
||||
from typing import TYPE_CHECKING, Iterable, Optional, Set, Tuple
|
||||
from collections.abc import Iterable
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from dvc.config import NoRemoteError, RemoteConfigError
|
||||
from dvc.fs.callbacks import Callback
|
||||
from dvc.log import logger
|
||||
from dvc.utils.objects import cached_property
|
||||
from dvc_data.hashfile.db import get_index
|
||||
@@ -36,11 +36,9 @@ class Remote:
|
||||
|
||||
path = self.path
|
||||
if self.worktree:
|
||||
path = self.fs.path.join(
|
||||
path, ".dvc", CacheManager.FILES_DIR, DEFAULT_ALGORITHM
|
||||
)
|
||||
path = self.fs.join(path, ".dvc", CacheManager.FILES_DIR, DEFAULT_ALGORITHM)
|
||||
else:
|
||||
path = self.fs.path.join(path, CacheManager.FILES_DIR, DEFAULT_ALGORITHM)
|
||||
path = self.fs.join(path, CacheManager.FILES_DIR, DEFAULT_ALGORITHM)
|
||||
return get_odb(self.fs, path, hash_name=DEFAULT_ALGORITHM, **self.config)
|
||||
|
||||
@cached_property
|
||||
@@ -53,7 +51,7 @@ class Remote:
|
||||
|
||||
def _split_legacy_hash_infos(
|
||||
hash_infos: Iterable["HashInfo"],
|
||||
) -> Tuple[Set["HashInfo"], Set["HashInfo"]]:
|
||||
) -> tuple[set["HashInfo"], set["HashInfo"]]:
|
||||
from dvc.cachemgr import LEGACY_HASH_NAMES
|
||||
|
||||
legacy = set()
|
||||
@@ -206,11 +204,13 @@ class DataCloud:
|
||||
jobs: Optional[int] = None,
|
||||
odb: "HashFileDB",
|
||||
) -> "TransferResult":
|
||||
from dvc.fs.callbacks import TqdmCallback
|
||||
|
||||
if odb.hash_name == "md5-dos2unix":
|
||||
cache = self.repo.cache.legacy
|
||||
else:
|
||||
cache = self.repo.cache.local
|
||||
with Callback.as_tqdm_callback(
|
||||
with TqdmCallback(
|
||||
desc=f"Pushing to {odb.fs.unstrip_protocol(odb.path)}",
|
||||
unit="file",
|
||||
) as cb:
|
||||
@@ -265,11 +265,13 @@ class DataCloud:
|
||||
jobs: Optional[int] = None,
|
||||
odb: "HashFileDB",
|
||||
) -> "TransferResult":
|
||||
from dvc.fs.callbacks import TqdmCallback
|
||||
|
||||
if odb.hash_name == "md5-dos2unix":
|
||||
cache = self.repo.cache.legacy
|
||||
else:
|
||||
cache = self.repo.cache.local
|
||||
with Callback.as_tqdm_callback(
|
||||
with TqdmCallback(
|
||||
desc=f"Fetching from {odb.fs.unstrip_protocol(odb.path)}",
|
||||
unit="file",
|
||||
) as cb:
|
||||
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
import os
|
||||
from collections.abc import Iterator
|
||||
from contextlib import contextmanager
|
||||
from dataclasses import dataclass
|
||||
from tempfile import NamedTemporaryFile
|
||||
from typing import TYPE_CHECKING, Any, Callable, Optional, Union
|
||||
|
||||
from sqlalchemy import create_engine # type: ignore[import]
|
||||
from sqlalchemy.engine import make_url as _make_url # type: ignore[import]
|
||||
from sqlalchemy.exc import NoSuchModuleError # type: ignore[import]
|
||||
|
||||
from dvc import env
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
from dvc.types import StrOrBytesPath
|
||||
from dvc.utils import env2bool
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from sqlalchemy.engine import URL, Connectable, Engine
|
||||
from sqlalchemy.sql.expression import Selectable # type: ignore[import]
|
||||
|
||||
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
def noop(_):
|
||||
pass
|
||||
|
||||
|
||||
def make_url(url: Union["URL", str], **kwargs: Any) -> "URL":
|
||||
return _make_url(url).set(**kwargs)
|
||||
|
||||
|
||||
def url_from_config(config: Union[str, "URL", dict[str, str]]) -> "URL":
|
||||
if isinstance(config, dict):
|
||||
return make_url(**config)
|
||||
return make_url(config)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def atomic_file(file: StrOrBytesPath, mode: str = "w+b"):
|
||||
head, tail = os.path.split(os.fsdecode(file))
|
||||
with NamedTemporaryFile(mode, prefix=tail + "-", dir=head, delete=False) as f:
|
||||
yield f
|
||||
os.replace(f.name, file)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Serializer:
|
||||
sql: "Union[str, Selectable]"
|
||||
con: "Union[str, Connectable]"
|
||||
chunksize: int = 10_000
|
||||
|
||||
def to_csv(self, file: StrOrBytesPath, progress=noop):
|
||||
import pandas as pd
|
||||
|
||||
idfs = pd.read_sql(self.sql, self.con, chunksize=self.chunksize)
|
||||
with atomic_file(file) as f:
|
||||
for i, df in enumerate(idfs):
|
||||
df.to_csv(f, header=i == 0, index=False)
|
||||
progress(len(df))
|
||||
|
||||
def to_json(self, file: StrOrBytesPath, progress=noop): # noqa: ARG002
|
||||
import pandas as pd
|
||||
|
||||
df = pd.read_sql(self.sql, self.con)
|
||||
with atomic_file(file) as f:
|
||||
df.to_json(f, orient="records")
|
||||
|
||||
def export(self, file: StrOrBytesPath, format: str = "csv", progress=noop): # noqa: A002
|
||||
if format == "json":
|
||||
return self.to_json(file, progress=progress)
|
||||
return self.to_csv(file, progress=progress)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Client:
|
||||
engine: "Engine"
|
||||
|
||||
def test_connection(self, onerror: Optional[Callable[[], Any]] = None) -> None:
|
||||
try:
|
||||
with self.engine.connect() as conn:
|
||||
conn.exec_driver_sql("select 1")
|
||||
except Exception as exc:
|
||||
if callable(onerror):
|
||||
onerror()
|
||||
logger.exception(
|
||||
"Could not connect to the database. "
|
||||
"Check your database credentials and try again.",
|
||||
exc_info=False,
|
||||
)
|
||||
raise DvcException("The database returned the following error") from exc
|
||||
|
||||
def export(
|
||||
self,
|
||||
sql: "Union[str, Selectable]",
|
||||
file: StrOrBytesPath,
|
||||
format: str = "csv", # noqa: A002
|
||||
progress=noop,
|
||||
) -> None:
|
||||
con = self.engine.connect()
|
||||
if format == "csv":
|
||||
con = con.execution_options(stream_results=True) # use server-side cursors
|
||||
|
||||
with con:
|
||||
serializer = Serializer(sql, con)
|
||||
return serializer.export(file, format=format, progress=progress)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def handle_error(url: "URL"):
|
||||
try:
|
||||
yield
|
||||
except (ModuleNotFoundError, NoSuchModuleError) as e:
|
||||
# TODO: write installation instructions
|
||||
driver = url.drivername
|
||||
raise DvcException(f"Could not load database driver for {driver!r}") from e
|
||||
|
||||
|
||||
@contextmanager
|
||||
def client(
|
||||
url_or_config: Union[str, "URL", dict[str, str]], **engine_kwargs: Any
|
||||
) -> Iterator[Client]:
|
||||
url = url_from_config(url_or_config)
|
||||
echo = env2bool(env.DVC_SQLALCHEMY_ECHO, False)
|
||||
engine_kwargs.setdefault("echo", echo)
|
||||
|
||||
with handle_error(url):
|
||||
engine = create_engine(url, **engine_kwargs)
|
||||
|
||||
try:
|
||||
yield Client(engine)
|
||||
finally:
|
||||
engine.dispose()
|
||||
+22
-18
@@ -1,9 +1,12 @@
|
||||
from collections import defaultdict
|
||||
from typing import Any, Dict, List, Mapping, Set
|
||||
from collections.abc import Mapping
|
||||
from typing import Any
|
||||
|
||||
from dvc.output import ARTIFACT_SCHEMA, DIR_FILES_SCHEMA, Output
|
||||
|
||||
from .base import Dependency
|
||||
from .dataset import DatasetDependency
|
||||
from .db import DbDependency
|
||||
from .param import ParamsDependency
|
||||
from .repo import RepoDependency
|
||||
|
||||
@@ -14,20 +17,27 @@ from .repo import RepoDependency
|
||||
SCHEMA: Mapping[str, Any] = {
|
||||
**ARTIFACT_SCHEMA,
|
||||
**RepoDependency.REPO_SCHEMA,
|
||||
**DbDependency.DB_SCHEMA,
|
||||
Output.PARAM_FILES: [DIR_FILES_SCHEMA],
|
||||
Output.PARAM_FS_CONFIG: dict,
|
||||
}
|
||||
|
||||
|
||||
def _get(stage, p, info, **kwargs):
|
||||
if info and info.get(RepoDependency.PARAM_REPO):
|
||||
repo = info.pop(RepoDependency.PARAM_REPO)
|
||||
return RepoDependency(repo, stage, p, info)
|
||||
d = info or {}
|
||||
params = d.pop(ParamsDependency.PARAM_PARAMS, None)
|
||||
repo = d.pop(RepoDependency.PARAM_REPO, None)
|
||||
|
||||
if info and info.get(ParamsDependency.PARAM_PARAMS):
|
||||
params = info.pop(ParamsDependency.PARAM_PARAMS)
|
||||
if params:
|
||||
return ParamsDependency(stage, p, params)
|
||||
if DbDependency.PARAM_DB in d:
|
||||
return DbDependency(stage, d)
|
||||
|
||||
assert p
|
||||
if DatasetDependency.is_dataset(p):
|
||||
return DatasetDependency(stage, p, info)
|
||||
if repo:
|
||||
return RepoDependency(repo, stage, p, info)
|
||||
return Dependency(stage, p, info, **kwargs)
|
||||
|
||||
|
||||
@@ -44,26 +54,20 @@ def loadd_from(stage, d_list):
|
||||
return ret
|
||||
|
||||
|
||||
def loads_from(stage, s_list, erepo=None, fs_config=None):
|
||||
def loads_from(stage, s_list, erepo=None, fs_config=None, db=None):
|
||||
assert isinstance(s_list, list)
|
||||
info = {RepoDependency.PARAM_REPO: erepo} if erepo else {}
|
||||
return [
|
||||
_get(
|
||||
stage,
|
||||
s,
|
||||
info.copy(),
|
||||
fs_config=fs_config,
|
||||
)
|
||||
for s in s_list
|
||||
]
|
||||
if db:
|
||||
info.update({"db": db})
|
||||
return [_get(stage, s, info.copy(), fs_config=fs_config) for s in s_list]
|
||||
|
||||
|
||||
def _merge_params(s_list) -> Dict[str, List[str]]:
|
||||
def _merge_params(s_list) -> dict[str, list[str]]:
|
||||
d = defaultdict(list)
|
||||
default_file = ParamsDependency.DEFAULT_PARAMS_FILE
|
||||
|
||||
# figure out completely tracked params file, and ignore specific keys
|
||||
wholly_tracked: Set[str] = set()
|
||||
wholly_tracked: set[str] = set()
|
||||
for key in s_list:
|
||||
if not isinstance(key, dict):
|
||||
continue
|
||||
|
||||
+8
-10
@@ -1,5 +1,3 @@
|
||||
from typing import Dict, Type
|
||||
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.fs import download as fs_download
|
||||
from dvc.output import Output
|
||||
@@ -25,15 +23,15 @@ class DependencyIsStageFileError(DvcException):
|
||||
class Dependency(Output):
|
||||
IS_DEPENDENCY = True
|
||||
|
||||
DoesNotExistError: Type[DvcException] = DependencyDoesNotExistError
|
||||
IsNotFileOrDirError: Type[DvcException] = DependencyIsNotFileOrDirError
|
||||
IsStageFileError: Type[DvcException] = DependencyIsStageFileError
|
||||
DoesNotExistError: type[DvcException] = DependencyDoesNotExistError
|
||||
IsNotFileOrDirError: type[DvcException] = DependencyIsNotFileOrDirError
|
||||
IsStageFileError: type[DvcException] = DependencyIsStageFileError
|
||||
|
||||
def workspace_status(self) -> Dict[str, str]:
|
||||
def workspace_status(self) -> dict[str, str]:
|
||||
if self.fs.version_aware:
|
||||
old_fs_path = self.fs_path
|
||||
try:
|
||||
self.fs_path = self.fs.path.version_path(self.fs_path, None)
|
||||
self.fs_path = self.fs.version_path(self.fs_path, None)
|
||||
if self.changed_meta():
|
||||
return {str(self): "update available"}
|
||||
finally:
|
||||
@@ -42,9 +40,9 @@ class Dependency(Output):
|
||||
|
||||
def update(self, rev=None):
|
||||
if self.fs.version_aware:
|
||||
self.fs_path = self.fs.path.version_path(self.fs_path, rev)
|
||||
self.fs_path = self.fs.version_path(self.fs_path, rev)
|
||||
self.meta = self.get_meta()
|
||||
self.fs_path = self.fs.path.version_path(self.fs_path, self.meta.version_id)
|
||||
self.fs_path = self.fs.version_path(self.fs_path, self.meta.version_id)
|
||||
|
||||
def download(self, to, jobs=None):
|
||||
fs_download(self.fs, self.fs_path, to.fs_path, jobs=jobs)
|
||||
@@ -52,7 +50,7 @@ class Dependency(Output):
|
||||
def save(self):
|
||||
super().save()
|
||||
if self.fs.version_aware:
|
||||
self.fs_path = self.fs.path.version_path(self.fs_path, self.meta.version_id)
|
||||
self.fs_path = self.fs.version_path(self.fs_path, self.meta.version_id)
|
||||
|
||||
def dumpd(self, **kwargs):
|
||||
if self.fs.version_aware:
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
from typing import TYPE_CHECKING, Any, ClassVar
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from funcy import compact, merge
|
||||
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc_data.hashfile.hash_info import HashInfo
|
||||
|
||||
from .db import AbstractDependency
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from dvc.stage import Stage
|
||||
|
||||
|
||||
class DatasetDependency(AbstractDependency):
|
||||
PARAM_DATASET = "dataset"
|
||||
DATASET_SCHEMA: ClassVar[dict] = {PARAM_DATASET: dict}
|
||||
|
||||
def __init__(self, stage: "Stage", p, info, *args, **kwargs):
|
||||
super().__init__(stage, info, *args, **kwargs)
|
||||
self.def_path = p
|
||||
self.name = urlparse(p).netloc
|
||||
dataset_info = info.get(self.PARAM_DATASET) or {}
|
||||
self.hash_info = HashInfo(self.PARAM_DATASET, dataset_info) # type: ignore[arg-type]
|
||||
self.hash_name = self.PARAM_DATASET
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.__class__.__name__}({self.def_path!r})"
|
||||
|
||||
def __str__(self):
|
||||
return self.def_path
|
||||
|
||||
@classmethod
|
||||
def is_dataset(cls, p: str):
|
||||
return urlparse(p).scheme == "ds"
|
||||
|
||||
@property
|
||||
def protocol(self):
|
||||
return None
|
||||
|
||||
def dumpd(self, **kwargs):
|
||||
return compact({self.PARAM_PATH: self.def_path, **self.hash_info.to_dict()})
|
||||
|
||||
def fill_values(self, values=None):
|
||||
"""Load params values dynamically."""
|
||||
self.hash_info = HashInfo(
|
||||
self.PARAM_DATASET, merge(self.hash_info.value, values or {})
|
||||
)
|
||||
|
||||
def workspace_status(self):
|
||||
ds = self.repo.datasets[self.name]
|
||||
if not ds.lock:
|
||||
return {str(self): "not in sync"}
|
||||
|
||||
info: dict[str, Any] = self.hash_info.value if self.hash_info else {} # type: ignore[assignment]
|
||||
lock = self.repo.datasets._lock_from_info(info)
|
||||
if not lock:
|
||||
return {str(self): "new"}
|
||||
if lock != ds.lock:
|
||||
return {str(self): "modified"}
|
||||
return {}
|
||||
|
||||
def status(self):
|
||||
return self.workspace_status()
|
||||
|
||||
def get_hash(self):
|
||||
ds = self.repo.datasets[self.name]
|
||||
if not ds.lock:
|
||||
if ds._invalidated:
|
||||
raise DvcException(
|
||||
"Dataset information is not in sync. "
|
||||
f"Run 'dvc ds update {self.name}' to sync."
|
||||
)
|
||||
raise DvcException("Dataset information missing from dvc.lock file")
|
||||
return HashInfo(self.PARAM_DATASET, ds.lock.to_dict()) # type: ignore[arg-type]
|
||||
|
||||
def save(self):
|
||||
self.hash_info = self.get_hash()
|
||||
|
||||
def download(self, to, jobs=None):
|
||||
raise NotImplementedError
|
||||
|
||||
def update(self, rev=None):
|
||||
raise NotImplementedError
|
||||
@@ -0,0 +1,121 @@
|
||||
from collections.abc import Iterator
|
||||
from contextlib import contextmanager
|
||||
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional
|
||||
|
||||
from funcy import compact, log_durations
|
||||
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
|
||||
from .base import Dependency
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from dvc.output import Output
|
||||
from dvc.repo import Repo
|
||||
from dvc.stage import Stage
|
||||
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def download_progress(to: "Output") -> Iterator[Callable[[int], Any]]:
|
||||
from dvc.ui import ui
|
||||
from dvc.ui._rich_progress import DbDownloadProgress
|
||||
|
||||
with log_durations(logger.debug, f"Saving to {to}"), DbDownloadProgress(
|
||||
console=ui.error_console,
|
||||
) as progress:
|
||||
task = progress.add_task("Saving", total=None, output=to)
|
||||
yield lambda n: progress.advance(task, advance=n)
|
||||
progress.update(task, description="Saved", total=0)
|
||||
|
||||
|
||||
class AbstractDependency(Dependency):
|
||||
"""Dependency without workspace/fs/fs_path"""
|
||||
|
||||
def __init__(self, stage: "Stage", info: dict[str, Any], *args, **kwargs):
|
||||
self.repo: "Repo" = stage.repo
|
||||
self.stage = stage
|
||||
self.fs = None
|
||||
self.fs_path = None
|
||||
self.def_path = None # type: ignore[assignment]
|
||||
self.info = info or {}
|
||||
|
||||
|
||||
class DbDependency(AbstractDependency):
|
||||
PARAM_CONNECTION = "connection"
|
||||
PARAM_DB = "db"
|
||||
PARAM_QUERY = "query"
|
||||
PARAM_TABLE = "table"
|
||||
PARAM_FILE_FORMAT = "file_format"
|
||||
DB_SCHEMA: ClassVar[dict] = {
|
||||
PARAM_DB: {
|
||||
PARAM_QUERY: str,
|
||||
PARAM_CONNECTION: str,
|
||||
PARAM_FILE_FORMAT: str,
|
||||
PARAM_TABLE: str,
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, stage: "Stage", info, *args, **kwargs):
|
||||
super().__init__(stage, info, *args, **kwargs)
|
||||
self.db_info: dict[str, str] = self.info.get(self.PARAM_DB, {})
|
||||
self.connection = self.db_info.get(self.PARAM_CONNECTION)
|
||||
|
||||
@property
|
||||
def sql(self) -> Optional[str]:
|
||||
return self.db_info.get(self.PARAM_QUERY) or self.db_info.get(self.PARAM_TABLE)
|
||||
|
||||
def __repr__(self):
|
||||
return "{}:{}".format(
|
||||
self.__class__.__name__, "".join(f"{k}=={v}" for k, v in self.info.items())
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
from dvc.utils.humanize import truncate_text
|
||||
|
||||
return truncate_text(self.sql or "", 50)
|
||||
|
||||
def workspace_status(self):
|
||||
return False # no workspace to check
|
||||
|
||||
def status(self):
|
||||
return self.workspace_status()
|
||||
|
||||
def save(self):
|
||||
"""nothing to save."""
|
||||
|
||||
def dumpd(self, **kwargs):
|
||||
db_info = compact(self.db_info)
|
||||
return {self.PARAM_DB: db_info} if db_info else {}
|
||||
|
||||
def update(self, rev=None):
|
||||
"""nothing to update."""
|
||||
|
||||
def download(
|
||||
self,
|
||||
to: "Output",
|
||||
jobs: Optional[int] = None, # noqa: ARG002
|
||||
file_format: Optional[str] = None,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
from dvc.database import client
|
||||
from dvc.ui import ui
|
||||
|
||||
sql = self.sql
|
||||
if not sql:
|
||||
raise DvcException("Cannot download: no query or table specified")
|
||||
|
||||
db_config = self.repo.config.get(self.PARAM_DB, {})
|
||||
config = db_config.get(self.connection)
|
||||
if not config:
|
||||
raise DvcException(f"connection {self.connection} not found in config")
|
||||
|
||||
file_format = file_format or self.db_info.get(self.PARAM_FILE_FORMAT, "csv")
|
||||
assert file_format
|
||||
with client(config) as db:
|
||||
msg = "Testing connection"
|
||||
with log_durations(logger.debug, msg), ui.status(msg) as status:
|
||||
db.test_connection(onerror=status.stop)
|
||||
with download_progress(to) as progress:
|
||||
db.export(sql, to.fs_path, format=file_format, progress=progress)
|
||||
+12
-15
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
import typing
|
||||
from collections import defaultdict
|
||||
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
||||
from typing import TYPE_CHECKING, Any, Optional
|
||||
|
||||
import dpath
|
||||
|
||||
@@ -37,7 +37,7 @@ class BadParamFileError(DvcException):
|
||||
def read_param_file(
|
||||
fs: "FileSystem",
|
||||
path: str,
|
||||
key_paths: Optional[List[str]] = None,
|
||||
key_paths: Optional[list[str]] = None,
|
||||
flatten: bool = False,
|
||||
**load_kwargs,
|
||||
) -> Any:
|
||||
@@ -54,12 +54,15 @@ def read_param_file(
|
||||
continue
|
||||
return ret
|
||||
|
||||
from dpath import merge
|
||||
from copy import deepcopy
|
||||
|
||||
for key_path in key_paths:
|
||||
from dpath import merge
|
||||
from funcy import distinct
|
||||
|
||||
for key_path in distinct(key_paths):
|
||||
merge(
|
||||
ret,
|
||||
dpath.search(config, key_path, separator="."),
|
||||
deepcopy(dpath.search(config, key_path, separator=".")),
|
||||
separator=".",
|
||||
)
|
||||
return ret
|
||||
@@ -73,10 +76,7 @@ class ParamsDependency(Dependency):
|
||||
self.params = list(params) if params else []
|
||||
hash_info = HashInfo()
|
||||
if isinstance(params, dict):
|
||||
hash_info = HashInfo(
|
||||
self.PARAM_PARAMS,
|
||||
params, # type: ignore[arg-type]
|
||||
)
|
||||
hash_info = HashInfo(self.PARAM_PARAMS, params) # type: ignore[arg-type]
|
||||
repo = repo or stage.repo
|
||||
path = path or os.path.join(repo.root_dir, self.DEFAULT_PARAMS_FILE)
|
||||
super().__init__(stage, path, repo=repo)
|
||||
@@ -100,14 +100,11 @@ class ParamsDependency(Dependency):
|
||||
for param in self.params:
|
||||
if param in values:
|
||||
info[param] = values[param]
|
||||
self.hash_info = HashInfo(
|
||||
self.PARAM_PARAMS,
|
||||
info, # type: ignore[arg-type]
|
||||
)
|
||||
self.hash_info = HashInfo(self.PARAM_PARAMS, info) # type: ignore[arg-type]
|
||||
|
||||
def read_params(
|
||||
self, flatten: bool = True, **kwargs: typing.Any
|
||||
) -> Dict[str, typing.Any]:
|
||||
) -> dict[str, typing.Any]:
|
||||
try:
|
||||
self.validate_filepath()
|
||||
except MissingParamsFile:
|
||||
@@ -131,7 +128,7 @@ class ParamsDependency(Dependency):
|
||||
|
||||
from funcy import ldistinct
|
||||
|
||||
status: Dict[str, Any] = defaultdict(dict)
|
||||
status: dict[str, Any] = defaultdict(dict)
|
||||
info = self.hash_info.value if self.hash_info else {}
|
||||
assert isinstance(info, dict)
|
||||
actual = self.read_params()
|
||||
|
||||
+17
-14
@@ -1,5 +1,5 @@
|
||||
from copy import deepcopy
|
||||
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
|
||||
from typing import TYPE_CHECKING, Any, ClassVar, Optional, Union
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -20,7 +20,7 @@ class RepoDependency(Dependency):
|
||||
PARAM_CONFIG = "config"
|
||||
PARAM_REMOTE = "remote"
|
||||
|
||||
REPO_SCHEMA = {
|
||||
REPO_SCHEMA: ClassVar[dict] = {
|
||||
PARAM_REPO: {
|
||||
vol.Required(PARAM_URL): str,
|
||||
PARAM_REV: str,
|
||||
@@ -30,7 +30,7 @@ class RepoDependency(Dependency):
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, def_repo: Dict[str, Any], stage: "Stage", *args, **kwargs):
|
||||
def __init__(self, def_repo: dict[str, Any], stage: "Stage", *args, **kwargs):
|
||||
self.def_repo = def_repo
|
||||
super().__init__(stage, *args, **kwargs)
|
||||
|
||||
@@ -64,28 +64,31 @@ class RepoDependency(Dependency):
|
||||
if self.def_repo.get(self.PARAM_REV_LOCK) is None:
|
||||
self.def_repo[self.PARAM_REV_LOCK] = rev
|
||||
|
||||
def dumpd(self, **kwargs) -> Dict[str, Union[str, Dict[str, str]]]:
|
||||
repo = {self.PARAM_URL: self.def_repo[self.PARAM_URL]}
|
||||
@classmethod
|
||||
def _dump_def_repo(cls, def_repo) -> dict[str, str]:
|
||||
repo = {cls.PARAM_URL: def_repo[cls.PARAM_URL]}
|
||||
|
||||
rev = self.def_repo.get(self.PARAM_REV)
|
||||
rev = def_repo.get(cls.PARAM_REV)
|
||||
if rev:
|
||||
repo[self.PARAM_REV] = self.def_repo[self.PARAM_REV]
|
||||
repo[cls.PARAM_REV] = def_repo[cls.PARAM_REV]
|
||||
|
||||
rev_lock = self.def_repo.get(self.PARAM_REV_LOCK)
|
||||
rev_lock = def_repo.get(cls.PARAM_REV_LOCK)
|
||||
if rev_lock:
|
||||
repo[self.PARAM_REV_LOCK] = rev_lock
|
||||
repo[cls.PARAM_REV_LOCK] = rev_lock
|
||||
|
||||
config = self.def_repo.get(self.PARAM_CONFIG)
|
||||
config = def_repo.get(cls.PARAM_CONFIG)
|
||||
if config:
|
||||
repo[self.PARAM_CONFIG] = config
|
||||
repo[cls.PARAM_CONFIG] = config
|
||||
|
||||
remote = self.def_repo.get(self.PARAM_REMOTE)
|
||||
remote = def_repo.get(cls.PARAM_REMOTE)
|
||||
if remote:
|
||||
repo[self.PARAM_REMOTE] = remote
|
||||
repo[cls.PARAM_REMOTE] = remote
|
||||
return repo
|
||||
|
||||
def dumpd(self, **kwargs) -> dict[str, Union[str, dict[str, str]]]:
|
||||
return {
|
||||
self.PARAM_PATH: self.def_path,
|
||||
self.PARAM_REPO: repo,
|
||||
self.PARAM_REPO: self._dump_def_repo(self.def_repo),
|
||||
}
|
||||
|
||||
def update(self, rev: Optional[str] = None):
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ def system_config_dir():
|
||||
|
||||
|
||||
def global_config_dir():
|
||||
return os.getenv(env.DVC_SYSTEM_CONFIG_DIR) or platformdirs.user_config_dir(
|
||||
return os.getenv(env.DVC_GLOBAL_CONFIG_DIR) or platformdirs.user_config_dir(
|
||||
APPNAME, APPAUTHOR
|
||||
)
|
||||
|
||||
|
||||
+55
-23
@@ -1,16 +1,6 @@
|
||||
import contextlib
|
||||
import os
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
Callable,
|
||||
Dict,
|
||||
List,
|
||||
Optional,
|
||||
Tuple,
|
||||
TypeVar,
|
||||
Union,
|
||||
)
|
||||
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, TypeVar, Union
|
||||
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
@@ -133,7 +123,7 @@ class FileMixin:
|
||||
d, _ = self._load(**kwargs)
|
||||
return d
|
||||
|
||||
def _load(self, **kwargs: Any) -> Tuple[Any, str]:
|
||||
def _load(self, **kwargs: Any) -> tuple[Any, str]:
|
||||
# it raises the proper exceptions by priority:
|
||||
# 1. when the file doesn't exists
|
||||
# 2. filename is not a DVC file
|
||||
@@ -156,7 +146,7 @@ class FileMixin:
|
||||
|
||||
return validate(d, cls.SCHEMA, path=fname) # type: ignore[arg-type]
|
||||
|
||||
def _load_yaml(self, **kwargs: Any) -> Tuple[Any, str]:
|
||||
def _load_yaml(self, **kwargs: Any) -> tuple[Any, str]:
|
||||
from dvc.utils import strictyaml
|
||||
|
||||
return strictyaml.load(
|
||||
@@ -181,10 +171,12 @@ class SingleStageFile(FileMixin):
|
||||
from dvc.schema import COMPILED_SINGLE_STAGE_SCHEMA as SCHEMA
|
||||
from dvc.stage.loader import SingleStageLoader as LOADER # noqa: N814
|
||||
|
||||
metrics: List[str] = []
|
||||
plots: Any = {}
|
||||
params: List[str] = []
|
||||
artifacts: Dict[str, Optional[Dict[str, Any]]] = {}
|
||||
datasets: ClassVar[list[dict[str, Any]]] = []
|
||||
datasets_lock: ClassVar[list[dict[str, Any]]] = []
|
||||
metrics: ClassVar[list[str]] = []
|
||||
plots: ClassVar[Any] = {}
|
||||
params: ClassVar[list[str]] = []
|
||||
artifacts: ClassVar[dict[str, Optional[dict[str, Any]]]] = {}
|
||||
|
||||
@property
|
||||
def stage(self) -> "Stage":
|
||||
@@ -249,6 +241,20 @@ class ProjectFile(FileMixin):
|
||||
if update_lock:
|
||||
self._dump_lockfile(stage, **kwargs)
|
||||
|
||||
def dump_dataset(self, dataset):
|
||||
with modify_yaml(self.path, fs=self.repo.fs) as data:
|
||||
datasets: list[dict] = data.setdefault("datasets", [])
|
||||
loc = next(
|
||||
(i for i, ds in enumerate(datasets) if ds["name"] == dataset["name"]),
|
||||
None,
|
||||
)
|
||||
if loc is not None:
|
||||
apply_diff(dataset, datasets[loc])
|
||||
datasets[loc] = dataset
|
||||
else:
|
||||
datasets.append(dataset)
|
||||
self.repo.scm_context.track_file(self.relpath)
|
||||
|
||||
def _dump_lockfile(self, stage, **kwargs):
|
||||
self._lockfile.dump(stage, **kwargs)
|
||||
|
||||
@@ -283,18 +289,18 @@ class ProjectFile(FileMixin):
|
||||
raise DvcException("ProjectFile has multiple stages. Please specify it's name.")
|
||||
|
||||
@cached_property
|
||||
def contents(self) -> Dict[str, Any]:
|
||||
def contents(self) -> dict[str, Any]:
|
||||
return self._load()[0]
|
||||
|
||||
@cached_property
|
||||
def lockfile_contents(self) -> Dict[str, Any]:
|
||||
def lockfile_contents(self) -> dict[str, Any]:
|
||||
return self._lockfile.load()
|
||||
|
||||
@cached_property
|
||||
def resolver(self) -> "DataResolver":
|
||||
from .parsing import DataResolver
|
||||
|
||||
wdir = self.repo.fs.path.parent(self.path)
|
||||
wdir = self.repo.fs.parent(self.path)
|
||||
return DataResolver(self.repo, wdir, self.contents)
|
||||
|
||||
@cached_property
|
||||
@@ -302,7 +308,7 @@ class ProjectFile(FileMixin):
|
||||
return self.LOADER(self, self.contents, self.lockfile_contents)
|
||||
|
||||
@property
|
||||
def metrics(self) -> List[str]:
|
||||
def metrics(self) -> list[str]:
|
||||
return self.contents.get("metrics", [])
|
||||
|
||||
@property
|
||||
@@ -310,11 +316,19 @@ class ProjectFile(FileMixin):
|
||||
return self.contents.get("plots", {})
|
||||
|
||||
@property
|
||||
def params(self) -> List[str]:
|
||||
def params(self) -> list[str]:
|
||||
return self.contents.get("params", [])
|
||||
|
||||
@property
|
||||
def artifacts(self) -> Dict[str, Optional[Dict[str, Any]]]:
|
||||
def datasets(self) -> list[dict[str, Any]]:
|
||||
return self.contents.get("datasets", [])
|
||||
|
||||
@property
|
||||
def datasets_lock(self) -> list[dict[str, Any]]:
|
||||
return self.lockfile_contents.get("datasets", [])
|
||||
|
||||
@property
|
||||
def artifacts(self) -> dict[str, Optional[dict[str, Any]]]:
|
||||
return self.contents.get("artifacts", {})
|
||||
|
||||
def remove(self, force=False):
|
||||
@@ -362,6 +376,24 @@ class Lockfile(FileMixin):
|
||||
self._check_gitignored()
|
||||
return {}, ""
|
||||
|
||||
def dump_dataset(self, dataset: dict):
|
||||
with modify_yaml(self.path, fs=self.repo.fs) as data:
|
||||
data.update({"schema": "2.0"})
|
||||
if not data:
|
||||
logger.info("Generating lock file '%s'", self.relpath)
|
||||
|
||||
datasets: list[dict] = data.setdefault("datasets", [])
|
||||
loc = next(
|
||||
(i for i, ds in enumerate(datasets) if ds["name"] == dataset["name"]),
|
||||
None,
|
||||
)
|
||||
if loc is not None:
|
||||
datasets[loc] = dataset
|
||||
else:
|
||||
datasets.append(dataset)
|
||||
data.setdefault("stages", {})
|
||||
self.repo.scm_context.track_file(self.relpath)
|
||||
|
||||
def dump(self, stage, **kwargs):
|
||||
stage_data = serialize.to_lockfile(stage, **kwargs)
|
||||
|
||||
|
||||
@@ -16,5 +16,6 @@ DVC_STUDIO_OFFLINE = "DVC_STUDIO_OFFLINE"
|
||||
DVC_STUDIO_REPO_URL = "DVC_STUDIO_REPO_URL"
|
||||
DVC_STUDIO_TOKEN = "DVC_STUDIO_TOKEN" # noqa: S105
|
||||
DVC_STUDIO_URL = "DVC_STUDIO_URL"
|
||||
DVC_SQLALCHEMY_ECHO = "DVC_SQLALCHEMY_ECHO"
|
||||
DVC_SYSTEM_CONFIG_DIR = "DVC_SYSTEM_CONFIG_DIR"
|
||||
DVC_UPDATER_ENDPOINT = "DVC_UPDATER_ENDPOINT"
|
||||
|
||||
+15
-3
@@ -1,6 +1,6 @@
|
||||
"""Exceptions raised by the dvc."""
|
||||
import errno
|
||||
from typing import TYPE_CHECKING, Dict, List, Optional, Set
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from dvc.utils import format_link
|
||||
|
||||
@@ -34,7 +34,7 @@ class OutputDuplicationError(DvcException):
|
||||
stages (list): list of paths to stages.
|
||||
"""
|
||||
|
||||
def __init__(self, output: str, stages: Set["Stage"]):
|
||||
def __init__(self, output: str, stages: set["Stage"]):
|
||||
from funcy import first
|
||||
|
||||
assert isinstance(output, str)
|
||||
@@ -241,7 +241,7 @@ class UploadError(FileTransferError):
|
||||
|
||||
|
||||
class CheckoutError(DvcException):
|
||||
def __init__(self, target_infos: List[str], stats: Dict[str, List[str]]):
|
||||
def __init__(self, target_infos: list[str], stats: dict[str, list[str]]):
|
||||
from dvc.utils import error_link
|
||||
|
||||
self.target_infos = target_infos
|
||||
@@ -357,3 +357,15 @@ class ArtifactNotFoundError(DvcException):
|
||||
|
||||
desc = f" @ {stage or version}" if (stage or version) else ""
|
||||
super().__init__(f"Unable to find artifact '{name}{desc}'")
|
||||
|
||||
|
||||
class RevCollectionError(DvcException):
|
||||
"""Thrown if a revision failed to be collected.
|
||||
|
||||
Args:
|
||||
rev (str): revision that failed (or "workspace").
|
||||
"""
|
||||
|
||||
def __init__(self, rev):
|
||||
self.rev = rev
|
||||
super().__init__(f"Failed to collect '{rev}'")
|
||||
|
||||
+15
-21
@@ -5,6 +5,8 @@ from dvc_http import HTTPFileSystem, HTTPSFileSystem # noqa: F401
|
||||
|
||||
from dvc.config import ConfigError as RepoConfigError
|
||||
from dvc.config_schema import SCHEMA, Invalid
|
||||
|
||||
# pylint: disable=unused-import
|
||||
from dvc_objects.fs import ( # noqa: F401
|
||||
LocalFileSystem,
|
||||
MemoryFileSystem,
|
||||
@@ -23,11 +25,10 @@ from dvc_objects.fs.errors import ( # noqa: F401
|
||||
ConfigError,
|
||||
RemoteMissingDepsError,
|
||||
)
|
||||
from dvc_objects.fs.path import Path # noqa: F401
|
||||
|
||||
from .callbacks import Callback
|
||||
from .callbacks import Callback # noqa: F401
|
||||
from .data import DataFileSystem # noqa: F401
|
||||
from .dvc import DVCFileSystem # noqa: F401
|
||||
from .dvc import DVCFileSystem
|
||||
from .git import GitFileSystem # noqa: F401
|
||||
|
||||
known_implementations.update(
|
||||
@@ -47,39 +48,32 @@ known_implementations.update(
|
||||
def download(
|
||||
fs: "FileSystem", fs_path: str, to: str, jobs: Optional[int] = None
|
||||
) -> int:
|
||||
with Callback.as_tqdm_callback(
|
||||
desc=f"Downloading {fs.path.name(fs_path)}",
|
||||
unit="files",
|
||||
) as cb:
|
||||
from dvc.scm import lfs_prefetch
|
||||
|
||||
from .callbacks import TqdmCallback
|
||||
|
||||
with TqdmCallback(desc=f"Downloading {fs.name(fs_path)}", unit="files") as cb:
|
||||
# NOTE: We use dvc-objects generic.copy over fs.get since it makes file
|
||||
# download atomic and avoids fsspec glob/regex path expansion.
|
||||
if fs.isdir(fs_path):
|
||||
from_infos = [
|
||||
path
|
||||
for path in fs.find(fs_path)
|
||||
if not path.endswith(fs.path.flavour.sep)
|
||||
path for path in fs.find(fs_path) if not path.endswith(fs.flavour.sep)
|
||||
]
|
||||
if not from_infos:
|
||||
localfs.makedirs(to, exist_ok=True)
|
||||
return 0
|
||||
to_infos = [
|
||||
localfs.path.join(to, *fs.path.relparts(info, fs_path))
|
||||
for info in from_infos
|
||||
localfs.join(to, *fs.relparts(info, fs_path)) for info in from_infos
|
||||
]
|
||||
else:
|
||||
from_infos = [fs_path]
|
||||
to_infos = [to]
|
||||
|
||||
if isinstance(fs, DVCFileSystem):
|
||||
lfs_prefetch(fs, from_infos)
|
||||
cb.set_size(len(from_infos))
|
||||
jobs = jobs or fs.jobs
|
||||
generic.copy(
|
||||
fs,
|
||||
from_infos,
|
||||
localfs,
|
||||
to_infos,
|
||||
callback=cb,
|
||||
batch_size=jobs,
|
||||
)
|
||||
generic.copy(fs, from_infos, localfs, to_infos, callback=cb, batch_size=jobs)
|
||||
return len(to_infos)
|
||||
|
||||
|
||||
@@ -164,5 +158,5 @@ def get_cloud_fs(repo_config, **kwargs):
|
||||
fs_path = cls._strip_protocol(url)
|
||||
|
||||
extras = cls._get_kwargs_from_urls(url)
|
||||
conf = {**extras, **remote_conf} # remote config takes priority
|
||||
conf = extras | remote_conf # remote config takes priority
|
||||
return cls, conf, fs_path
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user