Пример #1
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)
Пример #2
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,
                                  need_help_dependency=False)

            if value is not None:
                if isinstance(value, OptionValue):
                    pass
                elif value is True:
                    value = PositiveOptionValue()
                elif value is False or value == ():
                    value = NegativeOptionValue()
                elif isinstance(value, types.StringTypes):
                    value = PositiveOptionValue((value, ))
                elif isinstance(value, tuple):
                    value = PositiveOptionValue(value)
                else:
                    raise TypeError("Unexpected type: '%s'" %
                                    type(value).__name__)

                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 option_string:
            self._raw_options[option] = option_string

        when = self._conditions.get(option)
        if (when and not self._value_for(when, need_help_dependency=True)
                and value is not None and value.origin != 'default'):
            if value.origin == 'environment':
                # The value we return doesn't really matter, because of the
                # requirement for @depends to have the same when.
                return None
            raise InvalidOptionError(
                '%s is not available in this configuration' %
                option_string.split('=', 1)[0])

        return value
Пример #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
Пример #4
0
    def run(self, path):
        '''Executes the given file within the sandbox, and ensure the overall
        consistency of the executed script.'''
        self.exec_file(path)

        # All command line arguments should have been removed (handled) by now.
        for arg in self._helper:
            without_value = arg.split('=', 1)[0]
            if arg in self._implied_options:
                frameinfo, reason = self._implied_options[arg]
                raise ConfigureError(
                    '`%s`, emitted from `%s` line `%d`, was not handled.' %
                    (without_value, frameinfo[1], frameinfo[2]))
            raise InvalidOptionError('Unknown option: %s' % without_value)

        # All options must be referenced by some @depends function
        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(self.log_impl.info) as out:
                self._help.usage(out)
Пример #5
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)

            value = self._resolve(implied_option.value,
                                  need_help_dependency=False)

            if value is not None:
                if isinstance(value, OptionValue):
                    pass
                elif value is True:
                    value = PositiveOptionValue()
                elif value is False or value == ():
                    value = NegativeOptionValue()
                elif isinstance(value, types.StringTypes):
                    value = PositiveOptionValue((value,))
                elif isinstance(value, tuple):
                    value = PositiveOptionValue(value)
                else:
                    raise TypeError("Unexpected type: '%s'"
                                    % type(value).__name__)

                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 option_string:
            self._raw_options[option] = option_string

        return value
Пример #6
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 self._options.itervalues():
            # 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,
                                  need_help_dependency=False)
            if value is not None:
                raise ConfigureError(
                    '`%s`, emitted from `%s` line %d, is unknown.'
                    % (implied_option.option, implied_option.caller[1],
                       implied_option.caller[2]))

        # 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)
Пример #7
0
    def option_impl(self, *args, **kwargs):
        '''Implementation of option()
        This function creates and returns an Option() object, passing it the
        resolved arguments (uses the result of functions when functions are
        passed). In most cases, the result of this function is not expected to
        be used.
        Command line argument/environment variable parsing for this Option is
        handled here.
        '''
        args = [self._resolve(arg) for arg in args]
        kwargs = {k: self._resolve(v) for k, v in kwargs.iteritems()}
        option = Option(*args, **kwargs)
        if option.name in self._options:
            raise ConfigureError('Option `%s` already defined' %
                                 self._options[option.name].option)
        if option.env in self._options:
            raise ConfigureError('Option `%s` already defined' %
                                 self._options[option.env].option)
        if option.name:
            self._options[option.name] = option
        if option.env:
            self._options[option.env] = option

        try:
            value, option_string = self._helper.handle(option)
        except ConflictingOptionError as e:
            frameinfo, reason = self._implied_options[e.arg]
            raise InvalidOptionError(
                "'%s' implied by '%s' conflicts with '%s' from the %s" %
                (e.arg, reason, e.old_arg, e.old_origin))

        if self._help:
            self._help.add(option)

        self._option_values[option] = value
        self._raw_options[option] = (option_string.split('=', 1)[0]
                                     if option_string else option_string)
        return option
Пример #8
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:
                if isinstance(value, OptionValue):
                    pass
                elif value is True:
                    value = PositiveOptionValue()
                elif value is False or value == ():
                    value = NegativeOptionValue()
                elif isinstance(value, types.StringTypes):
                    value = PositiveOptionValue((value, ))
                elif isinstance(value, tuple):
                    value = PositiveOptionValue(value)
                else:
                    raise TypeError("Unexpected type: '%s'" %
                                    type(value).__name__)

                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 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])
            return None

        return value