Exemplo n.º 1
0
 def test_properties(self):
     test_file = os.path.join(self.test_dir, "recurring task.md")
     t = Task.from_file(test_file)
     self.assertListEqual([t.hold, t.done, t.ip, t.todo, t.abandoned],
                          [False, False, True, False, False])
     dtd = (t.due - datetime.datetime.now()).days + 1
     self.assertEqual(dtd, t.days_till_due)
Exemplo n.º 2
0
    def from_files(cls, path: str, id: str, coerce_pid_mismatches=False):
        """
        Generate a Project object from existing files.

        Args:
            path (str): The path of the project folder. Should already contain tasks and notes subdirs
            id (str): a single alphabetic character representing the project id. Must be unique
            coerce_pid_mismatches (bool): If True, will coerce existing tasks with mismatching project ids to match
                this project's id.

        Returns:
            Project object
        """
        tasks = []
        notes = []

        path = os.path.abspath(path)
        tasks_dir = os.path.join(path, tasks_subdir)
        notes_dir = os.path.join(path, notes_subdir)
        inactive_dir = os.path.join(tasks_dir, inactive_subdir)

        for subdir in (notes_dir, inactive_dir):
            if not os.path.exists(subdir):
                os.makedirs(subdir, exist_ok=False)

        for taskdir in (tasks_dir, inactive_dir):
            for ft in os.listdir(taskdir):
                f_full = os.path.abspath(os.path.join(taskdir, ft))
                if f_full.endswith(task_extension):
                    try:
                        t = Task.from_file(f_full)
                        tasks.append(t)
                    except DexcodeException:
                        warnings.warn(
                            f"File {f_full} has no dexcode. Please remove this file or make it into a task."
                        )

        for task in tasks:
            project_id = task.dexid[0]
            number_task_id = int(task.dexid[1:])
            if project_id != id:
                warnings.warn(
                    f"Task {task.dexid} does not have project id matching project {id}: {path}."
                )
                if coerce_pid_mismatches:
                    warnings.warn(
                        f"Converting task {task.dexid} to project {id}!")
                    task.set_dexid(f"{id}{number_task_id}")

        for fn in os.listdir(notes_dir):
            n_full = os.path.abspath(os.path.join(notes_dir, fn))
            if n_full.endswith(note_extension):
                n = Note.from_file(n_full)
                notes.append(n)

        return cls(path, id, tasks, notes)
Exemplo n.º 3
0
    def test_set_status(self):
        fname = 'example task.md'
        test_file = os.path.join(self.test_dir, fname)

        # checking setting the same status
        t = Task.from_file(test_file)
        self.assertEqual(t.status, todo_str)
        t.set_status(todo_str)
        t = Task.from_file(test_file)
        self.assertEqual(t.status, todo_str)

        t = Task.from_file(test_file)
        t.set_status(ip_str)
        t = Task.from_file(test_file)
        self.assertEqual(t.status, ip_str)

        t = Task.from_file(test_file)
        t.set_status(hold_str)
        t = Task.from_file(test_file)
        self.assertEqual(t.status, hold_str)

        # moving it into an inactive state from an active state
        t = Task.from_file(test_file)
        t.set_status(done_str)

        expected_newpath = os.path.join(
            os.path.join(self.test_dir, inactive_subdir), fname)
        self.assertTrue(t.path == expected_newpath)

        # changing the inactive state
        t = Task.from_file(expected_newpath)
        self.assertEqual(t.status, done_str)
        t.set_status(abandoned_str)
        self.assertEqual(t.status, abandoned_str)
        t = Task.from_file(expected_newpath)
        self.assertEqual(t.status, abandoned_str)

        # Changing from inactive to active stae
        t.set_status(todo_str)
        self.assertEqual(t.status, todo_str)
        self.assertEqual(t.path, test_file)
        t = Task.from_file(test_file)
        self.assertEqual(t.status, todo_str)
Exemplo n.º 4
0
 def test_task_from_file(self):
     test_flle = os.path.join(self.test_dir, "example task.md")
     t = Task.from_file(test_flle)
     self.assertEqual(t.dexid, "b44")
     self.assertEqual(t.effort, 2)
     self.assertEqual(t.importance, 5)
     self.assertEqual(t.status, "todo")
     self.assertListEqual(t.flags, ["n"])
     ref_time = datetime.datetime.strptime("2020-07-21", due_date_fmt)
     self.assertTrue(ref_time == t.due)
Exemplo n.º 5
0
 def test_rename(self):
     test_flle = os.path.join(self.test_dir, "example task.md")
     t = Task.from_file(test_flle)
     new_name = "renamed file"
     t.rename(new_name)
     self.assertTrue(
         os.path.exists(
             os.path.join(self.test_dir, f"{new_name}{task_extension}")))
     self.assertFalse(os.path.exists(os.path.join(self.test_dir,
                                                  test_flle)))
     self.assertEqual(t.name, new_name)
Exemplo n.º 6
0
    def test_task_new(self):
        local_task_file = "task_new task.md"
        test_file = os.path.join(self.test_dir, local_task_file)
        due = datetime.datetime.strptime("2020-08-19", due_date_fmt)
        t = Task.new("a144", test_file, 4, due, 3, "todo", ["r21"])
        self.assertTrue(os.path.exists(test_file))
        self.assertEqual(t.dexid, "a144")
        self.assertEqual(t.effort, 4)
        self.assertEqual(t.importance, 3)
        self.assertEqual(t.status, "todo")
        self.assertListEqual(t.flags, ["r21"])
        ref_time = datetime.datetime.strptime("2020-08-19", due_date_fmt)
        self.assertTrue(ref_time == t.due)

        # test an existing file without a dexcode
        local_task_file = "task_without_dexcode.md"
        test_file = os.path.join(self.test_dir, local_task_file)
        t = Task.new("a145", test_file, 4, due, 2, "todo", ["r7"])
        with open(t.path, "r") as f:
            self.assertTrue(t.dexcode in f.read())
Exemplo n.º 7
0
    def test_flag_setting(self):
        test_file = os.path.join(self.test_dir, 'example task.md')
        t = Task.from_file(test_file)

        test_flag = "r22"
        self.assertTrue("n" in t.flags)
        self.assertTrue(test_flag not in t.flags)
        t.add_flag(test_flag)
        self.assertTrue(test_flag in t.flags)
        t.rm_flag(test_flag)
        self.assertTrue(test_flag not in t.flags)
Exemplo n.º 8
0
    def create_new_task(self,
                        name: str,
                        effort: int,
                        due: datetime.datetime,
                        importance: int,
                        status: str,
                        flags: list,
                        edit_content: bool = False) -> Task:
        """
        Can be used non atomically. Arguments are mostly the same as for Task.

        Args:
            name (str): The name of the new task. Will be converted to a path by Project for use with Task.
            effort:
            due:
            importance:
            status:
            flags:
            edit_content:

        Returns:
            Task (the created task).
        """

        fname = name + task_extension
        path = os.path.join(os.path.join(self.path, tasks_subdir), fname)

        if status in (abandoned_str, done_str):
            raise DexException(
                "Cannot make a new task with an initially inactive status!")

        if path in [t.path for t in self.tasks.all]:
            raise FileOverwriteError(
                f"Task already exists with the name: {name}")

        all_task_numbers = [
            int(copy.deepcopy(t.dexid).replace(self.id, ""))
            for t in self._tasks
        ]
        max_task_numbers = max(all_task_numbers) if all_task_numbers else 0
        new_task_number = max_task_numbers + 1
        new_task_id = f"{self.id}{new_task_number}"
        t = Task.new(new_task_id,
                     path,
                     effort,
                     due,
                     importance,
                     status,
                     flags,
                     edit_content=edit_content)
        self._tasks.append(t)
        return t
Exemplo n.º 9
0
    def test_setters(self):
        test_file = os.path.join(self.test_dir, 'example task.md')
        t = Task.from_file(test_file)
        ny_2099 = datetime.datetime.strptime("2099-01-01", due_date_fmt)
        t.set_due(ny_2099)
        self.assertEqual(ny_2099, t.due)
        t = Task.from_file(test_file)
        self.assertEqual(ny_2099, t.due)

        t.set_importance(1)
        self.assertEqual(t.importance, 1)
        t = Task.from_file(test_file)
        self.assertEqual(t.importance, 1)

        t.set_effort(5)
        self.assertEqual(t.effort, 5)
        t = Task.from_file(test_file)
        self.assertEqual(t.effort, 5)

        t.set_dexid("f421")
        self.assertEqual(t.dexid, "f421")
        t = Task.from_file(test_file)
        self.assertEqual(t.dexid, "f421")
Exemplo n.º 10
0
    def test_recurrence(self):
        test_file_recurring = os.path.join(self.test_dir, "recurring task.md")
        t_recurring = Task.from_file(test_file_recurring)

        test_file_nonrecurring = os.path.join(self.test_dir, "example task.md")
        t_nonrecurring = Task.from_file(test_file_nonrecurring)

        recurrence, recurrence_time = t_recurring.recurrence
        self.assertTrue(recurrence)
        self.assertEqual(recurrence_time, 5)

        recurrence, recurrence_time = t_nonrecurring.recurrence
        self.assertFalse(recurrence)
        self.assertIsNone(recurrence_time)

        # Ensure due date is updated to the next due date when the recurring task is completed
        self.assertEqual(
            t_recurring.due,
            datetime.datetime.strptime("2020-07-25", due_date_fmt))
        t_recurring.set_status(done_str)

        self.assertEqual(
            t_recurring.due,
            datetime.datetime.strptime("2020-07-30", due_date_fmt))

        # completed recurring task should be set to todo, not done as it will never recur!
        self.assertEqual(t_recurring.status, todo_str)

        # Changing a recurring task from todo to done (i.e., updating the due)
        t_recurring.set_status(done_str)
        self.assertEqual(t_recurring.status, todo_str)
        print(t_recurring.due)
        self.assertEqual(
            t_recurring.due,
            datetime.datetime.strptime("2020-08-04", due_date_fmt))
        self.assertEqual(t_recurring.path, test_file_recurring)
Exemplo n.º 11
0
 def test_setting_recurrence(self):
     test_file = os.path.join(self.test_dir, 'example task.md')
     t = Task.from_file(test_file)
     self.assertEqual((False, None), t.recurrence)
     t.add_flag("r10")
     self.assertEqual((True, 10), t.recurrence)