Exemple #1
0
 def test_invalid(self):
     with pytest.raises(ValueError):
         guessrangefstr('3d', locale=locale_de, default_timedelta="1d")
     with pytest.raises(ValueError):
         guessrangefstr('35.1.2016', locale=locale_de, default_timedelta="1d")
     with pytest.raises(ValueError):
         guessrangefstr('1.1.2016 2x', locale=locale_de, default_timedelta="1d")
     with pytest.raises(ValueError):
         guessrangefstr('1.1.2016x', locale=locale_de, default_timedelta="1d")
     with pytest.raises(ValueError):
         guessrangefstr('xxx yyy zzz', locale=locale_de, default_timedelta="1d")
Exemple #2
0
 def test_invalid(self):
     with pytest.raises(ValueError):
         guessrangefstr('3d', locale=LOCALE_BERLIN)
     with pytest.raises(ValueError):
         guessrangefstr('35.1.2016', locale=LOCALE_BERLIN)
     with pytest.raises(ValueError):
         guessrangefstr('1.1.2016 2x', locale=LOCALE_BERLIN)
     with pytest.raises(ValueError):
         guessrangefstr('1.1.2016x', locale=LOCALE_BERLIN)
     with pytest.raises(ValueError):
         guessrangefstr('xxx yyy zzz', locale=LOCALE_BERLIN)
Exemple #3
0
def start_end_from_daterange(daterange, locale, default_timedelta=None):
    """
    convert a string description of a daterange into start and end datetime
    :param daterange: an iterable of strings that describes `daterange`
    :type daterange: tuple
    :param locale: locale settings
    :type locale: dict
    :param default_timedelta: default timedelta, if None is given and no end is
        specified, we assume start = end, in the form of '2d' for 2 days
    :type default_timedelta: str
    """
    if len(daterange) == 0:
        start = utils.datetime_fillin(end=False)
        if default_timedelta is None:
            end = utils.datetime_fillin(day=start)
        else:
            try:
                end = start + utils.guesstimedeltafstr(default_timedelta)
            except ValueError as e:
                raise InvalidDate(e)
    else:
        start, end, allday = utils.guessrangefstr(
            daterange, locale, default_timedelta=default_timedelta)
        if start is None or end is None:
            raise InvalidDate('Invalid date range: "%s"' %
                              (' '.join(daterange)))

    return start, end
Exemple #4
0
def start_end_from_daterange(daterange, locale, default_timedelta=None):
    """
    convert a string description of a daterange into start and end datetime
    :param daterange: an iterable of strings that describes `daterange`
    :type daterange: tuple
    :param locale: locale settings
    :type locale: dict
    :param default_timedelta: default timedelta, if None is given and no end is
        specified, we assume start = end, in the form of '2d' for 2 days
    :type default_timedelta: str
    """
    if len(daterange) == 0:
        start = utils.datetime_fillin(end=False)
        if default_timedelta is None:
            end = utils.datetime_fillin(day=start)
        else:
            try:
                end = start + utils.guesstimedeltafstr(default_timedelta)
            except ValueError as e:
                raise InvalidDate(e)
    else:
        start, end, allday = utils.guessrangefstr(
            daterange, locale, default_timedelta=default_timedelta)
        if start is None or end is None:
            raise InvalidDate('Invalid date range: "%s"' % (' '.join(daterange)))

    return start, end
Exemple #5
0
def start_end_from_daterange(daterange,
                             locale,
                             default_timedelta_date=timedelta(days=1),
                             default_timedelta_datetime=timedelta(hours=1)):
    """
    convert a string description of a daterange into start and end datetime

    if no description is given, return (today, today + default_timedelta_date)

    :param daterange: an iterable of strings that describes `daterange`
    :type daterange: tuple
    :param locale: locale settings
    :type locale: dict
    """
    if not daterange:
        start = datetime(*date.today().timetuple()[:3])
        end = start + default_timedelta_date
    else:
        start, end, allday = utils.guessrangefstr(
            daterange,
            locale,
            default_timedelta_date=default_timedelta_date,
            default_timedelta_datetime=default_timedelta_datetime,
        )
    return start, end
Exemple #6
0
def new_interactive(collection, calendar_name, conf, info, location=None,
                    categories=None, repeat=None, until=None, alarms=None,
                    format=None, env=None):
    try:
        info = utils.eventinfofstr(info, conf['locale'], adjust_reasonably=True, localize=False)
    except ValueError:
        info = dict()

    while True:
        summary = info.get('summary')
        if not summary:
            summary = None
        info['summary'] = prompt('summary', default=summary)
        if info['summary']:
            break
        echo("a summary is required")

    while True:
        range_string = None
        if info.get('dtstart') and info.get('dtend'):
            start_string = info["dtstart"].strftime(conf['locale']['datetimeformat'])
            end_string = info["dtend"].strftime(conf['locale']['datetimeformat'])
            range_string = start_string + ' ' + end_string
        daterange = prompt("datetime range", default=range_string)
        start, end, allday = utils.guessrangefstr(
            daterange, conf['locale'], adjust_reasonably=True)
        info['dtstart'] = start
        info['dtend'] = end
        info['allday'] = allday
        if info['dtstart'] and info['dtend']:
            break
        echo("invalid datetime range")

    while True:
        tz = info.get('timezone') or conf['locale']['default_timezone']
        timezone = prompt("timezone", default=str(tz))
        try:
            tz = pytz.timezone(timezone)
            info['timezone'] = tz
            break
        except pytz.UnknownTimeZoneError:
            echo("unknown timezone")

    info['description'] = prompt("description (or 'None')", default=info.get('description'))
    if info['description'] == 'None':
        info['description'] = ''

    event = new_from_args(
        collection, calendar_name, conf, format=format, env=env,
        location=location, categories=categories,
        repeat=repeat, until=until, alarms=alarms,
        **info)

    echo("event saved")

    term_width, _ = get_terminal_size()
    edit_event(event, collection, conf['locale'], width=term_width)
Exemple #7
0
def new_interactive(collection, calendar_name, conf, info, location=None,
                    categories=None, repeat=None, until=None, alarms=None,
                    format=None, env=None):
    info = utils.eventinfofstr(
        info, conf['locale'], default_timedelta="60m", adjust_reasonably=True, localize=False)
    while True:
        summary = info["summary"]
        if not summary:
            summary = None
        info['summary'] = prompt("summary", default=summary)
        if info['summary']:
            break
        echo("a summary is required")

    while True:
        range_string = None
        if info["dtstart"] and info["dtend"]:
            start_string = info["dtstart"].strftime(conf['locale']['datetimeformat'])
            end_string = info["dtend"].strftime(conf['locale']['datetimeformat'])
            range_string = start_string + ' ' + end_string
        daterange = prompt("datetime range", default=range_string)
        start, end, allday = utils.guessrangefstr(
            daterange, conf['locale'], default_timedelta='60m', adjust_reasonably=True)
        info['dtstart'] = start
        info['dtend'] = end
        info['allday'] = allday
        if info['dtstart'] and info['dtend']:
            break
        echo("invalid datetime range")

    while True:
        tz = info['timezone'] or conf['locale']['default_timezone']
        timezone = prompt("timezone", default=str(tz))
        try:
            tz = pytz.timezone(timezone)
            info['timezone'] = tz
            break
        except pytz.UnknownTimeZoneError:
            echo('unknown timezone')

    info['description'] = prompt('description (or "None")', default=info['description'])
    if info['description'] == "None":
        info['description'] = ''

    event = new_from_args(collection, calendar_name, conf, format=format, env=env,
                          location=location, categories=categories,
                          repeat=repeat, until=until, alarms=alarms, **info)

    echo("event saved")

    term_width, _ = get_terminal_size()
    edit_event(event, collection, conf['locale'], width=term_width)
Exemple #8
0
    def test_short_format_contains_year(self):
        """if the non long versions of date(time)format contained a year, the
        current year would be used instead of the given one, see #545

        same as above, but for guessrangefstr
        """
        locale = {
            'timeformat': '%H:%M',
            'dateformat': '%Y-%m-%d',
            'longdateformat': '%Y-%m-%d',
            'datetimeformat': '%Y-%m-%d %H:%M',
            'longdatetimeformat': '%Y-%m-%d %H:%M',
        }
        with freeze_time('2016-12-30 17:53'):
            assert (datetime(2017, 1, 1), datetime(2017, 1, 2), True) == \
                guessrangefstr('2017-1-1 2017-1-1', locale=locale)
Exemple #9
0
    def test_short_format_contains_year(self):
        """if the non long versions of date(time)format contained a year, the
        current year would be used instead of the given one, see #545

        same as above, but for guessrangefstr
        """
        locale = {
            'timeformat': '%H:%M',
            'dateformat': '%Y-%m-%d',
            'longdateformat': '%Y-%m-%d',
            'datetimeformat': '%Y-%m-%d %H:%M',
            'longdatetimeformat': '%Y-%m-%d %H:%M',
        }
        with freeze_time('2016-12-30 17:53'):
            assert (datetime(2017, 1, 1), datetime(2017, 1, 1), True) == \
                guessrangefstr('2017-1-1 2017-1-1', locale=locale, default_timedelta="1d")
Exemple #10
0
 def test_start_and_delta_3d(self):
     assert (datetime(2016, 1, 1), datetime(2016, 1, 4), True) == \
         guessrangefstr('1.1.2016 3d', locale=LOCALE_BERLIN)
Exemple #11
0
 def test_start_and_week(self):
     assert (datetime(2015, 12, 28), datetime(2016, 1, 5), True) == \
         guessrangefstr('1.1.2016 week', locale=LOCALE_BERLIN)
Exemple #12
0
 def test_start_and_eod(self):
     assert (datetime(2016, 1, 1, 10), datetime(2016, 1, 1, 23, 59, 59, 999999), False) == \
         guessrangefstr('1.1.2016 10:00 eod', locale=LOCALE_BERLIN)
Exemple #13
0
 def test_start_and_end_date_time(self):
     assert (datetime(2016, 1, 1, 10), datetime(2017, 1, 1, 22), False) == \
         guessrangefstr(
             '1.1.2016 10:00 1.1.2017 22:00', locale=LOCALE_BERLIN)
Exemple #14
0
 def test_start_and_no_end_date(self):
     assert (datetime(2016, 1, 1), datetime(2016, 1, 2), True) == \
         guessrangefstr('1.1.2016', locale=LOCALE_BERLIN)
Exemple #15
0
 def test_start_and_eod(self):
     assert (datetime(2016, 1, 1, 10), datetime(2016, 1, 1, 23, 59, 59, 999999), False) == \
         guessrangefstr('1.1.2016 10:00 eod', locale=locale_de, default_timedelta="1d")
Exemple #16
0
 def test_start_zero_day_delta(self):
     with pytest.raises(FatalError):
         guessrangefstr('1.1.2016 0d', locale=LOCALE_BERLIN)
Exemple #17
0
def edit_event(event, collection, locale, allow_quit=False, width=80):
    options = OrderedDict()
    if allow_quit:
        options["no"] = {"short": "n"}
    else:
        options["done"] = {"short": "n"}
    options["summary"] = {"short": "s", "attr": "summary"}
    options["description"] = {"short": "d", "attr": "description", "none": True}
    options["datetime range"] = {"short": "t"}
    options["repeat"] = {"short": "p"}
    options["location"] = {"short": "l", "attr": "location", "none": True}
    options["categories"] = {"short": "c", "attr": "categories", "none": True}
    options["alarm"] = {"short": "a"}
    options["Delete"] = {"short": "D"}
    if allow_quit:
        options["quit"] = {"short":  "q"}

    now = datetime.now()

    while True:
        choice = present_options(options, prefix="Edit?", width=width)
        if choice is None:
            echo("unknown choice")
            continue
        if choice == "no":
            return True
        if choice == "quit":
            return False

        edited = False

        if choice == "Delete":
            if confirm("Delete all occurances of event?"):
                collection.delete(event.href, event.etag, event.calendar)
                return True
        elif choice == "datetime range":
            current = event.format("{start} {end}", relative_to=now)
            value = prompt("datetime range", default=current)
            try:
                start, end, allday = utils.guessrangefstr(value, locale, default_timedelta="60m")
                event.update_start_end(start, end)
                edited = True
            except:
                echo("error parsing range")
        elif choice == "repeat":
            recur = event.recurobject
            freq = recur["freq"] if "freq" in recur else ""
            until = recur["until"] if "until" in recur else ""
            if not freq:
                freq = 'None'
            freq = prompt('frequency (or "None")', freq)
            if freq == 'None':
                event.update_rrule(None)
            else:
                until = prompt('until (or "None")', until)
                if until == 'None':
                    until = None
                rrule = utils.rrulefstr(freq, until, locale)
                event.update_rrule(rrule)
            edited = True
        elif choice == "alarm":
            default_alarms = []
            for a in event.alarms:
                s = utils.timedelta2str(-1 * a[0])
                default_alarms.append(s)

            default = ', '.join(default_alarms)
            if not default:
                default = 'None'
            alarm = prompt('alarm (or "None")', default)
            if alarm == "None":
                alarm = ""
            alarm_list = []
            for a in alarm.split(","):
                alarm_trig = -1 * utils.guesstimedeltafstr(a.strip())
                new_alarm = (alarm_trig, event.description)
                alarm_list += [new_alarm]
            event.update_alarms(alarm_list)
            edited = True
        else:
            attr = options[choice]["attr"]
            default = getattr(event, attr)
            question = choice

            allow_none = False
            if "none" in options[choice] and options[choice]["none"]:
                question += ' (or "None")'
                allow_none = True
                if not default:
                    default = 'None'

            value = prompt(question, default)
            if allow_none and value == "None":
                value = ""
            getattr(event, "update_" + attr)(value)
            edited = True

        if edited:
            event.increment_sequence()
            collection.update(event)
Exemple #18
0
 def test_time_tomorrow(self):
     assert (self.today16, self.tomorrow16, False) == \
         guessrangefstr('16:00', locale=locale_de, default_timedelta="1d")
     assert (self.today16, self.today17, False) == \
         guessrangefstr('16:00 17:00', locale=locale_de, default_timedelta="1d")
Exemple #19
0
 def test_start_and_end_date(self):
     assert (datetime(2016, 1, 1), datetime(2017, 1, 1), True) == \
         guessrangefstr('1.1.2016 1.1.2017', locale=locale_de, default_timedelta="1d")
Exemple #20
0
 def test_week(self):
     assert (datetime(2016, 2, 15), datetime(2016, 2, 22), True) == \
         guessrangefstr('week', locale=locale_de, default_timedelta="1d")
Exemple #21
0
 def test_start_and_week(self):
     assert (datetime(2015, 12, 28), datetime(2016, 1, 4), True) == \
         guessrangefstr('1.1.2016 week', locale=locale_de, default_timedelta="1d")
Exemple #22
0
 def test_start_dt_and_delta(self):
     assert (datetime(2016, 1, 1, 10), datetime(2016, 1, 4, 10), False) == \
         guessrangefstr('1.1.2016 10:00 3d', locale=LOCALE_BERLIN)
Exemple #23
0
 def test_tomorrow(self):
     assert (self.today_start, self.tomorrow16, True) == \
         guessrangefstr('today tomorrow 16:00', locale=locale_de)
Exemple #24
0
 def test_start_allday_and_delta_datetime(self):
     with pytest.raises(FatalError):
         guessrangefstr('1.1.2016 3d3m', locale=LOCALE_BERLIN)
Exemple #25
0
 def test_time_tomorrow(self):
     with freeze_time('2016-9-19 13:34'):
         assert (datetime(2016, 9, 19, 16), datetime(2016, 9, 19, 17), False) == \
             guessrangefstr('16:00', locale=LOCALE_BERLIN)
         assert (datetime(2016, 9, 19, 16), datetime(2016, 9, 19, 17), False) == \
             guessrangefstr('16:00 17:00', locale=LOCALE_BERLIN)
Exemple #26
0
 def test_week(self):
     assert (datetime(2016, 2, 15), datetime(2016, 2, 23), True) == \
         guessrangefstr('week', locale=LOCALE_BERLIN)
Exemple #27
0
 def test_start_and_end_date_time(self):
     assert (datetime(2016, 1, 1, 10), datetime(2017, 1, 1, 22), False) == \
         guessrangefstr(
             '1.1.2016 10:00 1.1.2017 22:00', locale=locale_de, default_timedelta="1d")
Exemple #28
0
 def test_tomorrow(self):
     # XXX remove me, we shouldn't support this anyway
     with freeze_time('2016-9-19 16:34'):
         assert (datetime(2016, 9, 19), datetime(2016, 9, 21, 16), True) == \
             guessrangefstr('today tomorrow 16:00', locale=LOCALE_BERLIN)
Exemple #29
0
 def test_today(self):
     assert (self.today13, self.today14, False) == \
         guessrangefstr('13:00 14:00', locale=locale_de)
     assert (self.today_start, self.tomorrow_start, True) == \
         guessrangefstr('today tomorrow', locale_de)
Exemple #30
0
def edit_event(event, collection, locale, allow_quit=False, width=80):
    options = OrderedDict()
    if allow_quit:
        options["no"] = {"short": "n"}
    else:
        options["done"] = {"short": "n"}
    options["summary"] = {"short": "s", "attr": "summary"}
    options["description"] = {
        "short": "d",
        "attr": "description",
        "none": True
    }
    options["datetime range"] = {"short": "t"}
    options["repeat"] = {"short": "p"}
    options["location"] = {"short": "l", "attr": "location", "none": True}
    options["categories"] = {"short": "c", "attr": "categories", "none": True}
    options["alarm"] = {"short": "a"}
    options["Delete"] = {"short": "D"}
    if allow_quit:
        options["quit"] = {"short": "q"}

    now = datetime.now()

    while True:
        choice = present_options(options, prefix="Edit?", width=width)
        if choice is None:
            echo("unknown choice")
            continue
        if choice == "no":
            return True
        if choice == "quit":
            return False

        edited = False

        if choice == "Delete":
            if confirm("Delete all occurences of event?"):
                collection.delete(event.href, event.etag, event.calendar)
                return True
        elif choice == "datetime range":
            current = event.format("{start} {end}", relative_to=now)
            value = prompt("datetime range", default=current)
            try:
                start, end, allday = utils.guessrangefstr(value, locale)
                event.update_start_end(start, end)
                edited = True
            except:
                echo("error parsing range")
        elif choice == "repeat":
            recur = event.recurobject
            freq = recur["freq"] if "freq" in recur else ""
            until = recur["until"] if "until" in recur else ""
            if not freq:
                freq = 'None'
            freq = prompt('frequency (or "None")', freq)
            if freq == 'None':
                event.update_rrule(None)
            else:
                until = prompt('until (or "None")', until)
                if until == 'None':
                    until = None
                rrule = utils.rrulefstr(freq, until, locale)
                event.update_rrule(rrule)
            edited = True
        elif choice == "alarm":
            default_alarms = []
            for a in event.alarms:
                s = utils.timedelta2str(-1 * a[0])
                default_alarms.append(s)

            default = ', '.join(default_alarms)
            if not default:
                default = 'None'
            alarm = prompt('alarm (or "None")', default)
            if alarm == "None":
                alarm = ""
            alarm_list = []
            for a in alarm.split(","):
                alarm_trig = -1 * utils.guesstimedeltafstr(a.strip())
                new_alarm = (alarm_trig, event.description)
                alarm_list += [new_alarm]
            event.update_alarms(alarm_list)
            edited = True
        else:
            attr = options[choice]["attr"]
            default = getattr(event, attr)
            question = choice

            allow_none = False
            if "none" in options[choice] and options[choice]["none"]:
                question += ' (or "None")'
                allow_none = True
                if not default:
                    default = 'None'

            value = prompt(question, default)
            if allow_none and value == "None":
                value = ""
            getattr(event, "update_" + attr)(value)
            edited = True

        if edited:
            event.increment_sequence()
            collection.update(event)
Exemple #31
0
 def test_today(self):
     with freeze_time('2016-9-19'):
         assert (datetime(2016, 9, 19, 13), datetime(2016, 9, 19, 14), False) == \
             guessrangefstr('13:00 14:00', locale=LOCALE_BERLIN)
         assert (datetime(2016, 9, 19), datetime(2016, 9, 21), True) == \
             guessrangefstr('today tomorrow', LOCALE_BERLIN)