def parse_query(course, expr_str): from django.db.models import Q def parse_terminal(pstate): next_tag = pstate.next_tag() if next_tag is _id: result = Q(user__id=int(pstate.next_match_obj().group(1))) pstate.advance() return result elif next_tag is _email: result = Q(user__email__iexact=pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _email_contains: result = Q(user__email__icontains=pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _user: result = Q(user__username__exact=pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _user_contains: result = Q(user__username__contains=pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _tagged: ptag, created = ParticipationTag.objects.get_or_create( course=course, name=pstate.next_match_obj().group(1)) result = Q(tags__pk=ptag.pk) pstate.advance() return result else: pstate.expected("terminal") def inner_parse(pstate, min_precedence=0): pstate.expect_not_end() if pstate.is_next(_not): pstate.advance() left_query = ~inner_parse(pstate, _PREC_NOT) elif pstate.is_next(_openpar): pstate.advance() left_query = inner_parse(pstate) pstate.expect(_closepar) pstate.advance() else: left_query = parse_terminal(pstate) did_something = True while did_something: did_something = False if pstate.is_at_end(): return left_query next_tag = pstate.next_tag() if next_tag is _and and _PREC_AND > min_precedence: pstate.advance() left_query = left_query & inner_parse(pstate, _PREC_AND) did_something = True elif next_tag is _or and _PREC_OR > min_precedence: pstate.advance() left_query = left_query | inner_parse(pstate, _PREC_OR) did_something = True elif (next_tag in _TERMINALS + [_not, _openpar] and _PREC_AND > min_precedence): left_query = left_query & inner_parse(pstate, _PREC_AND) did_something = True return left_query from pytools.lex import LexIterator, lex pstate = LexIterator( [(tag, s, idx, matchobj) for (tag, s, idx, matchobj) in lex(_LEX_TABLE, expr_str, match_objects=True) if tag is not _whitespace], expr_str) if pstate.is_at_end(): pstate.raise_parse_error("unexpected end of input") result = inner_parse(pstate) if not pstate.is_at_end(): pstate.raise_parse_error("leftover input after completed parse") return result
def parse_query(course, expr_str): from django.db.models import Q def parse_terminal(pstate): next_tag = pstate.next_tag() if next_tag is _id: result = Q(user__id=int(pstate.next_match_obj().group(1))) pstate.advance() return result elif next_tag is _email: result = Q(user__email__iexact=pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _email_contains: result = Q(user__email__icontains=pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _user: result = Q(user__username__exact=pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _user_contains: result = Q( user__username__contains=pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _institutional_id: result = Q(user__institutional_id__iexact=pstate.next_match_obj(). group(1)) pstate.advance() return result elif next_tag is _institutional_id_contains: result = Q(user__institutional_id__icontains=pstate.next_match_obj( ).group(1)) pstate.advance() return result elif next_tag is _tagged: ptag, created = ParticipationTag.objects.get_or_create( course=course, name=pstate.next_match_obj().group(1)) result = Q(tags__pk=ptag.pk) pstate.advance() return result elif next_tag is _role: result = Q(role=pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _status: result = Q(status=pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _has_started: flow_id = pstate.next_match_obj().group(1) result = (Q(flow_sessions__flow_id=flow_id) & Q(flow_sessions__course=course)) pstate.advance() return result elif next_tag is _has_submitted: flow_id = pstate.next_match_obj().group(1) result = (Q(flow_sessions__flow_id=flow_id) & Q(flow_sessions__course=course) & Q(flow_sessions__in_progress=False)) pstate.advance() return result else: pstate.expected("terminal") def inner_parse(pstate, min_precedence=0): pstate.expect_not_end() if pstate.is_next(_not): pstate.advance() left_query = ~inner_parse(pstate, _PREC_NOT) elif pstate.is_next(_openpar): pstate.advance() left_query = inner_parse(pstate) pstate.expect(_closepar) pstate.advance() else: left_query = parse_terminal(pstate) did_something = True while did_something: did_something = False if pstate.is_at_end(): return left_query next_tag = pstate.next_tag() if next_tag is _and and _PREC_AND > min_precedence: pstate.advance() left_query = left_query & inner_parse(pstate, _PREC_AND) did_something = True elif next_tag is _or and _PREC_OR > min_precedence: pstate.advance() left_query = left_query | inner_parse(pstate, _PREC_OR) did_something = True elif (next_tag in _TERMINALS + [_not, _openpar] and _PREC_AND > min_precedence): left_query = left_query & inner_parse(pstate, _PREC_AND) did_something = True return left_query from pytools.lex import LexIterator, lex pstate = LexIterator( [(tag, s, idx, matchobj) for (tag, s, idx, matchobj) in lex(_LEX_TABLE, expr_str, match_objects=True) if tag is not _whitespace], expr_str) if pstate.is_at_end(): pstate.raise_parse_error("unexpected end of input") result = inner_parse(pstate) if not pstate.is_at_end(): pstate.raise_parse_error("leftover input after completed parse") return result
def parse_match(expr_str): """Syntax examples:: * ``id:yoink and writes:a_temp`` * ``id:yoink and (not writes:a_temp or tagged:input)`` """ if not expr_str: return AllMatchExpression() def parse_terminal(pstate): next_tag = pstate.next_tag() if next_tag is _id: result = IdMatchExpression(pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _tag: result = TagMatchExpression(pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _writes: result = WritesMatchExpression(pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _reads: result = ReadsMatchExpression(pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _iname: result = InameMatchExpression(pstate.next_match_obj().group(1)) pstate.advance() return result else: pstate.expected("terminal") def inner_parse(pstate, min_precedence=0): pstate.expect_not_end() if pstate.is_next(_not): pstate.advance() left_query = NotMatchExpression(inner_parse(pstate, _PREC_NOT)) elif pstate.is_next(_openpar): pstate.advance() left_query = inner_parse(pstate) pstate.expect(_closepar) pstate.advance() else: left_query = parse_terminal(pstate) did_something = True while did_something: did_something = False if pstate.is_at_end(): return left_query next_tag = pstate.next_tag() if next_tag is _and and _PREC_AND > min_precedence: pstate.advance() left_query = AndMatchExpression( (left_query, inner_parse(pstate, _PREC_AND))) did_something = True elif next_tag is _or and _PREC_OR > min_precedence: pstate.advance() left_query = OrMatchExpression( (left_query, inner_parse(pstate, _PREC_OR))) did_something = True return left_query from pytools.lex import LexIterator, lex, InvalidTokenError try: pstate = LexIterator( [(tag, s, idx, matchobj) for (tag, s, idx, matchobj) in lex(_LEX_TABLE, expr_str, match_objects=True) if tag is not _whitespace], expr_str) except InvalidTokenError as e: from loopy.diagnostic import LoopyError raise LoopyError( "invalid match expression: '{match_expr}' ({err_type}: {err_str})" .format( match_expr=expr_str, err_type=type(e).__name__, err_str=str(e))) if pstate.is_at_end(): pstate.raise_parse_error("unexpected end of input") result = inner_parse(pstate) if not pstate.is_at_end(): pstate.raise_parse_error("leftover input after completed parse") return result
def parse_query(expr_str): def parse_terminal(pstate): next_tag = pstate.next_tag() if next_tag is _tag: return make_tag_query(pstate.next_str_and_advance()) elif next_tag is _negtag: return NotQuery(make_tag_query(pstate.next_str_and_advance()[1:])) elif next_tag is _fulltext: return FulltextQuery(pstate.next_str_and_advance()[1:-1]) elif next_tag is _dated: pstate.advance() return DatedQuery() elif next_tag in _STATELESS_TERMINALS: pstate.advance() return _STATELESS_TERMINALS[next_tag] elif next_tag in [_id]: result = IdQuery(int(pstate.next_match_obj().group(1))) pstate.advance() return result elif next_tag in [_before, _after]: from parsedatetime.parsedatetime import Calendar cal = Calendar() timetup = cal.parse(pstate.next_match_obj().group(1)) pstate.advance() import time return DateQuery(next_tag == _before, time.mktime(timetup[0])) else: pstate.expected("terminal") def inner_parse(pstate, min_precedence=0): pstate.expect_not_end() if pstate.is_next(_not): pstate.advance() left_query = make_not_query(inner_parse(pstate, _PREC_NOT)) elif pstate.is_next(_openpar): pstate.advance() left_query = inner_parse(pstate) pstate.expect(_closepar) pstate.advance() else: left_query = parse_terminal(pstate) did_something = True while did_something: did_something = False if pstate.is_at_end(): return left_query next_tag = pstate.next_tag() if next_tag is _and and _PREC_AND > min_precedence: pstate.advance() left_query = make_and_query( [left_query, inner_parse(pstate, _PREC_AND)]) did_something = True elif next_tag is _or and _PREC_OR > min_precedence: pstate.advance() left_query = make_or_query( [left_query, inner_parse(pstate, _PREC_OR)]) did_something = True elif (next_tag in _TERMINALS + [_not, _openpar] and _PREC_AND > min_precedence): left_query = make_and_query( [left_query, inner_parse(pstate, _PREC_AND)]) did_something = True return left_query from pytools.lex import LexIterator, lex pstate = LexIterator( [(tag, s, idx, matchobj) for (tag, s, idx, matchobj) in lex(_LEX_TABLE, expr_str, match_objects=True) if tag is not _whitespace], expr_str) if pstate.is_at_end(): return TagQuery(u"home") result = inner_parse(pstate) if not pstate.is_at_end(): pstate.raise_parse_error("leftover input after completed parse") return result
def parse_match(expr): """Syntax examples:: * ``id:yoink and writes:a_temp`` * ``id:yoink and (not writes:a_temp or tag:input)`` """ if not expr: return All() def parse_terminal(pstate): next_tag = pstate.next_tag() if next_tag is _id: result = Id(pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _tag: result = Tagged(pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _writes: result = Writes(pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _reads: result = Reads(pstate.next_match_obj().group(1)) pstate.advance() return result elif next_tag is _iname: result = Iname(pstate.next_match_obj().group(1)) pstate.advance() return result else: pstate.expected("terminal") def inner_parse(pstate, min_precedence=0): pstate.expect_not_end() if pstate.is_next(_not): pstate.advance() left_query = Not(inner_parse(pstate, _PREC_NOT)) elif pstate.is_next(_openpar): pstate.advance() left_query = inner_parse(pstate) pstate.expect(_closepar) pstate.advance() else: left_query = parse_terminal(pstate) did_something = True while did_something: did_something = False if pstate.is_at_end(): return left_query next_tag = pstate.next_tag() if next_tag is _and and _PREC_AND > min_precedence: pstate.advance() left_query = And((left_query, inner_parse(pstate, _PREC_AND))) did_something = True elif next_tag is _or and _PREC_OR > min_precedence: pstate.advance() left_query = Or((left_query, inner_parse(pstate, _PREC_OR))) did_something = True return left_query if isinstance(expr, MatchExpressionBase): return expr from pytools.lex import LexIterator, lex, InvalidTokenError try: pstate = LexIterator( [(tag, s, idx, matchobj) for (tag, s, idx, matchobj) in lex(_LEX_TABLE, expr, match_objects=True) if tag is not _whitespace], expr) except InvalidTokenError as e: from loopy.diagnostic import LoopyError raise LoopyError( "invalid match expression: '{match_expr}' ({err_type}: {err_str})". format(match_expr=expr, err_type=type(e).__name__, err_str=str(e))) if pstate.is_at_end(): pstate.raise_parse_error("unexpected end of input") result = inner_parse(pstate) if not pstate.is_at_end(): pstate.raise_parse_error("leftover input after completed parse") return result
def parse_query(expr_str): from django.db.backends.sqlite3.base import DatabaseWrapper as SQLite3DB if isinstance(db.connections["default"], SQLite3DB): WORD_BDRY = r"\b" else: WORD_BDRY = r"\y" from django.db.models import Q def parse_terminal(pstate): next_tag = pstate.next_tag() if next_tag is _tag: tag = PieceTag.objects.get( name=pstate.next_match_obj().group(1)) result = Q(tags__id=tag.id) pstate.advance() return result if next_tag is _assignment_tag: atag_ids = [ atag.id for atag in AssignmentTag.objects.filter( name=pstate.next_match_obj().group(1))] result = Q(coding_assignments__tags__id__in=atag_ids) pstate.advance() return result elif next_tag is _meta: text = pstate.next_match_obj().group(1) result = ( Q(title__icontains=text) | Q(notes__icontains=text) | Q(pub_date_unparsed__icontains=text) | Q(byline__icontains=text) | Q(url__icontains=text) | Q(extra_data_json__icontains=text) | Q(venue__name__icontains=text) ) pstate.advance() return result elif next_tag in [_pub_before, _pub_after]: import datetime mo = pstate.next_match_obj() date = datetime.date( year=int(mo.group(1)), month=int(mo.group(2)), day=int(mo.group(3)), ) if next_tag is _pub_before: result = Q(pub_date__lt=date) else: result = Q(pub_date__gt=date) pstate.advance() return result elif next_tag is _regex: re_value = pstate.next_match_obj().group(1) pstate.advance() return Q(content__iregex=re_value) | Q(title__iregex=re_value) elif next_tag is _word: re_value = r"{wb}{word}{wb}".format( wb=WORD_BDRY, word=pstate.next_match_obj().group(1)) pstate.advance() return Q(content__iregex=re_value) | Q(title__iregex=re_value) elif next_tag is _near: match_obj = pstate.next_match_obj() dist = int(match_obj.group(1)) word1 = match_obj.group(2) word2 = match_obj.group(3) regexes = [] for i in range(0, dist+1): regex = WORD_BDRY+word1 for j in range(i): regex += "\W+\w+" regex += r"\W+" + word2 + WORD_BDRY regexes.append(regex) re_value = "|".join(regexes) pstate.advance() return Q(content__iregex=re_value) | Q(title__iregex=re_value) elif next_tag is _fulltext: text = pstate.next_str_and_advance()[1:-1] return Q(content__icontains=text) | Q(title__icontains=text) elif next_tag in [_id]: result = Q(id=int(pstate.next_match_obj().group(1))) pstate.advance() return result elif next_tag in [_study_id]: result = Q(studies__id=int(pstate.next_match_obj().group(1))) pstate.advance() return result elif next_tag in [_sample_id]: result = Q(samples__id=int(pstate.next_match_obj().group(1))) pstate.advance() return result else: pstate.expected("terminal") def inner_parse(pstate, min_precedence=0): pstate.expect_not_end() if pstate.is_next(_not): pstate.advance() left_query = ~inner_parse(pstate, _PREC_NOT) elif pstate.is_next(_openpar): pstate.advance() left_query = inner_parse(pstate) pstate.expect(_closepar) pstate.advance() else: left_query = parse_terminal(pstate) did_something = True while did_something: did_something = False if pstate.is_at_end(): return left_query next_tag = pstate.next_tag() if next_tag is _and and _PREC_AND > min_precedence: pstate.advance() left_query = left_query & inner_parse(pstate, _PREC_AND) did_something = True elif next_tag is _or and _PREC_OR > min_precedence: pstate.advance() left_query = left_query | inner_parse(pstate, _PREC_OR) did_something = True elif (next_tag in _TERMINALS + [_not, _openpar] and _PREC_AND > min_precedence): left_query = left_query & inner_parse(pstate, _PREC_AND) did_something = True return left_query from pytools.lex import LexIterator, lex pstate = LexIterator( [(tag, s, idx, matchobj) for (tag, s, idx, matchobj) in lex(_LEX_TABLE, expr_str, match_objects=True) if tag is not _whitespace], expr_str) if pstate.is_at_end(): pstate.raise_parse_error("unexpected end of input") result = inner_parse(pstate) if not pstate.is_at_end(): pstate.raise_parse_error("leftover input after completed parse") return result
def parse_query(expr_str): def parse_terminal(pstate): next_tag = pstate.next_tag() if next_tag is _tag: return make_tag_query(pstate.next_str_and_advance()) elif next_tag is _negtag: return NotQuery(make_tag_query(pstate.next_str_and_advance()[1:])) elif next_tag is _fulltext: return FulltextQuery(pstate.next_str_and_advance()[1:-1]) elif next_tag is _dated: pstate.advance() return DatedQuery() elif next_tag in _STATELESS_TERMINALS: pstate.advance() return _STATELESS_TERMINALS[next_tag] elif next_tag in [_id]: result = IdQuery(int(pstate.next_match_obj().group(1))) pstate.advance() return result elif next_tag in [_before, _after]: from parsedatetime.parsedatetime import Calendar cal = Calendar() timetup = cal.parse(pstate.next_match_obj().group(1)) pstate.advance() import time return DateQuery(next_tag == _before, time.mktime(timetup[0])) else: pstate.expected("terminal") def inner_parse(pstate, min_precedence=0): pstate.expect_not_end() if pstate.is_next(_not): pstate.advance() left_query = make_not_query(inner_parse(pstate, _PREC_NOT)) elif pstate.is_next(_openpar): pstate.advance() left_query = inner_parse(pstate) pstate.expect(_closepar) pstate.advance() else: left_query = parse_terminal(pstate) did_something = True while did_something: did_something = False if pstate.is_at_end(): return left_query next_tag = pstate.next_tag() if next_tag is _and and _PREC_AND > min_precedence: pstate.advance() left_query = make_and_query( [left_query, inner_parse(pstate, _PREC_AND)]) did_something = True elif next_tag is _or and _PREC_OR > min_precedence: pstate.advance() left_query = make_or_query( [left_query, inner_parse(pstate, _PREC_OR)]) did_something = True elif (next_tag in _TERMINALS + [_not, _openpar] and _PREC_AND > min_precedence): left_query = make_and_query( [left_query, inner_parse(pstate, _PREC_AND)]) did_something = True return left_query from pytools.lex import LexIterator, lex pstate = LexIterator( [(tag, s, idx, matchobj) for (tag, s, idx, matchobj) in lex( _LEX_TABLE, expr_str, match_objects=True) if tag is not _whitespace], expr_str) if pstate.is_at_end(): return TagQuery(u"home") result = inner_parse(pstate) if not pstate.is_at_end(): pstate.raise_parse_error("leftover input after completed parse") return result