Пример #1
0
def get_message_offset(msg, base_interval=None):
    """Return deprecated message offset, or None.

    TODO - this function can be deleted once the deprecated cycle point offset
    placeholders are removed from cylc (see GitHub #1761).

    """

    offset = None
    global warned

    # cylc-5 [T+n] message offset - DEPRECATED
    m = BCOMPAT_MSG_RE_C5.match(msg)
    if m:
        if not warned:
            print >> sys.stderr, DEPRECN_WARN_TMPL % msg
            warned = True
        prefix, signed_offset, sign, offset, suffix = m.groups()
        if signed_offset is not None:
            offset = base_interval.get_inferred_child(
                signed_offset)
    else:
        # cylc-6 [<interval>] message offset - DEPRECATED
        n = BCOMPAT_MSG_RE_C6.match(msg)
        if n:
            if not warned:
                print >> sys.stderr, DEPRECN_WARN_TMPL % msg
                warned = True
            prefix, signed_offset, sign, offset, suffix = n.groups()
            if offset:
                offset = get_interval(signed_offset)
            else:
                offset = get_interval_cls().get_null()
        # else: Plain message, no offset.
    return offset
Пример #2
0
def get_message_offset(msg, base_interval=None):
    """Return deprecated message offset, or None.

    TODO - this function can be deleted once the deprecated cycle point offset
    placeholders are removed from cylc (see GitHub #1761).

    """

    offset = None
    global warned

    # cylc-5 [T+n] message offset - DEPRECATED
    m = BCOMPAT_MSG_RE_C5.match(msg)
    if m:
        if not warned:
            print >> sys.stderr, DEPRECN_WARN_TMPL % msg
            warned = True
        prefix, signed_offset, sign, offset, suffix = m.groups()
        if signed_offset is not None:
            offset = base_interval.get_inferred_child(signed_offset)
    else:
        # cylc-6 [<interval>] message offset - DEPRECATED
        n = BCOMPAT_MSG_RE_C6.match(msg)
        if n:
            if not warned:
                print >> sys.stderr, DEPRECN_WARN_TMPL % msg
                warned = True
            prefix, signed_offset, sign, offset, suffix = n.groups()
            if offset:
                offset = get_interval(signed_offset)
            else:
                offset = get_interval_cls().get_null()
        # else: Plain message, no offset.
    return offset
Пример #3
0
 def set_runahead(self, interval=None):
     if isinstance(interval, int) or isinstance(interval, basestring):
         # The unit is assumed to be hours (backwards compatibility).
         interval = str(interval)
         interval_cls = get_interval_cls()
         if interval_cls.TYPE == ISO8601_CYCLING_TYPE:
             interval = get_interval("PT%sH" % interval)
         else:
             interval = get_interval(interval)
     if interval is None:
         # No limit
         self.log.warning("setting NO custom runahead limit")
         self.custom_runahead_limit = None
     else:
         self.log.info("setting custom runahead limit to %s" % interval)
         self.custom_runahead_limit = interval
     self.release_runahead_tasks()
Пример #4
0
    def __init__(self,
                 task_name,
                 qualifier=None,
                 graph_offset_string=None,
                 cycle_point=None,
                 suicide=False,
                 outputs={},
                 base_interval=None):

        self.task_name = task_name
        self.suicide = suicide
        self.graph_offset_string = graph_offset_string
        self.cycle_point = cycle_point

        self.message = None
        self.message_offset = None
        self.builtin = None
        qualifier = qualifier or "succeeded"

        # Built-in trigger?
        try:
            self.builtin = task_state.get_legal_trigger_state(qualifier)
        except TaskStateError:
            pass
        else:
            return

        # Message trigger?
        try:
            msg = outputs[qualifier]
        except KeyError:
            raise TriggerError, ("ERROR: undefined trigger qualifier: %s:%s" %
                                 (task_name, qualifier))
        else:
            # Back compat for [T+n] in message string.
            m = re.match(BACK_COMPAT_MSG_RE, msg)
            msg_offset = None
            if m:
                prefix, signed_offset, sign, offset, suffix = m.groups()
                if offset:
                    msg_offset = base_interval.get_inferred_child(
                        signed_offset)
                else:
                    msg_offset = get_interval_cls().get_null()
            else:
                n = re.match(MSG_RE, msg)
                if n:
                    prefix, signed_offset, sign, offset, suffix = n.groups()
                    if offset:
                        msg_offset = get_interval(signed_offset)
                    else:
                        msg_offset = get_interval_cls().get_null()
                else:
                    raise TriggerError, (
                        "ERROR: undefined trigger qualifier: %s:%s" %
                        (task_name, qualifier))
            self.message = msg
            self.message_offset = msg_offset
Пример #5
0
 def _get_offset(self, offset=None):
     """Return and cache the standardised offset string."""
     if offset not in self._offsets:
         if offset:
             res = get_interval(offset).standardise()
         else:
             res = get_interval_cls().get_null_offset()
         self._offsets[offset] = str(res)
     return self._offsets[offset]
Пример #6
0
 def _get_offset(self, offset=None):
     """Return and cache the standardised offset string."""
     if offset not in self._offsets:
         if offset:
             res = get_interval(offset).standardise()
         else:
             res = get_interval_cls().get_null_offset()
         self._offsets[offset] = str(res)
     return self._offsets[offset]
Пример #7
0
    def __init__(
            self, task_name, qualifier=None, graph_offset_string=None,
            cycle_point=None, suicide=False, outputs={}, base_interval=None):

        self.task_name = task_name
        self.suicide = suicide
        self.graph_offset_string = graph_offset_string
        self.cycle_point = cycle_point

        self.message = None
        self.message_offset = None
        self.builtin = None
        qualifier = qualifier or "succeeded"

        # Built-in trigger?
        try:
            self.builtin = task_state.get_legal_trigger_state(qualifier)
        except TaskStateError:
            pass
        else:
            return

        # Message trigger?
        try:
            msg = outputs[qualifier]
        except KeyError:
            raise TriggerError, (
                    "ERROR: undefined trigger qualifier: %s:%s" % (
                        task_name, qualifier)
            )
        else:
            # Back compat for [T+n] in message string.
            m = re.match(BACK_COMPAT_MSG_RE, msg)
            msg_offset = None
            if m:
                prefix, signed_offset, sign, offset, suffix = m.groups()
                if offset:
                    msg_offset = base_interval.get_inferred_child(signed_offset)
                else:
                    msg_offset = get_interval_cls().get_null()
            else:
                n = re.match(MSG_RE, msg)
                if n:
                    prefix, signed_offset, sign, offset, suffix = n.groups()
                    if offset:
                        msg_offset = get_interval(signed_offset)
                    else:
                        msg_offset = get_interval_cls().get_null()
                else:
                    raise TriggerError, (
                            "ERROR: undefined trigger qualifier: %s:%s" % (
                                task_name, qualifier)
                    )
            self.message = msg
            self.message_offset = msg_offset
Пример #8
0
    def get_cleanup_cutoff_point(cls, my_point, offset_sequence_tuples):
        """Extract the max dependent cycle point for this point."""
        if not offset_sequence_tuples:
            # This task does not have dependent tasks at other cycles.
            return my_point
        cutoff_points = []
        for offset_string, sequence in offset_sequence_tuples:
            if offset_string is None:
                # This indicates a dependency that lasts for the whole run.
                return None
            if sequence is None:
                # This indicates a simple offset interval such as [-PT6H].
                cutoff_points.append(
                    my_point - get_interval(offset_string))
                continue
            if is_offset_absolute(offset_string):
                stop_point = sequence.get_stop_point()
                if stop_point:
                    # Stop point of the sequence is a good cutoff point for an
                    # absolute "offset"
                    cutoff_points.append(stop_point)
                    continue
                else:
                    # The dependency lasts for the whole run.
                    return None

            # This is a complicated offset like [02T00-P1W].
            dependent_point = sequence.get_start_point()

            my_cutoff_point = None
            while dependent_point is not None:
                # TODO: Is it realistically possible to hang in this loop?
                target_point = (
                    get_point_relative(offset_string, dependent_point))
                if target_point > my_point:
                    # Assume monotonic (target_point can never jump back).
                    break
                if target_point == my_point:
                    # We have found a dependent_point for my_point.
                    my_cutoff_point = dependent_point
                dependent_point = sequence.get_next_point_on_sequence(
                    dependent_point)
            if my_cutoff_point:
                # Choose the largest of the dependent points.
                cutoff_points.append(my_cutoff_point)
        if cutoff_points:
            max_cutoff_point = max(cutoff_points)
            if max_cutoff_point < my_point:
                # This is caused by future triggers - default to my_point.
                return my_point
            return max_cutoff_point
        # There aren't any dependent tasks in other cycles for my_point.
        return my_point
Пример #9
0
    def get_cleanup_cutoff_point(self, point):
        """Extract the max dependent cycle point for this point."""
        if not self.intercycle_offsets:
            # This task does not have dependent tasks at other cycles.
            return point
        cutoff_points = []
        for offset_string, sequence in self.intercycle_offsets:
            if offset_string is None:
                # This indicates a dependency that lasts for the whole run.
                return None
            if sequence is None:
                # This indicates a simple offset interval such as [-PT6H].
                cutoff_points.append(point - get_interval(offset_string))
                continue
            if is_offset_absolute(offset_string):
                stop_point = sequence.get_stop_point()
                if stop_point:
                    # Stop point of the sequence is a good cutoff point for an
                    # absolute "offset"
                    cutoff_points.append(stop_point)
                    continue
                else:
                    # The dependency lasts for the whole run.
                    return None

            # This is a complicated offset like [02T00-P1W].
            dependent_point = sequence.get_start_point()

            my_cutoff_point = None
            while dependent_point is not None:
                # TODO: Is it realistically possible to hang in this loop?
                target_point = (get_point_relative(offset_string,
                                                   dependent_point))
                if target_point > point:
                    # Assume monotonic (target_point can never jump back).
                    break
                if target_point == point:
                    # We have found a dependent_point for point.
                    my_cutoff_point = dependent_point
                dependent_point = sequence.get_next_point_on_sequence(
                    dependent_point)
            if my_cutoff_point:
                # Choose the largest of the dependent points.
                cutoff_points.append(my_cutoff_point)
        if cutoff_points:
            max_cutoff_point = max(cutoff_points)
            if max_cutoff_point < point:
                # This is caused by future triggers - default to point.
                return point
            return max_cutoff_point
        # There aren't any dependent tasks in other cycles for point.
        return point
Пример #10
0
    def get_cleanup_cutoff_point(cls, my_point, offset_sequence_tuples):
        """Extract the max dependent cycle point for this point."""
        if not offset_sequence_tuples:
            # This task does not have dependent tasks at other cycles.
            return my_point
        cutoff_points = []
        for offset_string, sequence in offset_sequence_tuples:
            if offset_string is None:
                # This indicates a dependency that lasts for the whole run.
                return None
            if sequence is None:
                # This indicates a simple offset interval such as [-PT6H].
                cutoff_points.append(my_point - get_interval(offset_string))
                continue
            # This is a complicated offset like [02T00-P1W].
            dependent_point = sequence.get_start_point()

            matching_dependent_points = []
            while dependent_point is not None:
                # TODO: Is it realistically possible to hang in this loop?
                target_point = (get_point_relative(offset_string,
                                                   dependent_point))
                if target_point > my_point:
                    # Assume monotonic (target_point can never jump back).
                    break
                if target_point == my_point:
                    # We have found a dependent_point for my_point.
                    matching_dependent_points.append(dependent_point)
                dependent_point = sequence.get_next_point_on_sequence(
                    dependent_point)
            if matching_dependent_points:
                # Choose the largest of the dependent points.
                cutoff_points.append(matching_dependent_points[-1])
        if cutoff_points:
            max_cutoff_point = max(cutoff_points)
            if max_cutoff_point < my_point:
                # This is caused by future triggers - default to my_point.
                return my_point
            return max_cutoff_point
        # There aren't any dependent tasks in other cycles for my_point.
        return my_point
Пример #11
0
    def __init__(self, node, base_interval=None):
        node_in = node
        # Get task name and properties from a graph node name.

        # Graph node name is task name optionally followed by:
        # - output label: foo:m1
        # - intercycle dependence: foo[T-6]
        # These may be combined: foo[T-6]:m1
        # Task may be defined at initial cycle point: foo[^]
        # or relative to initial cycle point: foo[^+P1D]

        self.offset_is_from_ict = False
        self.offset_is_irregular = False
        self.is_absolute = False

        m = re.match(NODE_ISO_ICT_RE, node)
        if m:
            # node looks like foo[^], foo[^-P4D], foo[^]:fail, etc.
            self.is_absolute = True
            name, offset_string, outp = m.groups()
            self.offset_is_from_ict = True
            sign = ""
            prev_format = False
            # Can't always set syntax here, as we use [^] for backwards comp.
        else:
            m = re.match(NODE_ISO_RE, node)
            if m:
                # node looks like foo, foo:fail, foo[-PT6H], foo[-P4D]:fail...
                name, offset_string, outp = m.groups()
                sign = ""
                prev_format = False
            else:
                raise GraphNodeError('Illegal graph node: ' + node)

        if outp:
            self.special_output = True
            self.output = outp[1:]  # strip ':'
        else:
            self.special_output = False
            self.output = None

        if name:
            self.name = name
        else:
            raise GraphNodeError('Illegal graph node: ' + node)

        if self.offset_is_from_ict and not offset_string:
            offset_string = str(get_interval_cls().get_null_offset())
        if offset_string:
            self.intercycle = True
            if prev_format:
                self.offset_string = str(
                    base_interval.get_inferred_child(offset_string))
            else:
                if IRREGULAR_OFFSET_RE.search(offset_string):
                    self.offset_string = offset_string
                    self.offset_is_irregular = True
                else:
                    self.offset_string = str(
                        (get_interval(offset_string)).standardise())
        else:
            self.intercycle = False
            self.offset_string = None
Пример #12
0
    def __init__(self, node, base_interval=None):
        node_in = node
        # Get task name and properties from a graph node name.

        # Graph node name is task name optionally followed by:
        # - output label: foo:m1
        # - intercycle dependence: foo[T-6]
        # These may be combined: foo[T-6]:m1
        # Task may be defined at initial cycle point: foo[^]
        # or relative to initial cycle point: foo[^+P1D]

        self.offset_is_from_ict = False
        self.offset_is_irregular = False
        self.is_absolute = False

        m = re.match(NODE_ISO_ICT_RE, node)
        if m:
            # node looks like foo[^], foo[^-P4D], foo[^]:fail, etc.
            self.is_absolute = True
            name, offset_string, outp = m.groups()
            self.offset_is_from_ict = True
            sign = ""
            prev_format = False
            # Can't always set syntax here, as we use [^] for backwards comp.
            if offset_string:
                set_syntax_version(
                    VERSION_NEW, "graphnode: %s: ISO 8601 offset" % node)
        else:
            m = re.match(NODE_ISO_RE, node)
            if m:
                # node looks like foo, foo:fail, foo[-PT6H], foo[-P4D]:fail...
                name, offset_string, outp = m.groups()
                sign = ""
                prev_format = False
                if offset_string:
                    set_syntax_version(
                        VERSION_NEW, "graphnode: %s: ISO 8601 offset" % node)
            else:
                m = re.match(NODE_PREV_RE, node)
                if not m:
                    raise GraphNodeError('Illegal graph node: ' + node)
                # node looks like foo[T-6], foo[T-12]:fail...
                name, sign, offset_string, outp = m.groups()
                if sign and offset_string:
                    offset_string = sign + offset_string
                prev_format = True
                set_syntax_version(
                    VERSION_PREV,
                    "graphnode %s: old-style offset" % node
                )

        if outp:
            self.special_output = True
            self.output = outp[1:]  # strip ':'
        else:
            self.special_output = False
            self.output = None

        if name:
            self.name = name
        else:
            raise GraphNodeError('Illegal graph node: ' + node)

        if self.offset_is_from_ict and not offset_string:
            offset_string = str(get_interval_cls().get_null_offset())
        if offset_string:
            self.intercycle = True
            if prev_format:
                self.offset_string = str(
                    base_interval.get_inferred_child(offset_string))
            else:
                if IRREGULAR_OFFSET_RE.search(offset_string):
                    self.offset_string = offset_string
                    self.offset_is_irregular = True
                else:
                    self.offset_string = str(
                        (get_interval(offset_string)).standardise())
        else:
            self.intercycle = False
            self.offset_string = None