def parseLine(line): """Parse line of form: project some text @keyword1 @keyword2=12 some other text @return: a tuple of ("project", "some text some other text", keywordDict""" # First extract project name line = simplifySpaces(line) if line.count(" "): project, line = line.split(" ", 1) else: project = line line = "" line, keywordFilters = extractKeywords(line) return project, line, keywordFiltersToDict(keywordFilters)
def parseHumaneDateTime(line, hint=None, today=None): """Parse human date and time and return structured datetime object Datetime can be absolute (23/10/2008 10:38) or relative (+5M, +3H, +1D, +6W) @param line: human date / time @param hint: optional hint to tell whether time should be set to the beginning or the end of the day when not specified. @param today: optional parameter to define a fake today date. Useful for unit testing. @type line: str @return: datetime object""" def guessDate(text): out, fmt = testFormats(text, DATE_FORMATS) if not out: return None if not "%y" in fmt and not "%Y" in fmt: out = out.replace(year=today.year) return out.date() def applyTimeHint(date, hint): if not hint: return date if hint == TIME_HINT_BEGIN: return date.replace(hour=0, minute=0, second=0) elif hint == TIME_HINT_END: return date.replace(hour=23, minute=59, second=59) else: raise Exception("Unknown hint %s" % hint) line = basicparseutils.simplifySpaces(line).lower() if not line: raise YokadiException("Date is empty") if today is None: today = datetime.today().replace(microsecond=0) if line == "now": return today if line == "today": return applyTimeHint(today, hint) # Check for "+<delta>" format if line.startswith("+"): return today + parseDateTimeDelta(line[1:]) if line.startswith("-"): return today - parseDateTimeDelta(line[1:]) # Check for "<weekday> [<time>]" format firstWord = line.split()[0] weekdayDict = { "today": today.weekday(), "tomorrow": (today.weekday() + 1) % 7, } weekdayDict.update(WEEKDAYS) weekdayDict.update(SHORT_WEEKDAYS) weekday = weekdayDict.get(firstWord) if weekday is not None: date = today + timedelta(days=(weekday - today.weekday()) % 7) if " " in line: timeText = line.split(' ', 1)[1] tTime = guessTime(timeText) if tTime is None: raise YokadiException("Unable to understand time '%s'" % timeText) date = datetime.combine(date, tTime) else: date = applyTimeHint(date, hint) return date if " " in line: # Absolute date and time? dateText, timeText = line.split(' ', 1) tDate = guessDate(dateText) if tDate is not None: tTime = guessTime(timeText) if tTime is not None: return datetime.combine(tDate, tTime) # Only date? tDate = guessDate(line) if tDate is not None: dt = datetime.combine(tDate, today.time()) return applyTimeHint(dt, hint) # Only time? tTime = guessTime(line) if tTime is not None: tDate = datetime.combine(today.date(), tTime) if tTime > today.time(): return tDate else: return tDate + timedelta(days=1) raise YokadiException("Unable to understand date '%s'" % line)
def parseHumaneDateTime(line, hint=None, today=None): """Parse human date and time and return structured datetime object Datetime can be absolute (23/10/2008 10:38) or relative (+5M, +3H, +1D, +6W) @param line: human date / time @param hint: optional hint to tell whether time should be set to the beginning or the end of the day when not specified. @param today: optional parameter to define a fake today date. Useful for unit testing. @type line: str @return: datetime object""" def guessDate(text): out, fmt = testFormats(text, DATE_FORMATS) if not out: return None if "%y" not in fmt and "%Y" not in fmt: out = out.replace(year=today.year) return out.date() def applyTimeHint(date, hint): if not hint: return date if hint == TIME_HINT_BEGIN: return date.replace(hour=0, minute=0, second=0) elif hint == TIME_HINT_END: return date.replace(hour=23, minute=59, second=59) else: raise Exception("Unknown hint %s" % hint) line = basicparseutils.simplifySpaces(line).lower() if not line: raise YokadiException("Date is empty") if today is None: today = datetime.today().replace(microsecond=0) if line == "now": return today if line == "today": return applyTimeHint(today, hint) # Check for "+<delta>" format if line.startswith("+"): return today + parseDateTimeDelta(line[1:]) if line.startswith("-"): return today - parseDateTimeDelta(line[1:]) # Check for "<weekday> [<time>]" format firstWord = line.split()[0] weekdayDict = { "today": today.weekday(), "tomorrow": (today.weekday() + 1) % 7, } weekdayDict.update(WEEKDAYS) weekdayDict.update(SHORT_WEEKDAYS) weekday = weekdayDict.get(firstWord) if weekday is not None: date = today + timedelta(days=(weekday - today.weekday()) % 7) if " " in line: timeText = line.split(' ', 1)[1] tTime = guessTime(timeText) if tTime is None: raise YokadiException("Unable to understand time '%s'" % timeText) date = datetime.combine(date, tTime) else: date = applyTimeHint(date, hint) return date if " " in line: # Absolute date and time? dateText, timeText = line.split(' ', 1) tDate = guessDate(dateText) if tDate is not None: tTime = guessTime(timeText) if tTime is not None: return datetime.combine(tDate, tTime) # Only date? tDate = guessDate(line) if tDate is not None: dt = datetime.combine(tDate, today.time()) return applyTimeHint(dt, hint) # Only time? tTime = guessTime(line) if tTime is not None: tDate = datetime.combine(today.date(), tTime) if tTime > today.time(): return tDate else: return tDate + timedelta(days=1) raise YokadiException("Unable to understand date '%s'" % line)
def computeCompleteParameterPosition(text, line, begidx, endidx): before = simplifySpaces(line[:begidx].strip()) return before.count(" ") + 1