Bug 1257516 - Expose a sandboxed logger to moz.configure and use it. r?ted draft
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 25 Mar 2016 16:30:42 +0900
changeset 344664 d2099a95184bf367a69e144e4dcb248c049fb27c
parent 344663 28b0a6003af4ed16e4654b17afa8cd1656e6069a
child 344665 5fb421c3cb23fa0486da40cefacb69c15ddc6af6
push id13899
push userbmo:mh+mozilla@glandium.org
push dateFri, 25 Mar 2016 08:32:05 +0000
reviewersted
bugs1257516
milestone48.0a1
Bug 1257516 - Expose a sandboxed logger to moz.configure and use it. r?ted This removes the warn() function and makes the die() function use the logger instead of print.
build/moz.configure/checks.configure
build/moz.configure/init.configure
build/moz.configure/old.configure
build/moz.configure/util.configure
python/mozbuild/mozbuild/configure/__init__.py
--- a/build/moz.configure/checks.configure
+++ b/build/moz.configure/checks.configure
@@ -7,45 +7,41 @@
 # Templates implementing some generic checks.
 
 # Helper to display "checking" messages
 #   @checking('for foo')
 #   def foo():
 #       return 'foo'
 # is equivalent to:
 #   def foo():
-#       sys.stdout.write('checking for foo... ')
+#       log.info('checking for foo... ')
 #       ret = foo
-#       sys.stdout.write(ret + '\n')
+#       log.info(ret)
 #       return ret
 # This can be combined with e.g. @depends:
 #   @depends(some_option)
 #   @checking('for something')
 #   def check(value):
 #       ...
 # An optional callback can be given, that will be used to format the returned
 # value when displaying it.
 @template
 def checking(what, callback=None):
     def decorator(func):
-        @advanced
         def wrapped(*args, **kwargs):
-            import sys
-            print('checking', what, end='... ')
-            sys.stdout.flush()
+            log.info('checking %s... ', what)
             ret = func(*args, **kwargs)
             if callback:
-                print(callback(ret))
+                log.info(callback(ret))
             elif ret is True:
-                print('yes')
+                log.info('yes')
             elif ret is False:
-                print('no')
+                log.info('no')
             else:
-                print(ret)
-            sys.stdout.flush()
+                log.info(ret)
             return ret
         return wrapped
     return decorator
 
 
 # Template to check for programs in $PATH.
 #   check('PROG', ('a', 'b'))
 # will look for 'a' or 'b' in $PATH, and set_config PROG to the one
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -204,23 +204,23 @@ def virtualenv_python(env_python, build_
         if not found_python:
             die('The PYTHON environment variable does not contain '
                 'a valid path. Cannot find %s', python)
         python = found_python
     else:
         python = sys.executable
 
     if not manager.up_to_date(python):
-        warn('Creating Python environment')
+        log.info('Creating Python environment')
         manager.build(python)
 
     python = normsep(manager.python_path)
 
     if python != normsep(sys.executable):
-        warn('Reexecuting in the virtualenv')
+        log.info('Reexecuting in the virtualenv')
         if env_python:
             del os.environ['PYTHON']
         # One would prefer to use os.execl, but that's completely borked on
         # Windows.
         sys.exit(subprocess.call([python] + sys.argv))
 
     # We are now in the virtualenv
     import distutils.sysconfig
@@ -306,29 +306,29 @@ def wanted_mozconfig_variables(help):
          'ZIP',
      ])
 
 
 @depends(mozconfig, wanted_mozconfig_variables, '--help')
 def mozconfig_options(mozconfig, wanted_mozconfig_variables, help):
     if mozconfig['path']:
         helper = command_line_helper()
-        warn('Adding configure options from %s' % mozconfig['path'])
+        log.info('Adding configure options from %s' % mozconfig['path'])
         for arg in mozconfig['configure_args']:
-            warn('  %s' % arg)
+            log.info('  %s' % arg)
             # We could be using imply_option() here, but it has other
             # contraints that don't really apply to the command-line
             # emulation that mozconfig provides.
             helper.add(arg, origin='mozconfig', args=helper._args)
 
         def add(key, value):
             # See comment above wanted_mozconfig_variables
             if key in wanted_mozconfig_variables:
                 arg = '%s=%s' % (key, value)
-                warn('  %s' % arg)
+                log.info('  %s' % arg)
                 helper.add(arg, origin='mozconfig', args=helper._args)
 
         for key, value in mozconfig['env']['added'].iteritems():
             add(key, value)
         for key, (_, value) in mozconfig['env']['modified'].iteritems():
             add(key, value)
         for key, value in mozconfig['vars']['added'].iteritems():
             add(key, value)
--- a/build/moz.configure/old.configure
+++ b/build/moz.configure/old.configure
@@ -115,17 +115,17 @@ def prepare_configure(old_configure, moz
             glob.iglob(aclocal),
         ):
             if getmtime(input) > mtime:
                 break
         else:
             refresh = False
 
     if refresh:
-        warn('Refreshing %s with %s' % (old_configure, autoconf))
+        log.info('Refreshing %s with %s', old_configure, autoconf)
         with open(old_configure, 'wb') as fh:
             subprocess.check_call([
                 shell, autoconf,
                 '--localdir=%s' % os.path.dirname(old_configure),
                 old_configure + '.in'], stdout=fh)
 
     cmd = [shell, old_configure]
     with encoded_open('old-configure.vars', 'w') as out:
@@ -387,17 +387,17 @@ def old_configure(prepare_configure, ext
     # We also pass it the options from js/moz.configure so that it can pass
     # them down to js/src/configure. Note this list is empty when running
     # js/src/configure, in which case we don't need to pass those options
     # to old-configure since old-configure doesn't handle them anyways.
     if extra_old_configure_args:
         cmd += extra_old_configure_args
 
     # For debugging purpose, in case it's not what we'd expect.
-    warn('running %s' % ' '.join(quote(a) for a in cmd))
+    log.info('running %s', ' '.join(quote(a) for a in cmd))
     ret = subprocess.call(cmd)
     if ret:
         sys.exit(ret)
 
     raw_config = {}
     with encoded_open('config.data', 'r') as fh:
         code = compile(fh.read(), 'config.data', 'exec')
         # Every variation of the exec() function I tried led to:
--- a/build/moz.configure/util.configure
+++ b/build/moz.configure/util.configure
@@ -1,30 +1,20 @@
 # -*- 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
 @advanced
-def warn(*args):
-    'Print a warning.'
-    import sys
-    print(*args, file=sys.stderr)
-    sys.stderr.flush()
-
-
-@template
-@advanced
-def die(format, *args):
+def die(*args):
     'Print an error and terminate configure.'
     import sys
-    print(format % args, file=sys.stderr)
-    sys.stderr.flush()
+    log.error(*args)
     sys.exit(1)
 
 
 @template
 @advanced
 def configure_error(message):
     '''Raise a programming error and terminate configure.
     Primarily for use in moz.configure templates to sanity check
--- a/python/mozbuild/mozbuild/configure/__init__.py
+++ b/python/mozbuild/mozbuild/configure/__init__.py
@@ -135,16 +135,21 @@ class ConfigureSandbox(dict):
             handler = ConfigureOutputHandler(stdout, stderr)
             handler.setLevel(logging.INFO)
             handler.setFormatter(formatter)
             logger.addHandler(handler)
 
         else:
             assert isinstance(logger, logging.Logger)
 
+        self.log_impl = ReadOnlyNamespace(**{
+                k: getattr(logger, k)
+                for k in ('debug', 'info', 'warning', 'error')
+        })
+
         self._help = None
         self._help_option = self.option_impl('--help',
                                              help='print this message')
         self._seen.add(self._help_option)
         # self._option_impl('--help') will have set this if --help was on the
         # command line.
         if self._option_values[self._help_option]:
             self._help = HelpFormatter(argv[0])
@@ -194,17 +199,17 @@ class ConfigureSandbox(dict):
         for option in self._options.itervalues():
             if option not in self._seen:
                 raise ConfigureError(
                     'Option `%s` is not handled ; reference it with a @depends'
                     % option.option
                 )
 
         if self._help:
-            with LineIO(logging.getLogger('moz.configure').info) as out:
+            with LineIO(self.log_impl.info) as out:
                 self._help.usage(out)
 
     def __getitem__(self, key):
         impl = '%s_impl' % key
         func = getattr(self, impl, None)
         if func:
             return func
 
@@ -513,16 +518,17 @@ class ConfigureSandbox(dict):
         if func in self._prepared_functions:
             return func, func.func_globals
 
         glob = SandboxedGlobal(func.func_globals)
         glob.update(
             __builtins__=self.BUILTINS,
             __file__=self._paths[-1],
             os=self.OS,
+            log=self.log_impl,
         )
         func = wraps(func)(types.FunctionType(
             func.func_code,
             glob,
             func.__name__,
             func.func_defaults,
             func.func_closure
         ))