Bug 1296530 - Add a `when` argument to @depends(). r?chmanchester
--- a/python/mozbuild/mozbuild/configure/__init__.py
+++ b/python/mozbuild/mozbuild/configure/__init__.py
@@ -160,16 +160,19 @@ class ConfigureSandbox(dict):
self._implied_options = []
# Store all results from _prepare_function
self._prepared_functions = set()
# Queue of functions to execute, with their arguments
self._execution_queue = []
+ # Store the `when`s associated to some options/depends.
+ self._conditions = {}
+
self._helper = CommandLineHelper(environ, argv)
assert isinstance(config, dict)
self._config = config
if logger is None:
logger = moz_logger = logging.getLogger('moz.configure')
logger.setLevel(logging.DEBUG)
@@ -348,16 +351,20 @@ class ConfigureSandbox(dict):
% (obj.name, arg.name, arg.name))
elif self._help or need_help_dependency:
raise ConfigureError("Missing @depends for `%s`: '--help'" %
obj.name)
return self._value_for_depends_real(obj)
@memoize
def _value_for_depends_real(self, obj):
+ when = self._conditions.get(obj)
+ if when and not self._value_for(when):
+ return None
+
resolved_args = [self._value_for(d) for d in obj.dependencies]
return obj.func(*resolved_args)
@memoize
def _value_for_option(self, option):
implied = {}
for implied_option in self._implied_options[:]:
if implied_option.name not in (option.name, option.env):
@@ -444,17 +451,17 @@ class ConfigureSandbox(dict):
if option.env:
self._options[option.env] = option
if self._help:
self._help.add(option)
return option
- def depends_impl(self, *args):
+ def depends_impl(self, *args, **kwargs):
'''Implementation of @depends()
This function is a decorator. It returns a function that subsequently
takes a function and returns a dummy function. The dummy function
identifies the actual function for the sandbox, while preventing
further function calls from within the sandbox.
@depends() takes a variable number of option strings or dummy function
references. The decorated function is called as soon as the decorator
@@ -465,24 +472,36 @@ class ConfigureSandbox(dict):
The decorated function is altered to use a different global namespace
for its execution. This different global namespace exposes a limited
set of functions from os.path.
'''
if not args:
raise ConfigureError('@depends needs at least one argument')
+ for k in kwargs:
+ if k != 'when':
+ raise TypeError(
+ "depends_impl() got an unexpected keyword argument '%s'"
+ % k)
+
+ when = kwargs.get('when')
+ if when is not None:
+ when = self._dependency(when, '@depends', 'when')
+
dependencies = tuple(self._dependency(arg, '@depends') for arg in args)
def decorator(func):
if inspect.isgeneratorfunction(func):
raise ConfigureError(
'Cannot decorate generator functions with @depends')
func, glob = self._prepare_function(func)
depends = DependsFunction(self, func, dependencies)
+ if when:
+ self._conditions[depends] = when
# Only @depends functions with a dependency on '--help' are
# executed immediately. Everything else is queued for later
# execution.
if self._help_option in dependencies:
self._value_for(depends)
elif not self._help:
self._execution_queue.append((self._value_for, (depends,)))
--- a/python/mozbuild/mozbuild/test/configure/test_configure.py
+++ b/python/mozbuild/mozbuild/test/configure/test_configure.py
@@ -873,16 +873,55 @@ class TestConfigure(unittest.TestCase):
def foo(_):
return
'''):
self.get_config()
self.assertEquals(e.exception.message,
"depends_impl() got an unexpected keyword argument 'foo'")
+ def test_depends_when(self):
+ with self.moz_configure('''
+ @depends('--help')
+ def always(_):
+ return True
+ @depends('--help')
+ def never(_):
+ return False
+
+ @depends('--help', when=always)
+ def foo(_):
+ return 'foo'
+
+ set_config('FOO', foo)
+
+ @depends('--help', when=never)
+ def bar(_):
+ return 'bar'
+
+ set_config('BAR', bar)
+
+ option('--with-qux', help='qux')
+ @depends('--help', when='--with-qux')
+ def qux(_):
+ return 'qux'
+
+ set_config('QUX', qux)
+ '''):
+ config = self.get_config()
+ self.assertEquals(config, {
+ 'FOO': 'foo',
+ })
+
+ config = self.get_config(['--with-qux'])
+ self.assertEquals(config, {
+ 'FOO': 'foo',
+ 'QUX': 'qux',
+ })
+
def test_imports_failures(self):
with self.assertRaises(ConfigureError) as e:
with self.moz_configure('''
@imports('os')
@template
def foo(value):
return value
'''):