summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Schwartz <eschwartz93@gmail.com>2024-07-05 13:52:40 -0400
committerEli Schwartz <eschwartz93@gmail.com>2024-07-05 13:52:40 -0400
commitf2112d0baa379e01d7ce8a961005f5b7c102d9a9 (patch)
treedd3ab36af18e2c78a756bcf81be15a780ed2cb6c
parent1ca002a78a48faaf74aa61fcd28b4f2fa5937b47 (diff)
downloadmeson-f2112d0baa379e01d7ce8a961005f5b7c102d9a9.tar.gz
Revert "Clarify mutable objects usage"
This reverts commit 9f02d0a3e5a5ffc82256391c244b1af38e41ef78. It turns out that this does introduce a behavioral change in existing users of ConfigurationData, which it wasn't supposed to (it was supposed to preserve behavior there, and add a new *warning* for EnvironmentVariables). This breaks projects such as pulseaudio, libvirt, and probably more. Roll back the change and try again after 1.5.0 is released. Fixes: #13372
-rw-r--r--docs/markdown/Configuration.md2
-rw-r--r--docs/yaml/objects/cfg_data.yaml12
-rw-r--r--docs/yaml/objects/env.yaml13
-rw-r--r--mesonbuild/interpreter/interpreterobjects.py26
-rw-r--r--mesonbuild/interpreterbase/_unholder.py4
-rw-r--r--mesonbuild/interpreterbase/baseobjects.py21
-rwxr-xr-xtest cases/common/113 interpreter copy mutable var on assignment/check_env.py7
-rw-r--r--test cases/common/113 interpreter copy mutable var on assignment/meson.build34
-rw-r--r--test cases/failing/70 configuration immutable/input0
-rw-r--r--test cases/failing/70 configuration immutable/meson.build12
-rw-r--r--test cases/failing/70 configuration immutable/test.json7
11 files changed, 36 insertions, 102 deletions
diff --git a/docs/markdown/Configuration.md b/docs/markdown/Configuration.md
index b5875e55e..48f071e6c 100644
--- a/docs/markdown/Configuration.md
+++ b/docs/markdown/Configuration.md
@@ -39,7 +39,7 @@ use a single `configuration_data` object as many times as you like,
but it becomes immutable after being passed to the `configure_file`
function. That is, after it has been used once to generate output the
`set` function becomes unusable and trying to call it causes an error.
-*Since 1.5.0* Copy of immutable `configuration_data` is however mutable.
+Copy of immutable `configuration_data` is still immutable.
For more complex configuration file generation Meson provides a second
form. To use it, put a line like this in your configuration file.
diff --git a/docs/yaml/objects/cfg_data.yaml b/docs/yaml/objects/cfg_data.yaml
index 069cadbf6..03abb1709 100644
--- a/docs/yaml/objects/cfg_data.yaml
+++ b/docs/yaml/objects/cfg_data.yaml
@@ -1,14 +1,10 @@
name: cfg_data
long_name: Configuration data object
description: |
- This object encapsulates configuration values to be used for generating
- configuration files. A more in-depth description can be found in the
- [the configuration page](Configuration.md).
-
- This object becomes immutable after first use. This means that
- calling set() or merge_from() will cause an error if this object has
- already been used in any function arguments. However, assignment creates a
- mutable copy.
+ This object encapsulates
+ configuration values to be used for generating configuration files. A
+ more in-depth description can be found in the [the configuration wiki
+ page](Configuration.md).
methods:
- name: set
diff --git a/docs/yaml/objects/env.yaml b/docs/yaml/objects/env.yaml
index 3b2e2a851..714da4fe4 100644
--- a/docs/yaml/objects/env.yaml
+++ b/docs/yaml/objects/env.yaml
@@ -9,11 +9,6 @@ description: |
on the same `varname`. Earlier Meson versions would warn and only the last
operation took effect.
- *Since 1.5.0* This object becomes immutable after first use. This means that
- calling append(), prepend() or set() will cause a deprecation warning if this
- object has already been used in any function arguments. However, assignment
- creates a mutable copy.
-
example: |
```meson
env = environment()
@@ -23,14 +18,6 @@ example: |
env.append('MY_PATH', '2')
env.append('MY_PATH', '3')
env.prepend('MY_PATH', '0')
-
- # Deprecated since 1.5.0
- run_command('script.py', env: env)
- env.append('MY_PATH', '4')
-
- # Allowed and only env2 is modified
- env2 = env
- env2.append('MY_PATH', '4')
```
methods:
diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py
index 32f05bafb..d5c1efaa8 100644
--- a/mesonbuild/interpreter/interpreterobjects.py
+++ b/mesonbuild/interpreter/interpreterobjects.py
@@ -284,7 +284,6 @@ class EnvironmentVariablesHolder(ObjectHolder[mesonlib.EnvironmentVariables], Mu
def __init__(self, obj: mesonlib.EnvironmentVariables, interpreter: 'Interpreter'):
super().__init__(obj, interpreter)
- MutableInterpreterObject.__init__(self)
self.methods.update({'set': self.set_method,
'unset': self.unset_method,
'append': self.append_method,
@@ -309,14 +308,12 @@ class EnvironmentVariablesHolder(ObjectHolder[mesonlib.EnvironmentVariables], Mu
@typed_kwargs('environment.set', ENV_SEPARATOR_KW)
def set_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None:
name, values = args
- self.check_used(self.interpreter, fatal=False)
self.held_object.set(name, values, kwargs['separator'])
@FeatureNew('environment.unset', '1.4.0')
@typed_pos_args('environment.unset', str)
@noKwargs
def unset_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> None:
- self.check_used(self.interpreter, fatal=False)
self.held_object.unset(args[0])
@typed_pos_args('environment.append', str, varargs=str, min_varargs=1)
@@ -324,7 +321,6 @@ class EnvironmentVariablesHolder(ObjectHolder[mesonlib.EnvironmentVariables], Mu
def append_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None:
name, values = args
self.warn_if_has_name(name)
- self.check_used(self.interpreter, fatal=False)
self.held_object.append(name, values, kwargs['separator'])
@typed_pos_args('environment.prepend', str, varargs=str, min_varargs=1)
@@ -332,7 +328,6 @@ class EnvironmentVariablesHolder(ObjectHolder[mesonlib.EnvironmentVariables], Mu
def prepend_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None:
name, values = args
self.warn_if_has_name(name)
- self.check_used(self.interpreter, fatal=False)
self.held_object.prepend(name, values, kwargs['separator'])
@@ -343,7 +338,6 @@ class ConfigurationDataHolder(ObjectHolder[build.ConfigurationData], MutableInte
def __init__(self, obj: build.ConfigurationData, interpreter: 'Interpreter'):
super().__init__(obj, interpreter)
- MutableInterpreterObject.__init__(self)
self.methods.update({'set': self.set_method,
'set10': self.set10_method,
'set_quoted': self.set_quoted_method,
@@ -355,31 +349,32 @@ class ConfigurationDataHolder(ObjectHolder[build.ConfigurationData], MutableInte
})
def __deepcopy__(self, memo: T.Dict) -> 'ConfigurationDataHolder':
- obj = ConfigurationDataHolder(copy.deepcopy(self.held_object), self.interpreter)
+ return ConfigurationDataHolder(copy.deepcopy(self.held_object), self.interpreter)
+
+ def is_used(self) -> bool:
+ return self.held_object.used
+
+ def __check_used(self) -> None:
if self.is_used():
- # Copies of used ConfigurationData used to be immutable. It is now
- # allowed but we need this flag to print a FeatureNew warning if
- # that happens.
- obj.mutable_feature_new = True
- return obj
+ raise InterpreterException("Can not set values on configuration object that has been used.")
@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.interpreter)
+ self.__check_used()
self.held_object.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(self.interpreter)
+ self.__check_used()
escaped_val = '\\"'.join(args[1].split('"'))
self.held_object.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.interpreter)
+ self.__check_used()
# bool is a subclass of int, so we need to check for bool explicitly.
# We already have typed_pos_args checking that this is either a bool or
# an int.
@@ -442,7 +437,6 @@ class ConfigurationDataHolder(ObjectHolder[build.ConfigurationData], MutableInte
@noKwargs
def merge_from_method(self, args: T.Tuple[build.ConfigurationData], kwargs: TYPE_kwargs) -> None:
from_object = args[0]
- self.check_used(self.interpreter)
self.held_object.values.update(from_object.values)
diff --git a/mesonbuild/interpreterbase/_unholder.py b/mesonbuild/interpreterbase/_unholder.py
index e32b77fc7..c62aafe8e 100644
--- a/mesonbuild/interpreterbase/_unholder.py
+++ b/mesonbuild/interpreterbase/_unholder.py
@@ -5,7 +5,7 @@ from __future__ import annotations
import typing as T
-from .baseobjects import InterpreterObject, MesonInterpreterObject, ObjectHolder, HoldableTypes, MutableInterpreterObject
+from .baseobjects import InterpreterObject, MesonInterpreterObject, ObjectHolder, HoldableTypes
from .exceptions import InvalidArguments
from ..mesonlib import HoldableObject, MesonBugException
@@ -13,8 +13,6 @@ if T.TYPE_CHECKING:
from .baseobjects import TYPE_var
def _unholder(obj: InterpreterObject) -> TYPE_var:
- if isinstance(obj, MutableInterpreterObject):
- obj.mark_used()
if isinstance(obj, ObjectHolder):
assert isinstance(obj.held_object, HoldableTypes)
return obj.held_object
diff --git a/mesonbuild/interpreterbase/baseobjects.py b/mesonbuild/interpreterbase/baseobjects.py
index c6864a478..9a119a98a 100644
--- a/mesonbuild/interpreterbase/baseobjects.py
+++ b/mesonbuild/interpreterbase/baseobjects.py
@@ -120,27 +120,6 @@ class MesonInterpreterObject(InterpreterObject):
class MutableInterpreterObject:
''' Dummy class to mark the object type as mutable '''
- def __init__(self) -> None:
- self.used = False
- self.mutable_feature_new = False
-
- def mark_used(self) -> None:
- self.used = True
-
- def is_used(self) -> bool:
- return self.used
-
- def check_used(self, interpreter: Interpreter, fatal: bool = True) -> None:
- from .decorators import FeatureDeprecated, FeatureNew
- if self.is_used():
- if fatal:
- raise InvalidArguments('Can not modify object after it has been used.')
- FeatureDeprecated.single_use('Modify object after it has been used', '1.5.0',
- interpreter.subproject, location=interpreter.current_node)
- elif self.mutable_feature_new:
- FeatureNew.single_use('Modify a copy of an immutable object', '1.5.0',
- interpreter.subproject, location=interpreter.current_node)
- self.mutable_feature_new = False
HoldableTypes = (HoldableObject, int, bool, str, list, dict)
TYPE_HoldableTypes = T.Union[TYPE_elementary, HoldableObject]
diff --git a/test cases/common/113 interpreter copy mutable var on assignment/check_env.py b/test cases/common/113 interpreter copy mutable var on assignment/check_env.py
deleted file mode 100755
index 034d29243..000000000
--- a/test cases/common/113 interpreter copy mutable var on assignment/check_env.py
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env python3
-
-import os
-import sys
-
-if sys.argv[1] not in os.environ:
- exit(42)
diff --git a/test cases/common/113 interpreter copy mutable var on assignment/meson.build b/test cases/common/113 interpreter copy mutable var on assignment/meson.build
index 3d4f3b039..d414bfc74 100644
--- a/test cases/common/113 interpreter copy mutable var on assignment/meson.build
+++ b/test cases/common/113 interpreter copy mutable var on assignment/meson.build
@@ -1,4 +1,4 @@
-project('foo', meson_version: '>=1.5')
+project('foo')
a = configuration_data()
a.set('HELLO', 1)
@@ -10,15 +10,6 @@ assert(b.has('HELLO'), 'Original config data should be set on copy')
configure_file(output : 'b.h', configuration : b)
-testcase expect_error('Can not modify object after it has been used.')
- b.set('WORLD', 1)
-endtestcase
-
-# A copy of immutable object is mutable. This should print FeatureNew warning
-# if meson_version is lower than 1.5.
-c = b
-c.set('WORLD', 1)
-
# This should still work, as we didn't use the original above but a copy!
a.set('WORLD', 1)
@@ -26,26 +17,3 @@ assert(a.has('WORLD'), 'New config data should have been set')
assert(not b.has('WORLD'), 'New config data set should not affect var copied earlier')
configure_file(output : 'a.h', configuration : a)
-
-env1 = environment()
-env1.set('FOO', '1')
-env2 = env1
-env1.set('BAR', '1')
-
-# FOO should be in env1 and env2
-run_command('check_env.py', 'FOO', env: env1, check: true)
-run_command('check_env.py', 'FOO', env: env2, check: true)
-
-# BAR should be only in env1
-run_command('check_env.py', 'BAR', env: env1, check: true)
-assert(run_command('check_env.py', 'BAR', env: env2, check: false).returncode() == 42)
-
-# This should print deprecation warning but still work
-env1.set('PLOP', '1')
-run_command('check_env.py', 'PLOP', env: env1, check: true)
-
-# A copy of used env should be mutable and not print warning
-env3 = env1
-env3.set('BAZ', '1')
-run_command('check_env.py', 'PLOP', env: env3, check: true)
-run_command('check_env.py', 'BAZ', env: env3, check: true)
diff --git a/test cases/failing/70 configuration immutable/input b/test cases/failing/70 configuration immutable/input
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/test cases/failing/70 configuration immutable/input
diff --git a/test cases/failing/70 configuration immutable/meson.build b/test cases/failing/70 configuration immutable/meson.build
new file mode 100644
index 000000000..b6cac4126
--- /dev/null
+++ b/test cases/failing/70 configuration immutable/meson.build
@@ -0,0 +1,12 @@
+project('configuration_data is immutable')
+
+a = configuration_data()
+
+configure_file(
+ configuration : a,
+ input : 'input',
+ output : 'output',
+)
+
+still_immutable = a
+still_immutable.set('hello', 'world')
diff --git a/test cases/failing/70 configuration immutable/test.json b/test cases/failing/70 configuration immutable/test.json
new file mode 100644
index 000000000..fc735fa38
--- /dev/null
+++ b/test cases/failing/70 configuration immutable/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/70 configuration immutable/meson.build:12:16: ERROR: Can not set values on configuration object that has been used."
+ }
+ ]
+}