environment(): Allow stacking append() and prepend() (#8547)

* environment(): Allow stacking append() and prepend()

* Update docs/markdown/Reference-manual.md

Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>

Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
pull/8573/head
Xavier Claessens 4 years ago committed by GitHub
parent de9df5128c
commit 1be13710ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      docs/markdown/Reference-manual.md
  2. 16
      docs/markdown/snippets/environment.md
  3. 2
      mesonbuild/build.py
  4. 14
      mesonbuild/interpreter.py
  5. 11
      run_unittests.py
  6. 6
      test cases/common/34 run program/check-env.py
  7. 6
      test cases/common/34 run program/meson.build
  8. 12
      test cases/unit/63 test env does not stack/meson.build
  9. 9
      test cases/unit/63 test env does not stack/script.py

@ -2752,8 +2752,19 @@ tests and other functions. It has the following methods.
joined by the separator, e.g. `env.set('FOO', 'BAR'),` sets envvar
`FOO` to value `BAR`. See `append()` above for how separators work.
**Note:** All these methods overwrite the previously-defined value(s)
if called twice with the same `varname`.
*Since 0.58.0* `append()` and `prepend()` methods can be called multiple times
on the same `varname`. Earlier Meson versions would warn and only the last
operation took effect.
```meson
env = environment()
# MY_PATH will be '0:1:2:3'
env.set('MY_PATH', '1')
env.append('MY_PATH', '2')
env.append('MY_PATH', '3')
env.prepend('MY_PATH', '0')
```
### `external library` object

@ -0,0 +1,16 @@
## Multiple append() and prepend() in `environment()` object
`append()` and `prepend()` methods can now be called multiple times
on the same `varname`. Earlier Meson versions would warn and only the last
opperation was taking effect.
```meson
env = environment()
# MY_PATH will be '0:1:2:3'
env.set('MY_PATH', '1')
env.append('MY_PATH', '2')
env.append('MY_PATH', '3')
env.prepend('MY_PATH', '0')
```

@ -433,7 +433,7 @@ class EnvironmentVariables:
def get_env(self, full_env: T.Dict[str, str]) -> T.Dict[str, str]:
env = full_env.copy()
for method, name, values, separator in self.envvars:
env[name] = method(full_env, name, values, separator)
env[name] = method(env, name, values, separator)
return env
class Target:

@ -241,9 +241,9 @@ class ConfigureFileHolder(InterpreterObject, ObjectHolder[build.ConfigureFile]):
class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder[build.EnvironmentVariables]):
def __init__(self, initial_values=None):
def __init__(self, initial_values=None, subproject: str = ''):
MutableInterpreterObject.__init__(self)
ObjectHolder.__init__(self, build.EnvironmentVariables())
ObjectHolder.__init__(self, build.EnvironmentVariables(), subproject)
self.methods.update({'set': self.set_method,
'append': self.append_method,
'prepend': self.prepend_method,
@ -274,12 +274,10 @@ class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder[build.En
return separator
def warn_if_has_name(self, name: str) -> None:
# Warn when someone tries to use append() or prepend() on an env var
# which already has an operation set on it. People seem to think that
# multiple append/prepend operations stack, but they don't.
# Multiple append/prepend operations was not supported until 0.58.0.
if self.held_object.has_name(name):
mlog.warning(f'Overriding previous value of environment variable {name!r} with a new one',
location=self.current_node)
m = f'Overriding previous value of environment variable {name!r} with a new one'
FeatureNew('0.58.0', m).use(self.subproject)
@stringArgs
@permittedKwargs({'separator'})
@ -4772,7 +4770,7 @@ This warning will become a hard error in a future Meson release.
raise InterpreterException('environment first argument must be a dictionary or a list')
else:
initial_values = {}
return EnvironmentVariablesHolder(initial_values)
return EnvironmentVariablesHolder(initial_values, self.subproject)
@stringArgs
@noKwargs

@ -2525,17 +2525,6 @@ class AllPlatformTests(BasePlatformTests):
self.build()
self.run_tests()
def test_env_ops_dont_stack(self):
'''
Test that env ops prepend/append do not stack, and that this usage issues a warning
'''
testdir = os.path.join(self.unit_test_dir, '63 test env does not stack')
out = self.init(testdir)
self.assertRegex(out, r'WARNING: Overriding.*TEST_VAR_APPEND')
self.assertRegex(out, r'WARNING: Overriding.*TEST_VAR_PREPEND')
self.assertNotRegex(out, r'WARNING: Overriding.*TEST_VAR_SET')
self.run_tests()
def test_testrepeat(self):
testdir = os.path.join(self.common_test_dir, '207 tap tests')
self.init(testdir)

@ -0,0 +1,6 @@
#!/usr/bin/env python3
import os
assert os.environ['MY_PATH'] == os.pathsep.join(['0', '1', '2'])

@ -77,3 +77,9 @@ if dd.found()
assert(ret.returncode() == 0, 'failed to run dd: ' + ret.stderr())
assert(ret.stdout() == '', 'stdout is "@0@" instead of empty'.format(ret.stdout()))
endif
env = environment()
env.append('MY_PATH', '1')
env.append('MY_PATH', '2')
env.prepend('MY_PATH', '0')
run_command('check-env.py', env: env, check: true)

@ -1,12 +0,0 @@
project('test env var stacking')
testenv = environment()
testenv.set('TEST_VAR_SET', 'some-value')
testenv.set('TEST_VAR_APPEND', 'some-value')
testenv.set('TEST_VAR_PREPEND', 'some-value')
testenv.append('TEST_VAR_APPEND', 'another-value-append', separator: ':')
testenv.prepend('TEST_VAR_PREPEND', 'another-value-prepend', separator: ':')
testenv.set('TEST_VAR_SET', 'another-value-set')
test('check env', find_program('script.py'), env: testenv)

@ -1,9 +0,0 @@
#!/usr/bin/env python3
import os
for name in ('append', 'prepend', 'set'):
envname = 'TEST_VAR_' + name.upper()
value = 'another-value-' + name
envvalue = os.environ[envname]
assert (envvalue == value), (name, envvalue)
Loading…
Cancel
Save