def test_s3_ssl_verify(tmp_dir, dvc): config = Config(validate=False) with config.edit() as conf: conf["remote"]["remote-name"] = {"url": "s3://bucket/dvc"} assert "ssl_verify" not in config["remote"]["remote-name"] with config.edit() as conf: section = conf["remote"]["remote-name"] section["ssl_verify"] = False assert (tmp_dir / ".dvc" / "config").read_text() == textwrap.dedent("""\ [core] no_scm = True ['remote "remote-name"'] url = s3://bucket/dvc ssl_verify = False """) with config.edit() as conf: section = conf["remote"]["remote-name"] section["ssl_verify"] = "/path/to/custom/cabundle.pem" assert (tmp_dir / ".dvc" / "config").read_text() == textwrap.dedent("""\ [core] no_scm = True ['remote "remote-name"'] url = s3://bucket/dvc ssl_verify = /path/to/custom/cabundle.pem """)
class CmdConfig(CmdBaseNoRepo): def __init__(self, args): super().__init__(args) self.config = Config(validate=False) def run(self): if self.args.list: if any((self.args.name, self.args.value, self.args.unset)): logger.error( "-l/--list can't be used together with any of these " "options: -u/--unset, name, value") return 1 conf = self.config.load_one(self.args.level) logger.info("\n".join(self._format_config(conf))) return 0 if self.args.name is None: logger.error("name argument is required") return 1 section, opt = self.args.name.lower().strip().split(".", 1) if self.args.value is None and not self.args.unset: conf = self.config.load_one(self.args.level) self._check(conf, section, opt) logger.info(conf[section][opt]) return 0 with self.config.edit(self.args.level) as conf: if self.args.unset: self._check(conf, section, opt) del conf[section][opt] else: self._check(conf, section) conf[section][opt] = self.args.value if self.args.name == "cache.type": logger.warning( "You have changed the 'cache.type' option. This doesn't update" " any existing workspace file links, but it can be done with:" "\n dvc checkout --relink") return 0 def _check(self, conf, section, opt=None): if section not in conf: msg = "section {} doesn't exist" raise ConfigError(msg.format(self.args.name)) if opt and opt not in conf[section]: msg = "option {} doesn't exist" raise ConfigError(msg.format(self.args.name)) @staticmethod def _format_config(config): for key, value in flatten(config).items(): yield f"{key}={value}"
class CmdConfig(CmdBaseNoRepo): def __init__(self, args): super().__init__(args) self.config = Config(validate=False) def run(self): section, opt = self.args.name.lower().strip().split(".", 1) if self.args.value is None and not self.args.unset: conf = self.config.load_one(self.args.level) self._check(conf, section, opt) logger.info(conf[section][opt]) return 0 with self.config.edit(self.args.level) as conf: if self.args.unset: self._check(conf, section, opt) del conf[section][opt] else: self._check(conf, section) conf[section][opt] = self.args.value if self.args.name == "cache.type": logger.warning( "You have changed the 'cache.type' option. This doesn't update" " any existing workspace file links, but it can be done with:" "\n dvc checkout --relink" ) return 0 def _check(self, conf, section, opt=None): if section not in conf: msg = "section {} doesn't exist" raise ConfigError(msg.format(self.args.name)) if opt and opt not in conf[section]: msg = "option {} doesn't exist" raise ConfigError(msg.format(self.args.name))
class CmdConfig(CmdBaseNoRepo): def __init__(self, args): from dvc.config import Config super().__init__(args) self.config = Config(validate=False) def run(self): if self.args.show_origin: if any((self.args.value, self.args.unset)): logger.error( "--show-origin can't be used together with any of these " "options: -u/--unset, value" ) return 1 if self.args.list: return self._list() if self.args.name is None: logger.error("name argument is required") return 1 remote, section, opt = self.args.name if self.args.value is None and not self.args.unset: return self._get(remote, section, opt) return self._set(remote, section, opt) def _list(self): if any((self.args.name, self.args.value, self.args.unset)): logger.error( "-l/--list can't be used together with any of these " "options: -u/--unset, name, value" ) return 1 levels = self._get_appropriate_levels(self.args.level) for level in levels: conf = self.config.read(level) prefix = self._config_file_prefix( self.args.show_origin, self.config, level ) configs = list(self._format_config(conf, prefix)) if configs: ui.write("\n".join(configs)) return 0 def _get(self, remote, section, opt): from dvc.config import ConfigError levels = self._get_appropriate_levels(self.args.level)[::-1] for level in levels: conf = self.config.read(level) if remote: conf = conf["remote"] try: self._check(conf, remote, section, opt) except ConfigError: if self.args.level: raise else: prefix = self._config_file_prefix( self.args.show_origin, self.config, level ) ui.write(prefix, conf[section][opt], sep="") break return 0 def _set(self, remote, section, opt): with self.config.edit(self.args.level) as conf: if remote: conf = conf["remote"] if self.args.unset: self._check(conf, remote, section, opt) del conf[section][opt] else: self._check(conf, remote, section) conf[section][opt] = self.args.value if self.args.name == "cache.type": logger.warning( "You have changed the 'cache.type' option. This doesn't update" " any existing workspace file links, but it can be done with:" "\n dvc checkout --relink" ) return 0 def _check(self, conf, remote, section, opt=None): from dvc.config import ConfigError name = "remote" if remote else "section" if section not in conf: raise ConfigError(f"{name} '{section}' doesn't exist") if opt and opt not in conf[section]: raise ConfigError( f"option '{opt}' doesn't exist in {name} '{section}'" ) def _get_appropriate_levels(self, levels): if levels: self._validate_level_for_non_repo_operation(levels) return [levels] if self.config.dvc_dir is None: return self.config.SYSTEM_LEVELS return self.config.LEVELS def _validate_level_for_non_repo_operation(self, level): from dvc.config import ConfigError if self.config.dvc_dir is None and level in self.config.REPO_LEVELS: raise ConfigError("Not inside a DVC repo") @staticmethod def _format_config(config, prefix=""): from dvc.utils.flatten import flatten for key, value in flatten(config).items(): yield f"{prefix}{key}={value}" @staticmethod def _config_file_prefix(show_origin, config, level): from dvc.repo import Repo if not show_origin: return "" level = level or "repo" fname = config.files[level] if level in ["local", "repo"]: fname = os.path.relpath(fname, start=Repo.find_root()) return fname + "\t"
class CmdConfig(CmdBaseNoRepo): def __init__(self, args): super().__init__(args) self.config = Config(validate=False) def run(self): if self.args.show_origin: if any((self.args.value, self.args.unset)): logger.error( "--show-origin can't be used together with any of these " "options: -u/--unset, value" ) return 1 if not self.args.level: logger.error( "--show-origin requires one of these options: " "--system, --global, --repo, --local" ) return 1 if self.args.list: if any((self.args.name, self.args.value, self.args.unset)): logger.error( "-l/--list can't be used together with any of these " "options: -u/--unset, name, value" ) return 1 conf = self.config.read(self.args.level) prefix = self._config_file_prefix( self.args.show_origin, self.config, self.args.level ) logger.info("\n".join(self._format_config(conf, prefix))) return 0 if self.args.name is None: logger.error("name argument is required") return 1 remote, section, opt = self.args.name if self.args.value is None and not self.args.unset: conf = self.config.read(self.args.level) prefix = self._config_file_prefix( self.args.show_origin, self.config, self.args.level ) if remote: conf = conf["remote"] self._check(conf, remote, section, opt) logger.info("{}{}".format(prefix, conf[section][opt])) return 0 with self.config.edit(self.args.level) as conf: if remote: conf = conf["remote"] if self.args.unset: self._check(conf, remote, section, opt) del conf[section][opt] else: self._check(conf, remote, section) conf[section][opt] = self.args.value if self.args.name == "cache.type": logger.warning( "You have changed the 'cache.type' option. This doesn't update" " any existing workspace file links, but it can be done with:" "\n dvc checkout --relink" ) return 0 def _check(self, conf, remote, section, opt=None): name = "remote" if remote else "section" if section not in conf: raise ConfigError(f"{name} '{section}' doesn't exist") if opt and opt not in conf[section]: raise ConfigError( f"option '{opt}' doesn't exist in {name} '{section}'" ) @staticmethod def _format_config(config, prefix=""): for key, value in flatten(config).items(): yield f"{prefix}{key}={value}" @staticmethod def _config_file_prefix(show_origin, config, level): if not show_origin: return "" level = level or "repo" fname = config.files[level] if level in ["local", "repo"]: fname = os.path.relpath(fname, start=Repo.find_root()) return fname + "\t"