1# This Source Code Form is subject to the terms of the Mozilla Public 2# License, v. 2.0. If a copy of the MPL was not distributed with this 3# file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5from __future__ import absolute_import, print_function, unicode_literals 6 7from StringIO import StringIO 8from . import ( 9 CombinedDependsFunction, 10 ConfigureError, 11 ConfigureSandbox, 12 DependsFunction, 13) 14from .lint_util import disassemble_as_iter 15from mozbuild.util import memoize 16 17 18class LintSandbox(ConfigureSandbox): 19 def __init__(self, environ=None, argv=None, stdout=None, stderr=None): 20 out = StringIO() 21 stdout = stdout or out 22 stderr = stderr or out 23 environ = environ or {} 24 argv = argv or [] 25 self._wrapped = {} 26 super(LintSandbox, self).__init__({}, environ=environ, argv=argv, 27 stdout=stdout, stderr=stderr) 28 29 def run(self, path=None): 30 if path: 31 self.include_file(path) 32 33 def _missing_help_dependency(self, obj): 34 if isinstance(obj, CombinedDependsFunction): 35 return False 36 if isinstance(obj, DependsFunction): 37 if (self._help_option in obj.dependencies or 38 obj in (self._always, self._never)): 39 return False 40 func, glob = self._wrapped[obj.func] 41 # We allow missing --help dependencies for functions that: 42 # - don't use @imports 43 # - don't have a closure 44 # - don't use global variables 45 if func in self._imports or func.func_closure: 46 return True 47 for op, arg in disassemble_as_iter(func): 48 if op in ('LOAD_GLOBAL', 'STORE_GLOBAL'): 49 # There is a fake os module when one is not imported, 50 # and it's allowed for functions without a --help 51 # dependency. 52 if arg == 'os' and glob.get('os') is self.OS: 53 continue 54 return True 55 return False 56 57 @memoize 58 def _value_for_depends(self, obj, need_help_dependency=False): 59 with_help = self._help_option in obj.dependencies 60 if with_help: 61 for arg in obj.dependencies: 62 if self._missing_help_dependency(arg): 63 raise ConfigureError( 64 "`%s` depends on '--help' and `%s`. " 65 "`%s` must depend on '--help'" 66 % (obj.name, arg.name, arg.name)) 67 elif ((self._help or need_help_dependency) and 68 self._missing_help_dependency(obj)): 69 raise ConfigureError("Missing @depends for `%s`: '--help'" % 70 obj.name) 71 return super(LintSandbox, self)._value_for_depends( 72 obj, need_help_dependency) 73 74 def _prepare_function(self, func): 75 wrapped, glob = super(LintSandbox, self)._prepare_function(func) 76 if wrapped not in self._wrapped: 77 self._wrapped[wrapped] = func, glob 78 return wrapped, glob 79