Пример #1
0
 def _validate_credentials(auth, settings):
     """
     Detects discrepancy in DVC config and cached credentials file.
     Usually happens when a second remote is added and it is using
     the same credentials default file. Or when someones decides to change
     DVC config client id or secret but forgets to remove the cached
     credentials file.
     """
     if not os.getenv(GDriveTree.GDRIVE_CREDENTIALS_DATA):
         if (
             settings["client_config"]["client_id"]
             != auth.credentials.client_id
             or settings["client_config"]["client_secret"]
             != auth.credentials.client_secret
         ):
             logger.warning(
                 "Client ID and secret configured do not match the "
                 "actual ones used\nto access the remote. Do you "
                 "use multiple GDrive remotes and forgot to\nset "
                 "`gdrive_user_credentials_file` for one or more of them? "
                 "Learn more at\n{}.\n".format(
                     format_link("https://man.dvc.org/remote/modify")
                 )
             )
Пример #2
0
def _add_props_arguments(parser):
    parser.add_argument(
        "-t",
        "--template",
        nargs="?",
        default=None,
        help=(
            "Special JSON or HTML schema file to inject with the data. "
            "See {}".format(
                format_link("https://man.dvc.org/plots#plot-templates")
            )
        ),
        metavar="<path>",
    ).complete = completion.FILE
    parser.add_argument(
        "-x", default=None, help="Field name for X axis.", metavar="<field>"
    )
    parser.add_argument(
        "-y", default=None, help="Field name for Y axis.", metavar="<field>"
    )
    parser.add_argument(
        "--no-header",
        action="store_false",
        dest="header",
        default=None,  # Use default None to distinguish when it's not used
        help="Provided CSV or TSV datafile does not have a header.",
    )
    parser.add_argument(
        "--title", default=None, metavar="<text>", help="Plot title."
    )
    parser.add_argument(
        "--x-label", default=None, help="X axis label", metavar="<text>"
    )
    parser.add_argument(
        "--y-label", default=None, help="Y axis label", metavar="<text>"
    )
Пример #3
0
def check_no_externals(stage):
    from urllib.parse import urlparse

    from dvc.utils import format_link

    # NOTE: preventing users from accidentally using external outputs. See
    # https://github.com/iterative/dvc/issues/1545 for more details.

    def _is_external(out):
        # NOTE: in case of `remote://` notation, the user clearly knows that
        # this is an advanced feature and so we shouldn't error-out.
        if out.is_in_repo or urlparse(out.def_path).scheme == "remote":
            return False
        return True

    outs = [str(out) for out in stage.outs if _is_external(out)]
    if not outs:
        return

    str_outs = ", ".join(outs)
    link = format_link("https://dvc.org/doc/user-guide/managing-external-data")
    raise StageExternalOutputsError(
        f"Output(s) outside of DVC project: {str_outs}. "
        f"See {link} for more info.")
Пример #4
0
def add_parser(subparsers, parent_parser):
    from dvc.command.config import parent_config_parser

    REMOTE_HELP = "Set up and manage data remotes."
    remote_parser = subparsers.add_parser(
        "remote",
        parents=[parent_parser],
        description=append_doc_link(REMOTE_HELP, "remote"),
        help=REMOTE_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )

    remote_subparsers = remote_parser.add_subparsers(
        dest="cmd",
        help="Use `dvc remote CMD --help` for "
        "command-specific help.",
    )

    fix_subparsers(remote_subparsers)

    REMOTE_ADD_HELP = "Add a new data remote."
    remote_add_parser = remote_subparsers.add_parser(
        "add",
        parents=[parent_config_parser, parent_parser],
        description=append_doc_link(REMOTE_ADD_HELP, "remote/add"),
        help=REMOTE_ADD_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    remote_add_parser.add_argument("name", help="Name of the remote")
    remote_add_parser.add_argument(
        "url",
        help="URL. See full list of supported urls at {}".format(
            format_link("https://man.dvc.org/remote")),
    )
    remote_add_parser.add_argument(
        "-d",
        "--default",
        action="store_true",
        default=False,
        help="Set as default remote.",
    )
    remote_add_parser.add_argument(
        "-f",
        "--force",
        action="store_true",
        default=False,
        help="Force overwriting existing configs",
    )
    remote_add_parser.set_defaults(func=CmdRemoteAdd)

    REMOTE_DEFAULT_HELP = "Set/unset the default data remote."
    remote_default_parser = remote_subparsers.add_parser(
        "default",
        parents=[parent_config_parser, parent_parser],
        description=append_doc_link(REMOTE_DEFAULT_HELP, "remote/default"),
        help=REMOTE_DEFAULT_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    remote_default_parser.add_argument("name",
                                       nargs="?",
                                       help="Name of the remote.")
    remote_default_parser.add_argument(
        "-u",
        "--unset",
        action="store_true",
        default=False,
        help="Unset default remote.",
    )
    remote_default_parser.set_defaults(func=CmdRemoteDefault)

    REMOTE_MODIFY_HELP = "Modify the configuration of a data remote."
    remote_modify_parser = remote_subparsers.add_parser(
        "modify",
        parents=[parent_config_parser, parent_parser],
        description=append_doc_link(REMOTE_MODIFY_HELP, "remote/modify"),
        help=REMOTE_MODIFY_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    remote_modify_parser.add_argument("name", help="Name of the remote.")
    remote_modify_parser.add_argument("option",
                                      help="Name of the option to modify.")
    remote_modify_parser.add_argument("value",
                                      nargs="?",
                                      help="(optional) Value of the option.")
    remote_modify_parser.add_argument(
        "-u",
        "--unset",
        default=False,
        action="store_true",
        help="Unset option.",
    )
    remote_modify_parser.set_defaults(func=CmdRemoteModify)

    REMOTE_LIST_HELP = "List all available data remotes."
    remote_list_parser = remote_subparsers.add_parser(
        "list",
        parents=[parent_config_parser, parent_parser],
        description=append_doc_link(REMOTE_LIST_HELP, "remote/list"),
        help=REMOTE_LIST_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    remote_list_parser.set_defaults(func=CmdRemoteList)

    REMOTE_REMOVE_HELP = "Remove a data remote."
    remote_remove_parser = remote_subparsers.add_parser(
        "remove",
        parents=[parent_config_parser, parent_parser],
        description=append_doc_link(REMOTE_REMOVE_HELP, "remote/remove"),
        help=REMOTE_REMOVE_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    remote_remove_parser.add_argument("name",
                                      help="Name of the remote to remove.")
    remote_remove_parser.set_defaults(func=CmdRemoteRemove)
    REMOTE_RENAME_HELP = "Rename a DVC remote"
    remote_rename_parser = remote_subparsers.add_parser(
        "rename",
        parents=[parent_config_parser, parent_parser],
        description=append_doc_link(REMOTE_RENAME_HELP, "remote/rename"),
        help=REMOTE_RENAME_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    remote_rename_parser.add_argument("name", help="Remote to be renamed")
    remote_rename_parser.add_argument("new", help="New name of the remote")
    remote_rename_parser.set_defaults(func=CmdRemoteRename)
Пример #5
0
import zc.lockfile
from funcy import retry

from dvc.exceptions import DvcException
from dvc.progress import Tqdm
from dvc.utils import format_link

DEFAULT_TIMEOUT = 3


FAILED_TO_LOCK_MESSAGE = (
    "Unable to acquire lock. Most likely another DVC process is running or "
    "was terminated abruptly. Check the page {} for other possible reasons "
    "and to learn how to resolve this."
).format(
    format_link("https://dvc.org/doc/user-guide/troubleshooting#lock-issue")
)


class LockError(DvcException):
    """Thrown when unable to acquire the lock for DVC repo."""


class Lock:
    """Class for DVC repo lock.

    Uses zc.lockfile as backend.
    """

    def __init__(self, lockfile, friendly=False, **kwargs):
        self._friendly = friendly
Пример #6
0
class CmdDataStatus(CmdDataBase):
    STATUS_LEN = 20
    STATUS_INDENT = "\t"
    UP_TO_DATE_MSG = "Data and pipelines are up to date."
    IN_SYNC_MSG = "Cache and remote '{remote}' are in sync."
    EMPTY_PROJECT_MSG = (
        "There are no data or pipelines tracked in this project yet.\n"
        "See {link} to get started!").format(
            link=format_link("https://dvc.org/doc/start"))

    def _normalize(self, s):
        s += ":"
        assert len(s) < self.STATUS_LEN
        return s + (self.STATUS_LEN - len(s)) * " "

    def _show(self, status, indent=0):
        ind = indent * self.STATUS_INDENT

        if isinstance(status, str):
            ui.write(f"{ind}{status}")
            return

        if isinstance(status, list):
            for entry in status:
                self._show(entry, indent)
            return

        assert isinstance(status, dict)

        for key, value in status.items():
            if isinstance(value, str):
                ui.write(f"{ind}{self._normalize(value)}{key}")
            elif value:
                ui.write(f"{ind}{key}:")
                self._show(value, indent + 1)

    def run(self):
        from dvc.repo import lock_repo

        indent = 1 if self.args.cloud else 0

        with lock_repo(self.repo):
            try:
                st = self.repo.status(
                    targets=self.args.targets,
                    jobs=self.args.jobs,
                    cloud=self.args.cloud,
                    remote=self.args.remote,
                    all_branches=self.args.all_branches,
                    all_tags=self.args.all_tags,
                    all_commits=self.args.all_commits,
                    with_deps=self.args.with_deps,
                    recursive=self.args.recursive,
                )
            except DvcException:
                logger.exception("")
                return 1

            if self.args.quiet:
                return bool(st)

            if self.args.json:
                import json

                ui.write(json.dumps(st))
                return 0

            if st:
                self._show(st, indent)
                return 0

            # additional hints for the user
            if not self.repo.index.stages:
                ui.write(self.EMPTY_PROJECT_MSG)
            elif self.args.cloud or self.args.remote:
                remote = self.args.remote or self.repo.config["core"].get(
                    "remote")
                ui.write(self.IN_SYNC_MSG.format(remote=remote))
            else:
                ui.write(self.UP_TO_DATE_MSG)

        return 0
Пример #7
0
    def _prepare_credentials(self, **config):
        from azure.identity.aio import DefaultAzureCredential

        # Disable spam from failed cred types for DefaultAzureCredential
        logging.getLogger("azure.identity.aio").setLevel(logging.ERROR)

        login_info = {}
        login_info["connection_string"] = config.get(
            "connection_string",
            _az_config().get("storage", "connection_string", None),
        )
        login_info["account_name"] = config.get(
            "account_name", _az_config().get("storage", "account", None)
        )
        login_info["account_key"] = config.get(
            "account_key", _az_config().get("storage", "key", None)
        )
        login_info["sas_token"] = config.get(
            "sas_token", _az_config().get("storage", "sas_token", None)
        )
        login_info["tenant_id"] = config.get("tenant_id")
        login_info["client_id"] = config.get("client_id")
        login_info["client_secret"] = config.get("client_secret")

        if not (login_info["account_name"] or login_info["connection_string"]):
            raise AzureAuthError(
                "Authentication to Azure Blob Storage requires either "
                "account_name or connection_string.\nLearn more about "
                "configuration settings at "
                + format_link("https://man.dvc.org/remote/modify")
            )

        any_secondary = any(
            value for key, value in login_info.items() if key != "account_name"
        )
        if (
            login_info["account_name"]
            and not any_secondary
            and not config.get("allow_anonymous_login", False)
        ):
            with fsspec_loop():
                login_info["credential"] = DefaultAzureCredential(
                    exclude_interactive_browser_credential=False,
                    exclude_environment_credential=config.get(
                        "exclude_environment_credential", False
                    ),
                    exclude_visual_studio_code_credential=config.get(
                        "exclude_visual_studio_code_credential", False
                    ),
                    exclude_shared_token_cache_credential=config.get(
                        "exclude_shared_token_cache_credential", False
                    ),
                    exclude_managed_identity_credential=config.get(
                        "exclude_managed_identity_credential", False
                    ),
                )

        for login_method, required_keys in [  # noqa
            ("connection string", ["connection_string"]),
            (
                "AD service principal",
                ["tenant_id", "client_id", "client_secret"],
            ),
            ("account key", ["account_name", "account_key"]),
            ("SAS token", ["account_name", "sas_token"]),
            (
                f"default credentials ({_DEFAULT_CREDS_STEPS})",
                ["account_name", "credential"],
            ),
            ("anonymous login", ["account_name"]),
        ]:
            if all(login_info.get(key) is not None for key in required_keys):
                break
        else:
            login_method = None

        self.login_method = login_method
        return login_info
Пример #8
0
def add_parser(subparsers, parent_parser):
    PLOTS_HELP = ("Generating plots for metrics stored in structured files "
                  "(JSON, CSV, TSV).")

    plots_parser = subparsers.add_parser(
        "plots",
        parents=[parent_parser],
        description=append_doc_link(PLOTS_HELP, "plots"),
        help=PLOTS_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    plots_subparsers = plots_parser.add_subparsers(
        dest="cmd",
        help="Use `dvc plots CMD --help` to display command-specific help.",
    )

    fix_subparsers(plots_subparsers)

    SHOW_HELP = "Generate a plots image file from a metrics file."
    plots_show_parser = plots_subparsers.add_parser(
        "show",
        parents=[parent_parser],
        description=append_doc_link(SHOW_HELP, "plots/show"),
        help=SHOW_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    plots_show_parser.add_argument(
        "-t",
        "--template",
        nargs="?",
        default=None,
        help=("Special JSON or HTML schema file to inject with the data. "
              "See {}".format(
                  format_link("https://man.dvc.org/plots#plot-templates"))),
    )
    plots_show_parser.add_argument(
        "-o",
        "--out",
        default=None,
        help="Destination path to save plots to.",
    )
    plots_show_parser.add_argument("-x",
                                   default=None,
                                   help="Field name for x axis.")
    plots_show_parser.add_argument("-y",
                                   default=None,
                                   help="Field name for y axis.")
    plots_show_parser.add_argument(
        "--no-csv-header",
        action="store_true",
        default=False,
        help="Required when CSV or TSV datafile does not have a header.",
    )
    plots_show_parser.add_argument(
        "--show-json",
        action="store_true",
        default=False,
        help="Show output in JSON format.",
    )
    plots_show_parser.add_argument("--title", default=None, help="Plot title.")
    plots_show_parser.add_argument("--xlab",
                                   default=None,
                                   help="X axis title.")
    plots_show_parser.add_argument("--ylab",
                                   default=None,
                                   help="Y axis title.")
    plots_show_parser.add_argument(
        "targets",
        nargs="*",
        help="Metrics files to visualize. Shows all plots by default.",
    )
    plots_show_parser.set_defaults(func=CmdPlotsShow)

    PLOTS_DIFF_HELP = (
        "Plot differences in metrics between commits in the DVC "
        "repository, or between the last commit and the workspace.")
    plots_diff_parser = plots_subparsers.add_parser(
        "diff",
        parents=[parent_parser],
        description=append_doc_link(PLOTS_DIFF_HELP, "plots/diff"),
        help=PLOTS_DIFF_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    plots_diff_parser.add_argument(
        "-t",
        "--template",
        nargs="?",
        default=None,
        help=("Special JSON or HTML schema to inject with the data. "
              "See {}".format(
                  format_link("https://man.dvc.org/plots#plot-templates"))),
    )
    plots_diff_parser.add_argument(
        "--targets",
        nargs="*",
        help="Metrics file to visualize. Shows all plots by default.",
    )
    plots_diff_parser.add_argument(
        "-o",
        "--out",
        default=None,
        help="Destination path to save plots to.",
    )
    plots_diff_parser.add_argument("-x",
                                   default=None,
                                   help="Field name for x axis.")
    plots_diff_parser.add_argument("-y",
                                   default=None,
                                   help="Field name for y axis.")
    plots_diff_parser.add_argument(
        "--no-csv-header",
        action="store_true",
        default=False,
        help="Provided CSV ot TSV datafile does not have a header.",
    )
    plots_diff_parser.add_argument(
        "--show-json",
        action="store_true",
        default=False,
        help="Show output in JSON format.",
    )
    plots_diff_parser.add_argument("--title", default=None, help="Plot title.")
    plots_diff_parser.add_argument("--xlab",
                                   default=None,
                                   help="X axis title.")
    plots_diff_parser.add_argument("--ylab",
                                   default=None,
                                   help="Y axis title.")
    plots_diff_parser.add_argument(
        "revisions",
        nargs="*",
        default=None,
        help="Git commits to plot from",
    )
    plots_diff_parser.set_defaults(func=CmdPlotsDiff)
Пример #9
0
def main(argv=None):
    """Run dvc CLI command.

    Args:
        argv: optional list of arguments to parse. sys.argv is used by default.

    Returns:
        int: command's return code.
    """
    args = None
    disable_other_loggers()

    outerLogLevel = logger.level
    try:
        args = parse_args(argv)

        if args.quiet:
            logger.setLevel(logging.CRITICAL)

        elif args.verbose:
            logger.setLevel(logging.DEBUG)

        cmd = args.func(args)
        ret = cmd.run()
    except ConfigError:
        logger.exception("configuration error")
        ret = 251
    except KeyboardInterrupt:
        logger.exception("interrupted by the user")
        ret = 252
    except NotDvcRepoError:
        logger.exception("")
        ret = 253
    except DvcParserError:
        ret = 254
    except Exception as exc:  # pylint: disable=broad-except
        if isinstance(exc, OSError) and exc.errno == errno.EMFILE:
            logger.exception(
                "too many open files, please visit "
                "{} to see how to handle this "
                "problem".format(
                    format_link("https://error.dvc.org/many-files")
                ),
                extra={"tb_only": True},
            )
        else:
            logger.exception("unexpected error")
        ret = 255
    finally:
        logger.setLevel(outerLogLevel)

        # Closing pools by-hand to prevent wierd messages when closing SSH
        # connections. See https://github.com/iterative/dvc/issues/3248 for
        # more info.
        close_pools()

        # Remove cached repos in the end of the call, these are anonymous
        # so won't be reused by any other subsequent run anyway.
        clean_repos()

    if ret != 0:
        logger.info(FOOTER)

    if analytics.is_enabled():
        analytics.collect_and_send_report(args, ret)

    return ret
Пример #10
0
 def __init__(self, hook_name):
     super().__init__(
         "Hook '{}' already exists. Please refer to {} for more "
         "info.".format(hook_name,
                        format_link("https://man.dvc.org/install")))
Пример #11
0
def add_parser(subparsers, parent_parser):
    from dvc.command.config import parent_config_parser

    machine_HELP = "Set up and manage cloud machines."
    machine_parser = subparsers.add_parser(
        "machine",
        parents=[parent_parser],
        description=append_doc_link(machine_HELP, "machine"),
        # NOTE: suppress help during development to hide command
        # help=machine_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )

    machine_subparsers = machine_parser.add_subparsers(
        dest="cmd",
        help="Use `dvc machine CMD --help` for "
        "command-specific help.",
    )

    fix_subparsers(machine_subparsers)

    machine_ADD_HELP = "Add a new data machine."
    machine_add_parser = machine_subparsers.add_parser(
        "add",
        parents=[parent_config_parser, parent_parser],
        description=append_doc_link(machine_ADD_HELP, "machine/add"),
        help=machine_ADD_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    machine_add_parser.add_argument("name", help="Name of the machine")
    machine_add_parser.add_argument(
        "cloud",
        help="Machine cloud. See full list of supported clouds at {}".format(
            format_link("https://github.com/iterative/"
                        "terraform-provider-iterative#machine")),
    )
    machine_add_parser.add_argument(
        "-d",
        "--default",
        action="store_true",
        default=False,
        help="Set as default machine.",
    )
    machine_add_parser.add_argument(
        "-f",
        "--force",
        action="store_true",
        default=False,
        help="Force overwriting existing configs",
    )
    machine_add_parser.set_defaults(func=CmdMachineAdd)

    machine_DEFAULT_HELP = "Set/unset the default machine."
    machine_default_parser = machine_subparsers.add_parser(
        "default",
        parents=[parent_config_parser, parent_parser],
        description=append_doc_link(machine_DEFAULT_HELP, "machine/default"),
        help=machine_DEFAULT_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    machine_default_parser.add_argument("name",
                                        nargs="?",
                                        help="Name of the machine")
    machine_default_parser.add_argument(
        "-u",
        "--unset",
        action="store_true",
        default=False,
        help="Unset default machine.",
    )
    machine_default_parser.set_defaults(func=CmdMachineDefault)

    machine_LIST_HELP = "List the configuration of one/all machines."
    machine_list_parser = machine_subparsers.add_parser(
        "list",
        parents=[parent_config_parser, parent_parser],
        description=append_doc_link(machine_LIST_HELP, "machine/list"),
        help=machine_LIST_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    machine_list_parser.add_argument(
        "--show-origin",
        default=False,
        action="store_true",
        help="Show the source file containing each config value.",
    )
    machine_list_parser.add_argument(
        "name",
        nargs="?",
        type=str,
        help="name of machine to specify",
    )
    machine_list_parser.set_defaults(func=CmdMachineList)
    machine_MODIFY_HELP = "Modify the configuration of an machine."
    machine_modify_parser = machine_subparsers.add_parser(
        "modify",
        parents=[parent_config_parser, parent_parser],
        description=append_doc_link(machine_MODIFY_HELP, "machine/modify"),
        help=machine_MODIFY_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    machine_modify_parser.add_argument("name", help="Name of the machine")
    machine_modify_parser.add_argument("option",
                                       help="Name of the option to modify.")
    machine_modify_parser.add_argument("value",
                                       nargs="?",
                                       help="(optional) Value of the option.")
    machine_modify_parser.add_argument(
        "-u",
        "--unset",
        default=False,
        action="store_true",
        help="Unset option.",
    )
    machine_modify_parser.set_defaults(func=CmdMachineModify)

    machine_RENAME_HELP = "Rename a machine "
    machine_rename_parser = machine_subparsers.add_parser(
        "rename",
        parents=[parent_config_parser, parent_parser],
        description=append_doc_link(machine_RENAME_HELP, "remote/rename"),
        help=machine_RENAME_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    machine_rename_parser.add_argument("name", help="Machine to be renamed")
    machine_rename_parser.add_argument("new", help="New name of the machine")
    machine_rename_parser.set_defaults(func=CmdMachineRename)

    machine_REMOVE_HELP = "Remove an machine."
    machine_remove_parser = machine_subparsers.add_parser(
        "remove",
        parents=[parent_config_parser, parent_parser],
        description=append_doc_link(machine_REMOVE_HELP, "machine/remove"),
        help=machine_REMOVE_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    machine_remove_parser.add_argument("name",
                                       help="Name of the machine to remove.")
    machine_remove_parser.set_defaults(func=CmdMachineRemove)

    machine_CREATE_HELP = "Create and start a machine instance."
    machine_create_parser = machine_subparsers.add_parser(
        "create",
        parents=[parent_parser],
        description=append_doc_link(machine_CREATE_HELP, "machine/create"),
        help=machine_CREATE_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    machine_create_parser.add_argument("name",
                                       help="Name of the machine to create.")
    machine_create_parser.set_defaults(func=CmdMachineCreate)

    machine_STATUS_HELP = (
        "List the status of running instances for one/all machines.")
    machine_status_parser = machine_subparsers.add_parser(
        "status",
        parents=[parent_parser],
        description=append_doc_link(machine_STATUS_HELP, "machine/status"),
        help=machine_STATUS_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    machine_status_parser.add_argument("name",
                                       nargs="?",
                                       help="(optional) Name of the machine.")
    machine_status_parser.set_defaults(func=CmdMachineStatus)

    machine_DESTROY_HELP = "Destroy an machine instance."
    machine_destroy_parser = machine_subparsers.add_parser(
        "destroy",
        parents=[parent_parser],
        description=append_doc_link(machine_DESTROY_HELP, "machine/destroy"),
        help=machine_DESTROY_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    machine_destroy_parser.add_argument(
        "name", help="Name of the machine instance to destroy.")
    machine_destroy_parser.set_defaults(func=CmdMachineDestroy)

    machine_SSH_HELP = "Connect to a machine via SSH."
    machine_ssh_parser = machine_subparsers.add_parser(
        "ssh",
        parents=[parent_parser],
        description=append_doc_link(machine_SSH_HELP, "machine/ssh"),
        help=machine_SSH_HELP,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    machine_ssh_parser.add_argument(
        "name", help="Name of the machine instance to connect to.")
    machine_ssh_parser.set_defaults(func=CmdMachineSsh)
Пример #12
0
class CmdDataStatus(CmdDataBase):
    STATUS_LEN = 20
    STATUS_INDENT = "\t"
    UP_TO_DATE_MSG = "Data and pipelines are up to date."
    EMPTY_PROJECT_MSG = (
        "There are no data or pipelines tracked in this project yet.\n"
        "See {link} to get started!").format(
            link=format_link("https://dvc.org/doc/start"))

    def _normalize(self, s):
        s += ":"
        assert len(s) < self.STATUS_LEN
        return s + (self.STATUS_LEN - len(s)) * " "

    def _show(self, status, indent=0):
        ind = indent * self.STATUS_INDENT

        if isinstance(status, str):
            logger.info(f"{ind}{status}")
            return

        if isinstance(status, list):
            for entry in status:
                self._show(entry, indent)
            return

        assert isinstance(status, dict)

        for key, value in status.items():
            if isinstance(value, str):
                logger.info("{}{}{}".format(ind, self._normalize(value), key))
            elif value:
                logger.info(f"{ind}{key}:")
                self._show(value, indent + 1)

    def run(self):
        indent = 1 if self.args.cloud else 0
        try:
            st = self.repo.status(
                targets=self.args.targets,
                jobs=self.args.jobs,
                cloud=self.args.cloud,
                remote=self.args.remote,
                all_branches=self.args.all_branches,
                all_tags=self.args.all_tags,
                all_commits=self.args.all_commits,
                with_deps=self.args.with_deps,
                recursive=self.args.recursive,
            )

            if self.args.quiet:
                return bool(st)

            if self.args.show_json:
                import json

                logger.info(json.dumps(st))
            elif st:
                self._show(st, indent)
            elif not self.repo.stages:
                logger.info(self.EMPTY_PROJECT_MSG)
            else:
                logger.info(self.UP_TO_DATE_MSG)

        except DvcException:
            logger.exception("")
            return 1
        return 0
Пример #13
0
def _log_exceptions(exc: Exception) -> Optional[int]:
    """Try to log some known exceptions, that are not DVCExceptions."""
    from dvc.utils import error_link, format_link

    if isinstance(exc, OSError):
        import errno

        if exc.errno == errno.EMFILE:
            logger.exception(
                "too many open files, please visit "
                "{} to see how to handle this "
                "problem".format(error_link("many-files")),
                extra={"tb_only": True},
            )
        else:
            _log_unknown_exceptions()
        return None

    from dvc.fs import AuthError, ConfigError, RemoteMissingDepsError

    if isinstance(exc, RemoteMissingDepsError):
        from dvc.utils.pkg import PKG

        proto = exc.protocol
        by_pkg = {
            "pip": f"pip install 'dvc[{proto}]'",
            "conda": f"conda install -c conda-forge dvc-{proto}",
        }

        cmd = by_pkg.get(PKG)
        if cmd:
            link = format_link("https://dvc.org/doc/install")
            hint = (f"To install dvc with those dependencies, run:\n"
                    "\n"
                    f"\t{cmd}\n"
                    "\n"
                    f"See {link} for more info.")
        else:
            link = format_link("https://github.com/iterative/dvc/issues")
            hint = f"\nPlease report this bug to {link}. Thank you!"

        logger.exception(
            f"URL '{exc.url}' is supported but requires these missing "
            f"dependencies: {exc.missing_deps}. {hint}",
            extra={"tb_only": True},
        )
        return None

    if isinstance(exc, (AuthError, ConfigError)):
        link = format_link("https://man.dvc.org/remote/modify")
        logger.exception("configuration error")
        logger.exception(
            f"{exc!s}\nLearn more about configuration settings at {link}.",
            extra={"tb_only": True},
        )
        return 251

    from dvc_data.hashfile.cache import DiskError

    if isinstance(exc, DiskError):
        from dvc.utils import relpath

        directory = relpath(exc.directory)
        logger.exception(
            f"Could not open pickled '{exc.type}' cache.\n"
            f"Remove the '{directory}' directory and then retry this command."
            f"\nSee {error_link('pickle')} for more information.",
            extra={"tb_only": True},
        )
        return None

    from dvc_data.stage import IgnoreInCollectedDirError

    if isinstance(exc, IgnoreInCollectedDirError):
        logger.exception("")
        return None

    _log_unknown_exceptions()
    return None