示例#1
0
文件: body.py 项目: spanezz/egt
    def force_load_tw(self, **kw):
        """
        Force lazy loading of TaskWarrior object, possibly with custom extra
        arguments.

        This is used in tests to instantiate TaskWarrior objects pointing to
        the test TaskWarrior configuration.
        """
        self._tw = taskw.TaskWarrior(marshal=True, **kw)
示例#2
0
    def testCreateFromTW(self):
        """
        Test import of new taskwarrior tasks in egt
        """
        import taskw
        tw = taskw.TaskWarrior(marshal=True, config_filename=self.taskrc)
        new_task = tw.task_add("new task", ["tag", "testtag1"],
                               project="testprj")
        tw.task_add("new parent task",
                    project="testprj",
                    depends=[new_task["uuid"]])
        tw = None

        self.write_project([
            "body line1",
            "body line2",
        ])
        proj = Project(self.projectfile, statedir=self.workdir.name)
        proj.body.force_load_tw(config_filename=self.taskrc)
        proj.load()

        self.assertEqual(len(proj.body.content), 2)
        self.assertEqual(len(proj.body.tasks), 0)

        proj.body.sync_tasks()

        self.assertEqual(len(proj.body.content), 5)
        self.assertEqual(len(proj.body.tasks), 2)

        task = proj.body.tasks[0]
        self.assertIsNotNone(task.task)
        self.assertFalse(task.is_new)
        self.assertIsNotNone(task.id)
        self.assertEqual(task.task["description"], "new task")
        self.assertEqual(task.task["tags"], ["tag", "testtag1"])
        self.assertEqual(task.task["project"], "testprj")

        with io.StringIO() as out:
            proj.body.print(out)
            body_lines = out.getvalue().splitlines()

        self.assertEqual(len(body_lines), 5)

        self.assertRegex(body_lines[0], r"^t\d+ \[[^]]+\] new task \+tag$")
        self.assertRegex(body_lines[1],
                         r"^t\d+ \[[^]]+\] new parent task depends:1$")
        self.assertEqual(body_lines[2], "")
        self.assertEqual(body_lines[3], "body line1")
        self.assertEqual(body_lines[4], "body line2")

        with open(os.path.join(self.workdir.name, "project-testprj.json"),
                  "rt") as fd:
            state = json.load(fd)
        tasks = state["tasks"]
        ids = tasks["ids"]
        self.assertEqual(len(ids), 2)
        self.assertEqual(ids[str(task.task["id"])], str(task.task["uuid"]))
示例#3
0
文件: sync.py 项目: leifdenby/twsync
def main():
    tw_cli = taskw.TaskWarrior()
    ti_cli = todoist.login_with_api_token(TODOIST_API_TOKEN)

    ti_tasks = ti_cli.get_tasks()
    tw_tasks = tw_cli.load_tasks()

    # NOTE: todoist only returns uncompleted tasks whereas taskwarrier returns
    # all

    for ti_task in ti_tasks:
        if ti_task.project.name in SKIP_TODOIST_PROJECT_NAMES:
            continue

        if not ti_task_synced_to_tw(ti_task=ti_task):
            create_tw_task(ti_task=ti_task, tw_cli=tw_cli)

    for tw_task in tw_tasks['pending']:
        if not tw_task_synced_to_ti(tw_task=tw_task):
            create_ti_task(tw_task=tw_task, ti_cli=ti_cli)
        else:
            # check if task has been marked completed on todoist by seeing if
            # it's in the list returned from todoist
            sync_rec = TodoistTaskWarrierSyncModel.get(
                taskwarrier=tw_task['uuid'])
            if not sync_rec.completed:
                ti_id = sync_rec.todoist
                if not ti_id in map(lambda t: t.id, ti_tasks):
                    mark_tw_task_complete(tw_task=tw_task, tw_cli=tw_cli)
                sync_rec.update(completed=True)

    for tw_task in tw_tasks['completed']:
        if tw_task_synced_to_ti(tw_task=tw_task):
            sync_rec = TodoistTaskWarrierSyncModel.get(
                taskwarrier=tw_task['uuid'])
            if not sync_rec.completed:
                ti_id = sync_rec.todoist
                mark_ti_task_complete(ti_id=ti_id,
                                      ti_tasks=ti_tasks,
                                      tw_task=tw_task)
                sync_rec.update(completed=True)
示例#4
0
def main():
    """
    Main function
    """

    taskwarrior = taskw.TaskWarrior()
    tasks = taskwarrior.load_tasks()

    # Only (over-)due and recurring tasks are considered for deletion:
    due_before = datetime.datetime.utcnow()
    due_before = due_before.replace(tzinfo=pytz.utc)

    # datetime.datetime.now()
    recurring_tasks_due = [
        task for task in tasks['completed']
        if 'recur' in task and 'parent' in task and 'due' in task
        and dateparse(task['due']) < due_before
    ]

    # Delete all but the first of all (over-)due and duplicate tasks:
    parents = collections.Counter(
        [task['parent'] for task in recurring_tasks_due])

    for parent in parents:
        count = parents[parent]
        if count > 1:
            dupe_tasks = [
                task for task in recurring_tasks_due
                if task['parent'] == parent
            ]
            dupe_tasks = sorted(dupe_tasks, key=lambda t: t['due'])
            # dupe_tasks_to_keep = dupe_tasks[0:1]
            dupe_tasks_to_trash = dupe_tasks[1:]
            print('Deleting {} duplicate due tasks: "{}"'.format(
                len(dupe_tasks_to_trash),
                dupe_tasks_to_trash[0]['description']))
            for task in dupe_tasks_to_trash:
                task_delete(task['uuid'])
示例#5
0
 def __init__(self):
     self.client = taskw.TaskWarrior()
     self.tasks = self.client.load_tasks()
示例#6
0
文件: body.py 项目: spanezz/egt
 def tw(self) -> taskw.TaskWarrior:
     if self._tw is None:
         self._tw = taskw.TaskWarrior(marshal=True)
     return self._tw
示例#7
0
    def testSyncDone(self):
        """
        Test handling of tasks present both in taskwarrior and in egt, when a
        task is marked done on taskwarrior
        """
        import taskw
        tw = taskw.TaskWarrior(marshal=True, config_filename=self.taskrc)
        new_task = tw.task_add("task", ["tag", "testtag1"], project="testprj")

        egt_id = new_task["id"] + 10

        # Add the task to egt's state using a different number than taskwarrior
        # has
        with open(os.path.join(self.workdir.name, "project-testprj.json"),
                  "wt") as fd:
            json.dump({"tasks": {
                "ids": {
                    egt_id: str(new_task["uuid"]),
                }
            }},
                      fd,
                      indent=1)

        self.write_project([
            "body line1",
            " t{} foo the bar".format(egt_id),
            "body line3",
        ])

        # Mark the task as done
        tw.task_done(uuid=new_task["uuid"])
        tw = None

        # Load the project and see
        proj = Project(self.projectfile, statedir=self.workdir.name)
        proj.body.force_load_tw(config_filename=self.taskrc)
        proj.load()

        self.assertEqual(len(proj.body.content), 3)
        self.assertEqual(len(proj.body.tasks), 1)
        self.assertEqual(proj.body.tasks[0], proj.body.content[1])
        task = proj.body.tasks[0]
        self.assertEqual(task.indent, " ")
        self.assertIsNone(task.task)
        self.assertFalse(task.is_new)
        self.assertEqual(task.id, egt_id)
        self.assertEqual(task.desc, "foo the bar")
        self.assertEqual(task.tags, set())
        self.assertFalse(task.is_orphan)

        proj.body.sync_tasks()

        self.assertEqual(len(proj.body.tasks), 1)
        self.assertEqual(task, proj.body.tasks[0])

        self.assertIsNotNone(task.task)
        self.assertFalse(task.is_new)
        self.assertIsNone(task.id)
        self.assertEqual(task.task["description"], "task")
        self.assertEqual(task.task["tags"], ["tag", "testtag1"])
        self.assertEqual(task.task["project"], "testprj")

        with io.StringIO() as out:
            proj.body.print(out)
            body_lines = out.getvalue().splitlines()

        self.assertEqual(len(body_lines), 3)
        self.assertEqual(body_lines[0], "body line1")
        self.assertRegex(body_lines[1], r"^ - \[[^]]+\] task \+tag$")
        self.assertEqual(body_lines[2], "body line3")

        with open(os.path.join(self.workdir.name, "project-testprj.json"),
                  "rt") as fd:
            state = json.load(fd)
        tasks = state["tasks"]
        ids = tasks["ids"]
        self.assertEqual(len(ids), 0)
示例#8
0
def get_reminder() -> typing.Text:
    logger = logging.getLogger(__name__)

    today = datetime.now(tzlocal()).replace(hour=0,
                                            minute=0,
                                            second=0,
                                            microsecond=0)
    tomorrow = today + ONE_DAY
    overmorrow = today + TWO_DAY

    next_monday = _get_next_monday(today)
    two_mondays_from_now = _get_two_mondays_from_now(today)

    logger.debug("Today is {}".format(today))
    logger.debug("Tomorrow is {}".format(tomorrow))
    logger.debug("Overmorrow is {}".format(overmorrow))
    logger.debug("Next Monday is {}".format(next_monday))
    logger.debug("Two Mondays from now is {}".format(two_mondays_from_now))
    task_warrior = taskw.TaskWarrior(marshal=True)
    all_tasks = task_warrior.load_tasks()

    buffer = StringIO()

    tasks: typing.Dict[typing.Text, typing.List[typing.Any]] = {
        "no_deadline": [],
        "due_today": [],
        "due_tomorrow": [],
        "due_this_week": [],
        "due_next_week": [],
        "future": [],
    }

    for task in all_tasks["pending"]:
        if "wait" in task and task["wait"] is not None and task["wait"] > today:
            continue

        if "due" not in task:
            logger.debug("This task does not have a due date")
            logger.debug("  {}".format(task["description"]))
            tasks["no_deadline"].append(task)

        elif today < task["due"] <= tomorrow:
            logger.debug("This task is due today")
            logger.debug("  {}: {}".format(task["due"], task["description"]))
            tasks["due_today"].append(task)

        elif tomorrow < task["due"] <= overmorrow:
            logger.debug("This task is due tomorrow")
            logger.debug("  {}: {}".format(task["due"], task["description"]))
            tasks["due_tomorrow"].append(task)

        elif overmorrow < task["due"] <= next_monday:
            logger.debug("This task is due this week")
            logger.debug("  {}: {}".format(task["due"], task["description"]))
            tasks["due_this_week"].append(task)

        elif next_monday < task["due"] <= two_mondays_from_now:
            logger.debug("This task is due next week")
            logger.debug("  {}: {}".format(task["due"], task["description"]))
            tasks["due_next_week"].append(task)

        else:
            logger.debug("This task is due sometime in the future")
            logger.debug("  {}: {}".format(task["due"], task["description"]))
            tasks["future"].append(task)

    labels = {
        "no_deadline": "Without deadline",
        "due_today": "Due today",
        "due_tomorrow": "Due tomorrow",
        "due_this_week": "Due this week",
        "due_next_week": "Due next week",
        "future": "In future",
    }

    show_date = {
        "no_deadline": False,
        "due_today": False,
        "due_tomorrow": False,
        "due_this_week": True,
        "due_next_week": True,
        "future": True,
    }

    for key, label in labels.items():
        if len(tasks[key]) > 0:
            print("## {}\n".format(label), file=buffer)
            for task in sorted(tasks[key],
                               key=itemgetter("urgency"),
                               reverse=True):
                print("-  {}".format(task["description"]), file=buffer, end="")
                if show_date[key]:
                    print(", due on ", file=buffer, end="")
                    if task["due"].year == today.year:
                        print(task["due"].strftime("%A %-d %B"),
                              file=buffer,
                              end="")
                    else:
                        print(task["due"].strftime("%A %-d %B %Y"),
                              file=buffer,
                              end="")
                print("", file=buffer)
            print("", file=buffer)

    return buffer.getvalue()
示例#9
0
 def __init__(self, factory, db=None, **kwargs):
     self._db = db or taskw.TaskWarrior(config_filename=kwargs['config'])
     self._factory = factory