Example #1
0
        def test_from_absolute_DDMMYYHHmmss(self):
            datetime = "13/12/21 11:23:45"
            from_absolute = XArrow.from_absolute(datetime)
            assert from_absolute.day == 13
            assert from_absolute.month == 12
            assert from_absolute.year == 2021
            assert from_absolute.hour == 11
            assert from_absolute.minute == 23
            assert from_absolute.second == 45

            datetime = "13/12 11:23:45"
            from_absolute = XArrow.from_absolute(datetime)
            assert from_absolute.day == 13
            assert from_absolute.month == 12
            assert from_absolute.hour == 11
            assert from_absolute.minute == 23
            assert from_absolute.second == 45

            datetime = "13/12/21 11:23"
            from_absolute = XArrow.from_absolute(datetime)
            assert from_absolute.day == 13
            assert from_absolute.month == 12
            assert from_absolute.year == 2021
            assert from_absolute.hour == 11
            assert from_absolute.minute == 23
            assert from_absolute.second == 0

            datetime = "13/12 11:23"
            from_absolute = XArrow.from_absolute(datetime)
            assert from_absolute.day == 13
            assert from_absolute.month == 12
            assert from_absolute.hour == 11
            assert from_absolute.minute == 23
            assert from_absolute.second == 00
Example #2
0
    def test_from_formatted(self):
        test_start_from_formatted = XArrow.from_formatted(TEST_START_ARROW)
        assert_arrows_soft_eq(test_start_from_formatted, TEST_START_ARROW)
        assert test_start_from_formatted is TEST_START_ARROW

        for fmt, expected_attrs in {
                FORMATS.date: ['year', 'month', 'day'],
                FORMATS.short_date: ['month', 'day'],
                FORMATS.time: ['hour', 'minute', 'second'],
                FORMATS.short_time: ['hour', 'minute'],
                FORMATS.datetime:
            ['year', 'month', 'day', 'hour', 'minute', 'second'],
                FORMATS.shorter_datetime:
            ['year', 'month', 'day', 'hour', 'minute'],
                FORMATS.short_datetime: ['month', 'day', 'hour', 'minute'],
        }.items():
            formatted = TEST_START_ARROW.format(fmt)
            from_formatted: XArrow = XArrow.from_formatted(formatted)
            assert_equal_attrs(from_formatted, TEST_START_ARROW,
                               *expected_attrs)
            for not_included_attr in TIME_UNITS - set(expected_attrs):
                assert getattr(
                    from_formatted,
                    not_included_attr) == 0 if not_included_attr in {
                        'hour', 'minute', 'second'
                    } else 1
Example #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}')
Example #4
0
def test_arrows2rel_time():
    present = XArrow.now()
    past = present.shift(weeks=-3, days=-3)
    assert arrows2rel_time(present, past) == '3 weeks & 3 days ago'

    present = XArrow.from_absolute('21/12/21')
    past = XArrow.from_absolute('01/12/21')
    secs = int((present - past).total_seconds())
    assert 20 * 24 * 3600 <= secs <= 21 * 24 * 3600
    ret = arrows2rel_time(present, past)
    assert ret == '2 weeks & 6 days ago'
Example #5
0
        def test_from_absolute_HHmmss(self):
            HHmmss = "02:00:00"
            from_absolute = XArrow.from_absolute(HHmmss)
            assert from_absolute.hour == 2
            assert from_absolute.minute == 0
            assert from_absolute.second == 0

            HHmmss = "02:53:49"
            from_absolute = XArrow.from_absolute(HHmmss)
            assert from_absolute.hour == 2
            assert from_absolute.minute == 53
            assert from_absolute.second == 49
Example #6
0
        def test_dehumanize_static(self):
            now_dehumanized = XArrow.dehumanize("now")
            now = XArrow.now()
            assert_arrows_soft_eq(now_dehumanized, now)

            today = XArrow.dehumanize('today')
            assert_arrows_soft_eq(today, now)

            yesterday = XArrow.dehumanize('yesterday')
            now_shift_yesterday = now.shift(days=-1)
            assert_arrows_soft_eq(now_shift_yesterday, yesterday)

            tomorrow = XArrow.dehumanize('tomorrow')
            now_shift_tomorrow = now.shift(days=+1)
            assert_arrows_soft_eq(now_shift_tomorrow, tomorrow)
Example #7
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
Example #8
0
 def on(self,
        name: Union[str, Activity],
        time: Union[str, XArrow] = None,
        tag: Union[str, Tag] = None,
        note: Union[str, Note] = None) -> Activity:
     """
     Raises:
         ValueError: if an activity with the same / similar name is already ongoing
     """
     if time is None:
         time = XArrow.now()
     try:
         ongoing_activity = self.ongoing_activity()
     except ValueError:
         # No ongoing activity -> start new activity
         day = self[time.DDMMYY]
         activity: Activity = day[name]
         activity.start(time, tag, note)
         return activity
     else:
         # Ongoing activity -> stop it and start new activity
         if name == ongoing_activity.name:
             raise ValueError(
                 f'{ongoing_activity.shortrepr()} is already ongoing')
         if ongoing_activity.has_similar_name(name):
             raise ValueError(
                 f'{ongoing_activity.shortrepr()} is ongoing, and has a similar name to {name!r}'
             )
         ongoing_activity.stop(time)
         day = self[time.DDMMYY]
         activity: Activity = day[name]
         activity.start(time, tag, note)
         return activity
Example #9
0
    def stop(self,
             time: Union[str, XArrow] = None,
             tag: Union[str, Tag] = None,
             note: Union[str, Note] = None) -> Entry:
        """
        Returns:
            Last entry.
        Raises:
            ValueError: if the activity is not ongoing
        """
        last_entry = self.safe_last_entry()
        if not last_entry or last_entry.end:
            raise ValueError(f'{self.shortrepr()} is not ongoing')
        if not time:
            time = XArrow.now()
        if last_entry.start > time:
            raise ValueError(
                f'Cannot stop {self.shortrepr()} before start time (tried to stop at {time!r})'
            )
        last_entry.end = time

        if tag:
            last_entry.tags.add(tag)
        if note:
            last_entry.notes.append(note)
        return last_entry
Example #10
0
    def test_on_got_to_office_08_20(self):
        work = Work()
        '''{ "02/11/21" : Day }'''
        assert isinstance(work, Work)
        assert isinstance(work, dict)
        assert not work
        assert len(work) == 0

        entry = Entry(start="02:20")
        assert entry
        assert entry.start
        assert isinstance(entry.start, XArrow)
        absolute = XArrow.from_absolute("02:20")
        entry_start = entry.start
        assert_arrows_soft_eq(entry_start, absolute)

        name = "Got to office"
        activity = Activity(name=name)
        assert not activity  # because list
        assert len(activity) == 0
        assert isinstance(activity.name, Colored)
        assert activity.name == name

        activity.append(entry)
        assert activity
        assert len(activity) == 1
        assert activity[0] == entry

        day = work[entry.start.DDMMYY]
        assert isinstance(day, Day)
        day[name] = activity
        assert day[
            name] == activity, f"{day[str(activity.name)] = }, {activity = }"
        assert work
        assert len(work) == 1
Example #11
0
        def test_from_absolute_now(self):
            now = XArrow.now().replace(second=0)
            from_absolute_now = XArrow.from_absolute(now)
            assert_arrows_soft_eq(from_absolute_now, now)
            assert from_absolute_now is now

            for fmt in [  # FORMATS.date,
                    # FORMATS.short_date:       ['month', 'day'],
                    FORMATS.time,
                    FORMATS.short_time,
                    # FORMATS.datetime:         ['year', 'month', 'day', 'hour', 'minute', 'second'],
                    # FORMATS.shorter_datetime: ['year', 'month', 'day', 'hour', 'minute'],
                    # FORMATS.short_datetime:   ['month', 'day', 'hour', 'minute'],
            ]:
                formatted = now.format(fmt)
                from_absolute_formatted: XArrow = XArrow.from_absolute(
                    formatted)
                assert_arrows_soft_eq(from_absolute_formatted, now)
Example #12
0
    def test_from_day(self):
        days = [
            'sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday',
            'saturday'
        ]

        for num, day in enumerate(days, start=1):
            for char_index in range(2, len(day) + 1):
                arrow_from_day = XArrow.from_day(day[:char_index])
                assert arrow_from_day.strftime('%A').lower() == day
Example #13
0
def test_log_01_12_21(capsys):
    raw_data = dedent('''
    ["01/12/21"]
    "Got to office" = "10:00"
    
    [["01/12/21"."Integration"]]
    synced = true
    start = 10:30:00
    end = 11:00:00
    
    [["01/12/21"."Integration"]]
    synced = true
    start = 11:20:00
    end = 11:40:00
    
    [["01/12/21"."Integration - Weak WIFI Password"]]
    synced = true
    start = 13:30:00
    end = 13:40:00
    notes = {"13:40:00" = "With Vlad, tested, done, everything as expected"}
    
    [["01/12/21"."immediate endTime quiet time default value is empty str"]]
    start = 14:00:00
    end = 17:30:00
    jira = "ASM-13925"
    synced = true
    ''')
    sheet_path = '/tmp/timefred-sheet--test-action--test-log--test-log-01-12-21.toml'
    with open(sheet_path, 'w') as sheet:
        sheet.write(raw_data)

    with temp_sheet(sheet_path):
        log_action('01/12/21')

    captured = capsys.readouterr()
    output = captured.out
    output_lines = output.splitlines()
    now = XArrow.now()
    past = XArrow.from_absolute('01/12/21')
    from timefred.time.timeutils import arrows2rel_time
    assert decolor(output_lines[0]
                   ) == f'Wednesday, 01/12/21 | {arrows2rel_time(now, past)}'
Example #14
0
 def test_sub(self):
     minute = 60
     hour = minute * 60
     day = hour * 24
     week = day * 7
     present = XArrow.now()
     past = present.shift(weeks=-3, days=-3)
     td = present - past
     assert td.days == 3 * 7 + 3
     secs = int(td.total_seconds())
     assert secs == 3 * week + 3 * day
Example #15
0
 def test_init_with_all_fields(self):
     entry = Entry(start="02:00:00",
                   end="03:00:00",
                   synced=True,
                   notes=[{
                       "02:30:00": "PR-5000"
                   }],
                   tags=["meeting"])
     assert entry
     assert entry.start == XArrow.from_absolute("02:00:00")
     assert entry.end == XArrow.from_absolute("03:00:00")
     assert entry.synced is True
     assert entry.notes
     assert isinstance(entry.notes, list)
     assert entry.notes == [Note({"02:30:00": "PR-5000"})]
     assert isinstance(entry.notes[0], Note)
     assert entry.notes[0] == Note({"02:30:00": "PR-5000"})
     assert entry.notes[0].time == XArrow.from_absolute("02:30:00")
     assert entry.notes[0].content == "PR-5000"
     assert entry.tags == [Tag("meeting")]
     assert next(iter(entry.tags)) == Tag("meeting")
     assert isinstance(next(iter(entry.tags)), Tag)
Example #16
0
 def test_sanity(self):
     note = Note({"17:00": "PR-6091"})
     assert isinstance(note.time, XArrow)
     assert note.time == XArrow.from_absolute("17:00")
     assert note.time.hour == 17
     assert note.time.minute == 0
     assert note.time.second == 0, note.time.second
     assert note.content == "PR-6091"
     if not os.getenv('TIMEFRED_REPR', '').lower() in ('no', 'disable'):
         assert repr(
             note
         ) == f"Note(content = 'PR-6091', time = XArrow ⟨{TEST_START_ARROW.DDMMYY} 17:00:00⟩)", repr(
             note)
Example #17
0
 def stop(self,
          time: Union[str, XArrow] = None,
          tag: Union[str, Tag] = None,
          note: Union[str, Note] = None) -> Optional[Activity]:
     """
     Raises:
         ValueError: if there is no ongoing activity
     """
     ongoing_activity = self.ongoing_activity()
     if not time:
         time = XArrow.now()
     ongoing_activity.stop(time=time, tag=tag, note=note)
     stopped_activity = ongoing_activity
     return stopped_activity
Example #18
0
def default_work(day: XArrow = None) -> Work:
    """
    Returns Work of one day with a single activity, "Got to office": [{"start": "02:20"}]
    """
    if not day:
        day = XArrow.now()
    sheet = {
        day.DDMMYY: {
            "Got to office": [{
                "start": "02:20:00"
            }],
            # "Integration": [{"start": "02:20:00", "end": "02:30:00"}]
        }
    }
    work = Work(Day, **sheet)
    return work
Example #19
0
        def test_stop_when_not_ongoing(self):
            log.title(f"test_models.test_stop_when_not_ongoing()")
            work = default_work(TEST_START_ARROW)
            day: Day = work.__getitem__(TEST_START_ARROW.DDMMYY)
            got_to_office_activity: Activity = day.__getitem__("Got to office")
            assert got_to_office_activity.ongoing() is True

            now = XArrow.now()
            entry: Entry = got_to_office_activity.stop(now)
            assert entry is got_to_office_activity.safe_last_entry()
            assert entry.end == now

            assert got_to_office_activity.ongoing() is False

            with assert_raises(ValueError,
                               f'{got_to_office_activity} is not ongoing'):
                got_to_office_activity.stop()
Example #20
0
 def test_from_human_static(self):
     now = XArrow.from_human('now')
     today = XArrow.from_human('today')
     assert now == today == XArrow.now()
     yesterday = XArrow.from_human('yesterday')
     assert yesterday == now.shift(days=-1)
     assert yesterday.day == now.day - 1
     eight_days_ago = XArrow.from_human('8 days ago')
     assert eight_days_ago == now.shift(days=-8)
     assert eight_days_ago.day == now.day - 8
     dec_first_21 = XArrow.from_human('01/12/21')
     assert dec_first_21.year == 2021
     assert dec_first_21.month == 12
     assert dec_first_21.day == 1
     thursday = XArrow.from_human('thursday')
     assert thursday.strftime('%A') == 'Thursday'
Example #21
0
def status(show_notes=False):
    ensure_working()

    data = store.load()
    current = Entry(**data[-1])
    duration = Timespan(current.start, XArrow.now()).human_duration
    # diff = timegap(current.start, now())

    # notes = current.get('notes')
    if not show_notes or not current.notes:
        print(
            f'You have been working on {current.name.colored} for {c.time(duration)}.'
        )
        return

    print('\n    '.join([
        f'You have been working on {current.name_colored} for {c.time(duration)}.\nNotes:',  # [rgb(170,170,170)]
        *[f'{c.grey100("o")} {n.pretty()}' for n in current.notes]
    ]))
Example #22
0
        def test_stop_before_last_entry_started(self):
            log.title(f"test_models.test_stop_before_last_entry_started()")
            work = default_work(TEST_START_ARROW)

            day: Day = work.__getitem__(TEST_START_ARROW.DDMMYY)
            assert work[TEST_START_ARROW.DDMMYY] is day

            got_to_office_activity: Activity = day.__getitem__("Got to office")
            assert got_to_office_activity.ongoing() is True
            assert day['Got to office'] is got_to_office_activity

            last_entry: Entry = got_to_office_activity[-1]
            assert got_to_office_activity.safe_last_entry() is last_entry

            yesterday = XArrow.dehumanize('yesterday')
            with assert_raises(
                    ValueError,
                    f'Cannot stop {got_to_office_activity.shortrepr()} before start time (tried to stop at {yesterday!r})'
            ):
                got_to_office_activity.stop(yesterday)
Example #23
0
        def test_from_absolute_time(self):
            from datetime import time
            abs_time = time(hour=11, minute=0, second=0)
            from_absolute = XArrow.from_absolute(abs_time)
            assert from_absolute.hour == 11
            assert from_absolute.minute == 0
            assert from_absolute.second == 0

            abs_time = time(hour=11, minute=23, second=0)
            from_absolute = XArrow.from_absolute(abs_time)
            assert from_absolute.hour == 11
            assert from_absolute.minute == 23
            assert from_absolute.second == 0

            abs_time = time(hour=11, minute=23, second=45)
            from_absolute = XArrow.from_absolute(abs_time)
            assert from_absolute.hour == 11
            assert from_absolute.minute == 23
            assert from_absolute.second == 45

            abs_time = time(hour=11, minute=0, second=45)
            from_absolute = XArrow.from_absolute(abs_time)
            assert from_absolute.hour == 11
            assert from_absolute.minute == 0
            assert from_absolute.second == 45

            abs_time = time(hour=0, minute=0, second=45)
            from_absolute = XArrow.from_absolute(abs_time)
            assert from_absolute.hour == 0
            assert from_absolute.minute == 0
            assert from_absolute.second == 45

            abs_time = time(hour=0, minute=23, second=45)
            from_absolute = XArrow.from_absolute(abs_time)
            assert from_absolute.hour == 0
            assert from_absolute.minute == 23
            assert from_absolute.second == 45
Example #24
0
def parse_args(argv=[]) -> tuple[Callable, dict]:
    if not argv:
        argv = sys.argv
    # *** log
    # ** timefred
    # timefred -> log(detailed=True)
    argv_len = len(argv)
    if argv_len == 1:
        return action.log, {'detailed': True}

    # ** timefred thursday
    if len(argv[1]) > 1:
        if argv[1].lower() == 'yesterday':
            return action.log, {'time': argv[1], 'detailed': True}
        with suppress(ValueError):
            isoweekday(argv[1])
            return action.log, {'time': argv[1], 'detailed': True}

    head = argv[1]
    tail: list[str] = argv[2:]

    # ** log
    if head in ('l', 'l-', 'log', 'log-'):
        groupby = None
        with suppress(ValueError, AttributeError):
            groupby_idx = tail.index('-g')
            groupby = tail[groupby_idx + 1]
            tail = tail[:groupby_idx]
        if tail:
            time = ' '.join(tail)
        else:
            time = 'today'
        args = {'time': time, 'detailed': '-' not in head, 'groupby': groupby}
        return action.log, args

    # *** help
    if 'help' in head or head in ('-h', 'h'):
        print(__doc__, file=sys.stderr)
        sys.exit(0)

    # *** edit
    elif head in ('e', 'edit'):
        return action.edit, {}

    # *** on
    elif head in ('+', 'o', 'on'):
        if not tail:
            raise BadArguments("Need the name of whatever you are working on.")

        name = tail.pop(0)
        _tag = None
        _note = None
        if tail:
            with suppress(ValueError):
                _tag_idx = tail.index('-t')
                _tag = tail[_tag_idx + 1]
                tail = tail[:_tag_idx]
            with suppress(ValueError):
                _note_idx = tail.index('-n')
                _note = tail[_note_idx + 1]
                tail = tail[:_note_idx]
            time = XArrow.from_human(' '.join(tail) if tail else 'now')
        else:
            time = XArrow.now()
        args = {'name': name, 'time': time, 'tag': _tag, 'note': _note}
        return action.on, args

    # *** stop
    elif head in ('-', 'stop'):
        args = {'time': XArrow.from_human(' '.join(tail) if tail else 'now')}
        return action.stop, args

    # *** status
    elif head in ('?', '??', 's', 's+', 'status', 'status+'):
        args = {'show_notes': '+' in head}
        return action.status, args

    # *** tag
    elif head in ('t', 'tag'):
        if not tail:
            raise BadArguments("Please provide a tag.")

        if len(tail) == 2:
            _tag, time = tail
            args = {'tag': _tag, 'time': time}
        elif len(tail) == 1:
            args = {'tag': tail[0]}
        else:
            args = {'tag': ' '.join(tail)}
        return action.tag, args

    # *** note
    elif head in ('n', 'note'):
        if not tail:
            raise BadArguments("Please provide some text to be noted.")

        if len(tail) == 2:
            content, time = tail
            args = {'content': content, 'time': time}
        elif len(tail) == 1:
            args = {'content': tail[0]}
        else:
            args = {'content': ' '.join(tail)}
        return action.note, args

    # *** interrupt
    # elif head in ('i', 'interrupt'):
    # 	if not tail:
    # 		raise BadArguments("Need the name of whatever you are working on.")
    #
    # 	name = tail.pop(0)
    # 	args = {
    # 		'name': name,
    # 		'time': human2formatted(' '.join(tail) if tail else 'now'),
    # 		}
    # 	return interrupt, args

    # *** aggregate
    elif head == 'a' or head.startswith('ag'):
        if not tail:
            raise BadArguments("Need at least <start> <stop>")
        if len(tail) == 1:
            times = tail[0]
            if '-' in times:
                start, stop = map(str.strip, times.partition('-'))
            elif ' ' in times:
                start, stop = map(str.strip, times.partition(' '))
            else:
                raise BadArguments("Need at least <start> <stop>")
        else:
            start, stop, *tail = tail
        # start_arw = human2arrow(start)
        # stop_arw = human2arrow(stop)
        start_arw = XArrow.from_human(start)
        stop_arw = XArrow.from_human(stop)
        breakpoint()

    # *** _dev
    if head == '_dev':
        if tail[0] == 'generate completion':
            from timefred._dev import generate_completion
            return generate_completion, {}

    raise BadArguments("I don't understand %r" % (head, ))
Example #25
0
 def test_from_absolute_DDMMYY(self):
     DDMMYY = "13/12/21"
     from_absolute = XArrow.from_absolute(DDMMYY)
     assert from_absolute.day == 13
     assert from_absolute.month == 12
     assert from_absolute.year == 2021
Example #26
0
 def test_from_absolute_HHmm(self):
     HHmm = "02:00"
     from_absolute = XArrow.from_absolute(HHmm)
     assert from_absolute.hour == 2
     assert from_absolute.minute == 0
     assert from_absolute.second == 0
Example #27
0
 def test_dehumanize_advanced(
         self):  # can decide not to support if too difficult
     XArrow.dehumanize('1 days from now')
     XArrow.dehumanize('1 days from today')
Example #28
0
        def test_dehumanize_instance(self):
            now = XArrow.now()
            now_dehumanized = now.dehumanize("now")
            assert_arrows_soft_eq(now_dehumanized, now)

            today = now.dehumanize('today')
            assert_arrows_soft_eq(today, now)
            assert_arrows_soft_eq(today, now_dehumanized)

            # * Past
            # 1 day ago
            yesterday = now.dehumanize('yesterday')
            assert_arrows_soft_eq(now.shift(days=-1), yesterday)

            a_day_ago = now.dehumanize('a day ago')
            assert_arrows_soft_eq(a_day_ago, yesterday)

            _1_day_ago = now.dehumanize('1 day ago')
            assert_arrows_soft_eq(_1_day_ago, yesterday)

            _1d_ago = now.dehumanize('1d ago')
            assert_arrows_soft_eq(_1d_ago, yesterday)

            _1_days_ago = now.dehumanize('1 days ago')
            assert_arrows_soft_eq(_1_days_ago, yesterday)

            _1_d_ago = now.dehumanize('1 d ago')
            assert_arrows_soft_eq(_1_d_ago, yesterday)

            a_day = now.dehumanize('a day')
            assert_arrows_soft_eq(a_day, yesterday)

            _1_day = now.dehumanize('1 day')
            assert_arrows_soft_eq(_1_day, yesterday)

            _1d = now.dehumanize('1d')
            assert_arrows_soft_eq(_1d, yesterday)

            _1_d = now.dehumanize('1 d')
            assert_arrows_soft_eq(_1_d, yesterday)

            _1_days = now.dehumanize('1 days')
            assert_arrows_soft_eq(_1_days, yesterday)

            # 5 days ago
            five_days_ago = now.shift(days=-5)

            _5_day_ago = now.dehumanize('5 day ago')
            assert_arrows_soft_eq(_5_day_ago, five_days_ago)

            _5d_ago = now.dehumanize('5d ago')
            assert_arrows_soft_eq(_5d_ago, five_days_ago)

            _5_days_ago = now.dehumanize('5 days ago')
            assert_arrows_soft_eq(_5_days_ago, five_days_ago)

            _5_d_ago = now.dehumanize('5 d ago')
            assert_arrows_soft_eq(_5_d_ago, five_days_ago)

            _5_day = now.dehumanize('5 day')
            assert_arrows_soft_eq(_5_day, five_days_ago)

            _5d = now.dehumanize('5d')
            assert_arrows_soft_eq(_5d, five_days_ago)

            _5_d = now.dehumanize('5 d')
            assert_arrows_soft_eq(_5_d, five_days_ago)

            _5_days = now.dehumanize('5 days')
            assert_arrows_soft_eq(_5_days, five_days_ago)

            # months
            _5_months = now.dehumanize('5 months')
            assert_arrows_soft_eq(_5_months, now.shift(months=-5))

            _5_month = now.dehumanize('5 month')
            assert_arrows_soft_eq(_5_month, now.shift(months=-5))

            # Complex
            _5h_32m_1s_ago = now.dehumanize('5h 32m 1s ago')
            assert_arrows_soft_eq(_5h_32m_1s_ago,
                                  now.shift(hours=-5, minutes=-32, seconds=-1))

            _5_minutes_5_months = now.dehumanize('5 minutes 5 months')
            assert_arrows_soft_eq(_5_minutes_5_months,
                                  now.shift(minutes=-5, months=-5))

            _5m_5_months = now.dehumanize('5m 5 months')
            assert_arrows_soft_eq(_5m_5_months, now.shift(minutes=-5,
                                                          months=-5))

            _5m_5M = now.dehumanize('5m 5M')
            assert_arrows_soft_eq(_5m_5M, now.shift(minutes=-5, months=-5))

            _5m_5M_7w = now.dehumanize('5m 5M 7w')
            now_shift_5_minutes_5_months_7_weeks_ago = now.shift(minutes=-5,
                                                                 months=-5,
                                                                 weeks=-7)
            assert_arrows_soft_eq(_5m_5M_7w,
                                  now_shift_5_minutes_5_months_7_weeks_ago)

            for perm in permutations(['5m', '5M', '7w'], 3):
                complex = now.dehumanize(' '.join(perm))
                assert_arrows_soft_eq(
                    complex, now_shift_5_minutes_5_months_7_weeks_ago)

            # * Future
            in_1_days = now.dehumanize('in 1 days')
            tomorrow = now.dehumanize('tomorrow')
            assert_arrows_soft_eq(in_1_days, tomorrow)
            assert_arrows_soft_eq(now.shift(days=+1), tomorrow)
            assert_arrows_soft_eq(now.shift(days=+1), in_1_days)

            in_1_day = now.dehumanize('in 1 day')
            assert_arrows_soft_eq(in_1_day, tomorrow)

            in_5_days = now.dehumanize('in 5 days')
            assert_arrows_soft_eq(now.shift(days=+5), in_5_days)

            in_5_day = now.dehumanize('in 5 day')
            assert_arrows_soft_eq(in_5_day, now.shift(days=+5))

            now_shift_in_5_minutes_5_months_7_weeks = now.shift(minutes=+5,
                                                                months=+5,
                                                                weeks=+7)
            for perm in permutations(['5m', '5M', '7w'], 3):
                complex = now.dehumanize('in ' + ' '.join(perm))
                assert_arrows_soft_eq(complex,
                                      now_shift_in_5_minutes_5_months_7_weeks)
Example #29
0
from timefred.time import XArrow

print()
import os

os.environ.setdefault('TIMEFRED_TESTING', '1')
print(f"{os.environ['TIMEFRED_TESTING'] = }")
TEST_START_ARROW: XArrow = XArrow.now()
Example #30
0
        def test_dehumanize_vanilla(self):
            """Make sure we don't break vanilla Arrow.dehumanize() functionality"""
            log.title('TestXArrow.Test_dehumanize.test_dehumanize_vanilla')
            now = XArrow.now()
            now_dehumanized = XArrow.dehumanize("now")
            assert_arrows_soft_eq(now_dehumanized, now)
            assert_arrows_soft_eq(XArrow.dehumanize("just now"), now)
            # * 1 unit
            # "hour": "an hour", "days": "{0} days"
            for unit, expression in EnglishLocale.timeframes.items():
                for relative_fmt in ("{0} ago", "in {0}"):
                    if 'now' in expression:
                        continue
                    if '{0}' in expression:
                        shift = randint(2, 4)
                        hardcoded_number = expression.format(
                            shift)  # 3 seconds
                        human_expression = relative_fmt.format(
                            hardcoded_number)  # 3 seconds ago / in 3 seconds
                    else:
                        shift = 1
                        human_expression = relative_fmt.format(
                            expression)  # a second ago / in a second
                    dehumanized_static = XArrow.dehumanize(human_expression)

                    if 'ago' in relative_fmt:
                        shift *= -1
                    shift_kwargs = {unit.removesuffix('s') + 's': shift}
                    now = XArrow.now()
                    now_shifted = now.shift(**shift_kwargs)
                    try:
                        assert_arrows_soft_eq(dehumanized_static, now_shifted)
                    except AssertionError:
                        dehumanized_static = XArrow.dehumanize(
                            human_expression)
                        now = XArrow.now()
                        now_shifted = now.shift(**shift_kwargs)
                        assert_arrows_soft_eq(dehumanized_static, now_shifted)

                    dehumanized_instance = now.dehumanize(human_expression)
                    assert_arrows_soft_eq(dehumanized_instance, now_shifted)

            # * 2 units
            for time_unit_1 in TIME_UNITS:
                for time_unit_2 in TIME_UNITS:
                    if time_unit_1 == time_unit_2:
                        continue
                    if random() < 0.5:
                        continue
                    shift_1 = randint(2, 4)
                    shift_2 = randint(2, 4)
                    singular_time_unit_1 = (f"a" if time_unit_1 != "hour" else
                                            "an") + f" {time_unit_1}"
                    singular_time_unit_2 = (f"a" if time_unit_2 != "hour" else
                                            "an") + f" {time_unit_2}"
                    plural_time_unit_1 = f"{shift_1} {time_unit_1}s"
                    plural_time_unit_2 = f"{shift_2} {time_unit_2}s"
                    expressions = {}
                    for fmt in ["{0} and {1}", "{0}, {1}", "{0} {1}"]:
                        expressions[
                            fmt.format(plural_time_unit_1, plural_time_unit_2)
                            + " ago"] = (True, True)
                        expressions["in " + fmt.format(
                            plural_time_unit_1, plural_time_unit_2)] = (True,
                                                                        True)
                        expressions[fmt.format(plural_time_unit_1,
                                               singular_time_unit_2) +
                                    " ago"] = (True, False)
                        expressions["in " +
                                    fmt.format(plural_time_unit_1,
                                               singular_time_unit_2)] = (True,
                                                                         False)
                        expressions[fmt.format(singular_time_unit_1,
                                               plural_time_unit_2) +
                                    " ago"] = (False, True)
                        expressions["in " +
                                    fmt.format(singular_time_unit_1,
                                               plural_time_unit_2)] = (False,
                                                                       True)
                        expressions[fmt.format(singular_time_unit_1,
                                               singular_time_unit_2) +
                                    " ago"] = (False, False)
                        expressions["in " +
                                    fmt.format(singular_time_unit_1,
                                               singular_time_unit_2)] = (False,
                                                                         False)

                    for human_expression, quantity_tuple in expressions.items(
                    ):
                        shift_kwargs = {}
                        sign = 1 if human_expression.startswith("in ") else -1
                        if quantity_tuple[0]:
                            shift_kwargs[time_unit_1 + 's'] = shift_1 * sign
                        else:
                            shift_kwargs[time_unit_1 + 's'] = 1 * sign

                        if quantity_tuple[1]:
                            shift_kwargs[time_unit_2 + 's'] = shift_2 * sign
                        else:
                            shift_kwargs[time_unit_2 + 's'] = 1 * sign

                        now = XArrow.now()
                        dehumanized_instance_vanilla = Arrow.now().dehumanize(
                            human_expression)
                        dehumanized_instance_vanilla.microsecond = 0
                        dehumanized_static = XArrow.dehumanize(
                            human_expression)

                        now_shifted = now.shift(**shift_kwargs)
                        dehumanized_instance = now.dehumanize(human_expression)

                        try:
                            assert_arrows_soft_eq(dehumanized_instance,
                                                  now_shifted)
                            assert_arrows_soft_eq(dehumanized_static,
                                                  now_shifted)
                            assert_arrows_soft_eq(
                                dehumanized_instance,
                                dehumanized_instance_vanilla)
                            assert_arrows_soft_eq(
                                dehumanized_static,
                                dehumanized_instance_vanilla)
                        except AssertionError:
                            now = XArrow.now()
                            dehumanized_instance = now.dehumanize(
                                human_expression)
                            now_shifted = now.shift(**shift_kwargs)
                            assert_arrows_soft_eq(dehumanized_instance,
                                                  now_shifted)
                            dehumanized_static = XArrow.dehumanize(
                                human_expression)
                            assert_arrows_soft_eq(dehumanized_static,
                                                  now_shifted)
                            dehumanized_instance_vanilla = Arrow.now(
                            ).dehumanize(human_expression)
                            assert_arrows_soft_eq(
                                dehumanized_instance,
                                dehumanized_instance_vanilla)
                            assert_arrows_soft_eq(
                                dehumanized_static,
                                dehumanized_instance_vanilla)

                    # * 3 units
                    for time_unit_3 in TIME_UNITS:
                        if time_unit_3 == time_unit_1 or time_unit_3 == time_unit_2:
                            continue
                        if random() < 0.75:
                            continue
                        shift_3 = randint(2, 4)
                        singular_time_unit_3 = (f"a" if time_unit_3 != "hour"
                                                else "an") + f" {time_unit_3}"
                        plural_time_unit_3 = f"{shift_3} {time_unit_3}s"
                        expressions = {}
                        for fmt in [
                                "{0} and {1} and {2}",
                                "{0} and {1}, {2}",
                                "{0} and {1} {2}",
                                "{0}, {1}, {2}",
                                "{0}, {1} and {2}",
                                "{0}, {1} {2}",
                                "{0} {1} {2}",
                                "{0} {1}, {2}",
                                "{0} {1} and {2}",
                        ]:
                            for q1, q2, q3 in product(["plural", "singular"],
                                                      ["plural", "singular"],
                                                      ["plural", "singular"]):
                                past_human_expression = eval(
                                    f"fmt.format({q1}_time_unit_1, {q2}_time_unit_2, {q3}_time_unit_3) + ' ago'"
                                )
                                future_human_expression = eval(
                                    f"'in ' + fmt.format({q1}_time_unit_1, {q2}_time_unit_2, {q3}_time_unit_3)"
                                )
                                quantity_tuple = (q1 == "plural",
                                                  q2 == "plural",
                                                  q3 == "plural")
                                expressions[
                                    past_human_expression] = quantity_tuple
                                expressions[
                                    future_human_expression] = quantity_tuple
                        for human_expression, quantity_tuple in expressions.items(
                        ):
                            shift_kwargs = {}
                            sign = 1 if human_expression.startswith(
                                "in ") else -1
                            if quantity_tuple[0]:
                                shift_kwargs[time_unit_1 +
                                             's'] = shift_1 * sign
                            else:
                                shift_kwargs[time_unit_1 + 's'] = 1 * sign

                            if quantity_tuple[1]:
                                shift_kwargs[time_unit_2 +
                                             's'] = shift_2 * sign
                            else:
                                shift_kwargs[time_unit_2 + 's'] = 1 * sign

                            if quantity_tuple[2]:
                                shift_kwargs[time_unit_3 +
                                             's'] = shift_3 * sign
                            else:
                                shift_kwargs[time_unit_3 + 's'] = 1 * sign

                            now = XArrow.now()
                            dehumanized_instance_vanilla = Arrow.now(
                            ).dehumanize(human_expression)
                            dehumanized_static = XArrow.dehumanize(
                                human_expression)

                            now_shifted = now.shift(**shift_kwargs)
                            dehumanized_instance = now.dehumanize(
                                human_expression)

                            try:
                                assert_arrows_soft_eq(dehumanized_instance,
                                                      now_shifted)
                                assert_arrows_soft_eq(dehumanized_static,
                                                      now_shifted)
                                assert_arrows_soft_eq(
                                    dehumanized_instance,
                                    dehumanized_instance_vanilla)
                                assert_arrows_soft_eq(
                                    dehumanized_static,
                                    dehumanized_instance_vanilla)
                            except AssertionError:
                                now = XArrow.now()
                                dehumanized_instance = now.dehumanize(
                                    human_expression)
                                now_shifted = now.shift(**shift_kwargs)
                                assert_arrows_soft_eq(dehumanized_instance,
                                                      now_shifted)
                                dehumanized_static = XArrow.dehumanize(
                                    human_expression)
                                assert_arrows_soft_eq(dehumanized_static,
                                                      now_shifted)
                                dehumanized_instance_vanilla = Arrow.now(
                                ).dehumanize(human_expression)
                                assert_arrows_soft_eq(
                                    dehumanized_instance,
                                    dehumanized_instance_vanilla)
                                assert_arrows_soft_eq(
                                    dehumanized_static,
                                    dehumanized_instance_vanilla)