Bug 1257823 - Keep track of the dependencies of @depends functions draft
authorMike Hommey <mh+mozilla@glandium.org>
Wed, 23 Mar 2016 11:58:57 +0900
changeset 343868 da90bf5b50866a8974585f4355bf5db15c01f2e3
parent 343867 b15636d6abe6e47cd2f00073e3b8bb65e06ae4b8
child 343869 5f3eaeacbb233c2e1c276fbe11422e35ba7540a2
push id13691
push userbmo:mh+mozilla@glandium.org
push dateWed, 23 Mar 2016 10:00:34 +0000
bugs1257823
milestone48.0a1
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.
python/mozbuild/mozbuild/configure/__init__.py
--- 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