Bug 1296530 - Move more things in the new DependsFunction and add a repr() for it. r?chmanchester
--- a/build/moz.configure/util.configure
+++ b/build/moz.configure/util.configure
@@ -355,17 +355,17 @@ never = dependable(False)
# def option(value)
# return namespace(foo=value)
# set_config('FOO', delayed_getattr(option, 'foo')
@template
@imports('__sandbox__')
def delayed_getattr(func, key):
deps = __sandbox__._depends.get(func, ())
if deps:
- deps = deps.dependencies
+ deps = deps.sandboxed_dependencies
def result(value, _=None):
# The @depends function we're being passed may have returned
# None, or an object that simply doesn't have the wanted key.
# In that case, just return None.
return getattr(value, key, None)
# Automatically add a dependency on --help when the given @depends
--- a/python/mozbuild/mozbuild/configure/__init__.py
+++ b/python/mozbuild/mozbuild/configure/__init__.py
@@ -45,25 +45,43 @@ class ConfigureError(Exception):
class SandboxDependsFunction(object):
'''Sandbox-visible representation of @depends functions.'''
def __call__(self, *arg, **kwargs):
raise ConfigureError('The `%s` function may not be called'
% self.__name__)
class DependsFunction(object):
- __slots__ = ('func', 'dependencies')
- def __init__(self, func, dependencies):
+ __slots__ = ('func', 'dependencies', 'sandboxed')
+ def __init__(self, sandbox, func, dependencies):
+ assert isinstance(sandbox, ConfigureSandbox)
self.func = func
self.dependencies = dependencies
+ self.sandboxed = wraps(func)(SandboxDependsFunction())
+ sandbox._depends[self.sandboxed] = self
@property
def name(self):
return self.func.__name__
+ @property
+ def sandboxed_dependencies(self):
+ return [
+ d.sandboxed if isinstance(d, DependsFunction) else d
+ for d in self.dependencies
+ ]
+
+ def __repr__(self):
+ return '<%s.%s %s(%s)>' % (
+ self.__class__.__module__,
+ self.__class__.__name__,
+ self.name,
+ ', '.join(repr(d) for d in self.dependencies),
+ )
+
class SandboxedGlobal(dict):
'''Identifiable dict type for use as function global'''
def forbidden_import(*args, **kwargs):
raise ImportError('Importing modules is forbidden')
@@ -304,43 +322,45 @@ class ConfigureSandbox(dict):
if need_help_dependency and self._help_option not in f.dependencies:
raise ConfigureError("Missing @depends for `%s`: '--help'" %
f.name)
return self._value_for(arg)
return arg
def _value_for(self, obj):
if isinstance(obj, SandboxDependsFunction):
+ assert obj in self._depends
+ return self._value_for_depends(self._depends[obj])
+
+ elif isinstance(obj, DependsFunction):
return self._value_for_depends(obj)
elif isinstance(obj, Option):
return self._value_for_option(obj)
assert False
@memoize
def _value_for_depends(self, obj):
- assert obj in self._depends
- f = self._depends[obj]
- assert not inspect.isgeneratorfunction(f.func)
- with_help = self._help_option in f.dependencies
+ assert not inspect.isgeneratorfunction(obj.func)
+ with_help = self._help_option in obj.dependencies
if with_help:
- for arg in f.dependencies:
- if isinstance(arg, SandboxDependsFunction):
- if self._help_option not in self._depends[arg].dependencies:
+ for arg in obj.dependencies:
+ if isinstance(arg, DependsFunction):
+ if self._help_option not in arg.dependencies:
raise ConfigureError(
"`%s` depends on '--help' and `%s`. "
"`%s` must depend on '--help'"
- % (f.name, arg.__name__, arg.__name__))
+ % (obj.name, arg.name, arg.name))
elif self._help:
raise ConfigureError("Missing @depends for `%s`: '--help'" %
- f.name)
+ obj.name)
- resolved_args = [self._value_for(d) for d in f.dependencies]
- return f.func(*resolved_args)
+ 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):
continue
self._implied_options.remove(implied_option)
@@ -440,40 +460,40 @@ class ConfigureSandbox(dict):
raise ConfigureError("'%s' is not a known option. "
"Maybe it's declared too late?"
% arg)
arg = self._options[name]
self._seen.add(arg)
dependencies.append(arg)
elif isinstance(arg, SandboxDependsFunction):
assert arg in self._depends
+ arg = self._depends[arg]
dependencies.append(arg)
else:
raise TypeError(
"Cannot use object of type '%s' as argument to @depends"
% type(arg).__name__)
dependencies = tuple(dependencies)
def decorator(func):
if inspect.isgeneratorfunction(func):
raise ConfigureError(
'Cannot decorate generator functions with @depends')
func, glob = self._prepare_function(func)
- dummy = wraps(func)(SandboxDependsFunction())
- self._depends[dummy] = DependsFunction(func, dependencies)
+ depends = DependsFunction(self, func, dependencies)
# 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(dummy)
+ self._value_for(depends)
elif not self._help:
- self._execution_queue.append((self._value_for, (dummy,)))
+ self._execution_queue.append((self._value_for, (depends,)))
- return dummy
+ return depends.sandboxed
return decorator
def include_impl(self, what):
'''Implementation of include().
Allows to include external files for execution in the sandbox.
It is possible to use a @depends function as argument, in which case
the result of the function is the file name to include. This latter