Exemplo n.º 1
0
class Tasks(Model):
    """
    Main entry point for querying and managing local tasks.
    """
    logger = AppLogger("tasks").get_logger()

    def __init__(self, database):
        super().__init__(database, Task())
        self.__calendar = Calendar()
        self.__vars = CommonVariables()
        self.__date_generator = DateGenerator()

    def add(self, text, label, project, date_expression) -> List[Task]:
        assert type(text) and type(label) and type(project)\
               and type(date_expression) is str
        task_list = list()
        if self.__date_generator.validate_input(date_expression):
            for due_date in self.__date_generator.get_due_dates(
                    date_expression):
                task = Task(text)
                task.label = label
                task.project = project
                task.date_expression = date_expression
                task.due_date = due_date
                self.append(task)
                task_list.append(task)
        else:
            raise AttributeError(
                f"Provided date expression {date_expression} is invalid")

        return task_list

    def append(self, obj: Task):
        assert isinstance(obj, Task)
        return self.append_object(obj)

    def contains_due_date_range(self, task, min_date_string, max_date_string):
        assert isinstance(task, Task)
        assert type(min_date_string) and type(max_date_string) is str

        min_day = Day(
            datetime.strptime(min_date_string, self.__vars.date_format))
        max_day = Day(
            datetime.strptime(max_date_string, self.__vars.date_format))
        if len(task.due_date.date_string) > 0:
            day = Day(
                datetime.strptime(task.due_date.date_string,
                                  self.__vars.date_format))

            if min_day.to_date_time() < day.to_date_time(
            ) < max_day.to_date_time():
                return task

    def get_task(self, func) -> Task:
        for task in self.get_object_list():
            if func(task) is not None:
                self.logger.debug(
                    f"Retrieved task by index: {task.index}, text: {task.text}"
                )
                return task

    def get_task_list(self):
        return sorted(self.get_object_list(),
                      key=lambda task: task.due_date.date_string)

    def get_tasks_containing_text(self, value) -> List[Task]:
        """
        Selects all tasks that with a text value that contain the provided value
        :param value:
        :return: list of Task
        """
        assert type(value) is str
        return [
            task for task in self.get_task_list()
            if str(value).lower() in str(task.text).lower()
        ]

    def get_tasks_matching_text(self, value) -> List[Task]:
        """
        Selects all tasks with a text value that matches the provided value
        :param value:
        :return:
        """
        assert type(value) is str
        return [
            task for task in self.get_task_list()
            if str(value.lower() == str(task.text).lower())
        ]

    def get_task_by_index(self, index: int) -> Task:
        assert type(index) is int
        return self.get_task(lambda task: task
                             if task.index == index else None)

    def get_task_by_external_id(self, external_id: int) -> Task:
        assert type(external_id) is str
        return self.get_task(lambda task: task
                             if task.external_id == external_id else None)

    def get_task_by_id(self, task_id: str) -> Task:
        assert type(task_id) is str
        return self.get_task(lambda task: task
                             if task.unique_id == task_id else None)

    def get_task_by_name(self, task_name: str) -> Task:
        assert type(task_name) is str
        return self.get_task(lambda task: task
                             if task.text == task_name else None)

    def get_tasks_by_date(self, date_expression: str) -> List[Task]:
        assert type(date_expression) is str
        task_list = list()
        for due_date in self.__date_generator.get_due_dates(date_expression):
            for task in self.get_task_list():
                if task.due_date.date_string == due_date.date_string:
                    task_list.append(task)
        return task_list

    def get_tasks_within_date_range(self, min_date_string: str,
                                    max_date_string: str) -> List[Task]:
        assert type(min_date_string) is str
        assert type(max_date_string) is str
        return [
            task
            for task in self.get_task_list() if self.contains_due_date_range(
                task, min_date_string, max_date_string)
        ]

    def get_tasks_by_status(self, is_completed: bool) -> List[Task]:
        assert type(is_completed) is bool

        if is_completed:
            return [
                task for task in self.get_task_list() if task.is_completed()
            ]
        else:
            return [
                task for task in self.get_task_list()
                if not task.is_completed()
            ]

    def get_tasks_by_project(self, project: str) -> List[Task]:
        assert type(project) is str
        return self.get_list_by_type("project", project)

    def get_tasks_by_label(self, label: str) -> List[Task]:
        assert type(label) is str
        return self.get_list_by_type("label", label)

    def get_filtered_list(self) -> List[Task]:
        return [task for task in self.get_task_list() if not task.deleted]

    def delete(self, task_id: str) -> Task:
        assert type(task_id) is str

        task = self.get_task_by_id(task_id)
        if task is not None:
            task.deleted = True
            self.replace_object(task.index, task)
            return task
        else:
            raise TaskKeyError()

    def undelete(self, task_id: str) -> Task:
        assert type(task_id) is str

        task = self.get_task_by_id(task_id)
        if task is not None:
            task.deleted = False
            self.replace_object(task.index, task)
            return task
        else:
            raise TaskKeyError()

    def complete(self, task_id: str) -> Task:
        assert type(task_id) is str

        task = self.get_task_by_id(task_id)
        if task is not None:
            task.complete()
            self.replace_object(task.index, task)
            return task
        else:
            raise TaskKeyError()

    def reset(self, task_id: str) -> Task:
        """
        Resets the due date to today on the selected task
        :param task_id:
        :return:
        """
        assert type(task_id) is str

        task = self.get_task_by_id(task_id)
        if task is not None:
            due_date = DueDate()
            due_date.completed = False
            due_date.date_string = Today().to_date_string()
            task.due_date = due_date
            self.replace_object(task.index, task)
            return task
        else:
            raise TaskKeyError()

    def replace(self, local_task: Task, remote_task: Task) -> Task:
        assert isinstance(remote_task, Task)
        assert isinstance(local_task, Task)

        remote_task.index = local_task.index
        remote_task.unique_id = local_task.unique_id
        remote_task.due_date = local_task.due_date

        self.replace_object(local_task.index, remote_task)
        self.logger.debug(
            f"Replaced local_task: {dict(local_task)} with remote_task: {dict(remote_task)}"
        )
        return remote_task

    def edit(self, index: int, text: str, label: str, project: str,
             date_expression: str) -> Task:

        task = self.get_task_by_index(index)
        if task is not None:
            task.text = text
            task.project = project
            task.label = label

            due_date = self.__date_generator.get_due_date(date_expression)
            if due_date is not None:
                task.date_expression = date_expression
                task.due_date.date_string = due_date.date_string

            self.replace_object(task.index, task)
            return task
        else:
            raise TaskKeyError()

    def reschedule(self, today) -> None:
        assert type(today) is Today or Day
        task_list = self.get_task_list()
        for task in task_list:
            if self.__calendar.is_past(
                    task.due_date, today
            ) and task.due_date.completed is False and task.deleted is False:
                task.due_date.date_string = today.to_date_string()
        self.update_objects(task_list)

    def get_list_by_type(self,
                         parameter_name: str,
                         value: str,
                         task_list=None) -> list:
        """
        Returns list of tasks when a task parameter (ie. project, text, label) matches
        a single value.
        :param parameter_name:
        :param value:
        :param task_list:
        :return:
        """
        assert type(parameter_name) is str
        assert type(value) is str

        if task_list is None:
            task_list = self.get_task_list()
        else:
            assert type(task_list) is list

        return list(
            filter(lambda t: getattr(t, parameter_name) == value, task_list))

    def __sort(self, parameter_name: str) -> list:
        assert type(parameter_name) is str
        return [
            t for t in sorted(self.get_task_list(),
                              key=lambda t: getattr(t, parameter_name))
        ]

    def get_label_list(self) -> List[str]:
        return self.unique("label", self.get_task_list())

    def get_project_list(self) -> List[str]:
        return self.unique("project", self.get_task_list())

    def get_due_date_list(self) -> List[str]:
        return list(
            set([task.due_date.date_string for task in self.get_task_list()]))

    @staticmethod
    def unique(parameter_name: str, task_list: list) -> List[str]:
        assert type(parameter_name) is str
        assert type(task_list) is list
        unique_set = set([getattr(task, parameter_name) for task in task_list])
        return sorted(list(unique_set))

    def clear(self):
        self.clear_objects()
Exemplo n.º 2
0
class TestDateGenerator(unittest.TestCase):
    def match_date(self, current_date_string, date_expression,
                   expected_date_string):
        current_date_time = datetime.strptime(current_date_string,
                                              CommonVariables().date_format)
        self.date_generator.current_day = Day(current_date_time)
        due_date_list = self.date_generator.get_due_dates(date_expression)
        return due_date_list[0].date_string == expected_date_string

    def get_date_count(self, current_date_string, date_expression):
        current_date_time = datetime.strptime(current_date_string,
                                              CommonVariables().date_format)
        self.date_generator.current_day = Day(current_date_time)
        due_date_list = self.date_generator.get_due_dates(date_expression)
        return len(due_date_list)

    def setUp(self):
        self.today = Today()
        self.vars = CommonVariables()
        self.date_generator = DateGenerator()
        self.march1 = datetime.strptime('2019-03-01', self.vars.date_format)

    def tearDown(self):
        pass

    def test_pad_number(self):
        current_date_time = datetime.strptime('2019-03-12',
                                              self.vars.date_format)
        day = Day(current_date_time)
        date_list = day.to_date_list()
        self.assertListEqual(date_list, ['2019-03-12'])

    def test_get_date_when_in_same_week(self):
        self.assertTrue(self.match_date('2019-03-12', 'w', '2019-03-13'))

    def test_get_date_when_in_next_week(self):
        self.assertTrue(self.match_date('2019-03-12', 'm', '2019-03-18'))

    def test_get_date_when_in_next_month(self):
        self.assertTrue(self.match_date('2019-03-29', 'tu', '2019-04-02'))

    def test_get_date_when_today(self):
        self.assertTrue(
            self.match_date(self.today.to_date_string(), 'today',
                            self.today.to_date_string()))

    def test_get_date_when_tomorrow(self):
        self.assertTrue(self.match_date('2019-03-29', 'tomorrow',
                                        '2019-03-30'))

    def test_get_date_when_next_week(self):
        self.assertTrue(
            self.match_date('2019-03-17', 'next week', '2019-03-18'))
        self.assertTrue(
            self.match_date('2019-03-18', 'next week', '2019-03-25'))
        self.assertTrue(
            self.match_date('2019-03-29', 'next week', '2019-04-01'))

    def test_get_date_when_next_month(self):
        self.assertTrue(
            self.match_date('2019-07-02', 'next month', '2019-08-01'))
        self.assertTrue(
            self.match_date('2019-12-02', 'next month', '2020-01-01'))

    def test_get_date_when_every_day(self):
        self.date_generator.current_day = Day(self.march1)
        due_date_list = self.date_generator.get_due_dates("every day")
        self.assertTrue(len(due_date_list) == 62)

    def test_get_date_count_when_every_weekday(self):
        self.vars.recurring_month_limit = 2
        day_count = self.get_date_count('2019-03-01', 'every weekday')
        self.assertTrue(day_count == 44)

    def test_get_date_when_every_weekday(self):
        self.vars.recurring_month_limit = 2
        self.date_generator.current_day = Day(self.march1)
        due_date_list = self.date_generator.get_due_dates("every weekday")
        self.assertTrue(len(due_date_list) == 44)
        self.assertTrue(due_date_list[0].date_string == "2019-03-01")
        self.assertTrue(due_date_list[1].date_string == "2019-03-04")
        self.assertTrue(due_date_list[2].date_string == "2019-03-05")
        self.assertTrue(due_date_list[3].date_string == "2019-03-06")
        self.assertTrue(due_date_list[4].date_string == "2019-03-07")

    def test_get_date_when_every_sunday(self):
        self.vars.recurring_month_limit = 2
        self.assertTrue(self.get_date_count('2019-03-01', 'every su') == 9)

    def test_get_date_when_every_monday(self):
        self.vars.recurring_month_limit = 2
        self.assertTrue(self.get_date_count('2019-03-01', 'every m') == 9)

    def test_get_date_when_every_tuesday(self):
        self.vars.recurring_month_limit = 2
        self.assertTrue(self.get_date_count('2019-03-01', 'every tu') == 9)

    def test_get_date_when_every_wednesday(self):
        self.vars.recurring_month_limit = 2
        self.assertTrue(self.get_date_count('2019-03-01', 'every w') == 9)

    def test_get_date_when_every_thursday(self):
        self.vars.recurring_month_limit = 2
        self.assertTrue(self.get_date_count('2019-03-01', 'every th') == 8)

    def test_get_date_when_every_friday(self):
        self.vars.recurring_month_limit = 2
        day_count = self.get_date_count('2019-03-01', 'every f')
        self.assertTrue(day_count == 9)

    def test_get_date_when_every_saturday(self):
        self.vars.recurring_month_limit = 2
        self.assertTrue(self.get_date_count('2019-03-01', 'every sa') == 9)

    def test_short_date(self):
        due_date_list = self.date_generator.get_due_dates("apr 14")
        self.assertTrue(len(due_date_list) == 1)
        self.assertTrue(due_date_list[0].date_string == '2021-04-14')

    def test_validate_input(self):
        self.assertTrue(self.date_generator.validate_input("every weekday"))
        self.assertTrue(self.date_generator.validate_input("every tu"))
        self.assertTrue(self.date_generator.validate_input("m"))
        self.assertTrue(self.date_generator.validate_input("today"))
        self.assertFalse(self.date_generator.validate_input("every"))
        self.assertFalse(self.date_generator.validate_input("24"))
        self.assertFalse(self.date_generator.validate_input("monday"))
        self.assertTrue(self.date_generator.validate_input("apr 21"))
        self.assertFalse(self.date_generator.validate_input("apr"))

    def test_empty_date_handler(self):
        due_date_list = self.date_generator.get_due_dates("empty")
        self.assertTrue(len(due_date_list) == 1)
        due_date = due_date_list[0]
        self.assertEqual(due_date.date_string, "")
        self.assertFalse(due_date.completed)

    def test_year_month_date_handler(self):
        due_date_list = self.date_generator.get_due_dates("2019-03-019")
        self.assertTrue(len(due_date_list) == 1)
        self.assertFalse(due_date_list[0].completed)

        due_date_list = self.date_generator.get_due_dates("2019-03-01")
        self.assertTrue(len(due_date_list) == 1)
        self.assertFalse(due_date_list[0].completed)
        self.assertTrue(due_date_list[0].date_string == "2019-03-01")

    def test_get_due_date(self):
        due_date = self.date_generator.get_due_date("this week")
        self.assertTrue(len(due_date.date_string) == 0)
        due_date = self.date_generator.get_due_date("sep 24")
        self.assertIn("09-24", due_date.date_string)