예제 #1
0
def test_sanity():
    log.title(f"test_sanity()")
    work = default_work(TEST_START_ARROW)
    work.stop()
    with temp_sheet("/tmp/timefred-sheet-test_log__test_sanity.toml"):
        store.dump(work)
        log_action()
예제 #2
0
def edit():
    if "EDITOR" not in os.environ:
        raise NoEditor("Please set the 'EDITOR' environment variable")
    
    data = store.load()
    yml = yaml.safe_dump(data, default_flow_style=False, allow_unicode=True)
    
    cmd = os.getenv('EDITOR')
    fd, temp_path = tempfile.mkstemp(prefix='timefred.')
    with open(temp_path, "r+") as f:
        f.write(yml.replace('\n- ', '\n\n- '))
        f.seek(0)
        subprocess.check_call(cmd + ' ' + temp_path, shell=True)
        yml = f.read()
        f.truncate()
    
    os.close(fd)
    os.remove(temp_path)
    
    try:
        data = yaml.load(yml)
    except:
        raise InvalidYAML("Oops, that YAML doesn't appear to be valid!")
    
    store.dump(data)
예제 #3
0
def note(content, time="now"):
    time = XArrow.from_human(time)
    # time = human2arrow(time)
    if time > XArrow.now():
        raise BadTime(f"in the future: {time}")
    content_and_time = content.strip() + f' ({time.HHmmss})'
    work = store.load()
    idx = -1
    item = Entry(**work[idx])
    if time < item.start:
        # Note for something in the past
        idx, item_in_range = next((i, item) for i, item in enumerate(map(lambda w: Entry(**w), reversed(work)), 1) if item.start.full == time.full)
        idx *= -1
        
        if item_in_range.name == item.name:
            item = item_in_range
        else:
            if not confirm(f'{item.name_colored} started only at {c.time(item.start.strftime("%X"))},\n'
                           f'note to {item_in_range.name_colored} (started at {c.time(item_in_range.start.strftime("%X"))})?'):
                return
            item = item_in_range
    
    for n in item.notes:
        if n.is_similar(content):
            if not confirm(f'{item.name_colored} already has this note: {c.b(c.note(n))}.\n'
                           'Add anyway?'):
                return
    
    item.notes.append(content_and_time)
    work[idx]['notes'] = item.notes
    store.dump(work)
    
    print(f'Noted {c.b(c.note(content_and_time))} to {item.name_colored}')
예제 #4
0
 def test_load_store(self, work=None):
     log.title(f"test_load_store({work = })")
     if not work:
         work = default_work()
     with temp_sheet(
             "/tmp/timefred-sheet-test_on_device_validation_08_30.toml"
     ):
         store.dump(work)
         work = store.load()
     self.test_sanity(work=work)
예제 #5
0
 def test_dump(self):
     work = default_work()
     log.title(f"test_dump({work = })")
     # os.environ['TIMEFRED_SHEET'] = "/tmp/timefred-sheet-test_on_device_validation_08_30.toml"
     # config.sheet.path = "/tmp/timefred-sheet-test_on_device_validation_08_30.toml"
     # store.path = "/tmp/timefred-sheet-test_on_device_validation_08_30.toml"
     with temp_sheet(
             "/tmp/timefred-sheet-test_on_device_validation_08_30.toml"):
         store.dump(work)
         work = store.load()
예제 #6
0
def tag(_tag, time="now") -> bool:
    time = XArrow.from_human(time)
    # time = human2arrow(time)
    if time > time.now():
        raise BadTime(f"in the future: {time}")
    work = store.load()
    idx = -1
    item = Entry(**work[idx])
    if time < item.start:
        # Tag something in the past
        idx = -1 * next(i for i, work in enumerate(reversed(work), 1)
                        if Entry(**work).start <= time)
        item_in_range = Entry(**work[idx])
        if not confirm(
                f'{item.name_colored} started only at {c.time(item.start.strftime("%X"))}, '
                f'Tag {item_in_range.name_colored} (started at {c.time(item_in_range.start.strftime("%X"))})?'
        ):
            return False
        item = item_in_range
    tag_colored = c.tag(_tag)
    if any(
            util.normalize_str(_tag) == t
            for t in map(util.normalize_str, item.tags)):
        print(f'{item.name_colored} already has tag {tag_colored}.')
        return False
    item.tags.add(_tag)
    work[idx]['tags'] = item.tags

    ok = store.dump(work)
    if ok:
        print(f"Okay, tagged {item.name_colored} with {tag_colored}.")
    else:
        print(f"Failed writing to sheet")
    return ok
예제 #7
0
def on(name: str, time: Union[str, XArrow], tag=None, note=None):
    work = store.load()
    if work:
        day = work[time.DDMMYY]
        activity = day[name]
        if activity.ongoing() and activity.has_similar_name(name):
            print(
                f'{c.orange("Already")} working on {activity.name.colored} since {c.time(activity.start.DDMMYYHHmmss)} ;)'
            )
            return True
        ok = stop(time)
        if ok:
            return on(name, time, tag)
        breakpoint()
        return False

    entry = Entry(start=time)
    # assert entry
    # assert entry.start
    # assert isinstance(entry.start, XArrow)

    activity = Activity(name=name)
    # assert not activity
    # assert len(activity) == 0
    # assert activity.name == 'Got to office', f"activity.name is not 'Got to office' but rather {activity.name!r}"
    # assert isinstance(activity.name, Colored), f'Not Colored, but rather {type(activity.name)}'
    activity.append(entry)
    # assert len(activity) == 1
    if tag:
        entry.tags.add(tag)

    if note:
        note = Note(note, time)
        entry.notes.append(note)

    # work[entry.start.DDMMYY].append({str(activity.name): activity.dict(exclude=('timespan', 'name'))})
    day = work[entry.start.DDMMYY]
    day[str(activity.name)] = activity
    # work[activity.start.DDMMYY].append(activity)
    # work.append(activity.dict())
    ok = store.dump(work)
    if not ok:
        breakpoint()

    # message = f'{c.green("Started")} working on {activity.name_colored} at {c.time(reformat(time, timeutils.FORMATS.date_time))}'
    message = f'{c.green("Started")} working on {activity.name.colored} at {c.time(entry.start.DDMMYYHHmmss)}'
    if tag:
        message += f". Tag: {c.tag(tag)}"

    if note:
        message += f". Note: {note.pretty()}"
    print(message)
예제 #8
0
def stop(end: XArrow, tag: Tag = None, note: Note = None) -> bool:
    # ensure_working()
    
    work: Work = store.load()
    ongoing_activity: Activity = work.ongoing_activity()
    entry: Entry = ongoing_activity.stop(end, tag, note)
    
    if entry.start.day < end.day:
        if not util.confirm(f'{ongoing_activity.name} started on {c.time(entry.start.DDMMYYHHmmss)}, continue?'):
            # TODO: activity is wrongly stopped now, should revert or prevent
            return False
    
    ok = store.dump(work)
    print(f'{c.yellow("Stopped")} working on {ongoing_activity.name.colored} at {c.time(entry.end.DDMMYYHHmmss)}. ok: {ok}')
    return ok