environment: Support taking values from dict

Related to #5955.
pull/5702/head
Marc-André Lureau 6 years ago committed by Xavier Claessens
parent 18897b6afd
commit a65d5801f3
  1. 9
      docs/markdown/External-commands.md
  2. 18
      docs/markdown/Reference-manual.md
  3. 8
      docs/markdown/snippets/env_dict.md
  4. 45
      mesonbuild/interpreter.py
  5. 10
      test cases/unit/69 test env value/meson.build
  6. 6
      test cases/unit/69 test env value/test.py

@ -16,7 +16,14 @@ output = r.stdout().strip()
errortxt = r.stderr().strip() errortxt = r.stderr().strip()
``` ```
Additionally, since 0.50.0, you can pass the command [`environment`](Reference-manual.html#environment-object) object: Since 0.52.0, you can pass the command environment as a dictionary:
```meson
run_command('command', 'arg1', 'arg2', env: {'FOO': 'bar'})
```
Since 0.50.0, you can also pass the command
[`environment`](Reference-manual.html#environment-object) object:
```meson ```meson
env = environment() env = environment()

@ -104,7 +104,10 @@ Add a custom test setup that can be used to run the tests with a
custom setup, for example under Valgrind. The keyword arguments are custom setup, for example under Valgrind. The keyword arguments are
the following: the following:
- `env` an [environment object](#environment-object) to use a custom environment - `env` environment variables to set, such as `['NAME1=value1',
'NAME2=value2']`, or an [`environment()`
object](#environment-object) which allows more sophisticated
environment juggling. *Since 0.52.0* a dictionary is also accepted.
- `exe_wrapper` a list containing the wrapper command or script followed by the arguments to it - `exe_wrapper` a list containing the wrapper command or script followed by the arguments to it
- `gdb` if `true`, the tests are also run under `gdb` - `gdb` if `true`, the tests are also run under `gdb`
- `timeout_multiplier` a number to multiply the test timeout with - `timeout_multiplier` a number to multiply the test timeout with
@ -491,12 +494,16 @@ Print the argument string and halts the build process.
### environment() ### environment()
``` meson ``` meson
environment_object environment() environment_object environment(...)
``` ```
Returns an empty [environment variable Returns an empty [environment variable
object](#environment-object). Added in 0.35.0. object](#environment-object). Added in 0.35.0.
Since *0.52.0* takes an optional dictionary as first argument. If
provided, each key/value pair is added into the `environment_object`
as if `set()` method was called for each of them.
### executable() ### executable()
``` meson ``` meson
@ -1256,7 +1263,10 @@ This function supports the following keyword arguments:
be checked, and the configuration will fail if it is non-zero. The default is be checked, and the configuration will fail if it is non-zero. The default is
`false`. `false`.
Since 0.47.0 Since 0.47.0
- `env` an [environment object](#environment-object) to use a custom environment - `env` environment variables to set, such as `['NAME1=value1',
'NAME2=value2']`, or an [`environment()`
object](#environment-object) which allows more sophisticated
environment juggling. *Since 0.52.0* a dictionary is also accepted.
Since 0.50.0 Since 0.50.0
See also [External commands](External-commands.md). See also [External commands](External-commands.md).
@ -1489,7 +1499,7 @@ Keyword arguments are the following:
- `env` environment variables to set, such as `['NAME1=value1', - `env` environment variables to set, such as `['NAME1=value1',
'NAME2=value2']`, or an [`environment()` 'NAME2=value2']`, or an [`environment()`
object](#environment-object) which allows more sophisticated object](#environment-object) which allows more sophisticated
environment juggling environment juggling. *Since 0.52.0* a dictionary is also accepted.
- `is_parallel` when false, specifies that no other test must be - `is_parallel` when false, specifies that no other test must be
running at the same time as this test running at the same time as this test

@ -0,0 +1,8 @@
## Support taking environment values from a dictionary
`environment()` now accepts a dictionary as first argument. If
provided, each key/value pair is added into the `environment_object`
as if `set()` method was called for each of them.
On the various functions that take an `env:` keyword argument, you may
now give a dictionary.

@ -222,13 +222,28 @@ class ConfigureFileHolder(InterpreterObject, ObjectHolder):
class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder): class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder):
def __init__(self): def __init__(self, initial_values=None):
MutableInterpreterObject.__init__(self) MutableInterpreterObject.__init__(self)
ObjectHolder.__init__(self, build.EnvironmentVariables()) ObjectHolder.__init__(self, build.EnvironmentVariables())
self.methods.update({'set': self.set_method, self.methods.update({'set': self.set_method,
'append': self.append_method, 'append': self.append_method,
'prepend': self.prepend_method, 'prepend': self.prepend_method,
}) })
if isinstance(initial_values, dict):
for k, v in initial_values.items():
self.set_method([k, v], {})
elif isinstance(initial_values, list):
for e in initial_values:
if '=' not in e:
raise InterpreterException('Env var definition must be of type key=val.')
(k, val) = e.split('=', 1)
k = k.strip()
val = val.strip()
if ' ' in k:
raise InterpreterException('Env var key must not have spaces in it.')
self.set_method([k, val], {})
elif initial_values:
raise AssertionError('Unsupported EnvironmentVariablesHolder initial_values')
def __repr__(self): def __repr__(self):
repr_str = "<{0}: {1}>" repr_str = "<{0}: {1}>"
@ -3360,19 +3375,14 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
envlist = kwargs.get('env', EnvironmentVariablesHolder()) envlist = kwargs.get('env', EnvironmentVariablesHolder())
if isinstance(envlist, EnvironmentVariablesHolder): if isinstance(envlist, EnvironmentVariablesHolder):
env = envlist.held_object env = envlist.held_object
elif isinstance(envlist, dict):
FeatureNew('environment dictionary', '0.52.0').use(self.subproject)
env = EnvironmentVariablesHolder(envlist)
env = env.held_object
else: else:
envlist = listify(envlist) envlist = listify(envlist)
# Convert from array to environment object # Convert from array to environment object
env = EnvironmentVariablesHolder() env = EnvironmentVariablesHolder(envlist)
for e in envlist:
if '=' not in e:
raise InterpreterException('Env var definition must be of type key=val.')
(k, val) = e.split('=', 1)
k = k.strip()
val = val.strip()
if ' ' in k:
raise InterpreterException('Env var key must not have spaces in it.')
env.set_method([k, val], {})
env = env.held_object env = env.held_object
return env return env
@ -3936,9 +3946,18 @@ different subdirectory.
argsdict[lang] = argsdict.get(lang, []) + args argsdict[lang] = argsdict.get(lang, []) + args
@noKwargs @noKwargs
@noPosargs @noArgsFlattening
def func_environment(self, node, args, kwargs): def func_environment(self, node, args, kwargs):
return EnvironmentVariablesHolder() if len(args) > 1:
raise InterpreterException('environment takes only one optional positional arguments')
elif len(args) == 1:
FeatureNew('environment positional arguments', '0.52.0').use(self.subproject)
initial_values = args[0]
if not isinstance(initial_values, dict) and not isinstance(initial_values, list):
raise InterpreterException('environment first argument must be a dictionary or a list')
else:
initial_values = {}
return EnvironmentVariablesHolder(initial_values)
@stringArgs @stringArgs
@noKwargs @noKwargs

@ -0,0 +1,10 @@
project('test env value')
testpy = find_program('test.py')
val = ['1', '2', '3']
foreach v: val
test('check env', testpy, args: [v], env: {'TEST_VAR': v})
endforeach
test('check env', testpy, args: ['4'], env: environment({'TEST_VAR': '4'}))
test('check env', testpy, args: ['5'], env: environment(['TEST_VAR=5']))

@ -0,0 +1,6 @@
#!/usr/bin/env python3
import os
import sys
assert(os.environ['TEST_VAR'] == sys.argv[1])
Loading…
Cancel
Save