Beispiel #1
0
    def test_get(self):
        # 存在しないパスをgetする
        self.assertFalse(os.path.exists(self.root))
        self.assertIsNone(Manager.get(self.root, self.profile))

        # タスクトリでないディレクトリをgetする
        self.assertIsNone(Manager.get('/Users/taku', self.profile))

        # 空タスクトリをputしてからgetする
        t0 = Tasktory('', 1)
        Manager.put(self.root, t0, self.profile)
        self.assertTrue(os.path.exists(self.root))
        self.assertTrue(os.path.isfile(os.path.join(self.root, self.profile)))
        t0_ = Manager.get(self.root, self.profile, False)
        self.assertIsNot(t0, t0_)
        self.check(t0_, '', 1, None, OPEN, None, '')
        t0_ = Manager.get(self.root, self.profile)
        self.check(t0_, 'work', 1, None, OPEN, None, '')

        # 名前付きタスクトリ
        t1 = Tasktory('#123.あいうえお', 123, CLOSE)
        t1.add_time(10,20)
        t1.comments = 'コメント'
        Manager.put(self.root, t1, self.profile)
        self.assertTrue(os.path.exists(os.path.join(self.root, t1.name)))
        self.assertTrue(os.path.isfile(os.path.join(self.root, t1.name, self.profile)))
        t1_ = Manager.get(os.path.join(self.root, t1.name), self.profile, False)
        self.check(t1_, '#123.あいうえお', 123, None, CLOSE, None, 'コメント')
        return
 def leaf(self, attrs):
     task = Tasktory(
             self.root + attrs['PATH'],
             attrs['DEADLINE'], attrs['STATUS'], attrs['COMMENT'])
     for start, sec in attrs['TIMETABLE']:
         task.punch(start, sec)
     return task
Beispiel #3
0
    def commit_task(self, date, attrs):

        # コミットしたタスクの数
        commit_num = 0

        # タスクを作成する
        if not attrs:
            return 0
        leafs, inners = zip(*(self.tb.build(attr) for attr in attrs))
        # leafs, inners = zip(*map(self.tb.build, attrs))

        # 当日の午前零時から翌日の午前零時
        a = datetime.datetime(date.year, date.month, date.day, 0, 0, 0)
        b = a + datetime.timedelta(1)
        a = int(a.timestamp())
        b = int(b.timestamp())

        def at_date(t):
            return a <= t[0] and t[0] < b

        # 内部ノードは存在しないもののみコミットする
        for task in sum(inners, []):
            if not Tasktory.istask(task.path):
                task.sync()
                commit_num += 1
                self.info("CREATE", str(task))

        # 葉ノードは変更があるもののみコミットする
        for task in leafs:
            # 存在しなければコミットする
            if not Tasktory.istask(task.path):
                task.sync()
                commit_num += 1
                self.info("CREATE", str(task))
                continue

            # 既存のタスクを復元する
            org = Tasktory.restore(task.path)

            # 変更が無ければ無視する
            if all([
                    org.deadline == task.deadline,
                    org.status == task.status,
                    set(filter(at_date, org.timetable)) == set(task.timetable),
                    org.comment == task.comment,
                    ]):
                continue

            # 当日分の作業時間を削除する
            org.timetable = [t for t in org.timetable if not at_date(t)]

            # マージしてコミットする
            org.merge(task).sync()
            commit_num += 1
            self.info("UPDATE", str(task))

        return commit_num
Beispiel #4
0
def timetable():

    # クエリが無ければ、クエリを付けてリダイレクト
    if not request.query.date:
        redirect("{}?date={}".format(URL_TIMETABLE,
                                     datetime.date.today().toordinal()))

    # クエリパラメータから日付取得
    date = datetime.date.fromordinal(int(request.query.date))

    # コンフィグ読み込み
    config = configparser.ConfigParser()
    config.read(MAIN_CONF_FILE)

    # タスク復元
    tasks = Tasktory.restore(config["Main"]["ROOT"])

    # HTMLテンプレートを準備する
    env = Environment(loader=FileSystemLoader(HTML_DIR))
    template = env.get_template("timetable.html")

    # テンプレートに渡す変数を用意する
    a = datetime.datetime(date.year, date.month, date.day, 0, 0, 0)
    b = a + datetime.timedelta(1)
    a = int(a.timestamp())
    b = int(b.timestamp())

    return template.render(path=URL_TIMETABLE,
                           today=date,
                           tasks=[t for t in tasks if t.at(date)],
                           root=config["Main"]["ROOT"],
                           a=a,
                           b=b)
Beispiel #5
0
    def commit(self):
        # ジャーナルを解析する
        date, attrs, memos, _ = self.read()

        # ファイルシステムにコミットする
        commit_task_num = self.commit_task(date, attrs)

        # メモのタスクが存在するか確認する
        for memo in memos:
            if not Tasktory.istask(memo["PATH"]):
                raise JournalManagerNoExistTaskOfMemoError(memo["PATH"])

        # メモをコミットする
        now = datetime.datetime.now()
        for memo in memos:
            if Tasktory.restore(memo["PATH"]).memo.put(now, memo["TEXT"]):
                self.info("MEMO", memo["PATH"])

        return commit_task_num, len(memos)
Beispiel #6
0
    def test_get_tree(self):
        # 存在しないパス
        self.assertFalse(os.path.exists(self.root))
        self.assertIsNone(Manager.get_tree(self.root, self.profile))

        # タスクトリでないパス
        self.assertIsNone(Manager.get_tree('/Users/taku', self.profile))

        # タスクトリ
        t0 = Tasktory('', 1)
        t1 = Tasktory('00.あ', 2)
        t2 = Tasktory('01.か', 3)
        t21 = Tasktory('02.き', 4)
        t22 = Tasktory('02.きき', 5)
        t0.append(t1)
        t0.append(t2)
        t2.append(t21)
        t2.append(t22)
        for node in t0:
            Manager.put(self.root, node, self.profile)

        t0_ = Manager.get_tree(self.root, self.profile)
        for n, n_ in zip(t0, t0_):
            self.check(n_, n.name, n.deadline, n_.parent,
                    n.status, n.category, n.comments)
        return
Beispiel #7
0
    def analize(self, root):
        # ルートパスからタスクトリ名一覧を取得する
        paths = [(p, n) for p, names, _ in walk(root) for n in names]
        tasknames = [n for p, n in paths if Tasktory.istask(join(p, n))]

        # 番号付き名前分離
        names = [self.r_name.match(n).group(1) for n in tasknames]

        # バージョンタグ
        ver_tags = list(set([n for n in names if self.r_ver.match(n)]))

        # リビジョンタグ
        rev_tags = list(set([n for n in names if self.r_rev.match(n)]))

        # 番号タグ
        num_tags = list(set([n for n in names if self.r_num.match(n)]))

        # 重複タグ
        dup_tags = list(set([n for n in names if names.count(n) > 1]))

        return ver_tags + rev_tags + num_tags + dup_tags + self.reg_tags
Beispiel #8
0
    def analize(self, root):
        # ルートパスからタスクトリ名一覧を取得する
        paths = [(p, n) for p, names, _ in walk(root) for n in names]
        tasknames = [n for p, n in paths if Tasktory.istask(join(p, n))]

        # 番号付き名前分離
        names = [self.r_name.match(n).group(1) for n in tasknames]

        # バージョンタグ
        ver_tags = list(set([n for n in names if self.r_ver.match(n)]))

        # リビジョンタグ
        rev_tags = list(set([n for n in names if self.r_rev.match(n)]))

        # 番号タグ
        num_tags = list(set([n for n in names if self.r_num.match(n)]))

        # 重複タグ
        dup_tags = list(set([n for n in names if names.count(n) > 1]))

        return ver_tags + rev_tags + num_tags + dup_tags + self.reg_tags
Beispiel #9
0
def sync():
    # コンフィグ読み込み
    config = configparser.ConfigParser()
    config.read(MAIN_CONF_FILE)
    root_path = config["Main"]["ROOT"]

    # テスト
    day0 = datetime.datetime.fromordinal(request.json["date"])
    day1 = day0 + datetime.timedelta(1)
    ts0 = int(day0.timestamp())
    ts1 = int(day1.timestamp())
    for data in request.json["datas"]:
        task = Tasktory.restore(root_path + data["path"])
        print(task.path)
        for s, t in filter(lambda v: ts0 <= v[0] < ts1, task.timetable):
            print(s, t)
        print()
        for term in data["terms"]:
            print(ts0 + term["s"] * 60, term["t"] * 60)
        print()
    return
Beispiel #10
0
    def checkout(self, date):
        # 既存のジャーナルからメモを読み出す
        _, _, _, plain_memo = self.read()

        # ファイルシステムからタスクを復元する
        root_task = Tasktory.restore(self.root)
        if root_task is None:
            tasks = []
        else:
            self.jt.date = date
            tasks = [t for t in root_task if self.jt.test(t)]

        # tasksのuniqを取る
        tasks = unique(tasks, lambda t: t.path)

        # ジャーナルディレクトリを作成する
        os.makedirs(os.path.dirname(self.journal), exist_ok=True)

        # ジャーナルを書き出す
        with open(self.journal, 'w', encoding='utf-8') as f:
            f.write(self.jb.build(date, tasks, plain_memo))
Beispiel #11
0
def sync():
    # コンフィグ読み込み
    config = configparser.ConfigParser()
    config.read(MAIN_CONF_FILE)
    root_path = config["Main"]["ROOT"]

    # テスト
    day0 = datetime.datetime.fromordinal(request.json["date"])
    day1 = day0 + datetime.timedelta(1)
    ts0 = int(day0.timestamp())
    ts1 = int(day1.timestamp())
    for data in request.json["datas"]:
        task = Tasktory.restore(root_path + data["path"])
        print(task.path)
        for s, t in filter(lambda v: ts0 <= v[0] < ts1, task.timetable):
            print(s, t)
        print()
        for term in data["terms"]:
            print(ts0 + term["s"] * 60, term["t"] * 60)
        print()
    return
Beispiel #12
0
def timetable():

    # クエリが無ければ、クエリを付けてリダイレクト
    if not request.query.date:
        redirect("{}?date={}".format(
            URL_TIMETABLE,
            datetime.date.today().toordinal()
            ))

    # クエリパラメータから日付取得
    date = datetime.date.fromordinal(int(request.query.date))

    # コンフィグ読み込み
    config = configparser.ConfigParser()
    config.read(MAIN_CONF_FILE)

    # タスク復元
    tasks = Tasktory.restore(config["Main"]["ROOT"])

    # HTMLテンプレートを準備する
    env = Environment(loader=FileSystemLoader(HTML_DIR))
    template = env.get_template("timetable.html")

    # テンプレートに渡す変数を用意する
    a = datetime.datetime(date.year, date.month, date.day, 0, 0, 0)
    b = a + datetime.timedelta(1)
    a = int(a.timestamp())
    b = int(b.timestamp())

    return template.render(
            path=URL_TIMETABLE,
            today=date,
            tasks=[t for t in tasks if t.at(date)],
            root=config["Main"]["ROOT"],
            a=a,
            b=b
            )
Beispiel #13
0
    def test_journal(self):
        j_tmpl ="""%YEAR/%MONTH/%DAY
$ Todo
%OPENTASKS
$ Wait
%WAITTASKS
$ Done
%CLOSETASKS
$ Const
%CONSTTASKS
$ MEMO
%MEMO
"""
        date = datetime.date(2014, 4, 1)
        j_tmpl = RWTemplate(j_tmpl)
        tl_tmpl = RWTemplate('%PATH @%DEADLINE [%TIMES]')
        tm_tmpl = RWTemplate('%SHOUR:%SMIN-%EHOUR:%EMIN')
        tm_delim = ','
        stamp = datetime.date(2014, 4, 1).toordinal()
        tstamp = datetime.datetime(2014, 4, 1, 0, 0, 0).timestamp()

        # None
        self.assertRaises(TypeError, Journal.journal,
            date, None, '', j_tmpl, tl_tmpl, tm_tmpl, tm_delim, 365)

        # 出力タスクトリなし
        root = Tasktory('', stamp + 366)
        j = Journal.journal(date, root, '',
                j_tmpl, tl_tmpl, tm_tmpl, tm_delim, 365)
        journal = """2014/04/01
$ Todo

$ Wait

$ Done

$ Const

$ MEMO

"""
        self.assertEqual(j, journal)

        # タスクトリ
        root = Tasktory('', stamp + 366); root.comments += 'Root task'
        proj = Tasktory('Project', stamp + 30); proj.comments += 'Project task'
        root.append(proj)
        task1 = Tasktory('Task1', stamp + 3).add_time(tstamp, 3600)
        task1.comments = 'task1\nほげほげ'
        proj.append(task1)
        task2 = Tasktory('Task2', stamp + 3).add_time(
                tstamp+3600, 3600).add_time(tstamp+10800, 3600)
        proj.append(task2)
        task3 = Tasktory('Task3', stamp + 0, CLOSE).add_time(tstamp+7200, 3600)
        proj.append(task3)
        ctask = Tasktory('ConstTask', stamp + 365, CONST).add_time(tstamp+14400, 3600)
        proj.append(ctask)

        j = Journal.journal(date, root, 'This is memo\nhogehoge',
                j_tmpl, tl_tmpl, tm_tmpl, tm_delim, 365)

        journal = """2014/04/01
$ Todo
/Project @30 []
 # Project task
/Project/Task1 @3 [0:00-1:00]
 # task1
 # ほげほげ
/Project/Task2 @3 [1:00-2:00,3:00-4:00]

$ Wait

$ Done

$ Const
/Project/ConstTask @365 [4:00-5:00]

$ MEMO
This is memo
hogehoge
"""
        self.assertEqual(j, journal)
        return
Beispiel #14
0
import datetime
import configparser

from jinja2 import Environment, FileSystemLoader

from lib.core.Tasktory import Tasktory
from lib.common.common import HTML_DIR
from lib.common.common import MAIN_CONF_FILE

if __name__ == '__main__':
    config = configparser.ConfigParser()
    config.read(MAIN_CONF_FILE)

    # タスク作成
    tasks = Tasktory.restore(config["Main"]["ROOT"])

    # HTML作成準備
    env = Environment(loader=FileSystemLoader(HTML_DIR))
    template = env.get_template("timetable.html")
    path = "/Users/taku/tmp/html/test.html"

    today = datetime.date.today()
    a = datetime.datetime(today.year, today.month, today.day, 0, 0, 0)
    b = a + datetime.timedelta(1)
    a = int(a.timestamp())
    b = int(b.timestamp())

    # HTML書き出し
    with open(path, "w", encoding="utf-8") as f:
        f.write(template.render(
Beispiel #15
0
 def leaf(self, attrs):
     task = Tasktory(self.root + attrs['PATH'], attrs['DEADLINE'],
                     attrs['STATUS'], attrs['COMMENT'])
     for start, sec in attrs['TIMETABLE']:
         task.punch(start, sec)
     return task
Beispiel #16
0
 def inner(self, path, attrs):
     return Tasktory(self.root + path, attrs['DEADLINE'], Tasktory.OPEN, '')
Beispiel #17
0
    def test_taskline(self):
        date = datetime.date(2014, 4, 1)
        datestamp = date.toordinal()
        timestamp = int(datetime.datetime(2014, 4, 1).timestamp())
        tl_tmpl = RWTemplate('%PATH @%DEADLINE [%TIMES]')
        tm_tmpl = RWTemplate('%SHOUR:%SMIN-%EHOUR:%EMIN')
        tm_delim = ','

        # 空タスクトリ
        t = Tasktory('', datestamp + 3650)
        self.assertEqual(Journal.taskline(date, t, tl_tmpl, tm_tmpl, tm_delim),
                '/ @3650 []')

        # 名前付き
        t1 = Tasktory('#123.あいうえお', datestamp + 30)
        self.assertEqual(Journal.taskline(date, t1, tl_tmpl, tm_tmpl, tm_delim),
                '/#123.あいうえお @30 []')
        t.append(t1)
        t1.add_time(timestamp, 3600)
        self.assertEqual(Journal.taskline(date, t1, tl_tmpl, tm_tmpl, tm_delim),
                '/#123.あいうえお @30 [0:00-1:00]')

        t11 = Tasktory('かきくけこ', datestamp + 15)
        self.assertEqual(Journal.taskline(date, t11, tl_tmpl, tm_tmpl, tm_delim),
                '/かきくけこ @15 []')
        t1.append(t11)
        t11.add_time(timestamp+3600, 1800)
        t11.add_time(timestamp+36000, 7200)
        self.assertEqual(Journal.taskline(date, t11, tl_tmpl, tm_tmpl, tm_delim),
                '/#123.あいうえお/かきくけこ @15 [1:00-1:30,10:00-12:00]')
        return
Beispiel #18
0
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from configparser import ConfigParser
from lib.core.Tasktory import Tasktory
from lib.ui.report.Report import Report
from lib.common.common import MAIN_CONF_FILE

if __name__ == '__main__':
    config = ConfigParser()
    config.read(MAIN_CONF_FILE)

    root = Tasktory.restore(config["Main"]["ROOT"])

    report = Report("weekly.tmpl")
    print(report.test(root))
Beispiel #19
0
from lib.ui.journal.tester.JournalTester import JournalTester
from lib.common.common import MAIN_CONF_FILE

if __name__ == '__main__':
    # read config
    config = configparser.ConfigParser()
    config.read(MAIN_CONF_FILE)

    # today
    date = datetime.date.today() - datetime.timedelta(2)

    # TaskLineBuilder
    builder = TaskLineBuilder(date, config)

    root_dir = config['Main']['ROOT']
    root_task = Tasktory.restore(root_dir)
    root_task = [] if root_task is None else root_task

    # Filter test
    tester = JournalTester()
    tester.date = date

    # show all
    for task in root_task:
        print(builder.build(task), task.status)

    # show separator
    print("\n==========\n")

    # show
    for task in [t for t in root_task if tester.test(t)]: