armet/query/parser.py
def parse_segment(text):
    "we expect foo=bar"

    if not len(text):
        return NoopQuerySegment()

    q = QuerySegment()

    # First we need to split the segment into key/value pairs.  This is done
    # by attempting to split the sequence for each equality comparison.  Then
    # discard any that did not split properly.  Then chose the smallest key
    # (greedily chose the first comparator we encounter in the string)
    # followed by the smallest value (greedily chose the largest comparator
    # possible.)

    # translate into [('=', 'foo=bar')]
    equalities = zip(constants.OPERATOR_EQUALITIES, itertools.repeat(text))
    # Translate into [('=', ['foo', 'bar'])]
    equalities = map(lambda x: (x[0], x[1].split(x[0], 1)), equalities)
    # Remove unsplit entries and translate into [('=': ['foo', 'bar'])]
    # Note that the result from this stage is iterated over twice.
    equalities = list(filter(lambda x: len(x[1]) > 1, equalities))
    # Get the smallest key and use the length of that to remove other items
    key_len = len(min((x[1][0] for x in equalities), key=len))
    equalities = filter(lambda x: len(x[1][0]) == key_len, equalities)

    # Get the smallest value length. thus we have the earliest key and the
    # smallest value.
    op, (key, value) = min(equalities, key=lambda x: len(x[1][1]))

    key, directive = parse_directive(key)
    if directive:
        op = constants.OPERATOR_EQUALITY_FALLBACK
        q.directive = directive

    # Process negation.  This comes in both foo.not= and foo!= forms.
    path = key.split(constants.SEP_PATH)
    last = path[-1]

    # Check for !=
    if last.endswith(constants.OPERATOR_NEGATION):
        last = last[:-1]
        q.negated = not q.negated

    # Check for foo.not=
    if last == constants.PATH_NEGATION:
        path.pop(-1)
        q.negated = not q.negated

    q.values = value.split(constants.SEP_VALUE)

    # Check for suffixed operators (foo.gte=bar).  Prioritize suffixed
    # entries over actual equality checks.
    if path[-1] in constants.OPERATOR_SUFFIXES:

        # The case where foo.gte<=bar, which obviously makes no sense.
        if op not in constants.OPERATOR_FALLBACK:
            raise ValueError(
                'Both path-style operator and equality style operator '
                'provided.  Please provide only a single style operator.')

        q.operator = constants.OPERATOR_SUFFIX_MAP[path[-1]]
        path.pop(-1)
    else:
        q.operator = constants.OPERATOR_EQUALITY_MAP[op]

    if not len(path):
        raise ValueError('No attribute navigation path provided.')

    q.path = path

    return q
def parse_segment(text):
    "we expect foo=bar"

    if not len(text):
        return NoopQuerySegment()

    q = QuerySegment()

    # First we need to split the segment into key/value pairs.  This is done
    # by attempting to split the sequence for each equality comparison.  Then
    # discard any that did not split properly.  Then chose the smallest key
    # (greedily chose the first comparator we encounter in the string)
    # followed by the smallest value (greedily chose the largest comparator
    # possible.)

    # translate into [('=', 'foo=bar')]
    equalities = zip(constants.OPERATOR_EQUALITIES, itertools.repeat(text))
    # Translate into [('=', ['foo', 'bar'])]
    equalities = map(lambda x: (x[0], x[1].split(x[0], 1)), equalities)
    # Remove unsplit entries and translate into [('=': ['foo', 'bar'])]
    # Note that the result from this stage is iterated over twice.
    equalities = list(filter(lambda x: len(x[1]) > 1, equalities))
    # Get the smallest key and use the length of that to remove other items
    key_len = len(min((x[1][0] for x in equalities), key=len))
    equalities = filter(lambda x: len(x[1][0]) == key_len, equalities)

    # Get the smallest value length. thus we have the earliest key and the
    # smallest value.
    op, (key, value) = min(equalities, key=lambda x: len(x[1][1]))

    key, directive = parse_directive(key)
    if directive:
        op = constants.OPERATOR_EQUALITY_FALLBACK
        q.directive = directive

    # Process negation.  This comes in both foo.not= and foo!= forms.
    path = key.split(constants.SEP_PATH)
    last = path[-1]

    # Check for !=
    if last.endswith(constants.OPERATOR_NEGATION):
        last = last[:-1]
        q.negated = not q.negated

    # Check for foo.not=
    if last == constants.PATH_NEGATION:
        path.pop(-1)
        q.negated = not q.negated

    q.values = value.split(constants.SEP_VALUE)

    # Check for suffixed operators (foo.gte=bar).  Prioritize suffixed
    # entries over actual equality checks.
    if path[-1] in constants.OPERATOR_SUFFIXES:

        # The case where foo.gte<=bar, which obviously makes no sense.
        if op not in constants.OPERATOR_FALLBACK:
            raise ValueError(
                'Both path-style operator and equality style operator '
                'provided.  Please provide only a single style operator.')

        q.operator = constants.OPERATOR_SUFFIX_MAP[path[-1]]
        path.pop(-1)
    else:
        q.operator = constants.OPERATOR_EQUALITY_MAP[op]

    if not len(path):
        raise ValueError('No attribute navigation path provided.')

    q.path = path

    return q
def parse_segment ( text ) : if not len ( text ) : return NoopQuerySegment ( ) q = QuerySegment ( ) # First we need to split the segment into key/value pairs.  This is done # by attempting to split the sequence for each equality comparison.  Then # discard any that did not split properly.  Then chose the smallest key # (greedily chose the first comparator we encounter in the string) # followed by the smallest value (greedily chose the largest comparator # possible.) # translate into [('=', 'foo=bar')] equalities = zip ( constants . OPERATOR_EQUALITIES , itertools . repeat ( text ) ) # Translate into [('=', ['foo', 'bar'])] equalities = map ( lambda x : ( x [ 0 ] , x [ 1 ] . split ( x [ 0 ] , 1 ) ) , equalities ) # Remove unsplit entries and translate into [('=': ['foo', 'bar'])] # Note that the result from this stage is iterated over twice. equalities = list ( filter ( lambda x : len ( x [ 1 ] ) > 1 , equalities ) ) # Get the smallest key and use the length of that to remove other items key_len = len ( min ( ( x [ 1 ] [ 0 ] for x in equalities ) , key = len ) ) equalities = filter ( lambda x : len ( x [ 1 ] [ 0 ] ) == key_len , equalities ) # Get the smallest value length. thus we have the earliest key and the # smallest value. op , ( key , value ) = min ( equalities , key = lambda x : len ( x [ 1 ] [ 1 ] ) ) key , directive = parse_directive ( key ) if directive : op = constants . OPERATOR_EQUALITY_FALLBACK q . directive = directive # Process negation.  This comes in both foo.not= and foo!= forms. path = key . split ( constants . SEP_PATH ) last = path [ - 1 ] # Check for != if last . endswith ( constants . OPERATOR_NEGATION ) : last = last [ : - 1 ] q . negated = not q . negated # Check for foo.not= if last == constants . PATH_NEGATION : path . pop ( - 1 ) q . negated = not q . negated q . values = value . split ( constants . SEP_VALUE ) # Check for suffixed operators (foo.gte=bar).  Prioritize suffixed # entries over actual equality checks. if path [ - 1 ] in constants . OPERATOR_SUFFIXES : # The case where foo.gte<=bar, which obviously makes no sense. if op not in constants . OPERATOR_FALLBACK : raise ValueError ( 'Both path-style operator and equality style operator ' 'provided.  Please provide only a single style operator.' ) q . operator = constants . OPERATOR_SUFFIX_MAP [ path [ - 1 ] ] path . pop ( - 1 ) else : q . operator = constants . OPERATOR_EQUALITY_MAP [ op ] if not len ( path ) : raise ValueError ( 'No attribute navigation path provided.' ) q . path = path return q
we expect foo=bar
we expect foo = bar