def test_parse_expr_date(self): tue = datetime.strptime('Apr 9 2013 11:33PM', '%b %d %Y %I:%M%p') wed = datetime.strptime('Apr 10 2013 11:33PM', '%b %d %Y %I:%M%p') expr = parse_expr(tokenise ('today'), type_required=STRING_TYPE, now=tue)[0] self.assertEquals ("today", expr(None)) expr = parse_expr(tokenise ('today'), type_required = DATE_TYPE, now=tue)[0] self.assertEquals ("2013-04-09", date_range_to_str (expr(None))) expr = parse_expr(tokenise ('"last tues"'), type_required = DATE_TYPE, now=tue)[0] self.assertEquals ("2013-04-02", date_range_to_str (expr(None))) expr = parse_expr(tokenise ('due = today'), now=tue)[0] self.assertTrue (expr(Task(name="", date_due=tue))) expr = parse_expr(tokenise ('due = start'), now=tue)[0] self.assertTrue (expr(Task(name="", date_due=tue, date_to_start=tue))) self.assertFalse (expr(Task(name="", date_due=tue, date_to_start=wed))) self.assertFalse (expr(Task(name="", date_due=tue)))
def test_parse_expr_date(self): tue = datetime.strptime('Apr 9 2013 11:33PM', '%b %d %Y %I:%M%p') wed = datetime.strptime('Apr 10 2013 11:33PM', '%b %d %Y %I:%M%p') expr = parse_expr(tokenise('today'), type_required=STRING_TYPE, now=tue)[0] self.assertEquals("today", expr(None)) expr = parse_expr(tokenise('today'), type_required=DATE_TYPE, now=tue)[0] self.assertEquals("2013-04-09", date_range_to_str(expr(None))) expr = parse_expr(tokenise('"last tues"'), type_required=DATE_TYPE, now=tue)[0] self.assertEquals("2013-04-02", date_range_to_str(expr(None))) expr = parse_expr(tokenise('due = today'), now=tue)[0] self.assertTrue(expr(Task(name="", date_due=tue))) expr = parse_expr(tokenise('due = start'), now=tue)[0] self.assertTrue(expr(Task(name="", date_due=tue, date_to_start=tue))) self.assertFalse(expr(Task(name="", date_due=tue, date_to_start=wed))) self.assertFalse(expr(Task(name="", date_due=tue)))
def parse_expr (tokens, type_required=BOOL_TYPE, now = now (), level = 0): LOGGER.debug ('parsing %s tokens: %s', level, tokens) tok, tokens = next_token (tokens, [TEXT, QUOTED_TEXT, NOT, OPEN_BRACE]) (t,v) = tok # NOT if t == NOT: assert type_required == BOOL_TYPE, "expecting a ' + required_type' expression, not " + BOOL_TYPE expr, tokens, expr_type, expr_string = parse_expr (tokens, now=now, level=level+1) assert expr_type == BOOL_TYPE, "not must have a boolean argument" LOGGER.debug ('built %s:1 %s %s', level, expr_type, expr_string) return (lambda x: not expr (x)), tokens, BOOL_TYPE, 'not(' + expr_string + ')' # LHS if t == TEXT and v =='true': lhs = lambda x: True lhs_string = 'true' lhs_type = BOOL_TYPE elif t == TEXT and v =='false': lhs = lambda x: False lhs_string = 'true' lhs_type = BOOL_TYPE elif t == TEXT and v in ALIAS_LOOKUPS: field = ALIAS_LOOKUPS[v] lhs = lambda x: access_field(x, field) lhs_string = 'field:' + field if field in DATE_ALIAS_LOOKUPS: lhs_type = DATE_TYPE elif field in STRING_ALIAS_LOOKUPS: lhs_type = STRING_TYPE else: lhs_type = BOOL_TYPE elif t == OPEN_BRACE: lhs, tokens, lhs_type, lhs_string = parse_expr (tokens, now=now, level=level+1) tokens = next_token (tokens, [CLOSE_BRACE])[1] elif t == QUOTED_TEXT: text = v lhs = lambda x: unicode (text) lhs_string = '"' + v + '"' lhs_type = STRING_TYPE if type_required == DATE_TYPE: rng = process_date_specifier (now, text) lhs = lambda x: rng lhs_string = '[' + date_range_to_str(rng) + ']' lhs_type = DATE_TYPE elif t == TEXT: text = v lhs = lambda x: unicode (text) lhs_string = text lhs_type = STRING_TYPE if type_required == DATE_TYPE: rng = process_date_specifier (now, text) lhs = lambda x: rng lhs_string = '[' + date_range_to_str(rng) + ']' lhs_type = DATE_TYPE else: assert False, 'unexpected token: ' + v LOGGER.debug ('built %s:2 %s %s', level, lhs_type, lhs_string) # OPERATOR if len(tokens) == 0: LOGGER.debug ('built %s:3 %s %s', level, lhs_type, lhs_string) assert type_required == lhs_type, "expecting a " + type_required + ' got a ' + lhs_type + ': ' + lhs_string return lhs, tokens, lhs_type, lhs_string tok, tokens = next_token (tokens,[AND, OR, EQUAL, NOT_EQUAL, CLOSE_BRACE]) op,v = tok if op == CLOSE_BRACE: LOGGER.debug ('built %s:4 %s %s', level, lhs_type, lhs_string) assert type_required == lhs_type, "expecting a " + type_required + ' got a ' + lhs_type + ': ' + lhs_string return lhs, [tok] + tokens, lhs_type, lhs_string rhs, tokens, rhs_type, rhs_string = parse_expr (tokens, type_required = lhs_type, now=now, level=level+1) assert lhs_type == rhs_type, "incompatible types, " + lhs_type + ' ' + rhs_type assert type_required == BOOL_TYPE, "expecting a " + type_required + ' but got ' + BOOL_TYPE if op == AND: expr_string = '(' + lhs_string + ')AND(' + rhs_string + ')' LOGGER.debug ('built %s:5 %s %s', level, BOOL_TYPE, expr_string) return (lambda x: and_fn(lhs, rhs, x)), tokens, BOOL_TYPE, expr_string elif op == OR: expr_string = '(' + lhs_string + ')OR(' + rhs_string + ')' LOGGER.debug ('built %s:6 %s %s', level, BOOL_TYPE, expr_string) return (lambda x: or_fn(lhs, rhs, x)), tokens, BOOL_TYPE, expr_string elif op == EQUAL: expr_string = '(' + lhs_string + ')=(' + rhs_string + ')' LOGGER.debug ('built %s:7 %s %s', level, BOOL_TYPE, expr_string) return (lambda x: eq_fn (lhs (x), rhs (x))), tokens, BOOL_TYPE, expr_string elif op == NOT_EQUAL: expr_string = '(' + lhs_string + ')!=(' + rhs_string + ')' LOGGER.debug ('built %s:8 %s %s', level, BOOL_TYPE, expr_string) return (lambda x: ne_fn (lhs (x), rhs (x))), tokens, BOOL_TYPE, expr_string
def process_date_specifier_to_datestr (now, spec): rng = process_date_specifier (now, spec) return date_range_to_str (rng)
def process_date_specifier_to_datestr(now, spec): rng = process_date_specifier(now, spec) return date_range_to_str(rng)
def parse_expr(tokens, type_required=BOOL_TYPE, now=now(), level=0): LOGGER.debug('parsing %s tokens: %s', level, tokens) tok, tokens = next_token(tokens, [TEXT, QUOTED_TEXT, NOT, OPEN_BRACE]) (t, v) = tok # NOT if t == NOT: assert type_required == BOOL_TYPE, "expecting a ' + required_type' expression, not " + BOOL_TYPE expr, tokens, expr_type, expr_string = parse_expr(tokens, now=now, level=level + 1) assert expr_type == BOOL_TYPE, "not must have a boolean argument" LOGGER.debug('built %s:1 %s %s', level, expr_type, expr_string) return (lambda x: not expr(x) ), tokens, BOOL_TYPE, 'not(' + expr_string + ')' # LHS if t == TEXT and v == 'true': lhs = lambda x: True lhs_string = 'true' lhs_type = BOOL_TYPE elif t == TEXT and v == 'false': lhs = lambda x: False lhs_string = 'true' lhs_type = BOOL_TYPE elif t == TEXT and v in ALIAS_LOOKUPS: field = ALIAS_LOOKUPS[v] lhs = lambda x: access_field(x, field) lhs_string = 'field:' + field if field in DATE_ALIAS_LOOKUPS: lhs_type = DATE_TYPE elif field in STRING_ALIAS_LOOKUPS: lhs_type = STRING_TYPE else: lhs_type = BOOL_TYPE elif t == OPEN_BRACE: lhs, tokens, lhs_type, lhs_string = parse_expr(tokens, now=now, level=level + 1) tokens = next_token(tokens, [CLOSE_BRACE])[1] elif t == QUOTED_TEXT: text = v lhs = lambda x: unicode(text) lhs_string = '"' + v + '"' lhs_type = STRING_TYPE if type_required == DATE_TYPE: rng = process_date_specifier(now, text) lhs = lambda x: rng lhs_string = '[' + date_range_to_str(rng) + ']' lhs_type = DATE_TYPE elif t == TEXT: text = v lhs = lambda x: unicode(text) lhs_string = text lhs_type = STRING_TYPE if type_required == DATE_TYPE: rng = process_date_specifier(now, text) lhs = lambda x: rng lhs_string = '[' + date_range_to_str(rng) + ']' lhs_type = DATE_TYPE else: assert False, 'unexpected token: ' + v LOGGER.debug('built %s:2 %s %s', level, lhs_type, lhs_string) # OPERATOR if len(tokens) == 0: LOGGER.debug('built %s:3 %s %s', level, lhs_type, lhs_string) assert type_required == lhs_type, "expecting a " + type_required + ' got a ' + lhs_type + ': ' + lhs_string return lhs, tokens, lhs_type, lhs_string tok, tokens = next_token(tokens, [AND, OR, EQUAL, NOT_EQUAL, CLOSE_BRACE]) op, v = tok if op == CLOSE_BRACE: LOGGER.debug('built %s:4 %s %s', level, lhs_type, lhs_string) assert type_required == lhs_type, "expecting a " + type_required + ' got a ' + lhs_type + ': ' + lhs_string return lhs, [tok] + tokens, lhs_type, lhs_string rhs, tokens, rhs_type, rhs_string = parse_expr(tokens, type_required=lhs_type, now=now, level=level + 1) assert lhs_type == rhs_type, "incompatible types, " + lhs_type + ' ' + rhs_type assert type_required == BOOL_TYPE, "expecting a " + type_required + ' but got ' + BOOL_TYPE if op == AND: expr_string = '(' + lhs_string + ')AND(' + rhs_string + ')' LOGGER.debug('built %s:5 %s %s', level, BOOL_TYPE, expr_string) return (lambda x: and_fn(lhs, rhs, x)), tokens, BOOL_TYPE, expr_string elif op == OR: expr_string = '(' + lhs_string + ')OR(' + rhs_string + ')' LOGGER.debug('built %s:6 %s %s', level, BOOL_TYPE, expr_string) return (lambda x: or_fn(lhs, rhs, x)), tokens, BOOL_TYPE, expr_string elif op == EQUAL: expr_string = '(' + lhs_string + ')=(' + rhs_string + ')' LOGGER.debug('built %s:7 %s %s', level, BOOL_TYPE, expr_string) return ( lambda x: eq_fn(lhs(x), rhs(x))), tokens, BOOL_TYPE, expr_string elif op == NOT_EQUAL: expr_string = '(' + lhs_string + ')!=(' + rhs_string + ')' LOGGER.debug('built %s:8 %s %s', level, BOOL_TYPE, expr_string) return ( lambda x: ne_fn(lhs(x), rhs(x))), tokens, BOOL_TYPE, expr_string