Allow deprecating an option for a new one

pull/10299/head
Xavier Claessens 3 years ago committed by Eli Schwartz
parent 9528e7deb0
commit 3c8343b483
  1. 15
      docs/markdown/Build-options.md
  2. 16
      docs/markdown/snippets/deprecated_for_option.md
  3. 15
      mesonbuild/coredata.py
  4. 7
      mesonbuild/optinterpreter.py
  5. 5
      test cases/common/247 deprecated option/meson.build
  6. 8
      test cases/common/247 deprecated option/meson_options.txt

@ -149,6 +149,21 @@ option('o4', type: 'feature', deprecated: {'true': 'enabled', 'false': 'disabled
option('o5', type: 'boolean', deprecated: {'enabled': 'true', 'disabled': 'false', 'auto': 'false'})
```
Since *0.63.0* the `deprecated` keyword argument can take the name of a new option
that replace this option. In that case, setting a value on the deprecated option
will set the value on both the old and new names, assuming they accept the same
values.
```meson
# A boolean option has been replaced by a feature with another name, old true/false values
# are accepted by the new option for backward compatibility.
option('o6', type: 'boolean', value: 'true', deprecated: 'o7')
option('o7', type: 'feature', value: 'enabled', deprecated: {'true': 'enabled', 'false': 'disabled'})
# A project option is replaced by a module option
option('o8', type: 'string', value: '', deprecated: 'python.platlibdir')
```
## Using build options
```meson

@ -0,0 +1,16 @@
## Deprecate an option and replace it with a new one
The `deprecated` keyword argument can now take the name of a new option
that replace this option. In that case, setting a value on the deprecated option
will set the value on both the old and new names, assuming they accept the same
values.
```meson
# A boolean option has been replaced by a feature with another name, old true/false values
# are accepted by the new option for backward compatibility.
option('o1', type: 'boolean', value: 'true', deprecated: 'o2')
option('o2', type: 'feature', value: 'enabled', deprecated: {'true': 'enabled', 'false': 'disabled'})
# A project option is replaced by a module option
option('o3', type: 'string', value: '', deprecated: 'python.platlibdir')
```

@ -81,7 +81,7 @@ class UserOption(T.Generic[_T], HoldableObject):
if not isinstance(yielding, bool):
raise MesonException('Value of "yielding" must be a boolean.')
self.yielding = yielding
self.deprecated: T.Union[bool, T.Dict[str, str], T.List[str]] = False
self.deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False
def listify(self, value: T.Any) -> T.List[T.Any]:
return [value]
@ -660,6 +660,19 @@ class CoreData:
return v
newvalue = [replace(v) for v in opt.listify(value)]
value = ','.join(newvalue)
elif isinstance(opt.deprecated, str):
# Option is deprecated and replaced by another. Note that a project
# option could be replaced by a built-in or module option, which is
# why we use OptionKey.from_string(newname) instead of
# key.evolve(newname). We set the value on both the old and new names,
# assuming they accept the same value. That could for example be
# achieved by adding the values from old option as deprecated on the
# new option, for example in the case of boolean option is replaced
# by a feature option with a different name.
newname = opt.deprecated
newkey = OptionKey.from_string(newname).evolve(subproject=key.subproject)
mlog.deprecation(f'Option {key.name!r} is replaced by {newname!r}')
self.set_option(newkey, value)
opt.set_value(value)

@ -32,7 +32,7 @@ if T.TYPE_CHECKING:
'value': object,
'min': T.Optional[int],
'max': T.Optional[int],
'deprecated': T.Union[bool, T.Dict[str, str], T.List[str]],
'deprecated': T.Union[bool, str, T.Dict[str, str], T.List[str]],
})
ParserArgs = TypedDict('ParserArgs', {
'yield': bool,
@ -153,7 +153,7 @@ class OptionInterpreter:
KwargInfo('value', object),
KwargInfo('min', (int, type(None))),
KwargInfo('max', (int, type(None))),
KwargInfo('deprecated', (bool, ContainerTypeInfo(dict, str), ContainerTypeInfo(list, str)),
KwargInfo('deprecated', (bool, str, ContainerTypeInfo(dict, str), ContainerTypeInfo(list, str)),
default=False, since='0.60.0')
)
@typed_pos_args('option', str)
@ -177,7 +177,8 @@ class OptionInterpreter:
parser_kwargs = {k: v for k, v in kwargs.items() if k in known_parser_kwargs and v is not None}
opt = parser(description, T.cast('ParserArgs', parser_kwargs))
opt.deprecated = kwargs['deprecated']
if isinstance(opt.deprecated, str):
FeatureNew.single_use('String value to "deprecated" keyword argument', '0.63.0', self.subproject)
if key in self.options:
mlog.deprecation(f'Option {opt_name} already exists.')
self.options[key] = opt

@ -5,6 +5,8 @@ project('deprecated options',
'o3=a,b',
'o4=true',
'o5=auto',
'o6=false',
'o8=/foo',
]
)
@ -13,3 +15,6 @@ assert(get_option('o2') == ['a', 'b'])
assert(get_option('o3') == ['c', 'b'])
assert(get_option('o4').enabled())
assert(get_option('o5') == false)
assert(get_option('o6') == false)
assert(get_option('o7').disabled())
assert(get_option('python.platlibdir') == '/foo')

@ -13,3 +13,11 @@ option('o4', type: 'feature', deprecated: {'true': 'enabled', 'false': 'disabled
# A feature option has been replaced by a boolean, enabled/disabled/auto values are remapped.
option('o5', type: 'boolean', deprecated: {'enabled': 'true', 'disabled': 'false', 'auto': 'false'})
# A boolean option has been replaced by a feature with another name, old true/false values
# are accepted by the new option for backward compatibility.
option('o6', type: 'boolean', value: 'true', deprecated: 'o7')
option('o7', type: 'feature', value: 'enabled', deprecated: {'true': 'enabled', 'false': 'disabled'})
# A project option is replaced by a module option
option('o8', type: 'string', value: '', deprecated: 'python.platlibdir')

Loading…
Cancel
Save