Ejemplo n.º 1
0
    def unset_value(self, key: str) -> None:
        """Unset a value in the configuration."""
        self._ensure_have_load_only()

        assert self.load_only
        if key not in self._config[self.load_only]:
            raise ConfigurationError(f"No such key - {key}")

        fname, parser = self._get_parser_to_modify()

        if parser is not None:
            section, name = _disassemble_key(key)
            if not (
                parser.has_section(section) and parser.remove_option(section, name)
            ):
                # The option was not removed.
                raise ConfigurationError(
                    "Fatal Internal error [id=1]. Please report as a bug."
                )

            # The section may be empty after the option was removed.
            if not parser.items(section):
                parser.remove_section(section)
            self._mark_as_modified(fname, parser)

        del self._config[self.load_only][key]
Ejemplo n.º 2
0
    def __init__(self, isolated, load_only=None):
        # type: (bool, Kind) -> None
        super(Configuration, self).__init__()

        _valid_load_only = [kinds.USER, kinds.GLOBAL, kinds.VENV, None]
        if load_only not in _valid_load_only:
            raise ConfigurationError(
                "Got invalid value for load_only - should be one of {}".format(
                    ", ".join(map(repr, _valid_load_only[:-1]))
                )
            )
        self.isolated = isolated  # type: bool
        self.load_only = load_only  # type: Optional[Kind]

        # The order here determines the override order.
        self._override_order = [
            kinds.GLOBAL, kinds.USER, kinds.VENV, kinds.ENV, kinds.ENV_VAR
        ]

        self._ignore_env_names = ["version", "help"]

        # Because we keep track of where we got the data from
        self._parsers = {
            variant: [] for variant in self._override_order
        }  # type: Dict[Kind, List[Tuple[str, RawConfigParser]]]
        self._config = {
            variant: {} for variant in self._override_order
        }  # type: Dict[Kind, Dict[str, Any]]
        self._modified_parsers = []  # type: List[Tuple[str, RawConfigParser]]
Ejemplo n.º 3
0
 def get_value(self, key):
     # type: (str) -> Any
     """Get a value from the configuration.
     """
     try:
         return self._dictionary[key]
     except KeyError:
         raise ConfigurationError("No such key - {}".format(key))
Ejemplo n.º 4
0
def _disassemble_key(name):
    # type: (str) -> List[str]
    if "." not in name:
        error_message = (
            "Key does not contain dot separated section and key. "
            "Perhaps you wanted to use 'global.{}' instead?").format(name)
        raise ConfigurationError(error_message)
    return name.split(".", 1)
Ejemplo n.º 5
0
    def _get_parser_to_modify(self):
        # type: () -> Tuple[str, RawConfigParser]
        # Determine which parser to modify
        parsers = self._parsers[self.load_only]
        if not parsers:
            # This should not happen if everything works correctly.
            raise ConfigurationError(
                "Fatal Internal error [id=2]. Please report as a bug.")

        # Use the highest priority parser.
        return parsers[-1]
Ejemplo n.º 6
0
    def unset_value(self, key):
        # type: (str) -> None
        """Unset a value in the configuration.
        """
        self._ensure_have_load_only()

        if key not in self._config[self.load_only]:
            raise ConfigurationError("No such key - {}".format(key))

        fname, parser = self._get_parser_to_modify()

        if parser is not None:
            section, name = _disassemble_key(key)

            # Remove the key in the parser
            modified_something = False
            if parser.has_section(section):
                # Returns whether the option was removed or not
                modified_something = parser.remove_option(section, name)

            if modified_something:
                # name removed from parser, section may now be empty
                section_iter = iter(parser.items(section))
                try:
                    val = six.next(section_iter)
                except StopIteration:
                    val = None

                if val is None:
                    parser.remove_section(section)

                self._mark_as_modified(fname, parser)
            else:
                raise ConfigurationError(
                    "Fatal Internal error [id=1]. Please report as a bug."
                )

        del self._config[self.load_only][key]
Ejemplo n.º 7
0
 def _construct_parser(self, fname):
     # type: (str) -> RawConfigParser
     parser = configparser.RawConfigParser()
     # If there is no such file, don't bother reading it but create the
     # parser anyway, to hold the data.
     # Doing this is useful when modifying and saving files, where we don't
     # need to construct a parser.
     if os.path.exists(fname):
         try:
             parser.read(fname)
         except UnicodeDecodeError:
             raise ConfigurationError((
                 "ERROR: "
                 "Configuration file contains invalid %s characters.\n"
                 "Please fix your configuration, located at %s\n"
             ) % (locale.getpreferredencoding(False), fname))
     return parser
Ejemplo n.º 8
0
    def __init__(self, isolated: bool, load_only: Optional[Kind] = None) -> None:
        super().__init__()

        if load_only is not None and load_only not in VALID_LOAD_ONLY:
            raise ConfigurationError(
                "Got invalid value for load_only - should be one of {}".format(
                    ", ".join(map(repr, VALID_LOAD_ONLY))
                )
            )
        self.isolated = isolated
        self.load_only = load_only

        # Because we keep track of where we got the data from
        self._parsers: Dict[Kind, List[Tuple[str, RawConfigParser]]] = {
            variant: [] for variant in OVERRIDE_ORDER
        }
        self._config: Dict[Kind, Dict[str, Any]] = {
            variant: {} for variant in OVERRIDE_ORDER
        }
        self._modified_parsers: List[Tuple[str, RawConfigParser]] = []
Ejemplo n.º 9
0
 def _ensure_have_load_only(self):
     # type: () -> None
     if self.load_only is None:
         raise ConfigurationError("Needed a specific file to be modifying.")
     logger.debug("Will be working with %s variant only", self.load_only)
Ejemplo n.º 10
0
 def get_value(self, key: str) -> Any:
     """Get a value from the configuration."""
     try:
         return self._dictionary[key]
     except KeyError:
         raise ConfigurationError(f"No such key - {key}")