示例#1
0
    def test_option_value_compare(self):
        # OptionValue are tuple and equivalence should compare as tuples.
        val = PositiveOptionValue(('foo',))

        self.assertEqual(val[0], 'foo')
        self.assertEqual(val, PositiveOptionValue(('foo',)))
        self.assertNotEqual(val, PositiveOptionValue(('foo', 'bar')))

        # Can compare a tuple to an OptionValue.
        self.assertEqual(val, ('foo',))
        self.assertNotEqual(val, ('foo', 'bar'))

        # Different OptionValue types are never equal.
        self.assertNotEqual(val, OptionValue(('foo',)))

        # For usability reasons, we raise TypeError when attempting to compare
        # against a non-tuple.
        with self.assertRaisesRegexp(TypeError, 'cannot compare a'):
            val == 'foo'

        # But we allow empty option values to compare otherwise we can't
        # easily compare value-less types like PositiveOptionValue and
        # NegativeOptionValue.
        empty_positive = PositiveOptionValue()
        empty_negative = NegativeOptionValue()
        self.assertEqual(empty_positive, ())
        self.assertEqual(empty_positive, PositiveOptionValue())
        self.assertEqual(empty_negative, ())
        self.assertEqual(empty_negative, NegativeOptionValue())
        self.assertNotEqual(empty_positive, 'foo')
        self.assertNotEqual(empty_positive, ('foo',))
        self.assertNotEqual(empty_negative, 'foo')
        self.assertNotEqual(empty_negative, ('foo',))
示例#2
0
    def run(self, path=None):
        '''Executes the given file within the sandbox, as well as everything
        pending from any other included file, and ensure the overall
        consistency of the executed script(s).'''
        if path:
            self.include_file(path)

        for option in six.itervalues(self._options):
            # All options must be referenced by some @depends function
            if option not in self._seen:
                raise ConfigureError(
                    'Option `%s` is not handled ; reference it with a @depends'
                    % option.option)

            self._value_for(option)

        # All implied options should exist.
        for implied_option in self._implied_options:
            value = self._resolve(implied_option.value)
            if value is not None:
                # There are two ways to end up here: either the implied option
                # is unknown, or it's known but there was a dependency loop
                # that prevented the implication from being applied.
                option = self._options.get(implied_option.name)
                if not option:
                    raise ConfigureError(
                        '`%s`, emitted from `%s` line %d, is unknown.' %
                        (implied_option.option, implied_option.caller[1],
                         implied_option.caller[2]))
                # If the option is known, check that the implied value doesn't
                # conflict with what value was attributed to the option.
                option_value = self._value_for_option(option)
                if value != option_value:
                    reason = implied_option.reason
                    if isinstance(reason, Option):
                        reason = self._raw_options.get(reason) or reason.option
                        reason = reason.split('=', 1)[0]
                    value = OptionValue.from_(value)
                    raise InvalidOptionError(
                        "'%s' implied by '%s' conflicts with '%s' from the %s"
                        % (value.format(option.option), reason,
                           option_value.format(
                               option.option), option_value.origin))

        # All options should have been removed (handled) by now.
        for arg in self._helper:
            without_value = arg.split('=', 1)[0]
            msg = 'Unknown option: %s' % without_value
            if self._help:
                self._logger.warning(msg)
            else:
                raise InvalidOptionError(msg)

        # Run the execution queue
        for func, args in self._execution_queue:
            func(*args)

        if self._help:
            with LineIO(self.log_impl.info) as out:
                self._help.usage(out)
示例#3
0
    def _value_for_option(self, option):
        implied = {}
        for implied_option in self._implied_options[:]:
            if implied_option.name not in (option.name, option.env):
                continue
            self._implied_options.remove(implied_option)

            if (implied_option.when and
                not self._value_for(implied_option.when)):
                continue

            value = self._resolve(implied_option.value)

            if value is not None:
                value = OptionValue.from_(value)
                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
            if isinstance(reason, Option):
                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 value.origin == 'implied':
            recursed_value = getattr(self, '__value_for_option').get((option,))
            if recursed_value is not None:
                _, filename, line, _, _, _ = implied[value.format(option.option)].caller
                raise ConfigureError(
                    "'%s' appears somewhere in the direct or indirect dependencies when "
                    "resolving imply_option at %s:%d" % (option.option, filename, line))

        if option_string:
            self._raw_options[option] = option_string

        when = self._conditions.get(option)
        # If `when` resolves to a false-ish value, we always return None.
        # This makes option(..., when='--foo') equivalent to
        # option(..., when=depends('--foo')(lambda x: x)).
        if when and not self._value_for(when) and value is not None:
            # If the option was passed explicitly, we throw an error that
            # the option is not available. Except when the option was passed
            # from the environment, because that would be too cumbersome.
            if value.origin not in ('default', 'environment'):
                raise InvalidOptionError(
                    '%s is not available in this configuration'
                    % option_string.split('=', 1)[0])
            self._logger.log(TRACE, '%r = None', option)
            return None

        self._logger.log(TRACE, '%r = %r', option, value)
        return value