Commit 028ebf69 authored by Mike Hommey's avatar Mike Hommey
Browse files

Bug 1259960 - Make check_prog more flexible about the input it receives. r=chmanchester

parent 18a002cd
Loading
Loading
Loading
Loading
+23 −4
Original line number Diff line number Diff line
@@ -74,6 +74,11 @@ def checking(what, callback=None):
# - `progs` is a list (or tuple) of program names that will be searched for.
# - `what` is a human readable description of what is being looked for. It
#   defaults to the lowercase version of `var`.
# - `input` is a string reference to an existing option or a reference to a
#   @depends function resolving to explicit input for the program check.
#   The default is to create an option for the environment variable `var`.
#   This argument allows to use a different kind of option (possibly using a
#   configure flag), or doing some pre-processing with a @depends function.
# - `allow_missing` indicates whether not finding the program is an error.
#
# The simplest form is:
@@ -83,18 +88,32 @@ def checking(what, callback=None):
# use that value instead.
@template
@advanced
def check_prog(var, progs, what=None, allow_missing=False):
def check_prog(var, progs, what=None, input=None, allow_missing=False):
    from mozbuild.shellutil import quote

    if input:
        # Wrap input with type checking and normalization.
        @depends(input)
        def input(value):
            if not value:
                return
            if isinstance(value, str):
                return (value,)
            if isinstance(value, (tuple, list)) and len(value) == 1:
                return value
            configure_error('input must resolve to a tuple or a list with a '
                            'single element, or a string')
    else:
        option(env=var, nargs=1,
               help='Path to %s' % (what or 'the %s program' % var.lower()))
        input = var
    what = what or var.lower()

    if not isinstance(progs, (tuple, list)):
        configure_error('progs should be a list or tuple!')
    progs = list(progs)

    @depends(var)
    @depends(input)
    @checking('for %s' % what, lambda x: quote(x) if x else 'not found')
    def check(value):
        if value:
+3 −2
Original line number Diff line number Diff line
@@ -83,12 +83,13 @@ class ConfigureSandbox(dict):
        do_stuff(config)
    """

    # The default set of builtins.
    # The default set of builtins. We expose unicode as str to make sandboxed
    # files more python3-ready.
    BUILTINS = ReadOnlyDict({
        b: __builtins__[b]
        for b in ('None', 'False', 'True', 'int', 'bool', 'any', 'all', 'len',
                  'list', 'tuple', 'set', 'dict', 'isinstance')
    }, __import__=forbidden_import)
    }, __import__=forbidden_import, str=unicode)

    # Expose a limited set of functions from os.path
    OS = ReadOnlyNamespace(path=ReadOnlyNamespace(**{
+51 −0
Original line number Diff line number Diff line
@@ -170,6 +170,37 @@ class TestChecksConfigure(unittest.TestCase):
                              "DEBUG: cc: Trying 'unknown 3'\n"
                              'ERROR: Cannot find the target C compiler\n')

    def test_check_prog_input(self):
        config, out, status = self.get_result(
            'option("--with-ccache", nargs=1, help="ccache")\n'
            'check_prog("CCACHE", ("known-a",), input="--with-ccache")',
            ['--with-ccache=known-b'])
        self.assertEqual(status, 0)
        self.assertEqual(config, {'CCACHE': '/usr/local/bin/known-b'})
        self.assertEqual(out, 'checking for ccache... /usr/local/bin/known-b\n')

        script = (
            'option(env="CC", nargs=1, help="compiler")\n'
            '@depends("CC")\n'
            'def compiler(value):\n'
            '    return value[0].split()[0] if value else None\n'
            'check_prog("CC", ("known-a",), input=compiler)'
        )
        config, out, status = self.get_result(script)
        self.assertEqual(status, 0)
        self.assertEqual(config, {'CC': '/usr/bin/known-a'})
        self.assertEqual(out, 'checking for cc... /usr/bin/known-a\n')

        config, out, status = self.get_result(script, ['CC=known-b'])
        self.assertEqual(status, 0)
        self.assertEqual(config, {'CC': '/usr/local/bin/known-b'})
        self.assertEqual(out, 'checking for cc... /usr/local/bin/known-b\n')

        config, out, status = self.get_result(script, ['CC=known-b -m32'])
        self.assertEqual(status, 0)
        self.assertEqual(config, {'CC': '/usr/local/bin/known-b'})
        self.assertEqual(out, 'checking for cc... /usr/local/bin/known-b\n')

    def test_check_prog_configure_error(self):
        with self.assertRaises(ConfigureError) as e:
            self.get_result('check_prog("FOO", "foo")')
@@ -177,6 +208,26 @@ class TestChecksConfigure(unittest.TestCase):
        self.assertEqual(e.exception.message,
                         'progs should be a list or tuple!')

        with self.assertRaises(ConfigureError) as e:
            self.get_result(
                'foo = depends("--help")(lambda h: ("a", "b"))\n'
                'check_prog("FOO", ("known-a",), input=foo)'
            )

        self.assertEqual(e.exception.message,
                         'input must resolve to a tuple or a list with a '
                         'single element, or a string')

        with self.assertRaises(ConfigureError) as e:
            self.get_result(
                'foo = depends("--help")(lambda h: {"a": "b"})\n'
                'check_prog("FOO", ("known-a",), input=foo)'
            )

        self.assertEqual(e.exception.message,
                         'input must resolve to a tuple or a list with a '
                         'single element, or a string')


if __name__ == '__main__':
    main()