Esempio n. 1
0
def _advance_recurring_todo_helper(p_todo, p_offset):
    """
    Given a Todo item, return a new instance of a Todo item with the dates
    shifted according to the recurrence rule.

    The new date is calculated from the given p_offset value.

    When no recurrence tag is present, an exception is raised.
    """

    todo = Todo(p_todo.source())
    pattern = todo.tag_value('rec')

    if not pattern:
        raise NoRecurrenceException()

    length = todo.length()
    new_due = relative_date_to_date(pattern, p_offset)

    if not new_due:
        raise NoRecurrenceException()

    # pylint: disable=E1103
    todo.set_tag(config().tag_due(), new_due.isoformat())

    if todo.start_date():
        new_start = new_due - timedelta(length)
        todo.set_tag(config().tag_start(), new_start.isoformat())

    todo.set_creation_date(date.today())

    return todo
Esempio n. 2
0
    def match(self, p_todo):
        """
        Performs a match on a key:value tag in the todo.

        First it tries to convert the value and the user-entered expression to
        a date and makes a comparison if it succeeds, based on the given
        operator (default ==).
        Upon failure, it falls back to converting value and user-entered
        expression to an integer and makes a numerical comparison based on the
        given operator (default ==)
        As a last resort, it falls back to using a Grep filter to see if the
        user given expression is contained in the todo text.
        """
        if not self.key or not p_todo.has_tag(self.key):
            return False

        try:
            operand1 = date_string_to_date(p_todo.tag_value(self.key))
            operand2 = relative_date_to_date(self.value)

            if not operand2:
                operand2 = date_string_to_date(self.value)

        except ValueError:
            operand1 = p_todo.tag_value(self.key)
            operand2 = self.value

            try:
                operand1 = int(operand1)
                operand2 = int(operand2)
            except ValueError:
                grep = GrepFilter(self.expression)
                return grep.match(p_todo)

        return self.compare_operands(operand1, operand2)
Esempio n. 3
0
 def test_weekday_next_week(self):
     """
     When entering "Friday" on a Friday, return next week Friday instead of
     today.
     """
     result = relative_date_to_date("fri")
     self.assertTrue(result, self.friday)
Esempio n. 4
0
        def convert_date(p_tag):
            value = self.todo.tag_value(p_tag)

            if value:
                dateobj = relative_date_to_date(value)
                if dateobj:
                    self.todo.set_tag(p_tag, dateobj.isoformat())
Esempio n. 5
0
    def _execute_multi_specific(self):
        def _get_offset(p_todo):
            offset = p_todo.tag_value(
                config().tag_due(), date.today().isoformat())
            offset_date = date_string_to_date(offset)

            if offset_date < date.today():
                offset_date = date.today()

            return offset_date

        pattern = self.args[-1]
        self.printer.add_filter(PrettyPrinterNumbers(self.todolist))

        for todo in self.todos:
            offset = _get_offset(todo)
            new_due = relative_date_to_date(pattern, offset)

            if new_due:
                if self.move_start_date and todo.has_tag(config().tag_start()):
                    length = todo.length()
                    new_start = new_due - timedelta(length)
                    # pylint: disable=E1103
                    todo.set_tag(config().tag_start(), new_start.isoformat())

                # pylint: disable=E1103
                todo.set_tag(config().tag_due(), new_due.isoformat())

                self.todolist.set_dirty()
                self.out(self.printer.print_todo(todo))
            else:
                self.error("Invalid date pattern given.")
                break
Esempio n. 6
0
 def test_weekday_next_week(self):
     """
     When entering "Friday" on a Friday, return next week Friday instead of
     today.
     """
     result = relative_date_to_date("fri")
     self.assertTrue(result, self.friday)
Esempio n. 7
0
    def _execute_multi_specific(self):
        def _get_offset(p_todo):
            offset = p_todo.tag_value(config().tag_due(),
                                      date.today().isoformat())
            offset_date = date_string_to_date(offset)

            if offset_date < date.today():
                offset_date = date.today()

            return offset_date

        pattern = self.args[-1]
        self.printer.add_filter(PrettyPrinterNumbers(self.todolist))

        for todo in self.todos:
            offset = _get_offset(todo)
            new_due = relative_date_to_date(pattern, offset)

            if new_due:
                if self.move_start_date and todo.has_tag(config().tag_start()):
                    length = todo.length()
                    new_start = new_due - timedelta(length)
                    # pylint: disable=E1103
                    todo.set_tag(config().tag_start(), new_start.isoformat())

                # pylint: disable=E1103
                todo.set_tag(config().tag_due(), new_due.isoformat())

                self.todolist.set_dirty()
                self.out(self.printer.print_todo(todo))
            else:
                self.error("Invalid date pattern given.")
                break
Esempio n. 8
0
    def match(self, p_todo):
        if not self.key or not p_todo.has_tag(self.key):
            return False

        try:
            operand1 = date_string_to_date(p_todo.tag_value(self.key))
            operand2 = relative_date_to_date(self.value)

            if not operand2:
                operand2 = date_string_to_date(self.value)

        except ValueError:
            try:
                operand1 = int(p_todo.tag_value(self.key))
                operand2 = int(self.value)
            except ValueError:
                return False

        if self.operator == '<':
            return operand1 < operand2
        elif self.operator == '<=':
            return operand1 <= operand2
        elif self.operator == '=':
            return operand1 == operand2
        elif self.operator == '>=':
            return operand1 >= operand2
        elif self.operator == '>':
            return operand1 > operand2
        elif self.operator == '!':
            return operand1 != operand2

        return False
Esempio n. 9
0
def _advance_recurring_todo_helper(p_todo, p_offset):
    """
    Given a Todo item, return a new instance of a Todo item with the dates
    shifted according to the recurrence rule.

    The new date is calculated from the given p_offset value.

    When no recurrence tag is present, an exception is raised.
    """

    todo = Todo(p_todo.source())
    pattern = todo.tag_value('rec')

    if not pattern:
        raise NoRecurrenceException()

    length = todo.length()
    new_due = relative_date_to_date(pattern, p_offset)

    if not new_due:
        raise NoRecurrenceException()

    # pylint: disable=E1103
    todo.set_tag(config().tag_due(), new_due.isoformat())

    if todo.start_date():
        new_start = new_due - timedelta(length)
        todo.set_tag(config().tag_start(), new_start.isoformat())

    todo.set_creation_date(date.today())

    return todo
Esempio n. 10
0
            def convert_date(p_tag):
                value = p_todo.tag_value(p_tag)

                if value:
                    dateobj = relative_date_to_date(value)
                    if dateobj:
                        p_todo.set_tag(p_tag, dateobj.isoformat())
Esempio n. 11
0
    def test_one_month_ext(self):
        test_date1 = date(2015, 1, 29)
        test_date2 = date(2016, 1, 31)
        test_date3 = date(2015, 12, 31)
        test_date4 = date(2015, 7, 31)
        test_date5 = date(2015, 10, 31)

        result1 = relative_date_to_date('1m', test_date1)
        result2 = relative_date_to_date('1m', test_date2)
        result3 = relative_date_to_date('1m', test_date3)
        result4 = relative_date_to_date('1m', test_date4)
        result5 = relative_date_to_date('1m', test_date5)

        self.assertEqual(result1, date(2015, 2, 28))
        self.assertEqual(result2, date(2016, 2, 29))
        self.assertEqual(result3, date(2016, 1, 31))
        self.assertEqual(result4, date(2015, 8, 31))
        self.assertEqual(result5, date(2015, 11, 30))
Esempio n. 12
0
    def test_one_month_ext(self):
        test_date1 = date(2015, 1, 29)
        test_date2 = date(2016, 1, 31)
        test_date3 = date(2015, 12, 31)
        test_date4 = date(2015, 7, 31)
        test_date5 = date(2015, 10, 31)

        result1 = relative_date_to_date('1m', test_date1)
        result2 = relative_date_to_date('1m', test_date2)
        result3 = relative_date_to_date('1m', test_date3)
        result4 = relative_date_to_date('1m', test_date4)
        result5 = relative_date_to_date('1m', test_date5)

        self.assertEqual(result1, date(2015, 2, 28))
        self.assertEqual(result2, date(2016, 2, 29))
        self.assertEqual(result3, date(2016, 1, 31))
        self.assertEqual(result4, date(2015, 8, 31))
        self.assertEqual(result5, date(2015, 11, 30))
Esempio n. 13
0
    def _convert_relative_dates(self):
        is_start_tag = self.tag == config().tag_start()
        is_due_tag = self.tag == config().tag_due()

        if self.relative_date or is_start_tag or is_due_tag:
            real_date = relative_date_to_date(self.value)

            if real_date:
                self.value = real_date.isoformat()
Esempio n. 14
0
    def _convert_relative_dates(self):
        is_start_tag = self.tag == config().tag_start()
        is_due_tag = self.tag == config().tag_due()

        if self.relative_date or is_start_tag or is_due_tag:
            real_date = relative_date_to_date(self.value)

            if real_date:
                self.value = real_date.isoformat()
Esempio n. 15
0
    def match(self, p_todo):
        operand1 = self.getter(p_todo)
        operand2 = relative_date_to_date(self.value)

        if not operand2:
            operand2 = date_string_to_date(self.value)

        if operand1 and operand2:
            return self.compare_operands(operand1, operand2)
        else:
            return False
Esempio n. 16
0
    def _dates(self, p_word_before_cursor):
        to_absolute = lambda s: relative_date_to_date(s).isoformat()

        start_value_pos = p_word_before_cursor.find(':') + 1
        value = p_word_before_cursor[start_value_pos:]

        for reldate in _date_suggestions():
            if not reldate.startswith(value):
                continue

            yield Completion(reldate, -len(value), display_meta=to_absolute(reldate))
Esempio n. 17
0
    def match(self, p_todo):
        operand1 = self.getter(p_todo)
        operand2 = relative_date_to_date(self.value)

        if not operand2:
            operand2 = date_string_to_date(self.value)

        if operand1 and operand2:
            return self.compare_operands(operand1, operand2)
        else:
            return False
Esempio n. 18
0
    def process_flag(self, p_opt, p_value):
        super().process_flag(p_opt, p_value)

        if p_opt == "-s" or p_opt == "--strict":
            self.strict_recurrence = True
        elif p_opt == "-d" or p_opt == "--date":
            try:
                self.completion_date = relative_date_to_date(p_value)

                if not self.completion_date:
                    self.completion_date = date_string_to_date(p_value)
            except ValueError:
                self.completion_date = date.today()
Esempio n. 19
0
    def process_flag(self, p_opt, p_value):
        super().process_flag(p_opt, p_value)

        if p_opt == "-s" or p_opt == "--strict":
            self.strict_recurrence = True
        elif p_opt == "-d" or p_opt == "--date":
            try:
                self.completion_date = relative_date_to_date(p_value)

                if not self.completion_date:
                    self.completion_date = date_string_to_date(p_value)
            except ValueError:
                self.completion_date = date.today()
Esempio n. 20
0
    def match(self, p_todo):
        """
        Performs a match on a key:value tag in the todo.

        First it tries to convert the value and the user-entered expression to
        a date and makes a comparison if it succeeds, based on the given
        operator (default ==).
        Upon failure, it falls back to converting value and user-entered
        expression to an integer and makes a numerical comparison based on the
        given operator (default ==)
        As a last resort, it falls back to using a Grep filter to see if the
        user given expression is contained in the todo text.
        """
        if not self.key or not p_todo.has_tag(self.key):
            return False

        try:
            operand1 = date_string_to_date(p_todo.tag_value(self.key))
            operand2 = relative_date_to_date(self.value)

            if not operand2:
                operand2 = date_string_to_date(self.value)

        except ValueError:
            operand1 = p_todo.tag_value(self.key)
            operand2 = self.value

            try:
                operand1 = int(operand1)
                operand2 = int(operand2)
            except ValueError:
                grep = GrepFilter(self.expression)
                return grep.match(p_todo)

        if self.operator == '<':
            return operand1 < operand2
        elif self.operator == '<=':
            return operand1 <= operand2
        elif self.operator == '=':
            return operand1 == operand2
        elif self.operator == '>=':
            return operand1 >= operand2
        elif self.operator == '>':
            return operand1 > operand2
        elif self.operator == '!':
            return operand1 != operand2

        return False
Esempio n. 21
0
def advance_recurring_todo(p_todo, p_offset=None, p_strict=False):
    """
    Given a Todo item, return a new instance of a Todo item with the dates
    shifted according to the recurrence rule.

    Strict means that the real due date is taken as a offset, not today or a
    future date to determine the offset.

    When the todo item has no due date, then the date is used passed by the
    caller (defaulting to today).

    When no recurrence tag is present, an exception is raised.
    """
    todo = Todo(p_todo.source())
    pattern = todo.tag_value('rec')

    if not pattern:
        raise NoRecurrenceException()
    elif pattern.startswith('+'):
        p_strict = True
        # strip off the +
        pattern = pattern[1:]

    if p_strict:
        offset = p_todo.due_date() or p_offset or date.today()
    else:
        offset = p_offset or date.today()

    length = todo.length()
    new_due = relative_date_to_date(pattern, offset)

    if not new_due:
        raise NoRecurrenceException()

    # pylint: disable=E1103
    todo.set_tag(config().tag_due(), new_due.isoformat())

    if todo.start_date():
        new_start = new_due - timedelta(length)
        todo.set_tag(config().tag_start(), new_start.isoformat())

    if config().auto_creation_date():
        todo.set_creation_date(date.today())

    return todo
Esempio n. 22
0
def advance_recurring_todo(p_todo, p_offset=None, p_strict=False):
    """
    Given a Todo item, return a new instance of a Todo item with the dates
    shifted according to the recurrence rule.

    Strict means that the real due date is taken as a offset, not today or a
    future date to determine the offset.

    When the todo item has no due date, then the date is used passed by the
    caller (defaulting to today).

    When no recurrence tag is present, an exception is raised.
    """
    todo = Todo(p_todo.source())
    pattern = todo.tag_value('rec')

    if not pattern:
        raise NoRecurrenceException()
    elif pattern.startswith('+'):
        p_strict = True
        # strip off the +
        pattern = pattern[1:]

    if p_strict:
        offset = p_todo.due_date() or p_offset or date.today()
    else:
        offset = p_offset or date.today()

    length = todo.length()
    new_due = relative_date_to_date(pattern, offset)

    if not new_due:
        raise NoRecurrenceException()

    # pylint: disable=E1103
    todo.set_tag(config().tag_due(), new_due.isoformat())

    if todo.start_date():
        new_start = new_due - timedelta(length)
        todo.set_tag(config().tag_start(), new_start.isoformat())

    todo.set_creation_date(date.today())

    return todo
Esempio n. 23
0
def _dates(p_word_before_cursor):
    """ Generator for date completion. """
    def _date_suggestions():
        """
        Returns a list of relative date that is presented to the user as auto
        complete suggestions.
        """
        # don't use strftime, prevent locales to kick in
        days_of_week = {
            0: "Monday",
            1: "Tuesday",
            2: "Wednesday",
            3: "Thursday",
            4: "Friday",
            5: "Saturday",
            6: "Sunday"
        }

        dates = [
            'today',
            'tomorrow',
        ]

        # show days of week up to next week
        dow = datetime.date.today().weekday()
        for i in range(dow + 2 % 7, dow + 7):
            dates.append(days_of_week[i % 7])

        # and some more relative days starting from next week
        dates += ["1w", "2w", "1m", "2m", "3m", "1y"]

        return dates

    to_absolute = lambda s: relative_date_to_date(s).isoformat()

    start_value_pos = p_word_before_cursor.find(':') + 1
    value = p_word_before_cursor[start_value_pos:]

    for reldate in _date_suggestions():
        if not reldate.startswith(value):
            continue

        yield Completion(reldate, -len(value), display_meta=to_absolute(reldate))
Esempio n. 24
0
    def _execute_multi_specific(self):
        def _get_offset(p_todo):
            offset = p_todo.tag_value(config().tag_due(),
                                      date.today().isoformat())

            offset_date = date_string_to_date(offset)

            if offset_date < date.today():
                offset_date = date.today()

            return offset_date

        pattern = self.args[-1]
        self.printer.add_filter(PrettyPrinterNumbers(self.todolist))

        for todo in self.todos:
            try:
                offset = _get_offset(todo)
            except ValueError:
                self.error("Postponing todo item failed: invalid due date.")
                break

            new_due = relative_date_to_date(pattern, offset)

            if new_due:
                if self.move_start_date and todo.start_date():
                    length = todo.length()
                    new_start = new_due - timedelta(length)
                    # pylint: disable=E1103
                    todo.set_tag(config().tag_start(), new_start.isoformat())
                elif self.move_start_date and not todo.start_date():
                    self.error(
                        "Warning: todo item has no (valid) start date, therefore it was not adjusted."
                    )

                # pylint: disable=E1103
                todo.set_tag(config().tag_due(), new_due.isoformat())

                self.todolist.dirty = True
                self.out(self.printer.print_todo(todo))
            else:
                self.error("Invalid date pattern given.")
                break
Esempio n. 25
0
    def match(self, p_todo):
        """
        Performs a match on a key:value tag in the todo.

        First it tries to convert the value and the user-entered expression to
        a date and makes a comparison if it succeeds, based on the given
        operator (default ==).
        Upon failure, it falls back to converting value and user-entered
        expression to an integer and makes a numerical comparison based on the
        given operator (default ==)
        As a last resort, it falls back to using a Grep filter to see if the
        user given expression is contained in the todo text.
        """
        def resort_to_grep_filter():
            grep = GrepFilter(self.expression)
            return grep.match(p_todo)

        if not self.key or not p_todo.has_tag(self.key):
            return False

        if len(p_todo.tag_values(self.key)) > 1:
            # we cannot apply an ordening on a tag that appears more than once
            # in this todo item, therefore use a simple value match
            return resort_to_grep_filter()

        try:
            operand1 = date_string_to_date(p_todo.tag_value(self.key))
            operand2 = relative_date_to_date(self.value)

            if not operand2:
                operand2 = date_string_to_date(self.value)

        except ValueError:
            operand1 = p_todo.tag_value(self.key)
            operand2 = self.value

            try:
                operand1 = int(operand1)
                operand2 = int(operand2)
            except ValueError:
                return resort_to_grep_filter()

        return self.compare_operands(operand1, operand2)
Esempio n. 26
0
    def execute(self):
        def _get_offset(p_todo):
            offset = p_todo.tag_value(config().tag_due(),
                                      date.today().isoformat())
            offset_date = date_string_to_date(offset)

            if offset_date < date.today():
                offset_date = date.today()

            return offset_date

        if not super(PostponeCommand, self).execute():
            return False

        self._process_flags()

        try:
            todo = self.todolist.todo(self.argument(0))
            pattern = self.argument(1)

            offset = _get_offset(todo)
            new_due = relative_date_to_date(pattern, offset)

            if new_due:
                if self.move_start_date and todo.has_tag(config().tag_start()):
                    length = todo.length()
                    new_start = new_due - timedelta(length)
                    todo.set_tag(config().tag_start(), new_start.isoformat())

                todo.set_tag(config().tag_due(), new_due.isoformat())

                self.todolist.set_dirty()
                self.printer.add_filter(PrettyPrinterNumbers(self.todolist))
                self.out(self.printer.print_todo(todo))
            else:
                self.error("Invalid date pattern given.")

        except InvalidCommandArgument:
            self.error(self.usage())
        except (InvalidTodoException):
            self.error("Invalid todo number given.")
Esempio n. 27
0
 def test_zero_years(self):
     result = relative_date_to_date('0y')
     self.assertEqual(result, self.today)
Esempio n. 28
0
 def test_leap_year(self):
     test_date = date(2016, 2, 29)
     result1 = relative_date_to_date('1y', test_date)
     result2 = relative_date_to_date('4y', test_date)
     self.assertEqual(result1, date(2017, 2, 28))
     self.assertEqual(result2, date(2020, 2, 29))
Esempio n. 29
0
 def test_monday3(self):
     result = relative_date_to_date('mon')
     self.assertEqual(result, self.monday)
Esempio n. 30
0
 def test_one_week(self):
     result = relative_date_to_date('1w')
     self.assertEqual(result, date(2015, 11, 13))
Esempio n. 31
0
 def test_one_bday(self):
     result = relative_date_to_date('1b')
     self.assertEqual(result, self.monday)
Esempio n. 32
0
 def test_monday4(self):
     result = relative_date_to_date('mondayy')
     self.assertFalse(result)
Esempio n. 33
0
 def test_negative_period3(self):
     result = relative_date_to_date('-1b')
     self.assertEqual(result, date(2015, 11, 5))
Esempio n. 34
0
 def test_offset1(self):
     result = relative_date_to_date('1d', self.tomorrow)
     self.assertEqual(result, date(2015, 11, 8))
Esempio n. 35
0
 def test_leap_year(self):
     test_date = date(2016, 2, 29)
     result1 = relative_date_to_date('1y', test_date)
     result2 = relative_date_to_date('4y', test_date)
     self.assertEqual(result1, date(2017, 2, 28))
     self.assertEqual(result2, date(2020, 2, 29))
Esempio n. 36
0
 def test_zero_bdays(self):
     result = relative_date_to_date('0b')
     self.assertEqual(result, self.today)
Esempio n. 37
0
 def test_one_bday(self):
     result = relative_date_to_date('1b')
     self.assertEqual(result, self.monday)
Esempio n. 38
0
 def test_one_bweek(self):
     result = relative_date_to_date('5b')
     self.assertEqual(result, self.friday)
Esempio n. 39
0
 def test_one_week(self):
     result = relative_date_to_date('1w')
     self.assertEqual(result, date(2015, 11, 13))
Esempio n. 40
0
 def test_one_month(self):
     test_date = date(2015, 1, 10)
     result = relative_date_to_date('1m', test_date)
     self.assertEqual(result, date(2015, 2, 10))
Esempio n. 41
0
 def test_one_year(self):
     test_date = date(2015, 1, 10)
     result = relative_date_to_date('1y', test_date)
     self.assertEqual(result, date(2016, 1, 10))
Esempio n. 42
0
 def test_monday4(self):
     result = relative_date_to_date('mondayy')
     self.assertFalse(result)
Esempio n. 43
0
 def test_one_day(self):
     result = relative_date_to_date('1d')
     self.assertEqual(result, self.tomorrow)
Esempio n. 44
0
 def test_negative_period2(self):
     result = relative_date_to_date('-0d')
     self.assertTrue(result, self.today)
Esempio n. 45
0
 def test_negative_period4(self):
     result = relative_date_to_date('-5b')
     self.assertEqual(result, date(2015, 10, 30))
Esempio n. 46
0
 def test_negative_period4(self):
     result = relative_date_to_date('-5b')
     self.assertEqual(result, date(2015, 10, 30))
Esempio n. 47
0
 def test_negative_period3(self):
     result = relative_date_to_date('-1b')
     self.assertEqual(result, date(2015, 11, 5))
Esempio n. 48
0
 def test_one_day(self):
     result = relative_date_to_date('1d')
     self.assertEqual(result, self.tomorrow)
Esempio n. 49
0
 def test_negative_period2(self):
     result = relative_date_to_date('-0d')
     self.assertTrue(result, self.today)
Esempio n. 50
0
 def test_one_bweek(self):
     result = relative_date_to_date('5b')
     self.assertEqual(result, self.friday)
Esempio n. 51
0
 def test_offset1(self):
     result = relative_date_to_date('1d', self.tomorrow)
     self.assertEqual(result, date(2015, 11, 8))
Esempio n. 52
0
 def test_one_month(self):
     test_date = date(2015, 1, 10)
     result = relative_date_to_date('1m', test_date)
     self.assertEqual(result, date(2015, 2, 10))
Esempio n. 53
0
 def test_today2(self):
     result = relative_date_to_date('tod')
     self.assertEqual(result, self.today)
Esempio n. 54
0
 def test_one_year(self):
     test_date = date(2015, 1, 10)
     result = relative_date_to_date('1y', test_date)
     self.assertEqual(result, date(2016, 1, 10))
Esempio n. 55
0
 def test_tomorrow2(self):
     result = relative_date_to_date('tom')
     self.assertEqual(result, self.tomorrow)
Esempio n. 56
0
 def test_zero_months(self):
     result = relative_date_to_date('0m')
     self.assertEqual(result, self.today)
Esempio n. 57
0
 def test_yesterday2(self):
     result = relative_date_to_date('yes')
     self.assertEqual(result, self.yesterday)
Esempio n. 58
0
 def test_monday3(self):
     result = relative_date_to_date('mon')
     self.assertEqual(result, self.monday)
Esempio n. 59
0
 def test_zero_months(self):
     result = relative_date_to_date('0m')
     self.assertEqual(result, self.today)