예제 #1
0
    def test_parse_exclusions_list_spaces(self):
        """Tests the simple case of exclusion parsing"""
        expression = "PT1H!    (T03, T06,   T09)   "
        sequence, exclusion = parse_exclusion(expression)

        self.assertEqual(sequence, "PT1H")
        self.assertEqual(exclusion, ['T03', 'T06', 'T09'])
예제 #2
0
    def test_parse_exclusion_simple(self):
        """Tests the simple case of exclusion parsing"""
        expression = "PT1H!20000101T02Z"
        sequence, exclusion = parse_exclusion(expression)

        self.assertEqual(sequence, "PT1H")
        self.assertEqual(exclusion, ['20000101T02Z'])
예제 #3
0
    def test_parse_exclusions_list(self):
        """Tests the simple case of exclusion parsing"""
        expression = "PT1H!(T03, T06, T09)"
        sequence, exclusion = parse_exclusion(expression)

        self.assertEqual(sequence, "PT1H")
        self.assertEqual(exclusion, ['T03', 'T06', 'T09'])
예제 #4
0
    def test_parse_exclusion_simple(self):
        """Tests the simple case of exclusion parsing"""
        expression = "PT1H!20000101T02Z"
        sequence, exclusion = parse_exclusion(expression)

        self.assertEqual(sequence, "PT1H")
        self.assertEqual(exclusion, ['20000101T02Z'])
예제 #5
0
    def parse_recurrence(self,
                         expression,
                         context_start_point=None,
                         context_end_point=None):
        """Parse an expression in abbrev. or full ISO recurrence format."""
        expression, exclusion = parse_exclusion(expression)
        if context_start_point is None:
            context_start_point = self.context_start_point
        if context_end_point is None:
            context_end_point = self.context_end_point
        for rec_object, format_num in self._recur_format_recs:
            result = rec_object.search(expression)
            if not result:
                continue
            props = {}
            repetitions = result.groupdict().get("reps")
            if repetitions is not None:
                repetitions = int(repetitions)
            start = result.groupdict().get("start")
            end = result.groupdict().get("end")
            start_required = (format_num in [1, 3])
            end_required = (format_num in [1, 4])
            start_point, start_offset = self._get_point_from_expression(
                start,
                context_start_point,
                is_required=start_required,
                allow_truncated=True)
            try:
                end_point, end_offset = self._get_point_from_expression(
                    end,
                    context_end_point,
                    is_required=end_required,
                    allow_truncated=True)
            except CylcMissingContextPointError:
                raise CylcMissingFinalCyclePointError(
                    "This suite requires a final cycle point.")
            exclusion_point = None
            if exclusion:
                exclusion_point, excl_off = self._get_point_from_expression(
                    exclusion, None, is_required=False, allow_truncated=False)
                if excl_off:
                    exclusion_point += excl_off
            intv = result.groupdict().get("intv")
            intv_context_truncated_point = None
            if start_point is not None and start_point.truncated:
                intv_context_truncated_point = start_point
            if end_point is not None and end_point.truncated:
                intv_context_truncated_point = end_point
            interval = self._get_interval_from_expression(
                intv, context=intv_context_truncated_point)
            if format_num == 1:
                interval = None
            if repetitions == 1:
                # Set arbitrary interval (does not matter).
                interval = self.duration_parser.parse("P0Y")
            if start_point is not None:
                if start_point.truncated:
                    start_point += context_start_point
                if start_offset is not None:
                    start_point += start_offset
            if end_point is not None:
                if end_point.truncated:
                    end_point += context_end_point
                if end_offset is not None:
                    end_point += end_offset

            if (start_point is None and repetitions is None
                    and interval is not None
                    and context_start_point is not None):
                # isodatetime only reverses bounded end-point recurrences.
                # This is unbounded, and will come back in reverse order.
                # We need to reverse it.
                start_point = end_point
                repetitions = 1
                while start_point > context_start_point:
                    start_point -= interval
                    repetitions += 1
                end_point = None

            return isodatetime.data.TimeRecurrence(
                repetitions=repetitions,
                start_point=start_point,
                duration=interval,
                end_point=end_point), exclusion_point

        raise CylcTimeSyntaxError("Could not parse %s" % expression)
예제 #6
0
파일: integer.py 프로젝트: DamianAgius/cylc
    def __init__(self, dep_section, p_context_start, p_context_stop=None):
        """Parse state (start, stop, interval) from a graph section heading.
        The start and stop points are always on-sequence, context points
        might not be. If computed start and stop points are out of bounds,
        they will be set to None. Context is used only initially to define
        the sequence bounds."""
        SequenceBase.__init__(self, dep_section, p_context_start,
                              p_context_stop)

        # start context always exists
        self.p_context_start = IntegerPoint(p_context_start)
        # stop context may exist
        if p_context_stop:
            self.p_context_stop = IntegerPoint(p_context_stop)
        else:
            self.p_context_stop = None

        # state variables: start, stop, and step
        self.p_start = None
        self.p_stop = None
        self.i_step = None

        # offset must be stored to compute the runahead limit
        self.i_offset = IntegerInterval('P0')

        self.exclusions = None

        matched_recurrence = False
        expression, excl_points = parse_exclusion(dep_section)

        for rec, format_num in RECURRENCE_FORMAT_RECS:
            results = rec.match(expression)
            if not results:
                continue
            matched_recurrence = True
            reps = results.groupdict().get("reps")
            if reps is not None:
                reps = int(reps)
            start = results.groupdict().get("start")
            stop = results.groupdict().get("end")
            intv = results.groupdict().get("intv")
            if not start:
                start = None
            if not stop:
                stop = None
            if not intv:
                intv = None
            start_required = (format_num in [1, 3])
            end_required = (format_num in [1, 4])
            break

        if not matched_recurrence:
            raise ValueError("ERROR, bad integer cycling format: %s" %
                             expression)

        self.p_start = get_point_from_expression(start,
                                                 self.p_context_start,
                                                 is_required=start_required)
        self.p_stop = get_point_from_expression(stop,
                                                self.p_context_stop,
                                                is_required=end_required)
        if intv:
            self.i_step = IntegerInterval(intv)
        if format_num == 3:
            # REPEAT/START/PERIOD
            if not intv or reps is not None and reps <= 1:
                # one-off
                self.i_step = None
                self.p_stop = self.p_start
            else:
                self.i_step = IntegerInterval(intv)
                if reps:
                    self.p_stop = self.p_start + self.i_step * (reps - 1)
                elif self.p_context_stop:
                    # stop at the point <= self.p_context_stop
                    # use p_start as an on-sequence reference
                    remainder = (int(self.p_context_stop - self.p_start) %
                                 int(self.i_step))
                    self.p_stop = (self.p_context_stop -
                                   IntegerInterval.from_integer(remainder))
        elif format_num == 1:
            # REPEAT/START/STOP
            if reps == 1:
                # one-off: ignore stop point
                self.i_step = None
                self.p_stop = self.p_start
            else:
                self.i_step = IntegerInterval.from_integer(
                    int(self.p_stop - self.p_start) / (reps - 1))
        else:
            # This means that format_num == 4.
            # REPEAT/PERIOD/STOP
            if reps is not None:
                if reps <= 1:
                    # one-off
                    self.p_start = self.p_stop
                    self.i_step = None
                else:
                    self.i_step = IntegerInterval(intv)
                    self.p_start = (self.p_stop - self.i_step * (reps - 1))
            else:
                remainder = (int(self.p_context_stop - self.p_start) %
                             int(self.i_step))
                self.p_start = (self.p_context_start -
                                IntegerInterval.from_integer(remainder))

        if self.i_step and self.i_step < IntegerInterval.get_null():
            # (TODO - this should be easy to handle but needs testing)
            raise ValueError(
                "ERROR, negative intervals not supported yet: %s" %
                self.i_step)

        if self.i_step and self.p_start < self.p_context_start:
            # start from first point >= context start
            remainder = (int(self.p_context_start - self.p_start) %
                         int(self.i_step))
            self.p_start = (self.p_context_start +
                            IntegerInterval.from_integer(remainder))
            # if i_step is None here, points will just be None (out of bounds)

        if (self.i_step and self.p_stop and self.p_context_stop
                and self.p_stop > self.p_context_stop):
            # stop at first point <= context stop
            remainder = (int(self.p_context_stop - self.p_start) %
                         int(self.i_step))
            self.p_stop = (self.p_context_stop - self.i_step +
                           IntegerInterval.from_integer(remainder))
            # if i_step is None here, points will just be None (out of bounds)

        # Create a list of multiple exclusion points, if there are any.
        if excl_points:
            self.exclusions = IntegerExclusions(excl_points, self.p_start,
                                                self.p_stop)
        else:
            self.exclusions = None
예제 #7
0
파일: integer.py 프로젝트: trwhitcomb/cylc
    def __init__(self, dep_section, p_context_start, p_context_stop=None):
        """Parse state (start, stop, interval) from a graph section heading.
        The start and stop points are always on-sequence, context points
        might not be. If computed start and stop points are out of bounds,
        they will be set to None. Context is used only initially to define
        the sequence bounds."""
        SequenceBase.__init__(
            self, dep_section, p_context_start, p_context_stop)

        # start context always exists
        self.p_context_start = IntegerPoint(p_context_start)
        # stop context may exist
        if p_context_stop:
            self.p_context_stop = IntegerPoint(p_context_stop)
        else:
            self.p_context_stop = None

        # state variables: start, stop, and step
        self.p_start = None
        self.p_stop = None
        self.i_step = None

        # offset must be stored to compute the runahead limit
        self.i_offset = IntegerInterval('P0')

        self.exclusions = None

        matched_recurrence = False
        expression, excl_points = parse_exclusion(dep_section)

        for rec, format_num in RECURRENCE_FORMAT_RECS:
            results = rec.match(expression)
            if not results:
                continue
            matched_recurrence = True
            reps = results.groupdict().get("reps")
            if reps is not None:
                reps = int(reps)
            start = results.groupdict().get("start")
            stop = results.groupdict().get("end")
            intv = results.groupdict().get("intv")
            if not start:
                start = None
            if not stop:
                stop = None
            if not intv:
                intv = None
            start_required = (format_num in [1, 3])
            end_required = (format_num in [1, 4])
            break

        if not matched_recurrence:
            raise ValueError(
                "ERROR, bad integer cycling format: %s" % expression)

        self.p_start = get_point_from_expression(
            start, self.p_context_start, is_required=start_required)
        self.p_stop = get_point_from_expression(
            stop, self.p_context_stop, is_required=end_required)
        if intv:
            self.i_step = IntegerInterval(intv)
        if format_num == 3:
            # REPEAT/START/PERIOD
            if not intv or reps is not None and reps <= 1:
                # one-off
                self.i_step = None
                self.p_stop = self.p_start
            else:
                self.i_step = IntegerInterval(intv)
                if reps:
                    self.p_stop = self.p_start + self.i_step * (reps - 1)
                elif self.p_context_stop:
                    # stop at the point <= self.p_context_stop
                    # use p_start as an on-sequence reference
                    remainder = (int(self.p_context_stop - self.p_start) %
                                 int(self.i_step))
                    self.p_stop = (
                        self.p_context_stop - IntegerInterval.from_integer(
                            remainder)
                    )
        elif format_num == 1:
            # REPEAT/START/STOP
            if reps == 1:
                # one-off: ignore stop point
                self.i_step = None
                self.p_stop = self.p_start
            else:
                self.i_step = IntegerInterval.from_integer(
                    int(self.p_stop - self.p_start) / (reps - 1)
                )
        else:
            # This means that format_num == 4.
            # REPEAT/PERIOD/STOP
            if reps is not None:
                if reps <= 1:
                    # one-off
                    self.p_start = self.p_stop
                    self.i_step = None
                else:
                    self.i_step = IntegerInterval(intv)
                    self.p_start = (
                        self.p_stop - self.i_step * (reps - 1))
            else:
                remainder = (int(self.p_context_stop - self.p_start) %
                             int(self.i_step))
                self.p_start = (
                    self.p_context_start - IntegerInterval.from_integer(
                        remainder)
                )

        if self.i_step and self.i_step < IntegerInterval.get_null():
            # (TODO - this should be easy to handle but needs testing)
            raise ValueError(
                "ERROR, negative intervals not supported yet: %s" %
                self.i_step
            )

        if self.i_step and self.p_start < self.p_context_start:
            # start from first point >= context start
            remainder = (
                int(self.p_context_start - self.p_start) % int(self.i_step))
            self.p_start = (
                self.p_context_start + IntegerInterval.from_integer(
                    remainder)
            )
            # if i_step is None here, points will just be None (out of bounds)

        if (self.i_step and self.p_stop and self.p_context_stop and
                self.p_stop > self.p_context_stop):
            # stop at first point <= context stop
            remainder = (
                int(self.p_context_stop - self.p_start) % int(self.i_step))
            self.p_stop = (
                self.p_context_stop - self.i_step +
                IntegerInterval.from_integer(remainder)
            )
            # if i_step is None here, points will just be None (out of bounds)

        # Create a list of multiple exclusion points, if there are any.
        if excl_points:
            self.exclusions = IntegerExclusions(excl_points,
                                                self.p_start, self.p_stop)
        else:
            self.exclusions = None
예제 #8
0
    def parse_recurrence(self, expression, context_start_point=None, context_end_point=None):
        """Parse an expression in abbrev. or full ISO recurrence format."""
        expression, exclusion = parse_exclusion(expression)
        if context_start_point is None:
            context_start_point = self.context_start_point
        if context_end_point is None:
            context_end_point = self.context_end_point
        for rec_object, format_num in self._recur_format_recs:
            result = rec_object.search(expression)
            if not result:
                continue
            props = {}
            repetitions = result.groupdict().get("reps")
            if repetitions is not None:
                repetitions = int(repetitions)
            start = result.groupdict().get("start")
            end = result.groupdict().get("end")
            start_required = format_num in [1, 3]
            end_required = format_num in [1, 4]
            start_point, start_offset = self._get_point_from_expression(
                start, context_start_point, is_required=start_required, allow_truncated=True
            )
            try:
                end_point, end_offset = self._get_point_from_expression(
                    end, context_end_point, is_required=end_required, allow_truncated=True
                )
            except CylcMissingContextPointError:
                raise CylcMissingFinalCyclePointError("This suite requires a final cycle point.")
            exclusion_point = None
            if exclusion:
                exclusion_point, excl_off = self._get_point_from_expression(
                    exclusion, None, is_required=False, allow_truncated=False
                )
                if excl_off:
                    exclusion_point += excl_off
            intv = result.groupdict().get("intv")
            intv_context_truncated_point = None
            if start_point is not None and start_point.truncated:
                intv_context_truncated_point = start_point
            if end_point is not None and end_point.truncated:
                intv_context_truncated_point = end_point
            interval = self._get_interval_from_expression(intv, context=intv_context_truncated_point)
            if format_num == 1:
                interval = None
            if repetitions == 1:
                # Set arbitrary interval (does not matter).
                interval = self.duration_parser.parse("P0Y")
            if start_point is not None:
                if start_point.truncated:
                    start_point += context_start_point
                if start_offset is not None:
                    start_point += start_offset
            if end_point is not None:
                if end_point.truncated:
                    end_point += context_end_point
                if end_offset is not None:
                    end_point += end_offset

            if start_point is None and repetitions is None and interval is not None and context_start_point is not None:
                # isodatetime only reverses bounded end-point recurrences.
                # This is unbounded, and will come back in reverse order.
                # We need to reverse it.
                start_point = end_point
                repetitions = 1
                while start_point > context_start_point:
                    start_point -= interval
                    repetitions += 1
                end_point = None

            return (
                isodatetime.data.TimeRecurrence(
                    repetitions=repetitions, start_point=start_point, duration=interval, end_point=end_point
                ),
                exclusion_point,
            )

        raise CylcTimeSyntaxError("Could not parse %s" % expression)