aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/ast/introspection.py2
-rw-r--r--mesonbuild/backend/ninjabackend.py10
-rw-r--r--mesonbuild/build.py2
-rw-r--r--mesonbuild/cmake/executor.py2
-rw-r--r--mesonbuild/compilers/compilers.py8
-rw-r--r--mesonbuild/compilers/mixins/clike.py6
-rw-r--r--mesonbuild/coredata.py79
-rw-r--r--mesonbuild/dependencies/pkgconfig.py4
-rw-r--r--mesonbuild/interpreter/interpreter.py6
-rw-r--r--mesonbuild/interpreter/interpreterobjects.py4
-rw-r--r--mesonbuild/msetup.py4
-rw-r--r--mesonbuild/options.py33
12 files changed, 94 insertions, 66 deletions
diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py
index 1d7dd05..1197510 100644
--- a/mesonbuild/ast/introspection.py
+++ b/mesonbuild/ast/introspection.py
@@ -182,7 +182,7 @@ class IntrospectionInterpreter(AstInterpreter):
if self.subproject:
options = {}
for k in comp.get_options():
- v = copy.copy(self.coredata.optstore[k])
+ v = copy.copy(self.coredata.optstore.get_value_object(k))
k = k.evolve(subproject=self.subproject)
options[k] = v
self.coredata.add_compiler_options(options, lang, for_machine, self.environment, self.subproject)
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index d7421ff..b23eff9 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -623,7 +623,7 @@ class NinjaBackend(backends.Backend):
outfile.write('# Do not edit by hand.\n\n')
outfile.write('ninja_required_version = 1.8.2\n\n')
- num_pools = self.environment.coredata.optstore[OptionKey('backend_max_links')].value
+ num_pools = self.environment.coredata.optstore.get_value('backend_max_links')
if num_pools > 0:
outfile.write(f'''pool link_pool
depth = {num_pools}
@@ -657,7 +657,7 @@ class NinjaBackend(backends.Backend):
mlog.log_timestamp("Dist generated")
key = OptionKey('b_coverage')
if (key in self.environment.coredata.optstore and
- self.environment.coredata.optstore[key].value):
+ self.environment.coredata.optstore.get_value(key)):
gcovr_exe, gcovr_version, lcov_exe, lcov_version, genhtml_exe, llvm_cov_exe = environment.find_coverage_tools(self.environment.coredata)
mlog.debug(f'Using {gcovr_exe} ({gcovr_version}), {lcov_exe} and {llvm_cov_exe} for code coverage')
if gcovr_exe or (lcov_exe and genhtml_exe):
@@ -2287,7 +2287,7 @@ class NinjaBackend(backends.Backend):
return options
def generate_static_link_rules(self):
- num_pools = self.environment.coredata.optstore[OptionKey('backend_max_links')].value
+ num_pools = self.environment.coredata.optstore.get_value('backend_max_links')
if 'java' in self.environment.coredata.compilers.host:
self.generate_java_link()
for for_machine in MachineChoice:
@@ -2335,7 +2335,7 @@ class NinjaBackend(backends.Backend):
self.add_rule(NinjaRule(rule, cmdlist, args, description, **options, extra=pool))
def generate_dynamic_link_rules(self):
- num_pools = self.environment.coredata.optstore[OptionKey('backend_max_links')].value
+ num_pools = self.environment.coredata.optstore.get_value('backend_max_links')
for for_machine in MachineChoice:
complist = self.environment.coredata.compilers[for_machine]
for langname, compiler in complist.items():
@@ -3727,7 +3727,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
elem.add_dep(self.generate_custom_target_clean(ctlist))
if OptionKey('b_coverage') in self.environment.coredata.optstore and \
- self.environment.coredata.optstore[OptionKey('b_coverage')].value:
+ self.environment.coredata.optstore.get_value('b_coverage'):
self.generate_gcov_clean()
elem.add_dep('clean-gcda')
elem.add_dep('clean-gcno')
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 517845c..f174ef7 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -1243,7 +1243,7 @@ class BuildTarget(Target):
if kwargs.get(arg) is not None:
val = T.cast('bool', kwargs[arg])
elif k in self.environment.coredata.optstore:
- val = self.environment.coredata.optstore[k].value
+ val = self.environment.coredata.optstore.get_value(k)
else:
val = False
diff --git a/mesonbuild/cmake/executor.py b/mesonbuild/cmake/executor.py
index a8850d6..392063d 100644
--- a/mesonbuild/cmake/executor.py
+++ b/mesonbuild/cmake/executor.py
@@ -51,7 +51,7 @@ class CMakeExecutor:
self.cmakebin = None
return
- self.prefix_paths = self.environment.coredata.optstore[OptionKey('cmake_prefix_path', machine=self.for_machine)].value
+ self.prefix_paths = self.environment.coredata.optstore.get_value(OptionKey('cmake_prefix_path', machine=self.for_machine))
if self.prefix_paths:
self.extra_cmake_args += ['-DCMAKE_PREFIX_PATH={}'.format(';'.join(self.prefix_paths))]
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index ef0ea70..5849d8c 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -322,9 +322,9 @@ def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler',
if option_enabled(compiler.base_options, options, OptionKey('b_bitcode')):
args.append('-fembed-bitcode')
try:
- crt_val = options[OptionKey('b_vscrt')].value
- buildtype = options[OptionKey('buildtype')].value
try:
+ crt_val = options.get_value(OptionKey('b_vscrt'))
+ buildtype = options.get_value(OptionKey('buildtype'))
args += compiler.get_crt_compile_args(crt_val, buildtype)
except AttributeError:
pass
@@ -390,9 +390,9 @@ def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler',
args.extend(linker.get_allow_undefined_link_args())
try:
- crt_val = options[OptionKey('b_vscrt')].value
- buildtype = options[OptionKey('buildtype')].value
try:
+ crt_val = options.get_value(OptionKey('b_vscrt'))
+ buildtype = options.get_value(OptionKey('buildtype'))
args += linker.get_crt_link_args(crt_val, buildtype)
except AttributeError:
pass
diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py
index 87cb819..70e81a4 100644
--- a/mesonbuild/compilers/mixins/clike.py
+++ b/mesonbuild/compilers/mixins/clike.py
@@ -26,7 +26,7 @@ from ... import arglist
from ... import mesonlib
from ... import mlog
from ...linkers.linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker
-from ...mesonlib import LibType, OptionKey
+from ...mesonlib import LibType
from .. import compilers
from ..compilers import CompileCheckMode
from .visualstudio import VisualStudioLikeCompiler
@@ -376,8 +376,8 @@ class CLikeCompiler(Compiler):
# linking with static libraries since MSVC won't select a CRT for
# us in that case and will error out asking us to pick one.
try:
- crt_val = env.coredata.optstore[OptionKey('b_vscrt')].value
- buildtype = env.coredata.optstore[OptionKey('buildtype')].value
+ crt_val = env.coredata.optstore.get_value('b_vscrt')
+ buildtype = env.coredata.optstore.get_value('buildtype')
cargs += self.get_crt_compile_args(crt_val, buildtype)
except (KeyError, AttributeError):
pass
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 8804547..9f00a34 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -150,8 +150,8 @@ class DependencyCache:
def __calculate_subkey(self, type_: DependencyCacheType) -> T.Tuple[str, ...]:
data: T.Dict[DependencyCacheType, T.List[str]] = {
- DependencyCacheType.PKG_CONFIG: stringlistify(self.__builtins[self.__pkg_conf_key].value),
- DependencyCacheType.CMAKE: stringlistify(self.__builtins[self.__cmake_key].value),
+ DependencyCacheType.PKG_CONFIG: stringlistify(self.__builtins.get_value(self.__pkg_conf_key)),
+ DependencyCacheType.CMAKE: stringlistify(self.__builtins.get_value(self.__cmake_key)),
DependencyCacheType.OTHER: [],
}
assert type_ in data, 'Someone forgot to update subkey calculations for a new type'
@@ -415,27 +415,27 @@ class CoreData:
if opt.yielding:
# This option is global and not per-subproject
return
- value = opts_map[key.as_root()].value
+ value = opts_map.get_value(key.as_root())
else:
value = None
- opts_map[key] = opt.init_option(key, value, options.default_prefix())
+ opts_map.add_system_option(key, opt.init_option(key, value, options.default_prefix()))
def init_backend_options(self, backend_name: str) -> None:
if backend_name == 'ninja':
- self.optstore[OptionKey('backend_max_links')] = options.UserIntegerOption(
+ self.optstore.add_system_option('backend_max_links', options.UserIntegerOption(
'backend_max_links',
'Maximum number of linker processes to run or 0 for no '
'limit',
- (0, None, 0))
+ (0, None, 0)))
elif backend_name.startswith('vs'):
- self.optstore[OptionKey('backend_startup_project')] = options.UserStringOption(
+ self.optstore.add_system_option('backend_startup_project', options.UserStringOption(
'backend_startup_project',
'Default project to execute in Visual Studio',
- '')
+ ''))
def get_option(self, key: OptionKey) -> T.Union[T.List[str], str, int, bool]:
try:
- v = self.optstore[key].value
+ v = self.optstore.get_value(key)
return v
except KeyError:
pass
@@ -455,11 +455,11 @@ class CoreData:
if key.name == 'prefix':
value = self.sanitize_prefix(value)
else:
- prefix = self.optstore[OptionKey('prefix')].value
+ prefix = self.optstore.get_value('prefix')
value = self.sanitize_dir_option_value(prefix, key, value)
try:
- opt = self.optstore[key]
+ opt = self.optstore.get_value_object(key)
except KeyError:
raise MesonException(f'Tried to set unknown builtin option {str(key)}')
@@ -559,8 +559,8 @@ class CoreData:
assert value == 'custom'
return False
- dirty |= self.optstore[OptionKey('optimization')].set_value(opt)
- dirty |= self.optstore[OptionKey('debug')].set_value(debug)
+ dirty |= self.optstore.set_value('optimization', opt)
+ dirty |= self.optstore.set_value('debug', debug)
return dirty
@@ -572,30 +572,32 @@ class CoreData:
def get_external_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]:
# mypy cannot analyze type of OptionKey
- return T.cast('T.List[str]', self.optstore[OptionKey('args', machine=for_machine, lang=lang)].value)
+ key = OptionKey('args', machine=for_machine, lang=lang)
+ return T.cast('T.List[str]', self.optstore.get_value(key))
def get_external_link_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]:
# mypy cannot analyze type of OptionKey
- return T.cast('T.List[str]', self.optstore[OptionKey('link_args', machine=for_machine, lang=lang)].value)
+ key = OptionKey('link_args', machine=for_machine, lang=lang)
+ return T.cast('T.List[str]', self.optstore.get_value(key))
def update_project_options(self, options: 'MutableKeyedOptionDictType', subproject: SubProject) -> None:
for key, value in options.items():
if not key.is_project():
continue
if key not in self.optstore:
- self.optstore[key] = value
+ self.optstore.add_project_option(key, value)
continue
if key.subproject != subproject:
raise MesonBugException(f'Tried to set an option for subproject {key.subproject} from {subproject}!')
- oldval = self.optstore[key]
+ oldval = self.optstore.get_value(key)
if type(oldval) is not type(value):
- self.optstore[key] = value
+ self.optstore.set_value(key, value.value)
elif oldval.choices != value.choices:
# If the choices have changed, use the new value, but attempt
# to keep the old options. If they are not valid keep the new
# defaults but warn.
- self.optstore[key] = value
+ self.optstore.set_value(key, value)
try:
value.set_value(oldval.value)
except MesonException:
@@ -605,7 +607,7 @@ class CoreData:
# Find any extranious keys for this project and remove them
for key in self.optstore.keys() - options.keys():
if key.is_project() and key.subproject == subproject:
- del self.optstore[key]
+ self.optstore.remove(key)
def is_cross_build(self, when_building_for: MachineChoice = MachineChoice.HOST) -> bool:
if when_building_for == MachineChoice.BUILD:
@@ -616,13 +618,13 @@ class CoreData:
dirty = False
assert not self.is_cross_build()
for k in options.BUILTIN_OPTIONS_PER_MACHINE:
- o = self.optstore[k]
- dirty |= self.optstore[k.as_build()].set_value(o.value)
+ o = self.optstore.get_value_object(k)
+ dirty |= self.optstore.set_value(k.as_build(), o.value)
for bk, bv in self.optstore.items():
if bk.machine is MachineChoice.BUILD:
hk = bk.as_host()
try:
- hv = self.optstore[hk]
+ hv = self.optstore.get_value_object(hk)
dirty |= bv.set_value(hv.value)
except KeyError:
continue
@@ -637,10 +639,10 @@ class CoreData:
pfk = OptionKey('prefix')
if pfk in opts_to_set:
prefix = self.sanitize_prefix(opts_to_set[pfk])
- dirty |= self.optstore[OptionKey('prefix')].set_value(prefix)
+ dirty |= self.optstore.set_value('prefix', prefix)
for key in options.BUILTIN_DIR_NOPREFIX_OPTIONS:
if key not in opts_to_set:
- dirty |= self.optstore[key].set_value(options.BUILTIN_OPTIONS[key].prefixed_default(key, prefix))
+ dirty |= self.optstore.set_value(key, options.BUILTIN_OPTIONS[key].prefixed_default(key, prefix))
unknown_options: T.List[OptionKey] = []
for k, v in opts_to_set.items():
@@ -690,7 +692,7 @@ class CoreData:
# Always test this using the HOST machine, as many builtin options
# are not valid for the BUILD machine, but the yielding value does
# not differ between them even when they are valid for both.
- if subproject and k.is_builtin() and self.optstore[k.evolve(subproject='', machine=MachineChoice.HOST)].yielding:
+ if subproject and k.is_builtin() and self.optstore.get_value_object(k.evolve(subproject='', machine=MachineChoice.HOST)).yielding:
continue
# Skip base, compiler, and backend options, they are handled when
# adding languages and setting backend.
@@ -703,14 +705,14 @@ class CoreData:
self.set_options(options, subproject=subproject, first_invocation=env.first_invocation)
- def add_compiler_options(self, options: MutableKeyedOptionDictType, lang: str, for_machine: MachineChoice,
+ def add_compiler_options(self, c_options: MutableKeyedOptionDictType, lang: str, for_machine: MachineChoice,
env: Environment, subproject: str) -> None:
- for k, o in options.items():
+ for k, o in c_options.items():
value = env.options.get(k)
if value is not None:
o.set_value(value)
if not subproject:
- self.optstore[k] = o # override compiler option on reconfigure
+ self.optstore.set_value_object(k, o) # override compiler option on reconfigure
self.optstore.setdefault(k, o)
if subproject:
@@ -718,7 +720,7 @@ class CoreData:
value = env.options.get(sk) or value
if value is not None:
o.set_value(value)
- self.optstore[sk] = o # override compiler option on reconfigure
+ self.optstore.set_value_object(sk, o) # override compiler option on reconfigure
self.optstore.setdefault(sk, o)
def add_lang_args(self, lang: str, comp: T.Type['Compiler'],
@@ -742,19 +744,19 @@ class CoreData:
else:
skey = key
if skey not in self.optstore:
- self.optstore[skey] = copy.deepcopy(compilers.base_options[key])
+ self.optstore.add_system_option(skey, copy.deepcopy(compilers.base_options[key]))
if skey in env.options:
- self.optstore[skey].set_value(env.options[skey])
+ self.optstore.set_value(skey, env.options[skey])
enabled_opts.append(skey)
elif subproject and key in env.options:
- self.optstore[skey].set_value(env.options[key])
+ self.optstore.set_value(skey, env.options[key])
enabled_opts.append(skey)
if subproject and key not in self.optstore:
- self.optstore[key] = copy.deepcopy(self.optstore[skey])
+ self.optstore.add_system_option(key, copy.deepcopy(self.optstore.get_value_object(skey)))
elif skey in env.options:
- self.optstore[skey].set_value(env.options[skey])
+ self.optstore.set_value(skey, env.options[skey])
elif subproject and key in env.options:
- self.optstore[skey].set_value(env.options[key])
+ self.optstore.set_value(skey, env.options[key])
self.emit_base_options_warnings(enabled_opts)
def emit_base_options_warnings(self, enabled_opts: T.List[OptionKey]) -> None:
@@ -905,7 +907,7 @@ class OptionsView(abc.Mapping):
if not key.is_project():
opt = self.original_options.get(key)
if opt is None or opt.yielding:
- opt = self.original_options[key.as_root()]
+ opt = self.original_options.get(key.as_root())
else:
opt = self.original_options[key]
if opt.yielding:
@@ -917,6 +919,9 @@ class OptionsView(abc.Mapping):
opt.set_value(override_value)
return opt
+ def get_value(self, key):
+ return self[key].value
+
def __iter__(self) -> T.Iterator[OptionKey]:
return iter(self.original_options)
diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py
index b6647b4..a87f413 100644
--- a/mesonbuild/dependencies/pkgconfig.py
+++ b/mesonbuild/dependencies/pkgconfig.py
@@ -238,7 +238,7 @@ class PkgConfigCLI(PkgConfigInterface):
def _get_env(self, uninstalled: bool = False) -> EnvironmentVariables:
env = EnvironmentVariables()
key = OptionKey('pkg_config_path', machine=self.for_machine)
- extra_paths: T.List[str] = self.env.coredata.optstore[key].value[:]
+ extra_paths: T.List[str] = self.env.coredata.optstore.get_value(key)[:]
if uninstalled:
uninstalled_path = Path(self.env.get_build_dir(), 'meson-uninstalled').as_posix()
if uninstalled_path not in extra_paths:
@@ -397,7 +397,7 @@ class PkgConfigDependency(ExternalDependency):
#
# Only prefix_libpaths are reordered here because there should not be
# too many system_libpaths to cause library version issues.
- pkg_config_path: T.List[str] = self.env.coredata.optstore[OptionKey('pkg_config_path', machine=self.for_machine)].value
+ pkg_config_path: T.List[str] = self.env.coredata.optstore.get_value(OptionKey('pkg_config_path', machine=self.for_machine))
pkg_config_path = self._convert_mingw_paths(pkg_config_path)
prefix_libpaths = OrderedSet(sort_libpaths(list(prefix_libpaths), pkg_config_path))
system_libpaths: OrderedSet[str] = OrderedSet()
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index a423ed8..e8547ee 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -1061,9 +1061,9 @@ class Interpreter(InterpreterBase, HoldableObject):
return v
try:
- opt = self.coredata.optstore[key]
+ opt = self.coredata.optstore.get_value_object(key)
if opt.yielding and key.subproject and key.as_root() in self.coredata.optstore:
- popt = self.coredata.optstore[key.as_root()]
+ popt = self.coredata.optstore.get_value_object(key.as_root())
if type(opt) is type(popt):
opt = popt
else:
@@ -1543,7 +1543,7 @@ class Interpreter(InterpreterBase, HoldableObject):
if self.subproject:
options = {}
for k in comp.get_options():
- v = copy.copy(self.coredata.optstore[k])
+ v = copy.copy(self.coredata.optstore.get_value_object(k))
k = k.evolve(subproject=self.subproject)
options[k] = v
self.coredata.add_compiler_options(options, lang, for_machine, self.environment, self.subproject)
diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py
index f5dafa7..32f05ba 100644
--- a/mesonbuild/interpreter/interpreterobjects.py
+++ b/mesonbuild/interpreter/interpreterobjects.py
@@ -24,7 +24,7 @@ from ..interpreterbase import (
from ..interpreter.type_checking import NoneType, ENV_KW, ENV_SEPARATOR_KW, PKGCONFIG_DEFINE_KW
from ..dependencies import Dependency, ExternalLibrary, InternalDependency
from ..programs import ExternalProgram
-from ..mesonlib import HoldableObject, OptionKey, listify, Popen_safe
+from ..mesonlib import HoldableObject, listify, Popen_safe
import typing as T
@@ -90,7 +90,7 @@ class FeatureOptionHolder(ObjectHolder[options.UserFeatureOption]):
super().__init__(option, interpreter)
if option and option.is_auto():
# TODO: we need to cast here because options is not a TypedDict
- auto = T.cast('options.UserFeatureOption', self.env.coredata.optstore[OptionKey('auto_features')])
+ auto = T.cast('options.UserFeatureOption', self.env.coredata.optstore.get_value_object('auto_features'))
self.held_object = copy.copy(auto)
self.held_object.name = option.name
self.methods.update({'enabled': self.enabled_method,
diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py
index 8f561e4..931b1eb 100644
--- a/mesonbuild/msetup.py
+++ b/mesonbuild/msetup.py
@@ -273,9 +273,9 @@ class MesonApp:
# collect warnings about unsupported build configurations; must be done after full arg processing
# by Interpreter() init, but this is most visible at the end
- if env.coredata.optstore[mesonlib.OptionKey('backend')].value == 'xcode':
+ if env.coredata.optstore.get_value('backend') == 'xcode':
mlog.warning('xcode backend is currently unmaintained, patches welcome')
- if env.coredata.optstore[mesonlib.OptionKey('layout')].value == 'flat':
+ if env.coredata.optstore.get_value('layout') == 'flat':
mlog.warning('-Dlayout=flat is unsupported and probably broken. It was a failed experiment at '
'making Windows build artifacts runnable while uninstalled, due to PATH considerations, '
'but was untested by CI and anyways breaks reasonable use of conflicting targets in different subdirs. '
diff --git a/mesonbuild/options.py b/mesonbuild/options.py
index 6ffcf1a..e2da6c2 100644
--- a/mesonbuild/options.py
+++ b/mesonbuild/options.py
@@ -481,13 +481,36 @@ class OptionStore:
def __len__(self):
return len(self.d)
- def __setitem__(self, key, value):
- self.d[key] = value
+ def ensure_key(self,key: T.Union[OptionKey, str]) -> OptionKey:
+ if isinstance(key, str):
+ return OptionKey(key)
+ return key
- def __getitem__(self, key):
- return self.d[key]
+ def get_value_object(self, key: T.Union[OptionKey, str]) -> 'UserOption[T.Any]':
+ return self.d[self.ensure_key(key)]
- def __delitem__(self, key):
+ def get_value(self, key: T.Union[OptionKey, str]) -> 'T.Any':
+ return self.get_value_object(key).value
+
+ def add_system_option(self, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any'):
+ key = self.ensure_key(key)
+ self.d[key] = valobj
+
+ def add_project_option(self, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'):
+ key = self.ensure_key(key)
+ self.d[key] = valobj
+
+ def set_value(self, key: T.Union[OptionKey, str], new_value: 'T.Any') -> bool:
+ key = self.ensure_key(key)
+ return self.d[key].set_value(new_value)
+
+ # FIXME, this should be removed.
+ def set_value_object(self, key: T.Union[OptionKey, str], new_object: 'UserOption[T.Any]') -> bool:
+ key = self.ensure_key(key)
+ self.d[key] = new_object
+
+
+ def remove(self, key):
del self.d[key]
def __contains__(self, key):