Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
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