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")
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)
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
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
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)
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)
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)
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")
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)
def test_start_and_week(self): assert (datetime(2015, 12, 28), datetime(2016, 1, 5), True) == \ guessrangefstr('1.1.2016 week', locale=LOCALE_BERLIN)
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)
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)
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)
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")
def test_start_zero_day_delta(self): with pytest.raises(FatalError): guessrangefstr('1.1.2016 0d', locale=LOCALE_BERLIN)
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)
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")
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")
def test_week(self): assert (datetime(2016, 2, 15), datetime(2016, 2, 22), True) == \ guessrangefstr('week', locale=locale_de, default_timedelta="1d")
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")
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)
def test_tomorrow(self): assert (self.today_start, self.tomorrow16, True) == \ guessrangefstr('today tomorrow 16:00', locale=locale_de)
def test_start_allday_and_delta_datetime(self): with pytest.raises(FatalError): guessrangefstr('1.1.2016 3d3m', locale=LOCALE_BERLIN)
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)
def test_week(self): assert (datetime(2016, 2, 15), datetime(2016, 2, 23), True) == \ guessrangefstr('week', locale=LOCALE_BERLIN)
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")
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)
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)
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)
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)