Esempio n. 1
0
    def __init__(self, transDict, machine,
                 fromStateName):  # pylint: disable-msg=R0912
        """ Builds a _TransitionConfig from a dictionary representation. 
            This transition is not added to the machine. """

        self.machineName = machine.name

        # check for bad attributes
        badAttributes = set()
        for attribute in transDict.iterkeys():
            if attribute not in constants.VALID_TRANS_ATTRIBUTES:
                badAttributes.add(attribute)
        if badAttributes:
            raise exceptions.InvalidTransitionAttributeError(
                self.machineName, fromStateName, badAttributes)

        # transition event
        event = transDict.get(constants.TRANS_EVENT_ATTRIBUTE)
        if not event:
            raise exceptions.TransitionEventRequiredError(
                machine.name, fromStateName)
        try:
            # attempt to import the value of the event
            self.event = _resolveObject(event, machine.namespace)
        except (exceptions.UnknownModuleError, exceptions.UnknownClassError,
                exceptions.UnknownObjectError):
            # otherwise just use the value from the yaml
            self.event = event
        if not constants.NAME_RE.match(self.event):
            raise exceptions.InvalidTransitionEventNameError(
                self.machineName, fromStateName, self.event)

        # transition name
        self.name = '%s--%s' % (fromStateName, self.event)
        if not self.name:
            raise exceptions.TransitionNameRequiredError(self.machineName)
        if not constants.NAME_RE.match(self.name):
            raise exceptions.InvalidTransitionNameError(
                self.machineName, self.name)

        # transition from state
        if not fromStateName:
            raise exceptions.TransitionFromRequiredError(
                self.machineName, self.name)
        if fromStateName not in machine.states:
            raise exceptions.TransitionUnknownFromStateError(
                self.machineName, self.name, fromStateName)
        self.fromState = machine.states[fromStateName]

        # transition to state
        toStateName = transDict.get(constants.TRANS_TO_ATTRIBUTE)
        if not toStateName:
            raise exceptions.TransitionToRequiredError(self.machineName,
                                                       self.name)
        if toStateName not in machine.states:
            raise exceptions.TransitionUnknownToStateError(
                self.machineName, self.name, toStateName)
        self.toState = machine.states[toStateName]

        # transition namespace
        self.namespace = transDict.get(constants.NAMESPACE_ATTRIBUTE,
                                       machine.namespace)

        # transition task_retry_limit, min_backoff_seconds, max_backoff_seconds, task_age_limit, max_doublings
        # W0612:439:_TransitionConfig.__init__: Unused variable 'default'
        for (constant, attribute, default,
             exception) in TASK_ATTRIBUTES:  # pylint: disable-msg=W0612
            setattr(self, attribute,
                    getattr(machine, attribute))  # default from the machine
            if constant in transDict:
                setattr(self, attribute, transDict[constant])
                try:
                    i = int(getattr(self, attribute))
                    setattr(self, attribute, i)
                except ValueError:
                    raise exception(self.machineName, getattr(self, attribute))

        # if both max_retries and task_retry_limit specified, raise an exception
        if constants.MAX_RETRIES_ATTRIBUTE in transDict and constants.TASK_RETRY_LIMIT_ATTRIBUTE in transDict:
            raise exceptions.MaxRetriesAndTaskRetryLimitMutuallyExclusiveError(
                self.machineName)

        # transition maxRetries
        if constants.MAX_RETRIES_ATTRIBUTE in transDict:
            logging.warning(
                'max_retries is deprecated. Use task_retry_limit instead.')
            self.taskRetryLimit = transDict[constants.MAX_RETRIES_ATTRIBUTE]
            try:
                self.taskRetryLimit = int(self.taskRetryLimit)
            except ValueError:
                raise exceptions.InvalidMaxRetriesError(
                    self.name, self.taskRetryLimit)

        # transition countdown
        self.countdown = transDict.get(constants.TRANS_COUNTDOWN_ATTRIBUTE,
                                       constants.DEFAULT_COUNTDOWN)
        try:
            self.countdown = int(self.countdown)
        except ValueError:
            raise exceptions.InvalidCountdownError(self.countdown,
                                                   self.machineName,
                                                   self.fromState.name)
        if self.countdown and self.toState.fanInPeriod != constants.NO_FAN_IN:
            raise exceptions.UnsupportedConfigurationError(
                self.machineName, self.fromState.name,
                'Countdown cannot be specified on a transition to a fan_in state.'
            )

        # transition specific queue
        self.queueName = transDict.get(constants.QUEUE_NAME_ATTRIBUTE,
                                       machine.queueName)

        # resolve the class for action, if specified
        if constants.TRANS_ACTION_ATTRIBUTE in transDict:
            self.action = _resolveClass(
                transDict[constants.TRANS_ACTION_ATTRIBUTE], self.namespace)()
            if self.fromState.continuation:
                raise exceptions.UnsupportedConfigurationError(
                    self.machineName, self.fromState.name,
                    'Transition actions on transitions from continuation states are not supported.'
                )
            if self.toState.continuation:
                raise exceptions.UnsupportedConfigurationError(
                    self.machineName, self.fromState.name,
                    'Transition actions on transitions to continuation states are not supported.'
                )
            if self.fromState.fanInPeriod != constants.NO_FAN_IN:
                raise exceptions.UnsupportedConfigurationError(
                    self.machineName, self.fromState.name,
                    'Transition actions on transitions from fan_in states are not supported.'
                )
            if self.toState.fanInPeriod != constants.NO_FAN_IN:
                raise exceptions.UnsupportedConfigurationError(
                    self.machineName, self.fromState.name,
                    'Transition actions on transitions to fan_in states are not supported.'
                )
        else:
            self.action = None

        # test for exit actions when transitions to a continuation or a fan_in
        if self.toState.continuation and self.fromState.exit:
            raise exceptions.UnsupportedConfigurationError(
                self.machineName, self.fromState.name,
                'Exit actions on states with a transition to a continuation state are not supported.'
            )
        if self.toState.fanInPeriod != constants.NO_FAN_IN and self.fromState.exit:
            raise exceptions.UnsupportedConfigurationError(
                self.machineName, self.fromState.name,
                'Exit actions on states with a transition to a fan_in state are not supported.'
            )
Esempio n. 2
0
    def __init__(self, initDict, rootUrl=None):
        """ Configures the basic attributes of a machine. States and transitions are not handled
            here, but are added by an external client.
        """

        # machine name
        self.name = initDict.get(constants.MACHINE_NAME_ATTRIBUTE)
        if not self.name:
            raise exceptions.MachineNameRequiredError()
        if not constants.NAME_RE.match(self.name):
            raise exceptions.InvalidMachineNameError(self.name)

        # check for bad attributes
        badAttributes = set()
        for attribute in initDict.iterkeys():
            if attribute not in constants.VALID_MACHINE_ATTRIBUTES:
                badAttributes.add(attribute)
        if badAttributes:
            raise exceptions.InvalidMachineAttributeError(
                self.name, badAttributes)

        # machine queue, namespace
        self.queueName = initDict.get(constants.QUEUE_NAME_ATTRIBUTE,
                                      constants.DEFAULT_QUEUE_NAME)
        self.namespace = initDict.get(constants.NAMESPACE_ATTRIBUTE)

        # logging
        self.logging = initDict.get(constants.MACHINE_LOGGING_NAME_ATTRIBUTE,
                                    constants.LOGGING_DEFAULT)
        if self.logging not in constants.VALID_LOGGING_VALUES:
            raise exceptions.InvalidLoggingError(self.name, self.logging)

        # machine task_retry_limit, min_backoff_seconds, max_backoff_seconds, task_age_limit, max_doublings
        for (constant, attribute, default, exception) in TASK_ATTRIBUTES:
            setattr(self, attribute, default)
            if constant in initDict:
                setattr(self, attribute, initDict[constant])
                try:
                    i = int(getattr(self, attribute))
                    setattr(self, attribute, i)
                except ValueError:
                    raise exception(self.name, getattr(self, attribute))

        # if both max_retries and task_retry_limit specified, raise an exception
        if constants.MAX_RETRIES_ATTRIBUTE in initDict and constants.TASK_RETRY_LIMIT_ATTRIBUTE in initDict:
            raise exceptions.MaxRetriesAndTaskRetryLimitMutuallyExclusiveError(
                self.name)

        # machine max_retries - sets taskRetryLimit internally
        if constants.MAX_RETRIES_ATTRIBUTE in initDict:
            logging.warning(
                'max_retries is deprecated. Use task_retry_limit instead.')
            self.taskRetryLimit = initDict[constants.MAX_RETRIES_ATTRIBUTE]
            try:
                self.taskRetryLimit = int(self.taskRetryLimit)
            except ValueError:
                raise exceptions.InvalidMaxRetriesError(
                    self.name, self.taskRetryLimit)

        self.states = {}
        self.transitions = {}
        self.initialState = None
        self.finalStates = []

        # context types
        self.contextTypes = initDict.get(
            constants.MACHINE_CONTEXT_TYPES_ATTRIBUTE, {})
        for contextName, contextType in self.contextTypes.iteritems():
            self.contextTypes[contextName] = _resolveClass(
                contextType, self.namespace)

        self.rootUrl = rootUrl
        if not self.rootUrl:
            self.rootUrl = constants.DEFAULT_ROOT_URL
        elif not rootUrl.endswith('/'):
            self.rootUrl += '/'