diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index a6cfd5bf2..9d7cb4958 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -34,8 +34,9 @@ if T.TYPE_CHECKING: from . import dependencies from .compilers.compilers import Compiler, CompileResult # noqa: F401 from .environment import Environment + from .mesonlib import OptionOverrideProxy - OptionDictType = T.Dict[str, 'UserOption[T.Any]'] + OptionDictType = T.Union[T.Dict[str, 'UserOption[T.Any]'], OptionOverrideProxy] CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, str, T.Tuple[str, ...], str] version = '0.55.999' diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index 17d2733df..f2977717e 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -1696,7 +1696,7 @@ class OptionProxy(T.Generic[_T]): self.value = value -class OptionOverrideProxy: +class OptionOverrideProxy(collections.abc.MutableMapping): '''Mimic an option list but transparently override selected option values. @@ -1706,23 +1706,30 @@ class OptionOverrideProxy: # python 3.8 or typing_extensions def __init__(self, overrides: T.Dict[str, T.Any], *options: 'OptionDictType'): - self.overrides = overrides - self.options = options - - def __getitem__(self, option_name: str) -> T.Any: - for opts in self.options: - if option_name in opts: - return self._get_override(option_name, opts[option_name]) - raise KeyError('Option not found', option_name) - - def _get_override(self, option_name: str, base_opt: 'UserOption[T.Any]') -> T.Union[OptionProxy[T.Any], 'UserOption[T.Any]']: - if option_name in self.overrides: - return OptionProxy(base_opt.validate_value(self.overrides[option_name])) - return base_opt - - def copy(self) -> T.Dict[str, T.Any]: - result = {} # type: T.Dict[str, T.Any] - for opts in self.options: - for option_name in opts: - result[option_name] = self._get_override(option_name, opts[option_name]) - return result + self.overrides = overrides.copy() + self.options = {} # type: T.Dict[str, UserOption] + for o in options: + self.options.update(o) + + def __getitem__(self, key: str) -> T.Union['UserOption', OptionProxy]: + if key in self.options: + opt = self.options[key] + if key in self.overrides: + return OptionProxy(opt.validate_value(self.overrides[key])) + return opt + raise KeyError('Option not found', key) + + def __setitem__(self, key: str, value: T.Union['UserOption', OptionProxy]) -> None: + self.overrides[key] = value.value + + def __delitem__(self, key: str) -> None: + del self.overrides[key] + + def __iter__(self) -> T.Iterator[str]: + return iter(self.options) + + def __len__(self) -> int: + return len(self.options) + + def copy(self) -> 'OptionOverrideProxy': + return OptionOverrideProxy(self.overrides.copy(), self.options.copy()) diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index 66bbe2ab8..f7cbf8007 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -220,7 +220,7 @@ def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[s sub_core_options[sub + ':' + k] = o core_options.update(sub_core_options) - def add_keys(options: T.Dict[str, cdata.UserOption], section: str, machine: str = 'any') -> None: + def add_keys(options: 'cdata.OptionDictType', section: str, machine: str = 'any') -> None: for key in sorted(options.keys()): opt = options[key] optdict = {'name': key, 'value': opt.value, 'section': section, 'machine': machine}