Bug 1257326 - Provide reasons for implied options when the caller provides an immediate value. draft
authorChris Manchester <cmanchester@mozilla.com>
Mon, 09 May 2016 15:49:55 -0700
changeset 365068 193a188ca47ff6344ec36dda7021c8d931a4fbc4
parent 365027 e7f76f5e1f4ae2fe5b7c28ea32ac4c7b306a985c
child 365069 ca92564100c8ef00603bc5b6b349a7b047e9afe1
push id17624
push usercmanchester@mozilla.com
push dateTue, 10 May 2016 00:06:24 +0000
bugs1257326
milestone49.0a1
Bug 1257326 - Provide reasons for implied options when the caller provides an immediate value. MozReview-Commit-ID: A8IDPuwPqiP
python/mozbuild/mozbuild/configure/__init__.py
python/mozbuild/mozbuild/test/configure/data/imply_option/imm.configure
python/mozbuild/mozbuild/test/configure/test_configure.py
--- a/python/mozbuild/mozbuild/configure/__init__.py
+++ b/python/mozbuild/mozbuild/configure/__init__.py
@@ -340,18 +340,19 @@ class ConfigureSandbox(dict):
                 opt = value.format(implied_option.option)
                 self._helper.add(opt, 'implied')
                 implied[opt] = implied_option
 
         try:
             value, option_string = self._helper.handle(option)
         except ConflictingOptionError as e:
             reason = implied[e.arg].reason
-            reason = self._raw_options.get(reason) or reason.option
-            reason = reason.split('=', 1)[0]
+            if not isinstance(reason, types.StringTypes):
+                reason = self._raw_options.get(reason) or reason.option
+                reason = reason.split('=', 1)[0]
             raise InvalidOptionError(
                 "'%s' implied by '%s' conflicts with '%s' from the %s"
                 % (e.arg, reason, e.old_arg, e.old_origin))
 
         if option_string:
             self._raw_options[option] = option_string
 
         return value
@@ -669,16 +670,22 @@ class ConfigureSandbox(dict):
         if self._help:
             return
         if not reason and isinstance(value, DependsFunction):
             deps = self._depends[value][1]
             possible_reasons = [d for d in deps if d != self._help_option]
             if len(possible_reasons) == 1:
                 if isinstance(possible_reasons[0], Option):
                     reason = possible_reasons[0]
+        if not reason and (isinstance(value, (bool, tuple)) or
+                           isinstance(value, types.StringTypes)):
+            # A reason can be provided automatically when imply_option
+            # is called with an immediate value.
+            _, filename, line, _, _, _ = inspect.stack()[1]
+            reason = "imply_option at %s:%s" % (filename, line)
 
         if not reason:
             raise ConfigureError(
                 "Cannot infer what implies '%s'. Please add a `reason` to "
                 "the `imply_option` call."
                 % option)
 
         prefix, name, values = Option.split_option(option)
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/configure/data/imply_option/imm.configure
@@ -0,0 +1,32 @@
+# -*- 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/.
+
+imply_option('--enable-foo', True)
+
+option('--enable-foo', help='enable foo')
+
+@depends('--enable-foo', '--help')
+def foo(value, help):
+    if value:
+        return True
+
+imply_option('--enable-bar', ('foo', 'bar'))
+
+option('--enable-bar', nargs='*', help='enable bar')
+
+@depends('--enable-bar')
+def bar(value):
+    if value:
+        return value
+
+imply_option('--enable-baz', 'BAZ')
+
+option('--enable-baz', nargs=1, help='enable baz')
+
+@depends('--enable-baz')
+def bar(value):
+    if value:
+        return value
--- a/python/mozbuild/mozbuild/test/configure/test_configure.py
+++ b/python/mozbuild/mozbuild/test/configure/test_configure.py
@@ -575,16 +575,42 @@ class TestConfigure(unittest.TestCase):
         with self.assertRaises(ConfigureError) as e:
             self.get_config([], configure='imply_option/infer_ko.configure')
 
         self.assertEquals(
             e.exception.message,
             "Cannot infer what implies '--enable-bar'. Please add a `reason` "
             "to the `imply_option` call.")
 
+    def test_imply_option_immediate_value(self):
+        def get_config(*args):
+            return self.get_config(
+                *args, configure='imply_option/imm.configure')
+
+        config = get_config(['--help'])
+        self.assertEquals(config, {})
+
+        config = get_config([])
+        self.assertEquals(config, {})
+
+        with self.assertRaisesRegexp(InvalidOptionError,
+            "--enable-foo' implied by 'imply_option at .+imm.configure:7'"
+            " conflicts with '--disable-foo' from the command-line"):
+            get_config(['--disable-foo'])
+
+        with self.assertRaisesRegexp(InvalidOptionError,
+            "--enable-bar=foo,bar' implied by 'imply_option at .+imm.configure:16'"
+            " conflicts with '--enable-bar=a,b,c' from the command-line"):
+            get_config(['--enable-bar=a,b,c'])
+
+        with self.assertRaisesRegexp(InvalidOptionError,
+            "--enable-baz=BAZ' implied by 'imply_option at .+imm.configure:25'"
+            " conflicts with '--enable-baz=QUUX' from the command-line"):
+            get_config(['--enable-baz=QUUX'])
+
     def test_imply_option_failures(self):
         with self.assertRaises(ConfigureError) as e:
             with self.moz_configure('''
                 imply_option('--with-foo', ('a',), 'bar')
             '''):
                 self.get_config()
 
         self.assertEquals(e.exception.message,