def testFromHumaneString(self): testData = [ ("daily 10:00", RecurrenceRule(rrule.DAILY, byhour=10)), ("weekly FR 23:00", RecurrenceRule(rrule.WEEKLY, byweekday=4, byhour=23)), ("none", RecurrenceRule()), ("weekly fr 23:00", RecurrenceRule(rrule.WEEKLY, byweekday=4, byhour=23)), ("weekly Fr 23:00", RecurrenceRule(rrule.WEEKLY, byweekday=4, byhour=23)), ("weekly Friday 23:00", RecurrenceRule(rrule.WEEKLY, byweekday=4, byhour=23)), ("monthly 3 13:00", RecurrenceRule(rrule.MONTHLY, bymonthday=3, byhour=13)), ("monthly second friday 13:00", RecurrenceRule(rrule.MONTHLY, byweekday=RecurrenceRule.createWeekDay(weekday=4, pos=2), byhour=13)), ("yearly 3/07 11:20", RecurrenceRule(rrule.YEARLY, bymonth=7, bymonthday=3, byhour=11, byminute=20)), ("quarterly 14 11:20", RecurrenceRule(rrule.YEARLY, bymonth=(1, 4, 7, 10), bymonthday=14, byhour=11, byminute=20)), ("quarterly first monday 23:20", RecurrenceRule(rrule.YEARLY, bymonth=(1, 4, 7, 10), byweekday=RecurrenceRule.createWeekDay(weekday=0, pos=1), byhour=23, byminute=20)), ] + [(x.text, x.rule) for x in TEST_DATA] for text, expected in testData: with self.subTest(text=text): output = RecurrenceRule.fromHumaneString(text) self.assertEqual(output, expected, '\ninput: {}\noutput: {}\nexpected: {}'.format(text, output, expected))
def process_result_value(self, value, dialect): if value: dct = json.loads(value) value = RecurrenceRule.fromDict(dct) else: value = RecurrenceRule() return value
def testToFromDict(self): for row in TEST_DATA: with self.subTest(text=row.text): rule = RecurrenceRule.fromDict(row.dct) self.assertEqual(rule, row.rule, '\ninput: {}\nrule: {}\nexpected: {}'.format(row.dct, rule, row.rule)) dct = rule.toDict() self.assertEqual(dct, row.dct)
def testToFromDict(self): for row in TEST_DATA: with self.subTest(text=row.text): rule = RecurrenceRule.fromDict(row.dct) self.assertEqual(rule, row.rule, '\ninput: {}\nrule: {}\nexpected: {}'.format(row.dct, rule, row.rule) ) dct = rule.toDict() self.assertEqual(dct, row.dct)
def do_t_recurs(self, line): """Make a task recurs t_recurs <id> yearly <dd/mm> <HH:MM> t_recurs <id> monthly <dd> <HH:MM> t_recurs <id> monthly <first/second/third/last> <mo, tu, we, th, fr, sa, su> <hh:mm> t_recurs <id> quarterly <dd> <HH:MM> t_recurs <id> quarterly <first/second/third/last> <mo, tu, we, th, fr, sa, su> <hh:mm> t_recurs <id> weekly <mo, tu, we, th, fr, sa, su> <hh:mm> t_recurs <id> daily <HH:MM> t_recurs <id> none (remove recurrence)""" tokens = parseutils.simplifySpaces(line).split(" ", 1) if len(tokens) < 2: raise YokadiException("You should give at least two arguments: <task id> <recurrence>") task = self.getTaskFromId(tokens[0]) rule = RecurrenceRule.fromHumaneString(tokens[1]) task.setRecurrenceRule(rule) self.session.commit()
def do_t_recurs(self, line): """Make a task recurs t_recurs <id> yearly <dd/mm> <HH:MM> t_recurs <id> monthly <dd> <HH:MM> t_recurs <id> monthly <first/second/third/last> <mo, tu, we, th, fr, sa, su> <hh:mm> t_recurs <id> quarterly <dd> <HH:MM> t_recurs <id> quarterly <first/second/third/last> <mo, tu, we, th, fr, sa, su> <hh:mm> t_recurs <id> weekly <mo, tu, we, th, fr, sa, su> <hh:mm> t_recurs <id> daily <HH:MM> t_recurs <id> none (remove recurrence)""" tokens = parseutils.simplifySpaces(line).split(" ", 1) if len(tokens) < 2: raise YokadiException( "You should give at least two arguments: <task id> <recurrence>" ) task = self.getTaskFromId(tokens[0]) rule = RecurrenceRule.fromHumaneString(tokens[1]) task.setRecurrenceRule(rule) self.session.commit()
def testFromHumaneString(self): testData = [ ("daily 10:00", RecurrenceRule(rrule.DAILY, byhour=10)), ("weekly FR 23:00", RecurrenceRule(rrule.WEEKLY, byweekday=4, byhour=23)), ("none", RecurrenceRule()), ("weekly fr 23:00", RecurrenceRule(rrule.WEEKLY, byweekday=4, byhour=23)), ("weekly Fr 23:00", RecurrenceRule(rrule.WEEKLY, byweekday=4, byhour=23)), ("weekly Friday 23:00", RecurrenceRule(rrule.WEEKLY, byweekday=4, byhour=23)), ("monthly 3 13:00", RecurrenceRule(rrule.MONTHLY, bymonthday=3, byhour=13)), ("monthly second friday 13:00", RecurrenceRule(rrule.MONTHLY, byweekday=RecurrenceRule.createWeekDay(weekday=4, pos=2), byhour=13)), ("yearly 3/07 11:20", RecurrenceRule( rrule.YEARLY, bymonth=7, bymonthday=3, byhour=11, byminute=20)), ("quarterly 14 11:20", RecurrenceRule(rrule.YEARLY, bymonth=(1, 4, 7, 10), bymonthday=14, byhour=11, byminute=20)), ("quarterly first monday 23:20", RecurrenceRule(rrule.YEARLY, bymonth=(1, 4, 7, 10), byweekday=RecurrenceRule.createWeekDay(weekday=0, pos=1), byhour=23, byminute=20)), ] + [(x.text, x.rule) for x in TEST_DATA] for text, expected in testData: with self.subTest(text=text): output = RecurrenceRule.fromHumaneString(text) self.assertEqual( output, expected, '\ninput: {}\noutput: {}\nexpected: {}'.format( text, output, expected))
from yokadi.core.recurrencerule import RecurrenceRule from yokadi.core.yokadiexception import YokadiException # Use a date far away in the future because rrule does not work with dates in # the past. # This is a wednesday. REF_DATE = datetime(2200, 3, 19, 21, 30) TestRow = namedtuple("TestRow", ("text", "dct", "rule", "nextDate")) TEST_DATA = [ TestRow( "none", {}, RecurrenceRule(), None, ), TestRow( "daily 17:15", { "freq": rrule.DAILY, "bymonth": (), "bymonthday": (), "byweekday": (), "byhour": (17, ), "byminute": (15, ) }, RecurrenceRule(rrule.DAILY, byhour=17, byminute=15), REF_DATE.replace(day=20, hour=17, minute=15)), TestRow( "weekly monday 10:00", { "freq": rrule.WEEKLY,
{"freq": rrule.MONTHLY, "bymonth": (), "bymonthday": (2,), "byweekday": (), "byhour": (8,), "byminute": (27,)}, RecurrenceRule(rrule.MONTHLY, bymonthday=2, byhour=8, byminute=27), REF_DATE.replace(month=4, day=2, hour=8, minute=27) ), TestRow( "quarterly 2 8:27", {"freq": rrule.YEARLY, "bymonth": (1, 4, 7, 10), "bymonthday": (2,), "byweekday": (), "byhour": (8,), "byminute": (27,)}, RecurrenceRule(rrule.YEARLY, bymonth=(1, 4, 7, 10), bymonthday=2, byhour=8, byminute=27), REF_DATE.replace(month=4, day=2, hour=8, minute=27) ), TestRow( "monthly first wednesday 8:27", {"freq": rrule.MONTHLY, "bymonth": (), "bymonthday": (), "byweekday": {"pos": 1, "weekday": 2}, "byhour": (8,), "byminute": (27,)}, RecurrenceRule(rrule.MONTHLY, byweekday=RecurrenceRule.createWeekDay(pos=1, weekday=2), byhour=8, byminute=27), REF_DATE.replace(month=4, day=2, hour=8, minute=27) ), TestRow( "monthly last sunday 8:27", {"freq": rrule.MONTHLY, "bymonth": (), "bymonthday": (), "byweekday": {"pos": -1, "weekday": 6}, "byhour": (8,), "byminute": (27,)}, RecurrenceRule(rrule.MONTHLY, byweekday=RecurrenceRule.createWeekDay(pos=-1, weekday=6), byhour=8, byminute=27), REF_DATE.replace(month=3, day=30, hour=8, minute=27) ), TestRow( "yearly 23/2 8:27", {"freq": rrule.YEARLY, "bymonth": (2,), "bymonthday": (23,), "byweekday": (), "byhour": (8,), "byminute": (27,)}, RecurrenceRule(rrule.YEARLY, bymonth=2, bymonthday=23, byhour=8, byminute=27), REF_DATE.replace(year=2201, month=2, day=23, hour=8, minute=27)
class Task(Base): __tablename__ = "task" id = Column(Integer, primary_key=True) uuid = Column(Unicode, unique=True, default=uuidGenerator, nullable=False) title = Column(Unicode) creationDate = Column("creation_date", DateTime, nullable=False, default=datetime.now) dueDate = Column("due_date", DateTime, default=None) doneDate = Column("done_date", DateTime, default=None) description = Column(Unicode, default="", nullable=False) urgency = Column(Integer, default=0, nullable=False) status = Column(Enum("new", "started", "done"), default="new") recurrence = Column(RecurrenceRuleColumnType, nullable=False, default=RecurrenceRule()) projectId = Column("project_id", Integer, ForeignKey("project.id"), nullable=False) taskKeywords = relationship("TaskKeyword", cascade="all", backref="task") lock = relationship("TaskLock", cascade="all", backref="task") def setKeywordDict(self, dct): """ Defines keywords of a task. Dict is of the form: keywordName => value """ session = getSession() for taskKeyword in self.taskKeywords: session.delete(taskKeyword) for name, value in list(dct.items()): keyword = session.query(Keyword).filter_by(name=name).one() session.add(TaskKeyword(task=self, keyword=keyword, value=value)) def getKeywordDict(self): """ Returns all keywords of a task as a dict of the form: keywordName => value """ dct = {} for taskKeyword in self.taskKeywords: dct[taskKeyword.keyword.name] = taskKeyword.value return dct def getKeywordsAsString(self): """ Returns all keywords as a string like "key1=value1, key2=value2..." """ return ", ".join( list(("%s=%s" % k for k in list(self.getKeywordDict().items())))) def getUserKeywordsNameAsString(self): """ Returns all keywords keys as a string like "key1, key2, key3...". Internal keywords (starting with _) are ignored. """ keywords = [ k for k in list(self.getKeywordDict().keys()) if not k.startswith("_") ] keywords.sort() if keywords: return ", ".join(keywords) else: return "" def setStatus(self, status): """ Defines the status of the task, taking care of updating the done date and doing the right thing for recurrent tasks """ if self.recurrence and status == "done": self.dueDate = self.recurrence.getNext(self.dueDate) else: self.status = status if status == "done": self.doneDate = datetime.now().replace(second=0, microsecond=0) else: self.doneDate = None session = getSession() session.merge(self) def setRecurrenceRule(self, rule): """Set recurrence and update the due date accordingly""" self.recurrence = rule self.dueDate = rule.getNext() def __repr__(self): return "<Task id={} title={}>".format(self.id, self.title)