def get_result(self, command='', args=[], environ={}, prog='/bin/configure', extra_paths=None, includes=('util.configure', 'checks.configure')): config = {} out = StringIO() paths = { self.KNOWN_A: None, self.KNOWN_B: None, self.KNOWN_C: None, } if extra_paths: paths.update(extra_paths) environ = dict(environ) if 'PATH' not in environ: environ['PATH'] = os.pathsep.join( os.path.dirname(p) for p in paths) paths[self.OTHER_A] = None sandbox = ConfigureTestSandbox(paths, config, environ, [prog] + args, out, out) base_dir = os.path.join(topsrcdir, 'build', 'moz.configure') for f in includes: sandbox.include_file(os.path.join(base_dir, f)) status = 0 try: exec_(command, sandbox) sandbox.run() except SystemExit as e: status = e.code return config, out.getvalue(), status
def _get_one_import(self, what): # The special `__sandbox__` module gives access to the sandbox # instance. if what == '__sandbox__': return self # Special case for the open() builtin, because otherwise, using it # fails with "IOError: file() constructor not accessible in # restricted mode" if what == '__builtin__.open': return lambda *args, **kwargs: open(*args, **kwargs) # Special case os and os.environ so that os.environ is our copy of # the environment. if what == 'os.environ': return self._environ if what == 'os': return self._wrapped_os # And subprocess, so that its functions use our os.environ if what == 'subprocess': return self._wrapped_subprocess if what in ('subprocess.call', 'subprocess.check_call', 'subprocess.check_output', 'subprocess.Popen'): return getattr(self._wrapped_subprocess, what[len('subprocess.'):]) # Until this proves to be a performance problem, just construct an # import statement and execute it. import_line = '' if '.' in what: _from, what = what.rsplit('.', 1) if _from == '__builtin__' or _from.startswith('__builtin__.'): _from = _from.replace('__builtin__', 'six.moves.builtins') import_line += 'from %s ' % _from import_line += 'import %s as imported' % what glob = {} exec_(import_line, {}, glob) return glob['imported']
def _wrapped_subprocess(self): wrapped_subprocess = {} exec_("from subprocess import *", {}, wrapped_subprocess) def wrap(function): def wrapper(*args, **kwargs): if kwargs.get("env") is None: kwargs["env"] = dict(self._environ) # Subprocess on older Pythons can't handle unicode keys or # values in environment dicts while subprocess on newer Pythons # needs text in the env. Normalize automagically so callers # don't have to deal with this. kwargs["env"] = ensure_subprocess_env(kwargs["env"], encoding=system_encoding) return function(*args, **kwargs) return wrapper for f in ("call", "check_call", "check_output", "Popen", "run"): # `run` is new to python 3.5. In case this still runs from python2 # code, avoid failing here. if f in wrapped_subprocess: wrapped_subprocess[f] = wrap(wrapped_subprocess[f]) return ReadOnlyNamespace(**wrapped_subprocess)
def include_file(self, path): '''Include one file in the sandbox. Users of this class probably want Note: this will execute all template invocations, as well as @depends functions that depend on '--help', but nothing else. ''' if self._paths: path = mozpath.join(mozpath.dirname(self._paths[-1]), path) path = mozpath.normpath(path) if not mozpath.basedir(path, (mozpath.dirname(self._paths[0]),)): raise ConfigureError( 'Cannot include `%s` because it is not in a subdirectory ' 'of `%s`' % (path, mozpath.dirname(self._paths[0]))) else: path = mozpath.realpath(mozpath.abspath(path)) if path in self._all_paths: raise ConfigureError( 'Cannot include `%s` because it was included already.' % path) self._paths.append(path) self._all_paths.add(path) source = open(path, 'rb').read() code = compile(source, path, 'exec') exec_(code, self) self._paths.pop(-1)
def get_result(self, command='', args=[], environ={}, prog='/bin/configure', extra_paths=None, includes=('util.configure', 'checks.configure')): config = {} out = StringIO() paths = { self.KNOWN_A: None, self.KNOWN_B: None, self.KNOWN_C: None, } if extra_paths: paths.update(extra_paths) environ = dict(environ) if 'PATH' not in environ: environ['PATH'] = os.pathsep.join(os.path.dirname(p) for p in paths) paths[self.OTHER_A] = None sandbox = ConfigureTestSandbox(paths, config, environ, [prog] + args, out, out) base_dir = os.path.join(topsrcdir, 'build', 'moz.configure') for f in includes: sandbox.include_file(os.path.join(base_dir, f)) status = 0 try: exec_(command, sandbox) sandbox.run() except SystemExit as e: status = e.code return config, out.getvalue(), status
def include_file(self, path): '''Include one file in the sandbox. Users of this class probably want to use `run` instead. Note: this will execute all template invocations, as well as @depends functions that depend on '--help', but nothing else. ''' if self._paths: path = mozpath.join(mozpath.dirname(self._paths[-1]), path) path = mozpath.normpath(path) if not mozpath.basedir(path, (mozpath.dirname(self._paths[0]),)): raise ConfigureError( 'Cannot include `%s` because it is not in a subdirectory ' 'of `%s`' % (path, mozpath.dirname(self._paths[0]))) else: path = mozpath.realpath(mozpath.abspath(path)) if path in self._all_paths: raise ConfigureError( 'Cannot include `%s` because it was included already.' % path) self._paths.append(path) self._all_paths.add(path) source = open(path, 'rb').read() code = compile(source, path, 'exec') exec_(code, self) self._paths.pop(-1)
def _wrapped_os(self): wrapped_os = {} exec_("from os import *", {}, wrapped_os) # Special case os and os.environ so that os.environ is our copy of # the environment. wrapped_os["environ"] = self._environ return ReadOnlyNamespace(**wrapped_os)
def test(val, msg): out = StringIO() sandbox = ConfigureSandbox({}, stdout=out, stderr=out) base_dir = os.path.join(topsrcdir, "build", "moz.configure") sandbox.include_file(os.path.join(base_dir, "checks.configure")) exec_(to_exec, sandbox) sandbox["foo"](val) self.assertEqual(out.getvalue(), msg)
def do_compile_test(self, command, expected_test_content=None, expected_flags=None): paths = { os.path.abspath('/usr/bin/mockcc'): self.get_mock_compiler( expected_test_content=expected_test_content, expected_flags=expected_flags), } base_dir = os.path.join(topsrcdir, 'build', 'moz.configure') mock_compiler_defs = textwrap.dedent('''\ @depends('--help') def extra_toolchain_flags(_): return [] include('%s/compilers-util.configure') @compiler_class @depends('--help') def c_compiler(_): return namespace( flags=[], type='gcc', compiler=os.path.abspath('/usr/bin/mockcc'), wrapper=[], language='C', ) @compiler_class @depends('--help') def cxx_compiler(_): return namespace( flags=[], type='gcc', compiler=os.path.abspath('/usr/bin/mockcc'), wrapper=[], language='C++', ) ''' % mozpath.normsep(base_dir)) config = {} out = StringIO() sandbox = ConfigureTestSandbox(paths, config, {}, ['/bin/configure'], out, out) sandbox.include_file(os.path.join(base_dir, 'util.configure')) sandbox.include_file(os.path.join(base_dir, 'checks.configure')) exec_(mock_compiler_defs, sandbox) sandbox.include_file(os.path.join(base_dir, 'compile-checks.configure')) status = 0 try: exec_(command, sandbox) sandbox.run() except SystemExit as e: status = e.code return config, out.getvalue(), status
def _get_one_import(self, what): # The special `__sandbox__` module gives access to the sandbox # instance. if what == '__sandbox__': return self # Special case for the open() builtin, because otherwise, using it # fails with "IOError: file() constructor not accessible in # restricted mode". We also make open() look more like python 3's, # decoding to unicode strings unless the mode says otherwise. if what == '__builtin__.open' or what == 'builtins.open': if six.PY3: return open def wrapped_open(name, mode=None, buffering=None): args = (name, ) kwargs = {} if buffering is not None: kwargs['buffering'] = buffering if mode is not None: args += (mode, ) if 'b' in mode: return open(*args, **kwargs) kwargs['encoding'] = system_encoding return codecs.open(*args, **kwargs) return wrapped_open # Special case os and os.environ so that os.environ is our copy of # the environment. if what == 'os.environ': return self._environ if what == 'os': return self._wrapped_os # And subprocess, so that its functions use our os.environ if what == 'subprocess': return self._wrapped_subprocess if what in ('subprocess.call', 'subprocess.check_call', 'subprocess.check_output', 'subprocess.Popen'): return getattr(self._wrapped_subprocess, what[len('subprocess.'):]) # Until this proves to be a performance problem, just construct an # import statement and execute it. import_line = '' if '.' in what: _from, what = what.rsplit('.', 1) if _from == '__builtin__' or _from.startswith('__builtin__.'): _from = _from.replace('__builtin__', 'six.moves.builtins') import_line += 'from %s ' % _from if what == '__builtin__': what = 'six.moves.builtins' import_line += 'import %s as imported' % what glob = {} exec_(import_line, {}, glob) return glob['imported']
def execute(): # compile() inherits the __future__ from the module by default. We # do want Unicode literals. code = compile(source, path, 'exec') # We use ourself as the global namespace for the execution. There # is no need for a separate local namespace as moz.build execution # is flat, namespace-wise. old_source = self._current_source self._current_source = source try: exec_(code, self) finally: self._current_source = old_source
def get_target(self, args, env={}): if 'linux' in self.HOST: platform = 'linux2' elif 'mingw' in self.HOST: platform = 'win32' else: raise Exception('Missing platform for HOST {}'.format(self.HOST)) wrapped_sys = {} exec_('from sys import *', wrapped_sys) wrapped_sys['platform'] = platform modules = { 'sys': ReadOnlyNamespace(**wrapped_sys), } sandbox = self.get_sandbox({}, {}, args, env, modules=modules) return sandbox._value_for(sandbox['target']).alias
def get_result(self, command='', paths=None): paths = paths or {} config = {} out = StringIO() sandbox = ConfigureTestSandbox(paths, config, {}, ['/bin/configure'], out, out) sandbox.include_file(mozpath.join(topsrcdir, 'build', 'moz.configure', 'util.configure')) status = 0 try: exec_(command, sandbox) sandbox.run() except SystemExit as e: status = e.code return config, out.getvalue(), status
def do_compile_test(self, command, expected_test_content=None, expected_flags=None): paths = { os.path.abspath('/usr/bin/mockcc'): self.get_mock_compiler( expected_test_content=expected_test_content, expected_flags=expected_flags), } mock_compiler_defs = textwrap.dedent('''\ @depends('--help') def c_compiler(_): return namespace( flags=[], compiler=os.path.abspath('/usr/bin/mockcc'), wrapper=[], ) @depends('--help') def cxx_compiler(_): return namespace( flags=[], compiler=os.path.abspath('/usr/bin/mockcc'), wrapper=[], ) @depends('--help') def extra_toolchain_flags(_): return [] ''') config = {} out = StringIO() sandbox = ConfigureTestSandbox(paths, config, {}, ['/bin/configure'], out, out) base_dir = os.path.join(topsrcdir, 'build', 'moz.configure') sandbox.include_file(os.path.join(base_dir, 'util.configure')) sandbox.include_file(os.path.join(base_dir, 'checks.configure')) exec_(mock_compiler_defs, sandbox) sandbox.include_file(os.path.join(base_dir, 'compilechecks.configure')) status = 0 try: exec_(command, sandbox) sandbox.run() except SystemExit as e: status = e.code return config, out.getvalue(), status
def _wrapped_subprocess(self): wrapped_subprocess = {} exec_('from subprocess import *', {}, wrapped_subprocess) def wrap(function): def wrapper(*args, **kwargs): if 'env' not in kwargs: kwargs['env'] = encode(self._environ) return function(*args, **kwargs) return wrapper for f in ('call', 'check_call', 'check_output', 'Popen'): wrapped_subprocess[f] = wrap(wrapped_subprocess[f]) return ReadOnlyNamespace(**wrapped_subprocess)
def _wrapped_subprocess(self): wrapped_subprocess = {} exec_("from subprocess import *", {}, wrapped_subprocess) def wrap(function): def wrapper(*args, **kwargs): if kwargs.get("env") is None and self._environ: kwargs["env"] = dict(self._environ) return function(*args, **kwargs) return wrapper for f in ("call", "check_call", "check_output", "Popen", "run"): # `run` is new to python 3.5. In case this still runs from python2 # code, avoid failing here. if f in wrapped_subprocess: wrapped_subprocess[f] = wrap(wrapped_subprocess[f]) return ReadOnlyNamespace(**wrapped_subprocess)
def _wrapped_subprocess(self): wrapped_subprocess = {} exec_('from subprocess import *', {}, wrapped_subprocess) def wrap(function): def wrapper(*args, **kwargs): if 'env' not in kwargs: kwargs['env'] = dict(self._environ) # Subprocess on older Pythons can't handle unicode keys or # values in environment dicts while subprocess on newer Pythons # needs text in the env. Normalize automagically so callers # don't have to deal with this. kwargs['env'] = ensure_subprocess_env(kwargs['env'], encoding=system_encoding) return function(*args, **kwargs) return wrapper for f in ('call', 'check_call', 'check_output', 'Popen'): wrapped_subprocess[f] = wrap(wrapped_subprocess[f]) return ReadOnlyNamespace(**wrapped_subprocess)
def _get_one_import(self, what): # The special `__sandbox__` module gives access to the sandbox # instance. if what == '__sandbox__': return self # Special case for the open() builtin, because otherwise, using it # fails with "IOError: file() constructor not accessible in # restricted mode" if what == '__builtin__.open': return lambda *args, **kwargs: open(*args, **kwargs) # Until this proves to be a performance problem, just construct an # import statement and execute it. import_line = '' if '.' in what: _from, what = what.rsplit('.', 1) import_line += 'from %s ' % _from import_line += 'import %s as imported' % what glob = {} exec_(import_line, {}, glob) return glob['imported']
def _get_one_import(self, _from, _import, _as, glob): """Perform the given import, placing the result into the dict glob.""" if not _from and _import == '__builtin__': glob[_as or '__builtin__'] = __builtin__ return if _from == '__builtin__': _from = 'six.moves.builtins' # The special `__sandbox__` module gives access to the sandbox # instance. if not _from and _import == '__sandbox__': glob[_as or _import] = self return if self._handle_wrapped_import(_from, _import, _as, glob): return # If we've gotten this far, we should just do a normal import. # Until this proves to be a performance problem, just construct an # import statement and execute it. import_line = '%simport %s%s' % ( ('from %s ' % _from) if _from else '', _import, (' as %s' % _as) if _as else '') exec_(import_line, {}, glob)
def _wrapped_six(self): if six.PY3: return six wrapped_six = {} exec_("from six import *", {}, wrapped_six) wrapped_six_moves = {} exec_("from six.moves import *", {}, wrapped_six_moves) wrapped_six_moves_builtins = {} exec_("from six.moves.builtins import *", {}, wrapped_six_moves_builtins) # Special case for the open() builtin, because otherwise, using it # fails with "IOError: file() constructor not accessible in # restricted mode". We also make open() look more like python 3's, # decoding to unicode strings unless the mode says otherwise. def wrapped_open(name, mode=None, buffering=None): args = (name,) kwargs = {} if buffering is not None: kwargs["buffering"] = buffering if mode is not None: args += (mode,) if "b" in mode: return open(*args, **kwargs) kwargs["encoding"] = system_encoding return codecs.open(*args, **kwargs) wrapped_six_moves_builtins["open"] = wrapped_open wrapped_six_moves["builtins"] = ReadOnlyNamespace(**wrapped_six_moves_builtins) wrapped_six["moves"] = ReadOnlyNamespace(**wrapped_six_moves) return ReadOnlyNamespace(**wrapped_six)
def _apply_imports(self, func, glob): for _from, _import, _as in self._imports.get(func, ()): # The special `__sandbox__` module gives access to the sandbox # instance. if _from is None and _import == '__sandbox__': glob[_as or _import] = self continue # Special case for the open() builtin, because otherwise, using it # fails with "IOError: file() constructor not accessible in # restricted mode" if _from == '__builtin__' and _import == 'open': glob[_as or _import] = \ lambda *args, **kwargs: open(*args, **kwargs) continue # Until this proves to be a performance problem, just construct an # import statement and execute it. import_line = '' if _from: import_line += 'from %s ' % _from import_line += 'import %s' % _import if _as: import_line += ' as %s' % _as exec_(import_line, {}, glob)
def test_apply_imports(self): imports = [] class CountApplyImportsSandbox(ConfigureSandbox): def _apply_imports(self, *args, **kwargs): imports.append((args, kwargs)) super(CountApplyImportsSandbox, self)._apply_imports(*args, **kwargs) config = {} out = StringIO() sandbox = CountApplyImportsSandbox(config, {}, ['configure'], out, out) exec_( textwrap.dedent(''' @template @imports('sys') def foo(): return sys foo() foo()'''), sandbox) self.assertEquals(len(imports), 1)
def test_apply_imports(self): imports = [] class CountApplyImportsSandbox(ConfigureSandbox): def _apply_imports(self, *args, **kwargs): imports.append((args, kwargs)) super(CountApplyImportsSandbox, self)._apply_imports( *args, **kwargs) config = {} out = StringIO() sandbox = CountApplyImportsSandbox(config, {}, [], out, out) exec_(textwrap.dedent(''' @template @imports('sys') def foo(): return sys foo() foo()'''), sandbox ) self.assertEquals(len(imports), 1)
def _wrapped_sys(self): sys = {} exec_("from sys import *", sys) sys["platform"] = platform return ReadOnlyNamespace(**sys)
def do_compile_test(self, command, expected_test_content=None, expected_flags=None): paths = { os.path.abspath('/usr/bin/mockcc'): self.get_mock_compiler(expected_test_content=expected_test_content, expected_flags=expected_flags), } base_dir = os.path.join(topsrcdir, 'build', 'moz.configure') mock_compiler_defs = textwrap.dedent('''\ @depends(when=True) def extra_toolchain_flags(): return [] target = depends(when=True)(lambda: True) include('%s/compilers-util.configure') @template def wrap_compiler(compiler): return compiler_class(compiler, False) @wrap_compiler @depends(when=True) def c_compiler(): return namespace( flags=[], type='gcc', compiler=os.path.abspath('/usr/bin/mockcc'), wrapper=[], language='C', ) @wrap_compiler @depends(when=True) def cxx_compiler(): return namespace( flags=[], type='gcc', compiler=os.path.abspath('/usr/bin/mockcc'), wrapper=[], language='C++', ) ''' % mozpath.normsep(base_dir)) config = {} out = StringIO() sandbox = ConfigureTestSandbox(paths, config, {}, ['/bin/configure'], out, out) sandbox.include_file(os.path.join(base_dir, 'util.configure')) sandbox.include_file(os.path.join(base_dir, 'checks.configure')) exec_(mock_compiler_defs, sandbox) sandbox.include_file(os.path.join(base_dir, 'compile-checks.configure')) status = 0 try: exec_(command, sandbox) sandbox.run() except SystemExit as e: status = e.code return config, out.getvalue(), status
def test_checking(self): out = StringIO() sandbox = ConfigureSandbox({}, stdout=out, stderr=out) base_dir = os.path.join(topsrcdir, 'build', 'moz.configure') sandbox.include_file(os.path.join(base_dir, 'checks.configure')) exec_(textwrap.dedent(''' @checking('for a thing') def foo(value): return value '''), sandbox) foo = sandbox['foo'] foo(True) self.assertEqual(out.getvalue(), 'checking for a thing... yes\n') out.truncate(0) foo(False) self.assertEqual(out.getvalue(), 'checking for a thing... no\n') out.truncate(0) foo(42) self.assertEqual(out.getvalue(), 'checking for a thing... 42\n') out.truncate(0) foo('foo') self.assertEqual(out.getvalue(), 'checking for a thing... foo\n') out.truncate(0) data = ['foo', 'bar'] foo(data) self.assertEqual(out.getvalue(), 'checking for a thing... %r\n' % data) # When the function given to checking does nothing interesting, the # behavior is not altered exec_(textwrap.dedent(''' @checking('for a thing', lambda x: x) def foo(value): return value '''), sandbox) foo = sandbox['foo'] out.truncate(0) foo(True) self.assertEqual(out.getvalue(), 'checking for a thing... yes\n') out.truncate(0) foo(False) self.assertEqual(out.getvalue(), 'checking for a thing... no\n') out.truncate(0) foo(42) self.assertEqual(out.getvalue(), 'checking for a thing... 42\n') out.truncate(0) foo('foo') self.assertEqual(out.getvalue(), 'checking for a thing... foo\n') out.truncate(0) data = ['foo', 'bar'] foo(data) self.assertEqual(out.getvalue(), 'checking for a thing... %r\n' % data) exec_(textwrap.dedent(''' def munge(x): if not x: return 'not found' if isinstance(x, (str, bool, int)): return x return ' '.join(x) @checking('for a thing', munge) def foo(value): return value '''), sandbox) foo = sandbox['foo'] out.truncate(0) foo(True) self.assertEqual(out.getvalue(), 'checking for a thing... yes\n') out.truncate(0) foo(False) self.assertEqual(out.getvalue(), 'checking for a thing... not found\n') out.truncate(0) foo(42) self.assertEqual(out.getvalue(), 'checking for a thing... 42\n') out.truncate(0) foo('foo') self.assertEqual(out.getvalue(), 'checking for a thing... foo\n') out.truncate(0) foo(['foo', 'bar']) self.assertEqual(out.getvalue(), 'checking for a thing... foo bar\n')
def test_imports(self): config = {} out = StringIO() sandbox = ConfigureSandbox(config, {}, [], out, out) with self.assertRaises(ImportError): exec_(textwrap.dedent(''' @template def foo(): import sys foo()'''), sandbox ) exec_(textwrap.dedent(''' @template @imports('sys') def foo(): return sys'''), sandbox ) self.assertIs(sandbox['foo'](), sys) exec_(textwrap.dedent(''' @template @imports(_from='os', _import='path') def foo(): return path'''), sandbox ) self.assertIs(sandbox['foo'](), os.path) exec_(textwrap.dedent(''' @template @imports(_from='os', _import='path', _as='os_path') def foo(): return os_path'''), sandbox ) self.assertIs(sandbox['foo'](), os.path) exec_(textwrap.dedent(''' @template @imports('__builtin__') def foo(): return __builtin__'''), sandbox ) import __builtin__ self.assertIs(sandbox['foo'](), __builtin__) exec_(textwrap.dedent(''' @template @imports(_from='__builtin__', _import='open') def foo(): return open('%s')''' % os.devnull), sandbox ) f = sandbox['foo']() self.assertEquals(f.name, os.devnull) f.close() # This unlocks the sandbox exec_(textwrap.dedent(''' @template @imports(_import='__builtin__', _as='__builtins__') def foo(): import sys return sys'''), sandbox ) self.assertIs(sandbox['foo'](), sys) exec_(textwrap.dedent(''' @template @imports('__sandbox__') def foo(): return __sandbox__'''), sandbox ) self.assertIs(sandbox['foo'](), sandbox) exec_(textwrap.dedent(''' @template @imports(_import='__sandbox__', _as='s') def foo(): return s'''), sandbox ) self.assertIs(sandbox['foo'](), sandbox) # Nothing leaked from the function being executed self.assertEquals(sandbox.keys(), ['__builtins__', 'foo']) self.assertEquals(sandbox['__builtins__'], ConfigureSandbox.BUILTINS)
def _wrapped_sys(self): sys = {} exec_('from sys import *', sys) sys['platform'] = platform return ReadOnlyNamespace(**sys)
def test_imports(self): config = {} out = StringIO() sandbox = ConfigureSandbox(config, {}, ['configure'], out, out) with self.assertRaises(ImportError): exec_( textwrap.dedent(''' @template def foo(): import sys foo()'''), sandbox) exec_( textwrap.dedent(''' @template @imports('sys') def foo(): return sys'''), sandbox) self.assertIs(sandbox['foo'](), sys) exec_( textwrap.dedent(''' @template @imports(_from='os', _import='path') def foo(): return path'''), sandbox) self.assertIs(sandbox['foo'](), os.path) exec_( textwrap.dedent(''' @template @imports(_from='os', _import='path', _as='os_path') def foo(): return os_path'''), sandbox) self.assertIs(sandbox['foo'](), os.path) exec_( textwrap.dedent(''' @template @imports('__builtin__') def foo(): return __builtin__'''), sandbox) import __builtin__ self.assertIs(sandbox['foo'](), __builtin__) exec_( textwrap.dedent(''' @template @imports(_from='__builtin__', _import='open') def foo(): return open('%s')''' % os.devnull), sandbox) f = sandbox['foo']() self.assertEquals(f.name, os.devnull) f.close() # This unlocks the sandbox exec_( textwrap.dedent(''' @template @imports(_import='__builtin__', _as='__builtins__') def foo(): import sys return sys'''), sandbox) self.assertIs(sandbox['foo'](), sys) exec_( textwrap.dedent(''' @template @imports('__sandbox__') def foo(): return __sandbox__'''), sandbox) self.assertIs(sandbox['foo'](), sandbox) exec_( textwrap.dedent(''' @template @imports(_import='__sandbox__', _as='s') def foo(): return s'''), sandbox) self.assertIs(sandbox['foo'](), sandbox) # Nothing leaked from the function being executed self.assertEquals(sandbox.keys(), ['__builtins__', 'foo']) self.assertEquals(sandbox['__builtins__'], ConfigureSandbox.BUILTINS) exec_( textwrap.dedent(''' @template @imports('sys') def foo(): @depends(when=True) def bar(): return sys return bar bar = foo()'''), sandbox) with self.assertRaises(NameError) as e: sandbox._depends[sandbox['bar']].result() self.assertEquals(e.exception.message, "global name 'sys' is not defined")
def _wrapped_os(self): wrapped_os = {} exec_('from os import *', {}, wrapped_os) wrapped_os['environ'] = self._environ return ReadOnlyNamespace(**wrapped_os)
def test_checking(self): out = StringIO() sandbox = ConfigureSandbox({}, stdout=out, stderr=out) base_dir = os.path.join(topsrcdir, 'build', 'moz.configure') sandbox.include_file(os.path.join(base_dir, 'checks.configure')) exec_( textwrap.dedent(''' @checking('for a thing') def foo(value): return value '''), sandbox) foo = sandbox['foo'] foo(True) self.assertEqual(out.getvalue(), 'checking for a thing... yes\n') out.truncate(0) foo(False) self.assertEqual(out.getvalue(), 'checking for a thing... no\n') out.truncate(0) foo(42) self.assertEqual(out.getvalue(), 'checking for a thing... 42\n') out.truncate(0) foo('foo') self.assertEqual(out.getvalue(), 'checking for a thing... foo\n') out.truncate(0) data = ['foo', 'bar'] foo(data) self.assertEqual(out.getvalue(), 'checking for a thing... %r\n' % data) # When the function given to checking does nothing interesting, the # behavior is not altered exec_( textwrap.dedent(''' @checking('for a thing', lambda x: x) def foo(value): return value '''), sandbox) foo = sandbox['foo'] out.truncate(0) foo(True) self.assertEqual(out.getvalue(), 'checking for a thing... yes\n') out.truncate(0) foo(False) self.assertEqual(out.getvalue(), 'checking for a thing... no\n') out.truncate(0) foo(42) self.assertEqual(out.getvalue(), 'checking for a thing... 42\n') out.truncate(0) foo('foo') self.assertEqual(out.getvalue(), 'checking for a thing... foo\n') out.truncate(0) data = ['foo', 'bar'] foo(data) self.assertEqual(out.getvalue(), 'checking for a thing... %r\n' % data) exec_( textwrap.dedent(''' def munge(x): if not x: return 'not found' if isinstance(x, (str, bool, int)): return x return ' '.join(x) @checking('for a thing', munge) def foo(value): return value '''), sandbox) foo = sandbox['foo'] out.truncate(0) foo(True) self.assertEqual(out.getvalue(), 'checking for a thing... yes\n') out.truncate(0) foo(False) self.assertEqual(out.getvalue(), 'checking for a thing... not found\n') out.truncate(0) foo(42) self.assertEqual(out.getvalue(), 'checking for a thing... 42\n') out.truncate(0) foo('foo') self.assertEqual(out.getvalue(), 'checking for a thing... foo\n') out.truncate(0) foo(['foo', 'bar']) self.assertEqual(out.getvalue(), 'checking for a thing... foo bar\n')
def test_imports(self): config = {} out = StringIO() sandbox = ConfigureSandbox(config, {}, [], out, out) with self.assertRaises(ImportError): exec_(textwrap.dedent(''' @template def foo(): import sys foo()'''), sandbox ) exec_(textwrap.dedent(''' @template @imports('sys') def foo(): return sys'''), sandbox ) self.assertIs(sandbox['foo'](), sys) exec_(textwrap.dedent(''' @template @imports(_from='os', _import='path') def foo(): return path'''), sandbox ) self.assertIs(sandbox['foo'](), os.path) exec_(textwrap.dedent(''' @template @imports(_from='os', _import='path', _as='os_path') def foo(): return os_path'''), sandbox ) self.assertIs(sandbox['foo'](), os.path) exec_(textwrap.dedent(''' @template @imports('__builtin__') def foo(): return __builtin__'''), sandbox ) import __builtin__ self.assertIs(sandbox['foo'](), __builtin__) exec_(textwrap.dedent(''' @template @imports(_from='__builtin__', _import='open') def foo(): return open('%s')''' % os.devnull), sandbox ) f = sandbox['foo']() self.assertEquals(f.name, os.devnull) f.close() # This unlocks the sandbox exec_(textwrap.dedent(''' @template @imports(_import='__builtin__', _as='__builtins__') def foo(): import sys return sys'''), sandbox ) self.assertIs(sandbox['foo'](), sys) exec_(textwrap.dedent(''' @template @imports('__sandbox__') def foo(): return __sandbox__'''), sandbox ) self.assertIs(sandbox['foo'](), sandbox) exec_(textwrap.dedent(''' @template @imports(_import='__sandbox__', _as='s') def foo(): return s'''), sandbox ) self.assertIs(sandbox['foo'](), sandbox) # Nothing leaked from the function being executed self.assertEquals(sandbox.keys(), ['__builtins__', 'foo']) self.assertEquals(sandbox['__builtins__'], ConfigureSandbox.BUILTINS) exec_(textwrap.dedent(''' @template @imports('sys') def foo(): @depends(when=True) def bar(): return sys return bar bar = foo()'''), sandbox ) with self.assertRaises(NameError) as e: sandbox._depends[sandbox['bar']].result self.assertEquals(e.exception.message, "global name 'sys' is not defined")
def test_imports(self): config = {} out = StringIO() sandbox = ConfigureSandbox(config, {}, [], out, out) with self.assertRaises(ImportError): exec_( textwrap.dedent(''' @template def foo(): import sys foo()'''), sandbox) exec_( textwrap.dedent(''' @template @imports('sys') def foo(): return sys'''), sandbox) self.assertIs(sandbox['foo'](), sys) exec_( textwrap.dedent(''' @template @imports(_from='os', _import='path') def foo(): return path'''), sandbox) self.assertIs(sandbox['foo'](), os.path) exec_( textwrap.dedent(''' @template @imports(_from='os', _import='path', _as='os_path') def foo(): return os_path'''), sandbox) self.assertIs(sandbox['foo'](), os.path) exec_( textwrap.dedent(''' @template @imports('__builtin__') def foo(): return __builtin__'''), sandbox) import __builtin__ self.assertIs(sandbox['foo'](), __builtin__) exec_( textwrap.dedent(''' @template @imports(_from='__builtin__', _import='open') def foo(): return open('%s')''' % os.devnull), sandbox) f = sandbox['foo']() self.assertEquals(f.name, os.devnull) f.close() # This unlocks the sandbox exec_( textwrap.dedent(''' @template @imports(_import='__builtin__', _as='__builtins__') def foo(): import sys return sys'''), sandbox) self.assertIs(sandbox['foo'](), sys) exec_( textwrap.dedent(''' @template @imports('__sandbox__') def foo(): return __sandbox__'''), sandbox) self.assertIs(sandbox['foo'](), sandbox) exec_( textwrap.dedent(''' @template @imports(_import='__sandbox__', _as='s') def foo(): return s'''), sandbox) self.assertIs(sandbox['foo'](), sandbox) # Nothing leaked from the function being executed self.assertEquals(sandbox.keys(), ['__builtins__', 'foo']) self.assertEquals(sandbox['__builtins__'], ConfigureSandbox.BUILTINS)