Skip to content

Commit

Permalink
interpreterobjects: use typed_* for configuration_data.set*
Browse files Browse the repository at this point in the history
This removes the ability to use ConfigurationData as a dict, but
restricting the inputs to `str | int | bool`. This may be a little too
soon for this, and we may want to wait on that part, it's only bee 8
months since we started warning about this.
  • Loading branch information
dcbaker authored and eli-schwartz committed Jan 18, 2022
1 parent 7641bfd commit 5745256
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 54 deletions.
66 changes: 23 additions & 43 deletions mesonbuild/interpreter/interpreterobjects.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,11 @@ def prepend_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSe
self.held_object.prepend(name, values, kwargs['separator'])


_CONF_DATA_SET_KWS: KwargInfo[T.Optional[str]] = KwargInfo('description', (str, NoneType))


class ConfigurationDataObject(MutableInterpreterObject, MesonInterpreterObject):
def __init__(self, subproject: str, initial_values: T.Optional[T.Dict[str, T.Any]] = None) -> None:
def __init__(self, subproject: str, initial_values: T.Optional[T.Dict[str, T.Union[str, int, bool]]] = None) -> None:
self.used = False # These objects become immutable after use in configure_file.
super().__init__(subproject=subproject)
self.conf_data = build.ConfigurationData()
Expand All @@ -302,51 +305,28 @@ def is_used(self) -> bool:
def mark_used(self) -> None:
self.used = True

def validate_args(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.Tuple[str, T.Union[str, int, bool], T.Optional[str]]:
if len(args) == 1 and isinstance(args[0], list) and len(args[0]) == 2:
mlog.deprecation('Passing a list as the single argument to '
'configuration_data.set is deprecated. This will '
'become a hard error in the future.',
location=self.current_node)
args = args[0]

if len(args) != 2:
raise InterpreterException("Configuration set requires 2 arguments.")
def __check_used(self) -> None:
if self.used:
raise InterpreterException("Can not set values on configuration object that has been used.")
name, val = args
if not isinstance(val, (int, str)):
msg = f'Setting a configuration data value to {val!r} is invalid, ' \
'and will fail at configure_file(). If you are using it ' \
'just to store some values, please use a dict instead.'
mlog.deprecation(msg, location=self.current_node)
desc = kwargs.get('description', None)
if not isinstance(name, str):
raise InterpreterException("First argument to set must be a string.")
if desc is not None and not isinstance(desc, str):
raise InterpreterException('Description must be a string.')

# TODO: Remove the cast once we get rid of the deprecation
return name, T.cast(T.Union[str, bool, int], val), desc

@noArgsFlattening
def set_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None:
(name, val, desc) = self.validate_args(args, kwargs)
self.conf_data.values[name] = (val, desc)

def set_quoted_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None:
(name, val, desc) = self.validate_args(args, kwargs)
if not isinstance(val, str):
raise InterpreterException("Second argument to set_quoted must be a string.")
escaped_val = '\\"'.join(val.split('"'))
self.conf_data.values[name] = ('"' + escaped_val + '"', desc)

def set10_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None:
(name, val, desc) = self.validate_args(args, kwargs)
if val:
self.conf_data.values[name] = (1, desc)
else:
self.conf_data.values[name] = (0, desc)
@typed_pos_args('configuration_data.set', str, (str, int, bool))
@typed_kwargs('configuration_data.set', _CONF_DATA_SET_KWS)
def set_method(self, args: T.Tuple[str, T.Union[str, int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None:
self.__check_used()
self.conf_data.values[args[0]] = (args[1], kwargs['description'])

@typed_pos_args('configuration_data.set_quoted', str, str)
@typed_kwargs('configuration_data.set_quoted', _CONF_DATA_SET_KWS)
def set_quoted_method(self, args: T.Tuple[str, str], kwargs: 'kwargs.ConfigurationDataSet') -> None:
self.__check_used()
escaped_val = '\\"'.join(args[1].split('"'))
self.conf_data.values[args[0]] = (f'"{escaped_val}"', kwargs['description'])

@typed_pos_args('configuration_data.set10', str, (int, bool))
@typed_kwargs('configuration_data.set10', _CONF_DATA_SET_KWS)
def set10_method(self, args: T.Tuple[str, T.Union[int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None:
self.__check_used()
self.conf_data.values[args[0]] = (int(args[1]), kwargs['description'])

@typed_pos_args('configuration_data.has', (str, int, bool))
@noKwargs
Expand Down
5 changes: 5 additions & 0 deletions mesonbuild/interpreter/kwargs.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,8 @@ class DependencyGetVariable(TypedDict):
internal: T.Optional[str]
default_value: T.Optional[str]
pkgconfig_define: T.List[str]


class ConfigurationDataSet(TypedDict):

description: T.Optional[str]
3 changes: 0 additions & 3 deletions test cases/common/14 configure file/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,6 @@ configure_file(

test('configure-file', test_file)

cdata = configuration_data()
cdata.set('invalid_value', ['array'])

# Dictionaries

cdata = configuration_data({
Expand Down
8 changes: 1 addition & 7 deletions test cases/common/187 args flattening/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,6 @@ assert(arr == ['bar', 'baz'], 'get_variable with array fallback is broken')
set_variable('arr', ['bar', 'baz'])
assert(arr == ['bar', 'baz'], 'set_variable(array) is broken')

conf = configuration_data()
conf.set('foo', ['bar', 'baz'])
assert(conf.get('foo') == ['bar', 'baz'], 'configuration_data.set(array) is broken')

arr = conf.get('does-not-exist', ['bar', 'baz'])
assert(arr == ['bar', 'baz'], 'configuration_data.get with array fallback is broken')

arr = meson.get_cross_property('does-not-exist', ['bar', 'baz'])
assert(arr == ['bar', 'baz'], 'meson.get_cross_property with array fallback is broken')

Expand All @@ -27,5 +20,6 @@ assert(arr == ['bar', 'baz'], 'meson.get_external_property native:false with arr

# Test deprecated behaviour

conf = configuration_data()
conf.set(['foo', 'bar'])
message(conf.get('foo'))
1 change: 0 additions & 1 deletion unittests/allplatformstests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2306,7 +2306,6 @@ def test_configure_file_warnings(self):
self.assertEqual(f.read().strip(), b'/* #undef FOO_BAR */')
with open(os.path.join(self.builddir, 'nosubst-nocopy2.txt'), 'rb') as f:
self.assertEqual(f.read().strip(), b'')
self.assertRegex(out, r"DEPRECATION:.*\['array'\] is invalid.*dict")

def test_dirs(self):
with tempfile.TemporaryDirectory() as containing:
Expand Down

0 comments on commit 5745256

Please sign in to comment.