Bug 1257326 - Add a parameter to restrict accepted origins for an option in python configure. draft
authorChris Manchester <cmanchester@mozilla.com>
Mon, 09 May 2016 15:20:16 -0700
changeset 365025 885ec71eab3e8a243fc47fe28af04e70282195c2
parent 365024 021a389f44dfd317a8fe8be38ecc09b6eff57db4
child 365026 0606a59c04200f8aa27b0b89726a887dbc07bb12
push id17617
push usercmanchester@mozilla.com
push dateMon, 09 May 2016 22:22:03 +0000
Bug 1257326 - Add a parameter to restrict accepted origins for an option in python configure. MozReview-Commit-ID: 4Cme7fvl1fN
--- a/python/mozbuild/mozbuild/configure/help.py
+++ b/python/mozbuild/mozbuild/configure/help.py
@@ -11,16 +11,21 @@ from mozbuild.configure.options import O
 class HelpFormatter(object):
     def __init__(self, argv0):
         self.intro = ['Usage: %s [options]' % os.path.basename(argv0)]
         self.options = ['Options: [defaults in brackets after descriptions]']
         self.env = ['Environment variables:']
     def add(self, option):
         assert isinstance(option, Option)
+        if option.possible_origins == ('implied',):
+            # Don't display help if our option can only be implied.
+            return
         # TODO: improve formatting
         target = self.options if option.name else self.env
         opt = option.option
         if option.choices:
             opt += '={%s}' % ','.join(option.choices)
         help = option.help or ''
         if len(option.default):
             if help:
--- a/python/mozbuild/mozbuild/configure/options.py
+++ b/python/mozbuild/mozbuild/configure/options.py
@@ -112,23 +112,26 @@ class Option(object):
       number or the special values '?' (0 or 1), '*' (0 or more), or '+' (1 or
     - `default` can be used to give a default value to the option. When the
       `name` of the option starts with '--enable-' or '--with-', the implied
       default is an empty PositiveOptionValue. When it starts with '--disable-'
       or '--without-', the implied default is a NegativeOptionValue.
     - `choices` restricts the set of values that can be given to the option.
     - `help` is the option description for use in the --help output.
+    - `possible_origins` is a tuple of strings that are origins accepted for
+      this option. Example origins are 'mozconfig', 'implied', and 'environment'.
     __slots__ = (
         'id', 'prefix', 'name', 'env', 'nargs', 'default', 'choices', 'help',
+        'possible_origins',
     def __init__(self, name=None, env=None, nargs=None, default=None,
-                 choices=None, help=None):
+                 possible_origins=None, choices=None, help=None):
         if not name and not env:
             raise InvalidOptionError(
                 'At least an option name or an environment variable name must '
                 'be given')
         if name:
             if not isinstance(name, types.StringTypes):
                 raise InvalidOptionError('Option must be a string')
             if not name.startswith('--'):
@@ -153,16 +156,20 @@ class Option(object):
                 not istupleofstrings(default)):
             raise InvalidOptionError(
                 'default must be a bool, a string or a tuple of strings')
         if choices and not istupleofstrings(choices):
             raise InvalidOptionError(
                 'choices must be a tuple of strings')
         if not help:
             raise InvalidOptionError('A help string must be provided')
+        if possible_origins and not istupleofstrings(possible_origins):
+            raise InvalidOptionError(
+                'possible_origins must be a tuple of strings')
+        self.possible_origins = possible_origins
         if name:
             prefix, name, values = self.split_option(name)
             assert values == ()
             # --disable and --without options mean the default is enabled.
             # --enable and --with options mean the default is disabled.
             # However, we allow a default to be given so that the default
@@ -295,16 +302,21 @@ class Option(object):
         variable assignment (FOO=bar), returns the corresponding OptionValue.
         Note: variable assignments can come from either the environment or
         from the command line (e.g. `../configure CFLAGS=-O2`)
         if not option:
             return self.default
+        if self.possible_origins and origin not in self.possible_origins:
+            raise InvalidOptionError(
+                '%s can not be set by %s. Values are accepted from: %s' %
+                (option, origin, ', '.join(self.possible_origins)))
         prefix, name, values = self.split_option(option)
         option = self._join_option(prefix, name)
         assert name in (self.name, self.env)
         if prefix in ('disable', 'without'):
             if values != ():
                 raise InvalidOptionError('Cannot pass a value to %s' % option)
--- a/python/mozbuild/mozbuild/test/configure/test_options.py
+++ b/python/mozbuild/mozbuild/test/configure/test_options.py
@@ -780,11 +780,35 @@ class TestCommandLineHelper(unittest.Tes
         helper.add('--without-foo', 'other-origin')
         with self.assertRaises(ConflictingOptionError) as cm:
         self.assertEqual('--without-foo', cm.exception.arg)
         self.assertEqual('other-origin', cm.exception.origin)
         self.assertEqual('--with-foo=a,b', cm.exception.old_arg)
         self.assertEqual('command-line', cm.exception.old_origin)
+    def test_possible_origins(self):
+        with self.assertRaises(InvalidOptionError):
+            Option('--foo', possible_origins='command-line')
+        helper = CommandLineHelper({'BAZ': '1'}, ['cmd', '--foo', '--bar'])
+        foo = Option('--foo',
+                     possible_origins=('command-line',))
+        value, option = helper.handle(foo)
+        self.assertEquals(PositiveOptionValue(), value)
+        self.assertEquals('command-line', value.origin)
+        self.assertEquals('--foo', option)
+        bar = Option('--bar',
+                     possible_origins=('mozconfig',))
+        with self.assertRaisesRegexp(InvalidOptionError,
+            "--bar can not be set by command-line. Values are accepted from: mozconfig"):
+            helper.handle(bar)
+        baz = Option(env='BAZ',
+                     possible_origins=('implied',))
+        with self.assertRaisesRegexp(InvalidOptionError,
+            "BAZ=1 can not be set by environment. Values are accepted from: implied"):
+            helper.handle(baz)
 if __name__ == '__main__':