Beispiel #1
0
def sanitized_facets(input_facets):
    """
    Sanitize all the facets.

    It must be a dictionary of scalar values, or a dictionary of lists of scalar
    values.

        e.g. {'derp': 123, 'merp': [123, "hello"]}

    """
    if type(input_facets) != dict:
        raise ValidationError('"facets" must be dictionary')

    facets = []
    for facet_name, facet_values in input_facets.items():
        if type(facet_name) not in [str, unicode]:
            raise ValidationError("Facet names must be strings")

        facet_name = to_utf8_str(facet_name)
        if type(facet_values) in [str, unicode, int, float]:
            facet_values = [to_utf8_str(facet_values)]
        if type(facet_values) not in [list, set]:
            raise ValidationError("Facet values for '%s' must be a string, int or float"
                                  " - or a list containing only strings, ints and floats" % (facet_name,))
        for i in range(0, len(facet_values)):
            value = facet_values[i]
            if type(value) not in [int, str, unicode, float]:
                raise ValidationError("Facet '%s[%d]' must be a string, int or float" % (facet_name, i))                
        facets.append((facet_name, [to_utf8_str(tmp_value) for tmp_value in facet_values]))

    return sorted(facets, key=lambda x: x[0])
Beispiel #2
0
def sanitized_values(input_values):
    """
    Sanitize all values, it must be a dictionary of values
    """
    if type(input_values) != dict:
        raise ValidationError('"values" must be dictionary')

    values = []
    for value_name, value in input_values.items():
        if type(value_name) not in [str, unicode]:
            raise ValidationError("Value names must be strings")        
        if type(value) != int:
            raise ValidationError("Value '%s' must be an integer" % (value_name,))
        values.append((to_utf8_str(value_name), int(value)))

    return sorted(values, key=lambda x: x[0])
Beispiel #3
0
def make_record(data):
    """
    Make a record to be inserted into a bucket
    """
    if data is None:
        raise ValidationError('No data received')

    if type(data) != dict or 'facets' not in data or 'values' not in data:
        raise ValidationError('Data must be dictionary with "id", "facets" and "values" keys')    

    if 'id' not in data or type(data['id']) not in [int, str, unicode]:
        raise ValidationError('The "id" must be a string or int')

    record_id = to_utf8_str(data['id'])
    facets = sanitized_facets(data['facets'])
    values = sanitized_values(data['values'])    

    return {
        'id': record_id,
        'facets': facets,
        'values': values,
    }
Beispiel #4
0
def find_values(bucket):
    """
    Retrieves a list of the facet values underneath a parent facet.

    It accepts a JSON dictionry of the parent facet names and a limit on how 
    many sub-facets to return.

        {
            'tablet-days': {'facet': {'device': ['tablet', 'apple'],
                                      'time': ['2013', '1', '15']},
                            'limit': 50}
        }

    On success it will return the a standard API response including the
    'results' key which contains a 

        {
            'ok': true,
            'status': 200,
            'results': {
                'tablet-days': {'1': {'duration': 38289323,
                                      'datapoints': 4919}},
                               {'2': {'duration': 382829,
                                      'datapoints': 1234}}
            }
        }
    """
    start_time = unixtime()
    request = bottle.request
    query = request.json

    if query is None or type(query) != dict:
        bottle.abort(400, 'Must POST application/json dictionary')

    # Validate the searches
    searches = {}
    for name, search in query.items():
        if 'facet' not in search:
            bottle.abort(400, '"facet" key required for "%s"' % (name,))
        if 'limit' not in search:
            bottle.abort(400, '"limit" key required for "%s"' % (name,))
        try:
            limit = int(search.get('limit'))
        except ValueError:
            bottle.abort(400, 'Invalid "limit" for "%s"' % (name,))

        withvalues = bool(search.get('withvalues'))

        startkey = None
        if 'startkey' in search:
            try:
                startkey = to_utf8_str(search['startkey'])
            except TypeError:
                bottle.abort(400, 'Start key for "%s" is invalid type' % (name,))

        try:
            facet = sanitized_facets(search['facet'])
        except ValidationError, oops:
            LOG.info("'%s' contained invalid facet", name, exc_info=True)
            bottle.abort(400, "%s: %s" % (name, oops.message))
        searches[name] = {
            'facet': split_facet(facet),
            'limit': limit,
            'startkey': start,
            'withvalues': withvalues
        }