Bug 1257823 - Keep track of the dependencies of @depends functions
@depends functions are declared like the following:
@depends('--option', other_function, '--other-option', ...)
def ...
To simplify some of the processing related to those arguments it's
passed, keep a tuple of Option and DummyFunction objects corresponding
to those arguments.
--- a/python/mozbuild/mozbuild/configure/__init__.py
+++ b/python/mozbuild/mozbuild/configure/__init__.py
@@ -221,20 +221,20 @@ class ConfigureSandbox(dict):
raise KeyError('Cannot assign `%s` because it is neither a '
'@depends nor a @template' % key)
return super(ConfigureSandbox, self).__setitem__(key, value)
def _resolve(self, arg, need_help_dependency=True):
if isinstance(arg, DummyFunction):
assert arg in self._depends
- func = self._depends[arg]
+ func, deps = self._depends[arg]
assert not inspect.isgeneratorfunction(func)
assert func in self._results
- if need_help_dependency and not func.with_help:
+ if need_help_dependency and self._help_option not in deps:
raise ConfigureError("Missing @depends for `%s`: '--help'" %
func.__name__)
result = self._results[func]
return result
return arg
def option_impl(self, *args, **kwargs):
'''Implementation of option()
@@ -293,83 +293,84 @@ class ConfigureSandbox(dict):
for its execution. This different global namespace exposes a limited
set of functions from os.path, and one additional functions:
`imply_option`. It allows to inject additional options as if they had
been passed on the command line.
'''
if not args:
raise ConfigureError('@depends needs at least one argument')
- with_help = False
resolved_args = []
+ dependencies = []
for arg in args:
if isinstance(arg, types.StringTypes):
prefix, name, values = Option.split_option(arg)
if values != ():
raise ConfigureError("Option must not contain an '='")
if name not in self._options:
raise ConfigureError("'%s' is not a known option. "
"Maybe it's declared too late?"
% arg)
arg = self._options[name]
if arg == self._help_option:
with_help = True
self._seen.add(arg)
+ dependencies.append(arg)
assert arg in self._option_values or self._help
resolved_arg = self._option_values.get(arg)
elif isinstance(arg, DummyFunction):
assert arg in self._depends
- arg = self._depends[arg]
+ dependencies.append(arg)
+ arg, _ = self._depends[arg]
resolved_arg = self._results.get(arg)
else:
raise TypeError(
"Cannot use object of type '%s' as argument to @depends"
% type(arg))
resolved_args.append(resolved_arg)
+ dependencies = tuple(dependencies)
def decorator(func):
if inspect.isgeneratorfunction(func):
raise ConfigureError(
'Cannot decorate generator functions with @depends')
func, glob = self._prepare_function(func)
result = DependsOutput()
glob.update(
imply_option=result.imply_option,
)
dummy = wraps(func)(DummyFunction())
- self._depends[dummy] = func
- func.with_help = with_help
+ self._depends[dummy] = func, dependencies
+ with_help = self._help_option in dependencies
if with_help:
for arg in args:
if (isinstance(arg, DummyFunction) and
- not self._depends[arg].with_help):
+ self._help_option not in self._depends[arg][1]):
raise ConfigureError(
"`%s` depends on '--help' and `%s`. "
"`%s` must depend on '--help'"
% (func.__name__, arg.__name__, arg.__name__))
if self._help and not with_help:
return dummy
self._results[func] = func(*resolved_args)
for option, reason in result.implied_options:
self._helper.add(option, 'implied')
if not reason:
deps = []
- for name, value in zip(args, resolved_args):
- if not isinstance(value, OptionValue):
+ for arg in dependencies:
+ if not isinstance(arg, Option):
raise ConfigureError(
"Cannot infer what implied '%s'" % option)
- if name == '--help':
+ if arg == self._help_option:
continue
- prefix, opt, values = Option.split_option(name)
- deps.append(value.format(
- self._raw_options.get(self._options[opt])
- or name))
+ deps.append(self._raw_options.get(arg) or
+ self.arg.option)
if len(deps) != 1:
raise ConfigureError(
"Cannot infer what implied '%s'" % option)
reason = deps[0]
self._implied_options[option] = func, reason
return dummy