# SPDX-FileCopyrightText: © 2022-2023 Wojciech Trybus # SPDX-License-Identifier: GPL-3.0-or-later from typing import TypeVar, Generic, Optional, List from .parsers import Parser from .field_base import FieldBase T = TypeVar('T') class NonListField(FieldBase, Generic[T]): """Config field containing a basic, non-list value.""" def __init__( self, config_group: str, name: str, default: T, parser_type: Optional[type] = None, local: bool = False, ) -> None: super().__init__(config_group, name, default, parser_type, local) self._parser: Parser[T] = self._get_parser(type(self.default)) def read(self) -> T: """Return value from kritarc parsed to field type.""" raw = self.location.read(self.config_group, self.name) if raw is None: return self.default return self._parser.parse_to(raw) def _to_string(self, value: T) -> str: """Parse the field value to string using parser.""" return self._parser.parse_from(value) class ListField(FieldBase, Generic[T]): """Config field containing a list value.""" def __init__( self, config_group: str, name: str, default: List[T], parser_type: Optional[type] = None, local: bool = False, ) -> None: super().__init__(config_group, name, default, parser_type, local) self._parser: Parser[T] = self._get_parser( self._get_type(self.parser_type)) def write(self, value: List[T]) -> None: for element in value: if not isinstance(element, self._parser.type): raise ValueError(f"{value} not of type {type(self.default)}") super().write(value) def _get_type(self, passed_type: Optional[type]) -> type: """ Determine parser type based on default value or passed type. - For non empty list, parser depends on first list element. - For empty list, parsed type must be used directly """ if not self.default: if passed_type is None: raise ValueError("Type not given for a list") return passed_type return type(self.default[0]) def read(self) -> List[T]: """ Return value from kritarc parsed to field type. Each list element requires parsing. """ raw = self.location.read(self.config_group, self.name) if raw is None: return self.default if raw == "": return [] values_list = raw.split("\t") return [self._parser.parse_to(value) for value in values_list] def _to_string(self, value: List[T]) -> str: """Convert list of values to string by parsing each element alone.""" return "\t".join([self._parser.parse_from(item) for item in value])