mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-02 23:09:28 +01:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6d231f9cf | ||
|
|
322fcec5ca | ||
|
|
1e5b3603cc | ||
|
|
ffa630e8d5 | ||
|
|
1e9b60dc48 | ||
|
|
83dd2b2a7b | ||
|
|
d238350a2d | ||
|
|
06b9196371 | ||
|
|
b4f42242c9 | ||
|
|
fbdb566079 | ||
|
|
3d7bbb8492 | ||
|
|
fd7c891217 | ||
|
|
2b3b15f767 | ||
|
|
8c9358957c | ||
|
|
86dd0785a0 | ||
|
|
a8aec51c35 | ||
|
|
e9f2da4451 | ||
|
|
8d23a5e65a | ||
|
|
b2fc194e2b | ||
|
|
0def298b8c | ||
|
|
d678773b53 | ||
|
|
519cce3fe4 | ||
|
|
cbc111b519 | ||
|
|
4ee8f554a5 | ||
|
|
06565e18b4 | ||
|
|
2085bc8053 | ||
|
|
14cbf6470d | ||
|
|
36fa116e75 | ||
|
|
97f3d07480 | ||
|
|
4a2c4f76e5 | ||
|
|
eb8999a86b | ||
|
|
db870335e3 | ||
|
|
23d2ed3d59 | ||
|
|
46db3ac419 | ||
|
|
fcc69ab6eb | ||
|
|
d60557dd08 | ||
|
|
fc5147767f | ||
|
|
89b4beb7a4 | ||
|
|
48f1f52c1b | ||
|
|
3fee81f1be | ||
|
|
0bfce0b643 | ||
|
|
d9b2e67a0b | ||
|
|
4a0d56a793 | ||
|
|
825c823a37 | ||
|
|
b23ba58cd6 | ||
|
|
8fb67b71a5 | ||
|
|
5693775459 | ||
|
|
17f5508f49 | ||
|
|
c39ce6157d | ||
|
|
d59231febf | ||
|
|
b35b9420a1 | ||
|
|
46c65fdba2 | ||
|
|
5f8afb911e |
@@ -1,20 +0,0 @@
|
||||
[flake8]
|
||||
max_line_length = 88
|
||||
extend-ignore=
|
||||
# Whitespace before ':'
|
||||
E203
|
||||
# Line break occurred before a binary operator
|
||||
W503
|
||||
# unindexed parameters in the str.format, see:
|
||||
# https://pypi.org/project/flake8-string-format/
|
||||
P1
|
||||
max-complexity = 10
|
||||
show_source = true
|
||||
count = true
|
||||
min_python_version = 3.8.0
|
||||
per-file-ignores =
|
||||
dvc/testing/benchmarks/conftest.py:F401
|
||||
dvc/testing/conftest.py:F401
|
||||
dvc/testing/plugin.py:F401
|
||||
tests/conftest.py:F401
|
||||
tests/func/experiments/executor/test_ssh.py:F401
|
||||
+5
-35
@@ -2,11 +2,11 @@ default_language_version:
|
||||
python: python3
|
||||
|
||||
ci:
|
||||
skip: [mypy, pylint, dvc-pre-commit]
|
||||
skip: [mypy, dvc-pre-commit]
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.4.0
|
||||
rev: v4.5.0
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
- id: check-case-conflict
|
||||
@@ -17,44 +17,21 @@ repos:
|
||||
args: ['--assume-in-merge']
|
||||
- id: check-toml
|
||||
- id: check-yaml
|
||||
- id: debug-statements
|
||||
exclude: "dvc/_debug.py"
|
||||
- id: end-of-file-fixer
|
||||
- id: mixed-line-ending
|
||||
- id: sort-simple-yaml
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.9.1
|
||||
hooks:
|
||||
- id: black
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.12.0
|
||||
hooks:
|
||||
- id: isort
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: 'v0.0.291'
|
||||
rev: 'v0.1.5'
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [--fix, --exit-non-zero-on-fix]
|
||||
- id: ruff-format
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: v2.2.5
|
||||
rev: v2.2.6
|
||||
hooks:
|
||||
- id: codespell
|
||||
additional_dependencies: ["tomli"]
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 6.1.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
additional_dependencies:
|
||||
- flake8-string-format
|
||||
- flake8-typing-imports
|
||||
- repo: https://github.com/PyCQA/bandit
|
||||
rev: '1.7.5'
|
||||
hooks:
|
||||
- id: bandit
|
||||
args: ["-c", "pyproject.toml", "--quiet", "--format=custom"]
|
||||
files: ^dvc/
|
||||
additional_dependencies: [".[toml]"]
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: mypy
|
||||
@@ -64,13 +41,6 @@ repos:
|
||||
language: system
|
||||
types: [python]
|
||||
require_serial: true
|
||||
- id: pylint
|
||||
name: pylint
|
||||
entry: pylint
|
||||
files: ^dvc/
|
||||
language: system
|
||||
types: [python]
|
||||
require_serial: true
|
||||
- hooks:
|
||||
- args:
|
||||
- git-hook
|
||||
|
||||
+2
-2
@@ -90,8 +90,8 @@ Their results can be filtered and compared based on hyperparameters and metrics,
|
||||
|
||||
.. _`VS Code Extension`:
|
||||
|
||||
Visual Studio Code Extension
|
||||
============================
|
||||
VS Code Extension
|
||||
=================
|
||||
|
||||
|VS Code|
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# ruff: noqa: N999
|
||||
# pylint: disable=import-error
|
||||
|
||||
from PyInstaller.utils.hooks import collect_submodules, is_module_or_submodule
|
||||
|
||||
# Celery dynamically imports most celery internals at runtime
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# ruff: noqa: N999
|
||||
from PyInstaller.utils.hooks import copy_metadata # pylint:disable=import-error
|
||||
from PyInstaller.utils.hooks import copy_metadata
|
||||
|
||||
# needed for `dvc doctor` to show dep versions
|
||||
datas = copy_metadata("adlfs", recursive=True)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# ruff: noqa: N999
|
||||
from PyInstaller.utils.hooks import copy_metadata # pylint:disable=import-error
|
||||
from PyInstaller.utils.hooks import copy_metadata
|
||||
|
||||
datas = copy_metadata("flatten-dict")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# ruff: noqa: N999
|
||||
# pylint: disable=import-error
|
||||
|
||||
from PyInstaller.utils.hooks import collect_submodules
|
||||
|
||||
hiddenimports = collect_submodules("dvc_task")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# ruff: noqa: N999
|
||||
from PyInstaller.utils.hooks import copy_metadata # pylint:disable=import-error
|
||||
from PyInstaller.utils.hooks import copy_metadata
|
||||
|
||||
datas = copy_metadata("pydrive2")
|
||||
|
||||
+9
-8
@@ -14,7 +14,7 @@ def viztracer_profile(
|
||||
log_async: bool = False,
|
||||
):
|
||||
try:
|
||||
import viztracer # pylint: disable=import-error
|
||||
import viztracer
|
||||
except ImportError:
|
||||
print("Failed to run profiler, viztracer is not installed") # noqa: T201
|
||||
yield
|
||||
@@ -36,7 +36,7 @@ def yappi_profile(
|
||||
separate_threads: Optional[bool] = False,
|
||||
):
|
||||
try:
|
||||
import yappi # pylint: disable=import-error
|
||||
import yappi
|
||||
except ImportError:
|
||||
print("Failed to run profiler, yappi is not installed") # noqa: T201
|
||||
yield
|
||||
@@ -65,9 +65,9 @@ def yappi_profile(
|
||||
else:
|
||||
if ctx_id is not None:
|
||||
print(f"\nThread {ctx_id}") # noqa: T201
|
||||
st.print_all() # pylint:disable=no-member
|
||||
st.print_all()
|
||||
if ctx_id is None:
|
||||
threads.print_all() # pylint:disable=no-member
|
||||
threads.print_all()
|
||||
|
||||
yappi.clear_stats()
|
||||
|
||||
@@ -76,7 +76,7 @@ def yappi_profile(
|
||||
def instrument(html_output=False):
|
||||
"""Run a statistical profiler"""
|
||||
try:
|
||||
from pyinstrument import Profiler # pylint: disable=import-error
|
||||
from pyinstrument import Profiler
|
||||
except ImportError:
|
||||
print("Failed to run profiler, pyinstrument is not installed") # noqa: T201
|
||||
yield
|
||||
@@ -115,9 +115,9 @@ def profile(dump_path: Optional[str] = None):
|
||||
def debug():
|
||||
try:
|
||||
yield
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except Exception:
|
||||
try:
|
||||
import ipdb as pdb # noqa: T100, pylint: disable=import-error
|
||||
import ipdb as pdb # noqa: T100
|
||||
except ImportError:
|
||||
import pdb # type: ignore[no-redef] # noqa: T100
|
||||
pdb.post_mortem()
|
||||
@@ -145,7 +145,8 @@ def show_stack():
|
||||
signal.signal(signal.SIGQUIT, _sigshow)
|
||||
|
||||
try:
|
||||
signal.signal(signal.SIGINFO, _sigshow) # only available on macOS
|
||||
# only available on macOS
|
||||
signal.signal(signal.SIGINFO, _sigshow) # type: ignore[attr-defined]
|
||||
except AttributeError:
|
||||
pass
|
||||
yield
|
||||
|
||||
+14
-6
@@ -1,10 +1,11 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
from .env import DVC_NO_ANALYTICS
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
from .env import DVC_ANALYTICS_ENDPOINT, DVC_NO_ANALYTICS
|
||||
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
def collect_and_send_report(args=None, return_code=None):
|
||||
@@ -34,6 +35,8 @@ def collect_and_send_report(args=None, return_code=None):
|
||||
|
||||
with tempfile.NamedTemporaryFile(delete=False, mode="w") as fobj:
|
||||
json.dump(report, fobj)
|
||||
|
||||
logger.trace("Saving analytics report to %s", fobj.name)
|
||||
daemon(["analytics", fobj.name])
|
||||
|
||||
|
||||
@@ -65,7 +68,7 @@ def send(path):
|
||||
"""
|
||||
import requests
|
||||
|
||||
url = "https://analytics.dvc.org"
|
||||
url = os.environ.get(DVC_ANALYTICS_ENDPOINT, "https://analytics.dvc.org")
|
||||
headers = {"content-type": "application/json"}
|
||||
|
||||
with open(path, encoding="utf-8") as fobj:
|
||||
@@ -73,11 +76,16 @@ def send(path):
|
||||
|
||||
report.update(_runtime_info())
|
||||
|
||||
logger.debug("uploading report to %s", url)
|
||||
logger.trace("Sending %s to %s", report, url)
|
||||
|
||||
try:
|
||||
requests.post(url, json=report, headers=headers, timeout=5)
|
||||
except requests.exceptions.RequestException:
|
||||
logger.debug("failed to send analytics report", exc_info=True)
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.trace("", exc_info=True)
|
||||
logger.debug("failed to send analytics report %s", str(e))
|
||||
|
||||
logger.trace("removing report %s", path)
|
||||
os.remove(path)
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ ANNOTATION_SCHEMA = {
|
||||
Annotation.PARAM_LABELS: [str],
|
||||
Annotation.PARAM_META: object,
|
||||
}
|
||||
ARTIFACT_SCHEMA = {
|
||||
ARTIFACT_SCHEMA: Dict[Any, Any] = {
|
||||
Required(Artifact.PARAM_PATH): str,
|
||||
**ANNOTATION_SCHEMA, # type: ignore[arg-type]
|
||||
}
|
||||
|
||||
+1
-2
@@ -1,8 +1,7 @@
|
||||
from dvc.fs.dvc import _DVCFileSystem as DVCFileSystem
|
||||
|
||||
from .artifacts import artifacts_show
|
||||
from .data import open # pylint: disable=redefined-builtin
|
||||
from .data import get_url, read
|
||||
from .data import get_url, open, read
|
||||
from .experiments import exp_save, exp_show
|
||||
from .scm import all_branches, all_commits, all_tags
|
||||
from .show import metrics_show, params_show
|
||||
|
||||
+2
-2
@@ -55,7 +55,7 @@ def get_url(path, repo=None, rev=None, remote=None):
|
||||
|
||||
|
||||
class _OpenContextManager(GCM):
|
||||
def __init__(self, func, args, kwds): # pylint: disable=super-init-not-called
|
||||
def __init__(self, func, args, kwds):
|
||||
self.gen = func(*args, **kwds)
|
||||
self.func, self.args, self.kwds = ( # type: ignore[assignment]
|
||||
func,
|
||||
@@ -67,7 +67,7 @@ class _OpenContextManager(GCM):
|
||||
raise AttributeError("dvc.api.open() should be used in a with statement.")
|
||||
|
||||
|
||||
def open( # noqa: A001, pylint: disable=redefined-builtin
|
||||
def open( # noqa: A001
|
||||
path: str,
|
||||
repo: Optional[str] = None,
|
||||
rev: Optional[str] = None,
|
||||
|
||||
@@ -53,7 +53,7 @@ def _postprocess(exp_rows):
|
||||
except ValueError:
|
||||
exp_row[k] = v_str
|
||||
|
||||
if not exp_row[k]:
|
||||
elif not exp_row[k]:
|
||||
exp_row[k] = None
|
||||
|
||||
return exp_rows
|
||||
|
||||
@@ -2,7 +2,6 @@ from typing import Optional
|
||||
|
||||
try:
|
||||
# file is created during dvc build
|
||||
# pylint:disable=unused-import
|
||||
from . import _build # type: ignore[attr-defined, import]
|
||||
|
||||
PKG: Optional[str] = _build.PKG # type: ignore[assignment]
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@ def migrate_2_to_3(repo: "Repo", dry: bool = False):
|
||||
src = repo.cache.legacy
|
||||
dest = repo.cache.local
|
||||
if dry:
|
||||
oids = list(src._list_oids()) # pylint: disable=protected-access
|
||||
oids = list(src._list_oids())
|
||||
ui.write(
|
||||
f"{len(oids)} files will be re-hashed and migrated to the DVC 3.0 cache "
|
||||
"location."
|
||||
|
||||
+15
-10
@@ -2,15 +2,17 @@
|
||||
|
||||
import logging
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
from dvc.log import logger
|
||||
|
||||
# Workaround for CPython bug. See [1] and [2] for more info.
|
||||
# [1] https://github.com/aws/aws-cli/blob/1.16.277/awscli/clidriver.py#L55
|
||||
# [2] https://bugs.python.org/issue29288
|
||||
from typing import Optional
|
||||
|
||||
"".encode("idna")
|
||||
|
||||
logger = logging.getLogger("dvc")
|
||||
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class DvcParserError(Exception):
|
||||
@@ -165,18 +167,18 @@ def main(argv=None): # noqa: C901, PLR0912, PLR0915
|
||||
# the copied parent's standard file descriptors. If we make any logging
|
||||
# calls in this state it will cause an exception due to writing to a closed
|
||||
# file descriptor.
|
||||
if sys.stderr.closed: # pylint: disable=using-constant-test
|
||||
if not sys.stderr or sys.stderr.closed:
|
||||
logging.disable()
|
||||
elif sys.stdout.closed: # pylint: disable=using-constant-test
|
||||
elif not sys.stdout or sys.stdout.closed:
|
||||
logging.disable(logging.INFO)
|
||||
|
||||
args = None
|
||||
|
||||
outer_log_level = logger.level
|
||||
level = None
|
||||
try:
|
||||
args = parse_args(argv)
|
||||
|
||||
level = None
|
||||
if args.quiet:
|
||||
level = logging.CRITICAL
|
||||
elif args.verbose == 1:
|
||||
@@ -197,9 +199,9 @@ def main(argv=None): # noqa: C901, PLR0912, PLR0915
|
||||
logger.debug("v%s%s, %s on %s", __version__, pkg, pyv, platform())
|
||||
logger.debug("command: %s", " ".join(argv or sys.argv))
|
||||
|
||||
logger.trace(args) # type: ignore[attr-defined]
|
||||
logger.trace(args)
|
||||
|
||||
if not sys.stdout.closed and not args.quiet:
|
||||
if sys.stdout and not sys.stdout.closed and not args.quiet:
|
||||
from dvc.ui import ui
|
||||
|
||||
ui.enable()
|
||||
@@ -230,16 +232,19 @@ def main(argv=None): # noqa: C901, PLR0912, PLR0915
|
||||
logger.exception("")
|
||||
except DvcParserError:
|
||||
ret = 254
|
||||
except Exception as exc: # noqa: BLE001, pylint: disable=broad-except
|
||||
# pylint: disable=no-member
|
||||
except Exception as exc: # noqa: BLE001
|
||||
ret = _log_exceptions(exc) or 255
|
||||
|
||||
try:
|
||||
import os
|
||||
|
||||
from dvc import analytics
|
||||
|
||||
if analytics.is_enabled():
|
||||
analytics.collect_and_send_report(args, ret)
|
||||
|
||||
logger.trace("Process %s exiting with %s", os.getpid(), ret)
|
||||
|
||||
return ret
|
||||
finally:
|
||||
logger.setLevel(outer_log_level)
|
||||
|
||||
+4
-3
@@ -1,12 +1,13 @@
|
||||
import logging
|
||||
import os
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from dvc.log import logger
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from dvc.config import Config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdBase(ABC):
|
||||
@@ -31,7 +32,7 @@ class CmdBase(ABC):
|
||||
|
||||
|
||||
class CmdBaseNoRepo(CmdBase):
|
||||
def __init__(self, args): # pylint: disable=super-init-not-called
|
||||
def __init__(self, args):
|
||||
self.args = args
|
||||
|
||||
os.chdir(args.cd)
|
||||
|
||||
+7
-5
@@ -1,6 +1,5 @@
|
||||
"""Main parser for the dvc cli."""
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
from functools import lru_cache
|
||||
|
||||
@@ -27,6 +26,7 @@ from dvc.commands import (
|
||||
get_url,
|
||||
git_hook,
|
||||
imp,
|
||||
imp_db,
|
||||
imp_url,
|
||||
init,
|
||||
install,
|
||||
@@ -46,10 +46,11 @@ from dvc.commands import (
|
||||
update,
|
||||
version,
|
||||
)
|
||||
from dvc.log import logger
|
||||
|
||||
from . import DvcParserError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
COMMANDS = [
|
||||
init,
|
||||
@@ -65,6 +66,7 @@ COMMANDS = [
|
||||
data_sync,
|
||||
gc,
|
||||
imp,
|
||||
imp_db,
|
||||
imp_url,
|
||||
config,
|
||||
checkout,
|
||||
@@ -95,12 +97,12 @@ COMMANDS = [
|
||||
|
||||
|
||||
def _find_parser(parser, cmd_cls):
|
||||
defaults = parser._defaults # pylint: disable=protected-access
|
||||
defaults = parser._defaults
|
||||
if not cmd_cls or cmd_cls == defaults.get("func"):
|
||||
parser.print_help()
|
||||
raise DvcParserError
|
||||
|
||||
actions = parser._actions # pylint: disable=protected-access
|
||||
actions = parser._actions
|
||||
for action in actions:
|
||||
if not isinstance(action.choices, dict):
|
||||
# NOTE: we are only interested in subparsers
|
||||
@@ -112,7 +114,7 @@ def _find_parser(parser, cmd_cls):
|
||||
class DvcParser(argparse.ArgumentParser):
|
||||
"""Custom parser class for dvc CLI."""
|
||||
|
||||
def error(self, message, cmd_cls=None): # pylint: disable=arguments-differ
|
||||
def error(self, message, cmd_cls=None):
|
||||
logger.error(message)
|
||||
_find_parser(self, cmd_cls)
|
||||
|
||||
|
||||
@@ -2,6 +2,10 @@ import argparse
|
||||
|
||||
|
||||
class DictAction(argparse.Action):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.setdefault("metavar", "<name>=<value>")
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def __call__(self, parser, args, values, option_string=None): # noqa: ARG002
|
||||
d = getattr(args, self.dest) or {}
|
||||
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdAdd(CmdBase):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import DictAction, append_doc_link, fix_subparsers
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdArtifactsGet(CmdBaseNoRepo):
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdCommit(CmdBase):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.completion import PREAMBLE
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
SUPPORTED_SHELLS = ["bash", "zsh"]
|
||||
@@ -18,7 +18,7 @@ class CmdCompletion(CmdBaseNoRepo):
|
||||
|
||||
shell = self.args.shell
|
||||
parser = self.args.parser
|
||||
script = shtab.complete(parser, shell=shell, preamble=PREAMBLE) # nosec B604
|
||||
script = shtab.complete(parser, shell=shell, preamble=PREAMBLE)
|
||||
ui.write(script, force=True)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
NAME_REGEX = r"^(?P<remote>remote\.)?(?P<section>[^\.]*)\.(?P<option>[^\.]*)$"
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
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__)
|
||||
|
||||
|
||||
class CmdDaemonBase(CmdBaseNoRepo):
|
||||
@@ -21,6 +24,8 @@ class CmdDaemonUpdater(CmdDaemonBase):
|
||||
config = Config(dvc_dir, validate=False)
|
||||
hardlink_lock = config.get("core", {}).get("hardlink_lock", False)
|
||||
updater = Updater(tmp_dir, hardlink_lock=hardlink_lock)
|
||||
|
||||
logger.info("Starting updater to fetch the latest version")
|
||||
updater.fetch(detach=False)
|
||||
|
||||
return 0
|
||||
@@ -30,6 +35,7 @@ class CmdDaemonAnalytics(CmdDaemonBase):
|
||||
def run(self):
|
||||
from dvc import analytics
|
||||
|
||||
logger.info("Sending analytics")
|
||||
analytics.send(self.args.target)
|
||||
|
||||
return 0
|
||||
|
||||
+1
-1
@@ -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)): # noqa: B301
|
||||
for out in outs_trie.itervalues(prefix=repo.fs.path.parts(path)):
|
||||
targets.extend(str(out))
|
||||
|
||||
return targets
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import argparse
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from funcy import chunks, compact, log_durations
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link, fix_subparsers
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
from dvc.utils import colorize
|
||||
|
||||
@@ -13,7 +13,7 @@ if TYPE_CHECKING:
|
||||
from dvc.repo.data import Status as DataStatus
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdDataStatus(CmdBase):
|
||||
@@ -106,9 +106,7 @@ class CmdDataStatus(CmdBase):
|
||||
return 0
|
||||
|
||||
def run(self) -> int:
|
||||
with log_durations(
|
||||
logger.trace, "in data_status" # type: ignore[attr-defined]
|
||||
):
|
||||
with log_durations(logger.trace, "in data_status"):
|
||||
status = self.repo.data_status(
|
||||
granular=self.args.granular,
|
||||
untracked_files=self.args.untracked_files,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdDataBase(CmdBase):
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdDestroy(CmdBase):
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
def _digest(checksum):
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdExperimentsApply(CmdBase):
|
||||
def run(self):
|
||||
self.repo.experiments.apply(self.args.experiment, force=self.args.force)
|
||||
if not self.args.force:
|
||||
ui.write(
|
||||
"The --no-force option is deprecated and will be removed in a future"
|
||||
" DVC release. To revert the result of 'exp apply', run:\n"
|
||||
"\n\tgit reset --hard\n"
|
||||
"\tgit stash apply refs/exps/apply/stash\n"
|
||||
)
|
||||
self.repo.experiments.apply(self.args.experiment)
|
||||
|
||||
return 0
|
||||
|
||||
@@ -25,11 +33,10 @@ def add_parser(experiments_subparsers, parent_parser):
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
experiments_apply_parser.add_argument(
|
||||
"-f",
|
||||
"--force",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Do not prompt when removing working directory files.",
|
||||
"--no-force",
|
||||
action="store_false",
|
||||
dest="force",
|
||||
help="Fail if this command would overwrite conflicting changes.",
|
||||
)
|
||||
experiments_apply_parser.add_argument(
|
||||
"experiment", help="Experiment to be applied."
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdExperimentsBranch(CmdBase):
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdExperimentsClean(CmdBase):
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.commands.metrics import DEFAULT_PRECISION
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdExperimentsDiff(CmdBase):
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdExecutorRun(CmdBaseNoRepo):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import InvalidArgumentError
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdExperimentsList(CmdBase):
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdExperimentsPull(CmdBase):
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import argparse
|
||||
import logging
|
||||
from typing import Any, Dict
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdExperimentsPush(CmdBase):
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdQueueWorker(CmdBase):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import InvalidArgumentError
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdExperimentsRemove(CmdBase):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import InvalidArgumentError
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdExperimentsRename(CmdBase):
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
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
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdExperimentsRun(CmdRepro):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdExperimentsSave(CmdBase):
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
import logging
|
||||
import re
|
||||
from datetime import date, datetime
|
||||
from typing import TYPE_CHECKING, Dict, Iterable
|
||||
@@ -10,6 +9,7 @@ from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.commands.metrics import DEFAULT_PRECISION
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
from dvc.utils.serialize import encode_exception
|
||||
|
||||
@@ -21,7 +21,7 @@ FILL_VALUE = "-"
|
||||
FILL_VALUE_ERRORED = "!"
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
experiment_types = {
|
||||
@@ -54,7 +54,7 @@ def baseline_styler(typ):
|
||||
return {"style": "bold"} if typ == "baseline" else {}
|
||||
|
||||
|
||||
def show_experiments( # noqa: C901
|
||||
def show_experiments(
|
||||
td: "TabularData",
|
||||
headers: Dict[str, Iterable[str]],
|
||||
keep=None,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdFreezeBase(CmdBase):
|
||||
|
||||
+6
-2
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdGC(CmdBase):
|
||||
@@ -26,6 +26,10 @@ class CmdGC(CmdBase):
|
||||
not_in_remote=self.args.not_in_remote,
|
||||
)
|
||||
|
||||
# Don't prompt during dry run
|
||||
if self.args.dry:
|
||||
self.args.force = True
|
||||
|
||||
if self.args.rev:
|
||||
self.args.num = self.args.num or 1
|
||||
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import DictAction, append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdGet(CmdBaseNoRepo):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import DictAction, append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdGetUrl(CmdBaseNoRepo):
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import fix_subparsers
|
||||
from dvc.exceptions import NotDvcRepoError
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdHookBase(CmdBaseNoRepo):
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import DictAction, append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdImport(CmdBase):
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
import argparse
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdImportDb(CmdBase):
|
||||
def run(self):
|
||||
if not (self.args.sql or self.args.model):
|
||||
raise argparse.ArgumentTypeError("Either of --sql or --model is required.")
|
||||
|
||||
self.repo.imp_db(
|
||||
url=self.args.url,
|
||||
rev=self.args.rev,
|
||||
project_dir=self.args.project_dir,
|
||||
sql=self.args.sql,
|
||||
model=self.args.model,
|
||||
profile=self.args.profile,
|
||||
target=self.args.target,
|
||||
output_format=self.args.output_format,
|
||||
out=self.args.out,
|
||||
force=self.args.force,
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
def add_parser(subparsers, parent_parser):
|
||||
IMPORT_HELP = (
|
||||
"Download file or directory tracked by DVC or by Git "
|
||||
"into the workspace, and track it."
|
||||
)
|
||||
|
||||
import_parser = subparsers.add_parser(
|
||||
"import-db",
|
||||
parents=[parent_parser],
|
||||
description=append_doc_link(IMPORT_HELP, "import"),
|
||||
add_help=False,
|
||||
)
|
||||
import_parser.add_argument(
|
||||
"--url", help="Location of DVC or Git repository to download from"
|
||||
)
|
||||
import_parser.add_argument(
|
||||
"--rev",
|
||||
nargs="?",
|
||||
help="Git revision (e.g. SHA, branch, tag)",
|
||||
metavar="<commit>",
|
||||
)
|
||||
import_parser.add_argument(
|
||||
"--project-dir", nargs="?", help="Subdirectory to the dbt project location"
|
||||
)
|
||||
|
||||
group = import_parser.add_mutually_exclusive_group()
|
||||
group.add_argument(
|
||||
"--sql",
|
||||
help="SQL query",
|
||||
)
|
||||
group.add_argument(
|
||||
"--model",
|
||||
help="Model name to download",
|
||||
)
|
||||
import_parser.add_argument("--profile", help="Profile to use")
|
||||
import_parser.add_argument("--target", help="Target to use")
|
||||
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.set_defaults(func=CmdImportDb)
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import DictAction, append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdImportUrl(CmdBase):
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
import colorama
|
||||
|
||||
from dvc import analytics
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.utils import boxify
|
||||
from dvc.utils import format_link as fmt_link
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
def _welcome_message():
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdInstall(CmdBase):
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import DictAction, append_doc_link
|
||||
from dvc.commands.ls.ls_colors import LsColors
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
def _format_entry(entry, fmt):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import DictAction, append_doc_link
|
||||
from dvc.log import logger
|
||||
|
||||
from .ls import show_entries
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdListUrl(CmdBaseNoRepo):
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link, fix_subparsers
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
from dvc.utils.serialize import encode_exception
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
DEFAULT_PRECISION = 5
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdMove(CmdBase):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link, fix_subparsers
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdParamsDiff(CmdBase):
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
from typing import TYPE_CHECKING, Dict, List, Optional
|
||||
|
||||
@@ -9,6 +8,7 @@ from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link, fix_subparsers
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
from dvc.utils import format_link
|
||||
|
||||
@@ -16,7 +16,7 @@ if TYPE_CHECKING:
|
||||
from dvc.render.match import RendererWithErrors
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
def _show_json(
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdQueueKill(CmdBase):
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdQueueLogs(CmdBase):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import InvalidArgumentError
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdQueueRemove(CmdBase):
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdQueueStart(CmdBase):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.compare import TabularData
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdQueueStatus(CmdBase):
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdQueueStop(CmdBase):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdRemove(CmdBase):
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.utils import relpath
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdRoot(CmdBaseNoRepo):
|
||||
|
||||
@@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Dict, Iterable, List
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link, fix_subparsers
|
||||
from dvc.log import logger
|
||||
from dvc.utils.cli_parse import parse_params
|
||||
from dvc.utils.humanize import truncate_text
|
||||
|
||||
@@ -14,7 +15,7 @@ if TYPE_CHECKING:
|
||||
from dvc.output import Output
|
||||
from dvc.stage import Stage
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
MAX_TEXT_LENGTH = 80
|
||||
|
||||
@@ -67,9 +68,7 @@ class CmdStageList(CmdBase):
|
||||
def _get_stages(self) -> Iterable["Stage"]:
|
||||
if self.args.all:
|
||||
stages: List["Stage"] = self.repo.index.stages
|
||||
logger.trace( # type: ignore[attr-defined]
|
||||
"%d no. of stages found", len(stages)
|
||||
)
|
||||
logger.trace("%d no. of stages found", len(stages))
|
||||
return stages
|
||||
|
||||
# removing duplicates while maintaining order
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import logging
|
||||
|
||||
from dvc.commands.data_sync import CmdDataBase
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
from dvc.utils import format_link
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdDataStatus(CmdDataBase):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdUnprotect(CmdBase):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdUpdate(CmdBase):
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from dvc.cli.command import CmdBaseNoRepo
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.log import logger
|
||||
from dvc.ui import ui
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class CmdVersion(CmdBaseNoRepo):
|
||||
|
||||
+3
-3
@@ -1,5 +1,4 @@
|
||||
"""DVC config objects."""
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from contextlib import contextmanager
|
||||
@@ -9,6 +8,7 @@ from typing import TYPE_CHECKING, Dict, Optional
|
||||
from funcy import compact, memoize, re_find
|
||||
|
||||
from dvc.exceptions import DvcException, NotDvcRepoError
|
||||
from dvc.log import logger
|
||||
|
||||
from .utils.objects import cached_property
|
||||
|
||||
@@ -16,7 +16,7 @@ if TYPE_CHECKING:
|
||||
from dvc.fs import FileSystem
|
||||
from dvc.types import DictStrAny, StrPath
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class ConfigError(DvcException):
|
||||
@@ -96,7 +96,7 @@ class Config(dict):
|
||||
config: Optional["DictStrAny"] = None,
|
||||
remote: Optional[str] = None,
|
||||
remote_config: Optional["DictStrAny"] = None,
|
||||
): # pylint: disable=super-init-not-called
|
||||
):
|
||||
from dvc.fs import LocalFileSystem
|
||||
|
||||
dvc_dir = os.fspath(dvc_dir) if dvc_dir else None
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import logging
|
||||
import os
|
||||
from urllib.parse import urlparse
|
||||
|
||||
@@ -16,7 +15,9 @@ from voluptuous import (
|
||||
Schema,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
Bool = All(
|
||||
Lower,
|
||||
@@ -256,6 +257,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,
|
||||
**REMOTE_COMMON,
|
||||
},
|
||||
"oss": {
|
||||
@@ -314,6 +318,8 @@ SCHEMA = {
|
||||
"feature": FeatureSchema(
|
||||
{
|
||||
Optional("machine", default=False): Bool,
|
||||
"db_profile": str,
|
||||
"db_target": str,
|
||||
},
|
||||
),
|
||||
"plots": {
|
||||
|
||||
+125
-72
@@ -3,132 +3,185 @@
|
||||
import inspect
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from subprocess import Popen # nosec B404
|
||||
from typing import List
|
||||
from contextlib import nullcontext
|
||||
from typing import TYPE_CHECKING, Any, List, Mapping, Optional, Sequence, Union
|
||||
|
||||
from dvc.env import DVC_DAEMON
|
||||
from dvc.log import logger
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import ContextManager
|
||||
|
||||
from dvc.env import DVC_DAEMON, DVC_DAEMON_LOGFILE
|
||||
from dvc.utils import fix_env, is_binary
|
||||
from dvc.utils.collections import ensure_list
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
def _suppress_resource_warning(popen: Popen):
|
||||
def _suppress_resource_warning(popen: subprocess.Popen) -> None:
|
||||
"""Sets the returncode to avoid ResourceWarning when popen is garbage collected."""
|
||||
# only use for daemon processes.
|
||||
# See https://bugs.python.org/issue38890.
|
||||
popen.returncode = 0
|
||||
|
||||
|
||||
def _popen(cmd, **kwargs) -> Popen:
|
||||
prefix = [sys.executable]
|
||||
if not is_binary():
|
||||
main_entrypoint = os.path.join(
|
||||
os.path.abspath(os.path.dirname(__file__)), "__main__.py"
|
||||
)
|
||||
prefix += [main_entrypoint]
|
||||
return Popen(
|
||||
prefix + cmd, close_fds=True, shell=False, **kwargs # nosec B603 # noqa: S603
|
||||
def _win_detached_subprocess(args: Sequence[str], **kwargs) -> int:
|
||||
assert os.name == "nt"
|
||||
|
||||
from subprocess import ( # type: ignore[attr-defined]
|
||||
CREATE_NEW_PROCESS_GROUP,
|
||||
CREATE_NO_WINDOW,
|
||||
STARTF_USESHOWWINDOW,
|
||||
STARTUPINFO,
|
||||
)
|
||||
|
||||
# https://stackoverflow.com/a/7006424
|
||||
# https://bugs.python.org/issue41619
|
||||
creationflags = CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW
|
||||
|
||||
def _spawn_windows(cmd, env):
|
||||
if sys.platform == "win32":
|
||||
from subprocess import ( # nosec B404
|
||||
CREATE_NEW_PROCESS_GROUP,
|
||||
CREATE_NO_WINDOW,
|
||||
STARTF_USESHOWWINDOW,
|
||||
STARTUPINFO,
|
||||
)
|
||||
|
||||
# https://stackoverflow.com/a/7006424
|
||||
# https://bugs.python.org/issue41619
|
||||
creationflags = CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW
|
||||
|
||||
startupinfo = STARTUPINFO()
|
||||
startupinfo.dwFlags |= STARTF_USESHOWWINDOW
|
||||
|
||||
popen = _popen(
|
||||
cmd, env=env, creationflags=creationflags, startupinfo=startupinfo
|
||||
)
|
||||
_suppress_resource_warning(popen)
|
||||
startupinfo = STARTUPINFO()
|
||||
startupinfo.dwFlags |= STARTF_USESHOWWINDOW
|
||||
popen = subprocess.Popen(
|
||||
args,
|
||||
close_fds=True,
|
||||
shell=False, # noqa: S603
|
||||
startupinfo=startupinfo,
|
||||
creationflags=creationflags,
|
||||
**kwargs,
|
||||
)
|
||||
_suppress_resource_warning(popen)
|
||||
return popen.pid
|
||||
|
||||
|
||||
def _spawn_posix(cmd, env):
|
||||
from dvc.cli import main
|
||||
def _get_dvc_args() -> List[str]:
|
||||
args = [sys.executable]
|
||||
if not is_binary():
|
||||
root_dir = os.path.abspath(os.path.dirname(__file__))
|
||||
main_entrypoint = os.path.join(root_dir, "__main__.py")
|
||||
args.append(main_entrypoint)
|
||||
return args
|
||||
|
||||
# `fork` will copy buffers, so we need to flush them before forking.
|
||||
# Otherwise, we will get duplicated outputs.
|
||||
if sys.stdout and not sys.stdout.closed:
|
||||
sys.stdout.flush()
|
||||
if sys.stderr and not sys.stderr.closed:
|
||||
sys.stderr.flush()
|
||||
|
||||
def _fork_process() -> int:
|
||||
assert os.name == "posix"
|
||||
|
||||
# NOTE: using os._exit instead of sys.exit, because dvc built
|
||||
# with PyInstaller has trouble with SystemExit exception and throws
|
||||
# errors such as "[26338] Failed to execute script __main__"
|
||||
try:
|
||||
# pylint: disable-next=no-member
|
||||
pid = os.fork() # type: ignore[attr-defined]
|
||||
if pid > 0:
|
||||
return
|
||||
return pid
|
||||
except OSError:
|
||||
logger.exception("failed at first fork")
|
||||
os._exit(1) # pylint: disable=protected-access
|
||||
os._exit(1)
|
||||
|
||||
os.setsid() # type: ignore[attr-defined] # pylint: disable=no-member
|
||||
os.setsid() # type: ignore[attr-defined]
|
||||
|
||||
try:
|
||||
# pylint: disable-next=no-member
|
||||
pid = os.fork() # type: ignore[attr-defined]
|
||||
if pid > 0:
|
||||
os._exit(0) # pylint: disable=protected-access
|
||||
os._exit(0)
|
||||
except OSError:
|
||||
logger.exception("failed at second fork")
|
||||
os._exit(1) # pylint: disable=protected-access
|
||||
os._exit(1)
|
||||
|
||||
sys.stdin.close()
|
||||
sys.stdout.close()
|
||||
sys.stderr.close()
|
||||
os.closerange(0, 3)
|
||||
|
||||
os.environ.update(env)
|
||||
main(cmd)
|
||||
|
||||
os._exit(0) # pylint: disable=protected-access
|
||||
# disconnect from the terminal
|
||||
fd = os.open(os.devnull, os.O_RDWR)
|
||||
for fd2 in range(3):
|
||||
os.dup2(fd, fd2)
|
||||
os.close(fd)
|
||||
return pid
|
||||
|
||||
|
||||
def _spawn(cmd, env):
|
||||
logger.debug("Trying to spawn '%s'", cmd)
|
||||
def _posix_detached_subprocess(args: Sequence[str], **kwargs) -> int:
|
||||
# double fork and execute a subprocess so that there are no zombies
|
||||
read_end, write_end = os.pipe()
|
||||
pid = _fork_process()
|
||||
if pid > 0: # in parent
|
||||
os.close(write_end)
|
||||
pid_str = os.read(read_end, 32).decode("utf8")
|
||||
os.close(read_end)
|
||||
return int(pid_str)
|
||||
|
||||
proc = subprocess.Popen(
|
||||
args,
|
||||
shell=False, # noqa: S603
|
||||
close_fds=True,
|
||||
**kwargs,
|
||||
)
|
||||
os.close(read_end)
|
||||
os.write(write_end, str(proc.pid).encode("utf8"))
|
||||
os.close(write_end)
|
||||
|
||||
exit_code = proc.wait()
|
||||
os._exit(exit_code)
|
||||
|
||||
|
||||
def _detached_subprocess(args: Sequence[str], **kwargs) -> int:
|
||||
"""Run in a detached subprocess."""
|
||||
kwargs.setdefault("stdin", subprocess.DEVNULL)
|
||||
kwargs.setdefault("stdout", subprocess.DEVNULL)
|
||||
kwargs.setdefault("stderr", subprocess.DEVNULL)
|
||||
|
||||
if os.name == "nt":
|
||||
_spawn_windows(cmd, env)
|
||||
elif os.name == "posix":
|
||||
_spawn_posix(cmd, env)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
logger.debug("Spawned '%s'", cmd)
|
||||
return _win_detached_subprocess(args, **kwargs)
|
||||
return _posix_detached_subprocess(args, **kwargs)
|
||||
|
||||
|
||||
def daemon(args):
|
||||
def _map_log_level_to_flag() -> Optional[str]:
|
||||
flags = {logging.DEBUG: "-v", logging.TRACE: "-vv"} # type: ignore[attr-defined]
|
||||
return flags.get(logger.getEffectiveLevel())
|
||||
|
||||
|
||||
def daemon(args: List[str]) -> None:
|
||||
"""Launch a `dvc daemon` command in a detached process.
|
||||
|
||||
Args:
|
||||
args (list): list of arguments to append to `dvc daemon` command.
|
||||
"""
|
||||
daemonize(["daemon", "-q", *args])
|
||||
if flag := _map_log_level_to_flag():
|
||||
args = [*args, flag]
|
||||
daemonize(["daemon", *args])
|
||||
|
||||
|
||||
def daemonize(cmd: List[str]):
|
||||
def _spawn(
|
||||
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()
|
||||
kwargs = {}
|
||||
if output_file:
|
||||
file = open(output_file, "ab") # noqa: SIM115
|
||||
kwargs = {"stdout": file, "stderr": file}
|
||||
|
||||
if executable is None:
|
||||
executable = _get_dvc_args()
|
||||
else:
|
||||
executable = ensure_list(executable)
|
||||
|
||||
with file:
|
||||
return _detached_subprocess(executable + args, env=env, **kwargs)
|
||||
|
||||
|
||||
def daemonize(args: List[str], executable: Union[None, str, List[str]] = None) -> None:
|
||||
if os.name not in ("posix", "nt"):
|
||||
return None
|
||||
|
||||
if os.environ.get(DVC_DAEMON):
|
||||
logger.debug("skipping launching a new daemon.")
|
||||
return
|
||||
|
||||
env = fix_env()
|
||||
env[DVC_DAEMON] = "1"
|
||||
if not is_binary():
|
||||
file_path = os.path.abspath(inspect.stack()[0][1])
|
||||
env["PYTHONPATH"] = os.path.dirname(os.path.dirname(file_path))
|
||||
env[DVC_DAEMON] = "1"
|
||||
|
||||
_spawn(cmd, env)
|
||||
logger.debug("Trying to spawn %r", args)
|
||||
pid = _spawn(args, executable, env, output_file=env.get(DVC_DAEMON_LOGFILE))
|
||||
logger.debug("Spawned %r with pid %s", args, pid)
|
||||
|
||||
+9
-11
@@ -1,6 +1,5 @@
|
||||
"""Draws DAG in ASCII."""
|
||||
|
||||
import logging
|
||||
import math
|
||||
import os
|
||||
|
||||
@@ -8,7 +7,9 @@ from grandalf.graphs import Edge, Graph, Vertex
|
||||
from grandalf.layouts import SugiyamaLayout
|
||||
from grandalf.routing import EdgeViewer, route_with_lines
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
from dvc.log import logger
|
||||
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class VertexViewer:
|
||||
@@ -22,17 +23,16 @@ class VertexViewer:
|
||||
HEIGHT = 3 # top and bottom box edges + text
|
||||
|
||||
def __init__(self, name):
|
||||
# pylint: disable=invalid-name
|
||||
self._h = self.HEIGHT # top and bottom box edges + text
|
||||
self._w = len(name) + 2 # right and left bottom edges + text
|
||||
|
||||
@property
|
||||
def h(self): # pylint: disable=invalid-name
|
||||
def h(self):
|
||||
"""Height of the box."""
|
||||
return self._h
|
||||
|
||||
@property
|
||||
def w(self): # pylint: disable=invalid-name
|
||||
def w(self):
|
||||
"""Width of the box."""
|
||||
return self._w
|
||||
|
||||
@@ -90,7 +90,6 @@ class AsciiCanvas:
|
||||
y1 (int): y coordinate where the line should end.
|
||||
char (str): character to draw the line with.
|
||||
"""
|
||||
# pylint: disable=too-many-arguments, too-many-branches
|
||||
if x0 > x1:
|
||||
x1, x0 = x0, x1
|
||||
y1, y0 = y0, y1
|
||||
@@ -234,11 +233,11 @@ def draw(vertices, edges):
|
||||
| 1 |
|
||||
+---+
|
||||
"""
|
||||
# pylint: disable=too-many-locals
|
||||
|
||||
# NOTE: coordinates might me negative, so we need to shift
|
||||
# everything to the positive plane before we actually draw it.
|
||||
Xs = [] # noqa: N806, pylint: disable=invalid-name
|
||||
Ys = [] # noqa: N806, pylint: disable=invalid-name
|
||||
Xs = [] # noqa: N806
|
||||
Ys = [] # noqa: N806
|
||||
|
||||
sug = _build_sugiyama_layout(vertices, edges)
|
||||
|
||||
@@ -250,7 +249,7 @@ def draw(vertices, edges):
|
||||
Ys.append(vertex.view.xy[1] + vertex.view.h)
|
||||
|
||||
for edge in sug.g.sE:
|
||||
for x, y in edge.view._pts: # pylint: disable=protected-access
|
||||
for x, y in edge.view._pts:
|
||||
Xs.append(x)
|
||||
Ys.append(y)
|
||||
|
||||
@@ -266,7 +265,6 @@ def draw(vertices, edges):
|
||||
|
||||
# NOTE: first draw edges so that node boxes could overwrite them
|
||||
for edge in sug.g.sE:
|
||||
# pylint: disable=protected-access
|
||||
assert len(edge.view._pts) > 1
|
||||
for index in range(1, len(edge.view._pts)):
|
||||
start = edge.view._pts[index - 1]
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
"""Manages dvc remotes that user can use with push/pull/status commands."""
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Iterable, Optional, Set, Tuple
|
||||
|
||||
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
|
||||
from dvc_data.hashfile.transfer import TransferResult
|
||||
@@ -15,7 +15,7 @@ if TYPE_CHECKING:
|
||||
from dvc_data.hashfile.hash_info import HashInfo
|
||||
from dvc_data.hashfile.status import CompareStatusResult
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class Remote:
|
||||
|
||||
@@ -4,6 +4,7 @@ from typing import Any, Dict, List, Mapping, Set
|
||||
from dvc.output import ARTIFACT_SCHEMA, DIR_FILES_SCHEMA, Output
|
||||
|
||||
from .base import Dependency
|
||||
from .db import DB_SCHEMA, PARAM_DB, DbDependency, DbtDependency
|
||||
from .param import ParamsDependency
|
||||
from .repo import RepoDependency
|
||||
|
||||
@@ -14,20 +15,28 @@ from .repo import RepoDependency
|
||||
SCHEMA: Mapping[str, Any] = {
|
||||
**ARTIFACT_SCHEMA,
|
||||
**RepoDependency.REPO_SCHEMA,
|
||||
**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 {}
|
||||
db = d.get(PARAM_DB, {})
|
||||
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_QUERY in db:
|
||||
return DbDependency(stage, info)
|
||||
if db:
|
||||
return DbtDependency(repo, stage, info)
|
||||
|
||||
assert p
|
||||
if repo:
|
||||
return RepoDependency(repo, stage, p, info)
|
||||
return Dependency(stage, p, info, **kwargs)
|
||||
|
||||
|
||||
@@ -44,9 +53,11 @@ 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 {}
|
||||
if db:
|
||||
info.update({"db": db})
|
||||
return [
|
||||
_get(
|
||||
stage,
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
import os
|
||||
from contextlib import contextmanager, nullcontext
|
||||
from typing import TYPE_CHECKING, Any, Dict, Iterator, Union
|
||||
|
||||
from funcy import compact
|
||||
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
from dvc.scm import SCM
|
||||
|
||||
from .base import Dependency
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from agate import Table
|
||||
from rich.status import Status
|
||||
|
||||
from dvc.stage import Stage
|
||||
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
PARAM_DB = "db"
|
||||
PARAM_PROFILE = "profile"
|
||||
PARAM_FILE_FORMAT = "file_format"
|
||||
|
||||
|
||||
def _get_db_config(config: Dict) -> Dict:
|
||||
conf = config.get("feature", {})
|
||||
pref = "db_"
|
||||
return {k.lstrip(pref): v for k, v in conf.items() if k.startswith(pref)}
|
||||
|
||||
|
||||
@contextmanager
|
||||
def log_status(msg, log=logger.debug) -> Iterator["Status"]:
|
||||
from funcy import log_durations
|
||||
|
||||
from dvc.ui import ui
|
||||
|
||||
with log_durations(log, msg), ui.status(msg) as status:
|
||||
yield status
|
||||
|
||||
|
||||
@contextmanager
|
||||
def chdir(path):
|
||||
wdir = os.getcwd()
|
||||
os.chdir(path)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
os.chdir(wdir)
|
||||
|
||||
|
||||
def export_to(table: "Table", to: str, file_format: str = "csv") -> None:
|
||||
exporter = {"csv": table.to_csv, "json": table.to_json}
|
||||
return exporter[file_format](to)
|
||||
|
||||
|
||||
class AbstractDependency(Dependency):
|
||||
"""Dependency without workspace/fs/fs_path"""
|
||||
|
||||
def __init__(self, stage: "Stage", info, *args, **kwargs):
|
||||
self.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_QUERY = "query"
|
||||
QUERY_SCHEMA = {PARAM_QUERY: str}
|
||||
|
||||
def __init__(self, stage: "Stage", info, *args, **kwargs):
|
||||
super().__init__(stage, info, *args, **kwargs)
|
||||
self.target = None
|
||||
|
||||
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
|
||||
|
||||
db_info = self.info.get(PARAM_DB, {})
|
||||
query = db_info.get(self.PARAM_QUERY, "[query]")
|
||||
return truncate_text(query, 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.info.get(PARAM_DB, {}))
|
||||
return {PARAM_DB: db_info} if db_info else {}
|
||||
|
||||
def update(self, rev=None):
|
||||
"""nothing to update."""
|
||||
|
||||
def download(self, to, jobs=None, file_format=None): # noqa: ARG002
|
||||
db_info = self.info.get(PARAM_DB, {})
|
||||
query = db_info.get(self.PARAM_QUERY)
|
||||
if not query:
|
||||
raise DvcException("Cannot download: no query specified")
|
||||
|
||||
from dvc.utils.db import _check_dbt, _profiles_dir, execute_sql
|
||||
|
||||
db_config = _get_db_config(self.repo.config)
|
||||
profile = db_info.get(PARAM_PROFILE) or db_config.get(PARAM_PROFILE)
|
||||
target = self.target or db_config.get("target")
|
||||
file_format = file_format or db_info.get(PARAM_FILE_FORMAT, "csv")
|
||||
|
||||
_check_dbt(self.PARAM_QUERY)
|
||||
profiles_dir = _profiles_dir(self.repo.root_dir)
|
||||
with log_status("Executing query") as status:
|
||||
table = execute_sql(
|
||||
query,
|
||||
profiles_dir,
|
||||
self.repo.root_dir,
|
||||
profile,
|
||||
target=target,
|
||||
status=status,
|
||||
)
|
||||
# NOTE: we keep everything in memory, and then export it out later.
|
||||
with log_status(f"Saving to {to}"):
|
||||
return export_to(table, to.fs_path, file_format)
|
||||
|
||||
|
||||
class DbtDependency(AbstractDependency):
|
||||
PARAM_MODEL = "model"
|
||||
PARAM_VERSION = "version"
|
||||
PARAM_PROJECT_DIR = "project_dir"
|
||||
DBT_SCHEMA = {
|
||||
PARAM_MODEL: str,
|
||||
PARAM_VERSION: str,
|
||||
PARAM_PROJECT_DIR: str,
|
||||
}
|
||||
|
||||
def __init__(self, def_repo: Dict[str, Any], stage: "Stage", info, *args, **kwargs):
|
||||
self.def_repo = def_repo or {}
|
||||
self.target = None
|
||||
super().__init__(stage, info, *args, **kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
return "{}:{}".format(
|
||||
self.__class__.__name__,
|
||||
"".join(f"{k}=={v}" for k, v in {**self.def_repo, **self.info}.items()),
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
from .repo import RepoDependency
|
||||
|
||||
repo = self.def_repo.get(RepoDependency.PARAM_URL)
|
||||
rev = self.def_repo.get(RepoDependency.PARAM_REV)
|
||||
|
||||
db_info = self.info.get(PARAM_DB, {})
|
||||
db = db_info.get(self.PARAM_MODEL, "")
|
||||
project_dir = db_info.get(self.PARAM_PROJECT_DIR, "")
|
||||
repo_info = ""
|
||||
if repo:
|
||||
repo_info += repo
|
||||
if rev:
|
||||
repo_info += f"@{rev}"
|
||||
if project_dir:
|
||||
repo_info += f":/{project_dir}"
|
||||
return db + (f"({repo_info})" if repo_info else "")
|
||||
|
||||
@property
|
||||
def locked_rev(self):
|
||||
from .repo import RepoDependency
|
||||
|
||||
return self.def_repo.get(RepoDependency.PARAM_REV_LOCK)
|
||||
|
||||
@property
|
||||
def rev(self):
|
||||
from .repo import RepoDependency
|
||||
|
||||
return self.def_repo.get(RepoDependency.PARAM_REV)
|
||||
|
||||
def workspace_status(self):
|
||||
if not self.def_repo:
|
||||
return
|
||||
|
||||
current = self._get_clone(self.locked_rev or self.rev).get_rev()
|
||||
updated = self._get_clone(self.rev).get_rev()
|
||||
if current != updated:
|
||||
return {str(self): "update available"}
|
||||
return {}
|
||||
|
||||
def status(self):
|
||||
return self.workspace_status()
|
||||
|
||||
def save(self):
|
||||
from .repo import RepoDependency
|
||||
|
||||
if not self.def_repo:
|
||||
return
|
||||
|
||||
rev = self._get_clone(self.locked_rev or self.rev).get_rev()
|
||||
if self.def_repo.get(RepoDependency.PARAM_REV_LOCK) is None:
|
||||
self.def_repo[RepoDependency.PARAM_REV_LOCK] = rev
|
||||
|
||||
def dumpd(self, **kwargs) -> Dict[str, Union[str, Dict[str, str]]]:
|
||||
from .repo import RepoDependency
|
||||
|
||||
def_repo = {}
|
||||
if self.def_repo:
|
||||
def_repo = RepoDependency._dump_def_repo(self.def_repo)
|
||||
|
||||
db_info = compact(self.info.get(PARAM_DB, {}))
|
||||
return compact({RepoDependency.PARAM_REPO: def_repo, PARAM_DB: db_info})
|
||||
|
||||
def _get_clone(self, rev):
|
||||
from dvc.repo.open_repo import _cached_clone
|
||||
|
||||
from .repo import RepoDependency
|
||||
|
||||
url = self.def_repo.get(RepoDependency.PARAM_URL)
|
||||
repo_root = self.repo.root_dir if self.repo else os.getcwd()
|
||||
return SCM(_cached_clone(url, rev) if url else repo_root)
|
||||
|
||||
def update(self, rev=None):
|
||||
from .repo import RepoDependency
|
||||
|
||||
if not self.def_repo:
|
||||
return
|
||||
|
||||
if rev:
|
||||
self.def_repo[RepoDependency.PARAM_REV] = rev
|
||||
else:
|
||||
rev = self.rev
|
||||
self.def_repo[RepoDependency.PARAM_REV_LOCK] = self._get_clone(rev).get_rev()
|
||||
|
||||
def download(self, to, jobs=None, file_format=None): # noqa: ARG002
|
||||
from dvc.ui import ui
|
||||
|
||||
from .repo import RepoDependency
|
||||
|
||||
project_dir = self.info.get(PARAM_DB, {}).get(self.PARAM_PROJECT_DIR, "")
|
||||
if self.def_repo:
|
||||
ctx = repo = self._get_clone(self.locked_rev or self.rev)
|
||||
self.def_repo[RepoDependency.PARAM_REV_LOCK] = repo.get_rev()
|
||||
root = wdir = repo.root_dir
|
||||
else:
|
||||
ctx = nullcontext()
|
||||
root = self.repo.root_dir
|
||||
wdir = self.stage.wdir
|
||||
|
||||
project_path = os.path.join(wdir, project_dir) if project_dir else root
|
||||
with ctx, chdir(project_path):
|
||||
self._download_db(to, file_format=file_format)
|
||||
ui.write(f"Saved file to {to}", styled=True)
|
||||
|
||||
def _download_db(self, to, version=None, file_format=None):
|
||||
from dvc.utils.db import get_model
|
||||
|
||||
db_info = self.info.get(PARAM_DB, {})
|
||||
model = db_info.get(self.PARAM_MODEL)
|
||||
if not model:
|
||||
raise DvcException("Cannot download, no model specified")
|
||||
|
||||
db_config = _get_db_config(self.repo.config)
|
||||
version = version or db_info.get(self.PARAM_VERSION)
|
||||
profile = db_info.get(PARAM_PROFILE) or db_config.get(PARAM_PROFILE)
|
||||
target = self.target or db_info.get("target")
|
||||
file_format = file_format or db_info.get(PARAM_FILE_FORMAT, "csv")
|
||||
|
||||
with log_status("Downloading model"):
|
||||
table = get_model(model, version=version, profile=profile, target=target)
|
||||
# NOTE: we keep everything in memory, and then export it out later.
|
||||
with log_status(f"Saving to {to}"):
|
||||
export_to(table, to.fs_path, file_format=file_format)
|
||||
|
||||
|
||||
DB_SCHEMA = {
|
||||
PARAM_DB: {
|
||||
PARAM_PROFILE: str,
|
||||
PARAM_FILE_FORMAT: str,
|
||||
**DbDependency.QUERY_SCHEMA,
|
||||
**DbtDependency.DBT_SCHEMA,
|
||||
},
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import logging
|
||||
import os
|
||||
import typing
|
||||
from collections import defaultdict
|
||||
@@ -7,6 +6,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
||||
import dpath
|
||||
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
from dvc.utils.serialize import ParseError, load_path
|
||||
from dvc_data.hashfile.hash_info import HashInfo
|
||||
|
||||
@@ -15,7 +15,7 @@ from .base import Dependency
|
||||
if TYPE_CHECKING:
|
||||
from dvc.fs import FileSystem
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class MissingParamsError(DvcException):
|
||||
@@ -132,8 +132,8 @@ class ParamsDependency(Dependency):
|
||||
from funcy import ldistinct
|
||||
|
||||
status: Dict[str, Any] = defaultdict(dict)
|
||||
assert isinstance(self.hash_info.value, dict)
|
||||
info = self.hash_info.value if self.hash_info else {}
|
||||
assert isinstance(info, dict)
|
||||
actual = self.read_params()
|
||||
|
||||
# NOTE: we want to preserve the order of params as specified in the
|
||||
|
||||
+19
-16
@@ -1,7 +1,7 @@
|
||||
from copy import deepcopy
|
||||
from typing import TYPE_CHECKING, Dict, Optional, Union
|
||||
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
|
||||
|
||||
from voluptuous import Any, Required
|
||||
import voluptuous as vol
|
||||
|
||||
from dvc.utils import as_posix
|
||||
|
||||
@@ -22,11 +22,11 @@ class RepoDependency(Dependency):
|
||||
|
||||
REPO_SCHEMA = {
|
||||
PARAM_REPO: {
|
||||
Required(PARAM_URL): str,
|
||||
vol.Required(PARAM_URL): str,
|
||||
PARAM_REV: str,
|
||||
PARAM_REV_LOCK: str,
|
||||
PARAM_CONFIG: Any(str, dict),
|
||||
PARAM_REMOTE: Any(str, dict),
|
||||
PARAM_CONFIG: vol.Any(str, dict),
|
||||
PARAM_REMOTE: vol.Any(str, dict),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
|
||||
+3
-7
@@ -1,5 +1,4 @@
|
||||
import contextlib
|
||||
import logging
|
||||
import os
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
@@ -14,6 +13,7 @@ from typing import (
|
||||
)
|
||||
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
from dvc.stage import serialize
|
||||
from dvc.stage.exceptions import (
|
||||
StageFileBadNameError,
|
||||
@@ -32,7 +32,7 @@ if TYPE_CHECKING:
|
||||
from .parsing import DataResolver
|
||||
from .stage import Stage
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
_T = TypeVar("_T")
|
||||
|
||||
DVC_FILE_SUFFIX = ".dvc"
|
||||
@@ -166,7 +166,6 @@ class FileMixin:
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
# pylint: disable-next=unused-argument
|
||||
def remove(self, force=False): # noqa: ARG002
|
||||
with contextlib.suppress(FileNotFoundError):
|
||||
os.unlink(self.path)
|
||||
@@ -208,7 +207,6 @@ class SingleStageFile(FileMixin):
|
||||
dump_yaml(self.path, serialize.to_single_stage_file(stage, **kwargs))
|
||||
self.repo.scm_context.track_file(self.relpath)
|
||||
|
||||
# pylint: disable-next=unused-argument
|
||||
def remove_stage(self, stage): # noqa: ARG002
|
||||
self.remove()
|
||||
|
||||
@@ -237,9 +235,7 @@ class ProjectFile(FileMixin):
|
||||
self.__dict__.pop("resolver", None)
|
||||
self.__dict__.pop("stages", None)
|
||||
|
||||
def dump(
|
||||
self, stage, update_pipeline=True, update_lock=True, **kwargs
|
||||
): # pylint: disable=arguments-differ
|
||||
def dump(self, stage, update_pipeline=True, update_lock=True, **kwargs):
|
||||
"""Dumps given stage appropriately in the dvcfile."""
|
||||
from dvc.stage import PipelineStage
|
||||
|
||||
|
||||
+4
-1
@@ -1,4 +1,6 @@
|
||||
DVC_ANALYTICS_ENDPOINT = "DVC_ANALYTICS_ENDPOINT"
|
||||
DVC_DAEMON = "DVC_DAEMON"
|
||||
DVC_DAEMON_LOGFILE = "DVC_DAEMON_LOGFILE"
|
||||
DVC_EXP_AUTO_PUSH = "DVC_EXP_AUTO_PUSH"
|
||||
DVC_EXP_BASELINE_REV = "DVC_EXP_BASELINE_REV"
|
||||
DVC_EXP_GIT_REMOTE = "DVC_EXP_GIT_REMOTE"
|
||||
@@ -12,6 +14,7 @@ DVC_SHOW_TRACEBACK = "DVC_SHOW_TRACEBACK"
|
||||
DVC_SITE_CACHE_DIR = "DVC_SITE_CACHE_DIR"
|
||||
DVC_STUDIO_OFFLINE = "DVC_STUDIO_OFFLINE"
|
||||
DVC_STUDIO_REPO_URL = "DVC_STUDIO_REPO_URL"
|
||||
DVC_STUDIO_TOKEN = "DVC_STUDIO_TOKEN" # noqa: S105 # nosec B105
|
||||
DVC_STUDIO_TOKEN = "DVC_STUDIO_TOKEN" # noqa: S105
|
||||
DVC_STUDIO_URL = "DVC_STUDIO_URL"
|
||||
DVC_SYSTEM_CONFIG_DIR = "DVC_SYSTEM_CONFIG_DIR"
|
||||
DVC_UPDATER_ENDPOINT = "DVC_UPDATER_ENDPOINT"
|
||||
|
||||
+1
-1
@@ -301,7 +301,7 @@ class URLMissingError(DvcException):
|
||||
super().__init__(f"The path '{url}' does not exist")
|
||||
|
||||
|
||||
class IsADirectoryError(DvcException): # noqa: A001,pylint:disable=redefined-builtin
|
||||
class IsADirectoryError(DvcException): # noqa: A001
|
||||
"""Raised when a file operation is requested on a directory."""
|
||||
|
||||
|
||||
|
||||
+2
-7
@@ -5,8 +5,6 @@ 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,
|
||||
@@ -46,9 +44,6 @@ known_implementations.update(
|
||||
)
|
||||
|
||||
|
||||
# pylint: enable=unused-import
|
||||
|
||||
|
||||
def download(
|
||||
fs: "FileSystem", fs_path: str, to: str, jobs: Optional[int] = None
|
||||
) -> int:
|
||||
@@ -166,8 +161,8 @@ def get_cloud_fs(repo_config, **kwargs):
|
||||
# should be treated as being a root path.
|
||||
fs_path = cls.root_marker
|
||||
else:
|
||||
fs_path = cls._strip_protocol(url) # pylint:disable=protected-access
|
||||
fs_path = cls._strip_protocol(url)
|
||||
|
||||
extras = cls._get_kwargs_from_urls(url) # pylint:disable=protected-access
|
||||
extras = cls._get_kwargs_from_urls(url)
|
||||
conf = {**extras, **remote_conf} # remote config takes priority
|
||||
return cls, conf, fs_path
|
||||
|
||||
+1
-2
@@ -1,4 +1,3 @@
|
||||
# pylint: disable=unused-import
|
||||
from contextlib import ExitStack
|
||||
from typing import TYPE_CHECKING, Any, BinaryIO, Dict, Optional, Union
|
||||
|
||||
@@ -72,7 +71,7 @@ class RichCallback(Callback):
|
||||
value: int = 0,
|
||||
progress: Optional["RichTransferProgress"] = None,
|
||||
desc: Optional[str] = None,
|
||||
bytes: bool = False, # noqa: A002, pylint: disable=redefined-builtin
|
||||
bytes: bool = False, # noqa: A002
|
||||
unit: Optional[str] = None,
|
||||
disable: bool = False,
|
||||
transient: bool = True,
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
import functools
|
||||
import logging
|
||||
import os
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from dvc.log import logger
|
||||
from dvc.utils import as_posix
|
||||
from dvc_objects.fs.base import FileSystem
|
||||
|
||||
@@ -10,7 +10,7 @@ if TYPE_CHECKING:
|
||||
from dvc_data.fs import DataFileSystem as _DataFileSystem
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class DataFileSystem(FileSystem):
|
||||
@@ -22,7 +22,7 @@ class DataFileSystem(FileSystem):
|
||||
return config
|
||||
|
||||
@functools.cached_property
|
||||
def fs( # pylint: disable=invalid-overridden-method
|
||||
def fs(
|
||||
self,
|
||||
) -> "_DataFileSystem":
|
||||
from dvc_data.fs import DataFileSystem as _DataFileSystem
|
||||
|
||||
+13
-21
@@ -1,6 +1,5 @@
|
||||
import errno
|
||||
import functools
|
||||
import logging
|
||||
import ntpath
|
||||
import os
|
||||
import posixpath
|
||||
@@ -11,6 +10,7 @@ from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Tuple, Type, Un
|
||||
from fsspec.spec import AbstractFileSystem
|
||||
from funcy import wrap_with
|
||||
|
||||
from dvc.log import logger
|
||||
from dvc_objects.fs.base import FileSystem
|
||||
from dvc_objects.fs.path import Path
|
||||
|
||||
@@ -20,7 +20,7 @@ if TYPE_CHECKING:
|
||||
from dvc.repo import Repo
|
||||
from dvc.types import DictStrAny, StrPath
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
RepoFactory = Union[Callable[..., "Repo"], Type["Repo"]]
|
||||
Key = Tuple[str, ...]
|
||||
@@ -72,7 +72,7 @@ def _get_dvc_path(dvc_fs, subkey):
|
||||
return dvc_fs.path.join(*subkey) if subkey else ""
|
||||
|
||||
|
||||
class _DVCFileSystem(AbstractFileSystem): # pylint:disable=abstract-method
|
||||
class _DVCFileSystem(AbstractFileSystem):
|
||||
cachable = False
|
||||
root_marker = "/"
|
||||
|
||||
@@ -84,9 +84,7 @@ class _DVCFileSystem(AbstractFileSystem): # pylint:disable=abstract-method
|
||||
subrepos: bool = False,
|
||||
repo_factory: Optional[RepoFactory] = None,
|
||||
fo: Optional[str] = None,
|
||||
# pylint:disable-next=unused-argument
|
||||
target_options: Optional[Dict[str, Any]] = None, # noqa: ARG002
|
||||
# pylint:disable-next=unused-argument
|
||||
target_protocol: Optional[str] = None, # noqa: ARG002
|
||||
config: Optional["DictStrAny"] = None,
|
||||
remote: Optional[str] = None,
|
||||
@@ -146,7 +144,7 @@ class _DVCFileSystem(AbstractFileSystem): # pylint:disable=abstract-method
|
||||
remote_config=remote_config,
|
||||
)
|
||||
assert repo is not None
|
||||
# pylint: disable=protected-access
|
||||
|
||||
repo_factory = repo._fs_conf["repo_factory"]
|
||||
self._repo_stack.enter_context(repo)
|
||||
|
||||
@@ -282,9 +280,7 @@ class _DVCFileSystem(AbstractFileSystem): # pylint:disable=abstract-method
|
||||
dvc_fs = self._datafss.get(repo_key)
|
||||
return repo, dvc_fs, subkey
|
||||
|
||||
def _open(
|
||||
self, path, mode="rb", **kwargs
|
||||
): # pylint: disable=arguments-renamed, arguments-differ
|
||||
def _open(self, path, mode="rb", **kwargs):
|
||||
if mode != "rb":
|
||||
raise OSError(errno.EROFS, os.strerror(errno.EROFS))
|
||||
|
||||
@@ -307,9 +303,7 @@ class _DVCFileSystem(AbstractFileSystem): # pylint:disable=abstract-method
|
||||
except FileNotFoundError:
|
||||
return False
|
||||
|
||||
def ls( # pylint: disable=arguments-differ # noqa: C901
|
||||
self, path, detail=True, dvc_only=False, **kwargs
|
||||
):
|
||||
def ls(self, path, detail=True, dvc_only=False, **kwargs):
|
||||
key = self._get_key_from_relative(path)
|
||||
repo, dvc_fs, subkey = self._get_subrepo_info(key)
|
||||
|
||||
@@ -320,7 +314,7 @@ class _DVCFileSystem(AbstractFileSystem): # pylint:disable=abstract-method
|
||||
with suppress(FileNotFoundError, NotADirectoryError):
|
||||
for info in dvc_fs.ls(dvc_path, detail=True):
|
||||
dvc_infos[dvc_fs.path.name(info["name"])] = info
|
||||
dvc_exists = bool(dvc_infos) or dvc_fs.exists(dvc_path)
|
||||
dvc_exists = True
|
||||
|
||||
fs_exists = False
|
||||
fs_infos = {}
|
||||
@@ -333,10 +327,13 @@ class _DVCFileSystem(AbstractFileSystem): # pylint:disable=abstract-method
|
||||
fs, fs_path, detail=True, ignore_subrepos=ignore_subrepos
|
||||
):
|
||||
fs_infos[fs.path.name(info["name"])] = info
|
||||
fs_exists = True
|
||||
except (FileNotFoundError, NotADirectoryError):
|
||||
pass
|
||||
|
||||
fs_exists = bool(fs_infos) or fs.exists(fs_path)
|
||||
if not (dvc_exists or fs_exists):
|
||||
# broken symlink or TreeError
|
||||
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), path)
|
||||
|
||||
dvcfiles = kwargs.get("dvcfiles", False)
|
||||
|
||||
@@ -344,10 +341,6 @@ class _DVCFileSystem(AbstractFileSystem): # pylint:disable=abstract-method
|
||||
paths = []
|
||||
names = set(dvc_infos.keys()) | set(fs_infos.keys())
|
||||
|
||||
if not names and (dvc_exists or fs_exists):
|
||||
# broken symlink or TreeError
|
||||
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), path)
|
||||
|
||||
for name in names:
|
||||
if not dvcfiles and _is_dvc_file(name):
|
||||
continue
|
||||
@@ -415,7 +408,7 @@ class _DVCFileSystem(AbstractFileSystem): # pylint:disable=abstract-method
|
||||
info["name"] = path
|
||||
return info
|
||||
|
||||
def get_file(self, rpath, lpath, **kwargs): # pylint: disable=arguments-differ
|
||||
def get_file(self, rpath, lpath, **kwargs):
|
||||
key = self._get_key_from_relative(rpath)
|
||||
fs_path = self._from_key(key)
|
||||
try:
|
||||
@@ -440,7 +433,6 @@ class DVCFileSystem(FileSystem):
|
||||
return config
|
||||
|
||||
@functools.cached_property
|
||||
# pylint: disable-next=invalid-overridden-method
|
||||
def fs(self) -> "_DVCFileSystem":
|
||||
return _DVCFileSystem(**self.fs_args)
|
||||
|
||||
@@ -452,7 +444,7 @@ class DVCFileSystem(FileSystem):
|
||||
return self.fs.isdvc(path, **kwargs)
|
||||
|
||||
@property
|
||||
def path(self) -> Path: # pylint: disable=invalid-overridden-method
|
||||
def path(self) -> Path:
|
||||
return self.fs.path
|
||||
|
||||
@property
|
||||
|
||||
+3
-3
@@ -10,7 +10,7 @@ if TYPE_CHECKING:
|
||||
from dvc.scm import Git
|
||||
|
||||
|
||||
class GitFileSystem(FileSystem): # pylint:disable=abstract-method
|
||||
class GitFileSystem(FileSystem):
|
||||
"""Proxies the repo file access methods to Git objects"""
|
||||
|
||||
protocol = "local"
|
||||
@@ -39,7 +39,7 @@ class GitFileSystem(FileSystem): # pylint:disable=abstract-method
|
||||
)
|
||||
|
||||
@functools.cached_property
|
||||
def fs( # pylint: disable=invalid-overridden-method
|
||||
def fs(
|
||||
self,
|
||||
) -> "FsspecGitFileSystem":
|
||||
from scmrepo.fs import GitFileSystem as FsspecGitFileSystem
|
||||
@@ -47,7 +47,7 @@ class GitFileSystem(FileSystem): # pylint:disable=abstract-method
|
||||
return FsspecGitFileSystem(**self.fs_args)
|
||||
|
||||
@functools.cached_property
|
||||
def path(self): # pylint: disable=invalid-overridden-method
|
||||
def path(self):
|
||||
return self.fs.path
|
||||
|
||||
@property
|
||||
|
||||
+2
-2
@@ -1,4 +1,3 @@
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from collections import namedtuple
|
||||
@@ -10,12 +9,13 @@ from pathspec.util import normalize_file
|
||||
from pygtrie import Trie
|
||||
|
||||
from dvc.fs import Schemes, localfs
|
||||
from dvc.log import logger
|
||||
from dvc.pathspec_math import PatternInfo, merge_patterns
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from dvc.fs import AnyFSPath, FileSystem
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
class DvcIgnore:
|
||||
|
||||
+4
-6
@@ -59,7 +59,7 @@ class LockBase(ABC):
|
||||
|
||||
|
||||
class LockNoop(LockBase):
|
||||
def __init__(self, *args, **kwargs): # pylint: disable=super-init-not-called
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._lock = False
|
||||
|
||||
def lock(self):
|
||||
@@ -149,9 +149,7 @@ class HardlinkLock(flufl.lock.Lock, LockBase):
|
||||
tmp_dir (str): a directory to store claim files.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, lockfile, tmp_dir=None, **kwargs
|
||||
): # pylint: disable=super-init-not-called
|
||||
def __init__(self, lockfile, tmp_dir=None, **kwargs):
|
||||
import socket
|
||||
|
||||
self._tmp_dir = tmp_dir
|
||||
@@ -176,7 +174,7 @@ class HardlinkLock(flufl.lock.Lock, LockBase):
|
||||
self._owned = True
|
||||
self._retry_errnos = []
|
||||
|
||||
def lock(self): # pylint: disable=arguments-differ
|
||||
def lock(self):
|
||||
try:
|
||||
super().lock(timedelta(seconds=DEFAULT_TIMEOUT))
|
||||
except flufl.lock.TimeOutError:
|
||||
@@ -187,7 +185,7 @@ class HardlinkLock(flufl.lock.Lock, LockBase):
|
||||
|
||||
if self._tmp_dir is not None:
|
||||
# Under Windows file path length is limited so we hash it
|
||||
hasher = hashlib.md5( # nosec B324, B303 # noqa: S324
|
||||
hasher = hashlib.md5( # noqa: S324
|
||||
self._claimfile.encode()
|
||||
)
|
||||
filename = hasher.hexdigest()
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
# using a separate module instead of using `dvc.logger` to not create an import-cycle.
|
||||
import logging
|
||||
|
||||
|
||||
class LoggerWithTrace(logging.Logger):
|
||||
# only for type checking
|
||||
trace = logging.debug
|
||||
|
||||
|
||||
logger: "LoggerWithTrace" = logging.getLogger() # type: ignore[assignment]
|
||||
+8
-10
@@ -8,7 +8,6 @@ import sys
|
||||
|
||||
import colorama
|
||||
|
||||
from dvc.env import DVC_SHOW_TRACEBACK
|
||||
from dvc.progress import Tqdm
|
||||
|
||||
|
||||
@@ -33,7 +32,6 @@ def add_logging_level(level_name, level_num, method_name=None):
|
||||
|
||||
def log_for_level(self, message, *args, **kwargs):
|
||||
if self.isEnabledFor(level_num):
|
||||
# pylint: disable=protected-access
|
||||
self._log(level_num, message, args, **kwargs)
|
||||
|
||||
def log_to_root(message, *args, **kwargs):
|
||||
@@ -151,8 +149,7 @@ class LoggerHandler(logging.StreamHandler):
|
||||
self.emit_pretty_exception(exc, verbose=_is_verbose())
|
||||
if not _is_verbose():
|
||||
return
|
||||
# pylint: disable-next=broad-except
|
||||
except Exception: # noqa: BLE001, S110 # nosec B110
|
||||
except Exception: # noqa: BLE001, S110
|
||||
pass
|
||||
|
||||
msg = self.format(record)
|
||||
@@ -160,7 +157,7 @@ class LoggerHandler(logging.StreamHandler):
|
||||
self.flush()
|
||||
except (BrokenPipeError, RecursionError):
|
||||
raise
|
||||
except Exception: # noqa: BLE001, pylint: disable=broad-except
|
||||
except Exception: # noqa: BLE001
|
||||
self.handleError(record)
|
||||
|
||||
|
||||
@@ -184,7 +181,10 @@ def set_loggers_level(level: int = logging.INFO) -> None:
|
||||
def setup(level: int = logging.INFO, log_colors: bool = True) -> None:
|
||||
colorama.init()
|
||||
|
||||
formatter = ColorFormatter(log_colors=log_colors and sys.stdout.isatty())
|
||||
color_out = log_colors and bool(sys.stdout) and sys.stdout.isatty()
|
||||
color_err = log_colors and bool(sys.stderr) and sys.stderr.isatty()
|
||||
|
||||
formatter = ColorFormatter(log_colors=color_out)
|
||||
|
||||
console_info = LoggerHandler(sys.stdout)
|
||||
console_info.setLevel(logging.INFO)
|
||||
@@ -203,10 +203,8 @@ def setup(level: int = logging.INFO, log_colors: bool = True) -> None:
|
||||
console_trace.setFormatter(formatter)
|
||||
console_trace.addFilter(exclude_filter(logging.DEBUG))
|
||||
|
||||
show_traceback = bool(os.environ.get(DVC_SHOW_TRACEBACK))
|
||||
err_formatter = ColorFormatter(
|
||||
log_colors=log_colors and sys.stderr.isatty(), show_traceback=show_traceback
|
||||
)
|
||||
show_traceback = bool(os.environ.get("DVC_SHOW_TRACEBACK"))
|
||||
err_formatter = ColorFormatter(log_colors=color_err, show_traceback=show_traceback)
|
||||
console_errors = LoggerHandler(sys.stderr)
|
||||
console_errors.setLevel(logging.WARNING)
|
||||
console_errors.setFormatter(err_formatter)
|
||||
|
||||
+18
-23
@@ -1,15 +1,14 @@
|
||||
import errno
|
||||
import logging
|
||||
import os
|
||||
import posixpath
|
||||
from collections import defaultdict
|
||||
from contextlib import suppress
|
||||
from operator import itemgetter
|
||||
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple, Type, Union
|
||||
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple, Type, Union
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import voluptuous as vol
|
||||
from funcy import collecting, first, project
|
||||
from voluptuous import All, And, Any, Coerce, Length, Lower, Required, SetTo
|
||||
|
||||
from dvc import prompt
|
||||
from dvc.exceptions import (
|
||||
@@ -20,6 +19,7 @@ from dvc.exceptions import (
|
||||
DvcException,
|
||||
MergeError,
|
||||
)
|
||||
from dvc.log import logger
|
||||
from dvc.utils import format_link
|
||||
from dvc.utils.objects import cached_property
|
||||
from dvc_data.hashfile import check as ocheck
|
||||
@@ -47,19 +47,19 @@ if TYPE_CHECKING:
|
||||
|
||||
from .ignore import DvcIgnoreFilter
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
CHECKSUM_SCHEMA = Any(
|
||||
CHECKSUM_SCHEMA = vol.Any(
|
||||
None,
|
||||
And(str, Length(max=0), SetTo(None)),
|
||||
And(Any(str, And(int, Coerce(str))), Length(min=3), Lower),
|
||||
vol.And(str, vol.Length(max=0), vol.SetTo(None)),
|
||||
vol.And(vol.Any(str, vol.And(int, vol.Coerce(str))), vol.Length(min=3), vol.Lower),
|
||||
)
|
||||
|
||||
CASE_SENSITIVE_CHECKSUM_SCHEMA = Any(
|
||||
CASE_SENSITIVE_CHECKSUM_SCHEMA = vol.Any(
|
||||
None,
|
||||
And(str, Length(max=0), SetTo(None)),
|
||||
And(Any(str, And(int, Coerce(str))), Length(min=3)),
|
||||
vol.And(str, vol.Length(max=0), vol.SetTo(None)),
|
||||
vol.And(vol.Any(str, vol.And(int, vol.Coerce(str))), vol.Length(min=3)),
|
||||
)
|
||||
|
||||
# NOTE: currently there are only 3 possible checksum names:
|
||||
@@ -331,7 +331,7 @@ class Output:
|
||||
plot=False,
|
||||
persist=False,
|
||||
desc=None,
|
||||
type=None, # noqa: A002, pylint: disable=redefined-builtin
|
||||
type=None, # noqa: A002
|
||||
labels=None,
|
||||
meta=None,
|
||||
remote=None,
|
||||
@@ -679,8 +679,6 @@ class Output:
|
||||
return False
|
||||
return self.fs.isfile(self.fs_path)
|
||||
|
||||
# pylint: disable=no-member
|
||||
|
||||
def ignore(self) -> None:
|
||||
if not self.use_scm_ignore:
|
||||
return
|
||||
@@ -696,8 +694,6 @@ class Output:
|
||||
|
||||
self.repo.scm_context.ignore_remove(self.fspath)
|
||||
|
||||
# pylint: enable=no-member
|
||||
|
||||
def save(self) -> None:
|
||||
if self.use_cache and not self.is_in_repo:
|
||||
raise DvcException(
|
||||
@@ -1021,7 +1017,6 @@ class Output:
|
||||
self.ignore_remove()
|
||||
|
||||
def move(self, out):
|
||||
# pylint: disable=no-member
|
||||
if self.protocol == "local" and self.use_scm_ignore:
|
||||
self.repo.scm_context.ignore_remove(self.fspath)
|
||||
|
||||
@@ -1132,7 +1127,7 @@ class Output:
|
||||
|
||||
try:
|
||||
self.get_dir_cache(jobs=jobs, remote=remote)
|
||||
except RemoteMissingDepsError: # pylint: disable=try-except-raise
|
||||
except RemoteMissingDepsError:
|
||||
raise
|
||||
except DvcException:
|
||||
logger.debug("failed to pull cache for '%s'", self)
|
||||
@@ -1160,7 +1155,7 @@ class Output:
|
||||
return obj.filter(prefix)
|
||||
return obj
|
||||
|
||||
def get_used_objs( # noqa: C901, PLR0911
|
||||
def get_used_objs( # noqa: PLR0911
|
||||
self, **kwargs
|
||||
) -> Dict[Optional["HashFileDB"], Set["HashInfo"]]:
|
||||
"""Return filtered set of used object IDs for this out."""
|
||||
@@ -1523,21 +1518,21 @@ META_SCHEMA = {
|
||||
Meta.PARAM_VERSION_ID: str,
|
||||
}
|
||||
|
||||
CLOUD_SCHEMA = All({str: {**META_SCHEMA, **CHECKSUMS_SCHEMA}}, Length(max=1))
|
||||
CLOUD_SCHEMA = vol.All({str: {**META_SCHEMA, **CHECKSUMS_SCHEMA}}, vol.Length(max=1))
|
||||
|
||||
ARTIFACT_SCHEMA = {
|
||||
ARTIFACT_SCHEMA: Dict[Any, Any] = {
|
||||
**CHECKSUMS_SCHEMA,
|
||||
**META_SCHEMA,
|
||||
Required(Output.PARAM_PATH): str,
|
||||
Output.PARAM_PATH: str,
|
||||
Output.PARAM_PERSIST: bool,
|
||||
Output.PARAM_CLOUD: CLOUD_SCHEMA,
|
||||
Output.PARAM_HASH: str,
|
||||
}
|
||||
|
||||
DIR_FILES_SCHEMA: Dict[str, Any] = {
|
||||
DIR_FILES_SCHEMA: Dict[Any, Any] = {
|
||||
**CHECKSUMS_SCHEMA,
|
||||
**META_SCHEMA,
|
||||
Required(Tree.PARAM_RELPATH): str,
|
||||
vol.Required(Tree.PARAM_RELPATH): str,
|
||||
Output.PARAM_CLOUD: CLOUD_SCHEMA,
|
||||
}
|
||||
|
||||
|
||||
+23
-6
@@ -18,6 +18,7 @@ from typing import (
|
||||
from funcy import collecting, first, isa, join, reraise
|
||||
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
from dvc.parsing.interpolate import ParseError
|
||||
from dvc.utils.objects import cached_property
|
||||
|
||||
@@ -45,7 +46,7 @@ if TYPE_CHECKING:
|
||||
from .context import SeqOrMap
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
STAGES_KWD = "stages"
|
||||
VARS_KWD = "vars"
|
||||
@@ -192,7 +193,7 @@ class DataResolver:
|
||||
def resolve(self):
|
||||
"""Used for testing purposes, otherwise use resolve_one()."""
|
||||
data = join(map(self.resolve_one, self.get_keys()))
|
||||
logger.trace("Resolved dvc.yaml:\n%s", data) # type: ignore[attr-defined]
|
||||
logger.trace("Resolved dvc.yaml:\n%s", data)
|
||||
return {STAGES_KWD: data}
|
||||
|
||||
def has_key(self, key: str):
|
||||
@@ -283,9 +284,7 @@ class EntryDefinition:
|
||||
except VarsAlreadyLoaded as exc:
|
||||
format_and_raise(exc, f"'{self.where}.{name}.vars'", self.relpath)
|
||||
|
||||
logger.trace( # type: ignore[attr-defined]
|
||||
"Context during resolution of stage %s:\n%s", name, context
|
||||
)
|
||||
logger.trace("Context during resolution of stage %s:\n%s", name, context)
|
||||
|
||||
with context.track() as tracked_data:
|
||||
# NOTE: we do not pop "wdir", and resolve it again
|
||||
@@ -499,8 +498,26 @@ class MatrixDefinition:
|
||||
iterable = self.context.resolve(self.matrix_data, unwrap=False)
|
||||
except (ContextError, ParseError) as exc:
|
||||
format_and_raise(exc, f"'{self.where}.{self.name}.matrix'", self.relpath)
|
||||
|
||||
# Matrix entries will have `key` and `item` added to the context.
|
||||
# Warn users if these are already in the context from the global vars.
|
||||
self._warn_if_overwriting([self.pair.key, self.pair.value])
|
||||
return iterable
|
||||
|
||||
def _warn_if_overwriting(self, keys: List[str]):
|
||||
warn_for = [k for k in keys if k in self.context]
|
||||
if warn_for:
|
||||
linking_verb = "is" if len(warn_for) == 1 else "are"
|
||||
logger.warning(
|
||||
(
|
||||
"%s %s already specified, "
|
||||
"will be overwritten for stages generated from '%s'"
|
||||
),
|
||||
" and ".join(warn_for),
|
||||
linking_verb,
|
||||
self.name,
|
||||
)
|
||||
|
||||
@cached_property
|
||||
def normalized_iterable(self) -> Dict[str, "DictStrAny"]:
|
||||
"""Convert sequence to Mapping with keys normalized."""
|
||||
@@ -540,7 +557,7 @@ class MatrixDefinition:
|
||||
with reraise(KeyError, EntryNotFound(err_message)):
|
||||
value = self.normalized_iterable[key]
|
||||
|
||||
temp_dict = {self.pair.value: value}
|
||||
temp_dict = {self.pair.key: key, self.pair.value: value}
|
||||
with self.context.set_temporarily(temp_dict, reserve=True):
|
||||
# optimization: item and key can be removed on __exit__() as they
|
||||
# are top-level values, and are not merged recursively.
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import logging
|
||||
from abc import ABC, abstractmethod
|
||||
from collections import defaultdict
|
||||
from collections.abc import Mapping, MutableMapping, MutableSequence, Sequence
|
||||
@@ -10,6 +9,7 @@ from typing import Any, Dict, List, Optional, Union
|
||||
from funcy import identity, lfilter, nullcontext, select
|
||||
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.log import logger
|
||||
from dvc.parsing.interpolate import (
|
||||
get_expression,
|
||||
get_matches,
|
||||
@@ -20,7 +20,7 @@ from dvc.parsing.interpolate import (
|
||||
validate_value,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logger.getChild(__name__)
|
||||
SeqOrMap = Union[Sequence, Mapping]
|
||||
DictStr = Dict[str, Any]
|
||||
|
||||
@@ -324,9 +324,7 @@ class Context(CtxDict):
|
||||
keys = [keys] if isinstance(keys, str) else keys
|
||||
params_file.update({key: node.value for key in keys})
|
||||
|
||||
def select(
|
||||
self, key: str, unwrap: bool = False
|
||||
): # pylint: disable=arguments-differ
|
||||
def select(self, key: str, unwrap: bool = False):
|
||||
"""Select the item using key, similar to `__getitem__`
|
||||
but can track the usage of the data on interpolation
|
||||
as well and can get from nested data structure by using
|
||||
@@ -436,7 +434,7 @@ class Context(CtxDict):
|
||||
self.merge_from(fs, default, wdir)
|
||||
else:
|
||||
msg = "%s does not exist, it won't be used in parametrization"
|
||||
logger.trace(msg, to_import) # type: ignore[attr-defined]
|
||||
logger.trace(msg, to_import)
|
||||
|
||||
stage_name = stage_name or ""
|
||||
for index, item in enumerate(vars_):
|
||||
|
||||
@@ -73,7 +73,7 @@ def embrace(s: str):
|
||||
|
||||
def escape_str(value):
|
||||
if os.name == "nt":
|
||||
from subprocess import list2cmdline # nosec B404
|
||||
from subprocess import list2cmdline
|
||||
|
||||
return list2cmdline([value])
|
||||
from shlex import quote
|
||||
@@ -82,12 +82,12 @@ def escape_str(value):
|
||||
|
||||
|
||||
@singledispatch
|
||||
def to_str(obj, config=None) -> str: # noqa: ARG001, pylint: disable=unused-argument
|
||||
def to_str(obj, config=None) -> str: # noqa: ARG001
|
||||
return str(obj)
|
||||
|
||||
|
||||
@to_str.register(bool)
|
||||
def _(obj: bool, config=None): # noqa: ARG001, pylint: disable=unused-argument
|
||||
def _(obj: bool, config=None): # noqa: ARG001
|
||||
return "true" if obj else "false"
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user