Loading python/mozbuild/mozbuild/configure/__init__.py +27 −3 Original line number Diff line number Diff line Loading @@ -234,7 +234,7 @@ class ConfigureSandbox(dict): if (not isinstance(value, DependsFunction) and value not in self._templates and not issubclass(value, Exception)): not (inspect.isclass(value) and issubclass(value, Exception))): raise KeyError('Cannot assign `%s` because it is neither a ' '@depends nor a @template' % key) Loading Loading @@ -393,8 +393,32 @@ class ConfigureSandbox(dict): (k[:-len('_impl')], getattr(self, k)) for k in dir(self) if k.endswith('_impl') and k != 'template_impl' ) self._templates.add(template) return template # Any function argument to the template must be prepared to be sandboxed. # If the template itself returns a function (in which case, it's very # likely a decorator), that function must be prepared to be sandboxed as # well. def wrap_template(template): @wraps(template) def wrapper(*args, **kwargs): def maybe_prepare_function(obj): if inspect.isfunction(obj): func, _ = self._prepare_function(obj) return func return obj args = [maybe_prepare_function(arg) for arg in args] kwargs = {k: maybe_prepare_function(v) for k, v in kwargs.iteritems()} ret = template(*args, **kwargs) if inspect.isfunction(ret): return wrap_template(ret) return ret return wrapper wrapper = wrap_template(template) self._templates.add(wrapper) return wrapper def advanced_impl(self, func): '''Implementation of @advanced. Loading python/mozbuild/mozbuild/test/configure/data/decorators.configure 0 → 100644 +44 −0 Original line number Diff line number Diff line # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. @template def simple_decorator(func): return func @template def wrapper_decorator(func): def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper @template def function_decorator(*args, **kwargs): # We could return wrapper_decorator from above here, but then we wouldn't # know if this works as expected because wrapper_decorator itself was # modified or because the right thing happened here. def wrapper_decorator(func): def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper return wrapper_decorator @depends('--help') @simple_decorator def foo(help): global FOO FOO = 1 @depends('--help') @wrapper_decorator def bar(help): global BAR BAR = 1 @depends('--help') @function_decorator('a', 'b', 'c') def qux(help): global QUX QUX = 1 python/mozbuild/mozbuild/test/configure/test_configure.py +11 −0 Original line number Diff line number Diff line Loading @@ -259,6 +259,17 @@ class TestConfigure(unittest.TestCase): self.assertIn('PLATFORM', config) self.assertEquals(config['PLATFORM'], sys.platform) def test_decorators(self): config = {} out = StringIO() sandbox = ConfigureSandbox(config, {}, [], out, out) sandbox.exec_file(mozpath.join(test_data_path, 'decorators.configure')) self.assertNotIn('FOO', sandbox) self.assertNotIn('BAR', sandbox) self.assertNotIn('QUX', sandbox) def test_set_config(self): def get_config(*args): return self.get_config(*args, configure='set_config.configure') Loading Loading
python/mozbuild/mozbuild/configure/__init__.py +27 −3 Original line number Diff line number Diff line Loading @@ -234,7 +234,7 @@ class ConfigureSandbox(dict): if (not isinstance(value, DependsFunction) and value not in self._templates and not issubclass(value, Exception)): not (inspect.isclass(value) and issubclass(value, Exception))): raise KeyError('Cannot assign `%s` because it is neither a ' '@depends nor a @template' % key) Loading Loading @@ -393,8 +393,32 @@ class ConfigureSandbox(dict): (k[:-len('_impl')], getattr(self, k)) for k in dir(self) if k.endswith('_impl') and k != 'template_impl' ) self._templates.add(template) return template # Any function argument to the template must be prepared to be sandboxed. # If the template itself returns a function (in which case, it's very # likely a decorator), that function must be prepared to be sandboxed as # well. def wrap_template(template): @wraps(template) def wrapper(*args, **kwargs): def maybe_prepare_function(obj): if inspect.isfunction(obj): func, _ = self._prepare_function(obj) return func return obj args = [maybe_prepare_function(arg) for arg in args] kwargs = {k: maybe_prepare_function(v) for k, v in kwargs.iteritems()} ret = template(*args, **kwargs) if inspect.isfunction(ret): return wrap_template(ret) return ret return wrapper wrapper = wrap_template(template) self._templates.add(wrapper) return wrapper def advanced_impl(self, func): '''Implementation of @advanced. Loading
python/mozbuild/mozbuild/test/configure/data/decorators.configure 0 → 100644 +44 −0 Original line number Diff line number Diff line # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. @template def simple_decorator(func): return func @template def wrapper_decorator(func): def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper @template def function_decorator(*args, **kwargs): # We could return wrapper_decorator from above here, but then we wouldn't # know if this works as expected because wrapper_decorator itself was # modified or because the right thing happened here. def wrapper_decorator(func): def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper return wrapper_decorator @depends('--help') @simple_decorator def foo(help): global FOO FOO = 1 @depends('--help') @wrapper_decorator def bar(help): global BAR BAR = 1 @depends('--help') @function_decorator('a', 'b', 'c') def qux(help): global QUX QUX = 1
python/mozbuild/mozbuild/test/configure/test_configure.py +11 −0 Original line number Diff line number Diff line Loading @@ -259,6 +259,17 @@ class TestConfigure(unittest.TestCase): self.assertIn('PLATFORM', config) self.assertEquals(config['PLATFORM'], sys.platform) def test_decorators(self): config = {} out = StringIO() sandbox = ConfigureSandbox(config, {}, [], out, out) sandbox.exec_file(mozpath.join(test_data_path, 'decorators.configure')) self.assertNotIn('FOO', sandbox) self.assertNotIn('BAR', sandbox) self.assertNotIn('QUX', sandbox) def test_set_config(self): def get_config(*args): return self.get_config(*args, configure='set_config.configure') Loading