예제 #1
0
def set_item(dbpath, uid, cid, data):

    obj = {'id': data['id']}
    obj['modified'] = round(time.time(), 2)
    obj['payload'] = data.get('payload', None)
    obj['payload_size'] = len(obj['payload']) if obj['payload'] else 0
    obj['sortindex'] = data.get('sortindex', None)
    obj['parentid'] = data.get('parentid', None)
    obj['predecessorid'] = data.get('predecessorid', None)
    obj['ttl'] = data.get('ttl', None)

    if obj['sortindex']:
        try:
            obj['sortindex'] = int(math.floor(float(obj['sortindex'])))
        except ValueError:
            return obj

    with sqlite3.connect(dbpath) as db:
        sql = ('main.%s (id VARCHAR(64) PRIMARY KEY, modified FLOAT,'
               'sortindex INTEGER, payload VARCHAR(256),'
               'payload_size INTEGER, parentid VARCHAR(64),'
               'predecessorid VARCHAR(64), ttl INTEGER)') % cid
        db.execute("CREATE table IF NOT EXISTS %s;" % sql)

        into = []
        values = []
        for k, v in iteritems(obj):
            into.append(k)
            values.append(v)

        try:
            db.execute("INSERT INTO %s (%s) VALUES (%s);" % \
                (cid, ', '.join(into), ','.join(['?' for x in values])), values)
        except sqlite3.IntegrityError:
            for k, v in iteritems(obj):
                if v is None: continue
                db.execute('UPDATE %s SET %s=? WHERE id=?;' % (cid, k),
                           [v, obj['id']])
        except sqlite3.InterfaceError:
            raise ValueError

    return obj
예제 #2
0
def set_item(dbpath, uid, cid, data):

    obj = {'id': data['id']}
    obj['modified'] = round(time.time(), 2)
    obj['payload'] = data.get('payload', None)
    obj['payload_size'] = len(obj['payload']) if obj['payload'] else 0
    obj['sortindex'] = data.get('sortindex', None)
    obj['parentid'] = data.get('parentid', None)
    obj['predecessorid'] = data.get('predecessorid', None)
    obj['ttl'] = data.get('ttl', None)

    if obj['sortindex']:
        try:
            obj['sortindex'] = int(math.floor(float(obj['sortindex'])))
        except ValueError:
            return obj

    with sqlite3.connect(dbpath) as db:
        sql = ('main.%s (id VARCHAR(64) PRIMARY KEY, modified FLOAT,'
               'sortindex INTEGER, payload VARCHAR(256),'
               'payload_size INTEGER, parentid VARCHAR(64),'
               'predecessorid VARCHAR(64), ttl INTEGER)') % cid
        db.execute("CREATE table IF NOT EXISTS %s;" % sql)

        into = []; values = []
        for k,v in iteritems(obj):
            into.append(k); values.append(v)

        try:
            db.execute("INSERT INTO %s (%s) VALUES (%s);" % \
                (cid, ', '.join(into), ','.join(['?' for x in values])), values)
        except sqlite3.IntegrityError:
            for k,v in iteritems(obj):
                if v is None: continue
                db.execute('UPDATE %s SET %s=? WHERE id=?;' % (cid, k), [v, obj['id']])
        except sqlite3.InterfaceError:
            raise ValueError

    return obj
예제 #3
0
def collection(app, environ, request, version, uid, cid):
    """/<float:version>/<username>/storage/<collection>"""

    if request.method == 'HEAD' or request.authorization.username != uid:
        return Response('Not Authorized', 401)

    dbpath = app.dbpath(uid, request.authorization.password)
    expire(dbpath, cid)

    ids    = request.args.get('ids', None)
    offset = request.args.get('offset', None)
    older  = request.args.get('older', None)
    newer  = request.args.get('newer', None)
    full   = request.args.get('full', False)
    index_above = request.args.get('index_above', None)
    index_below = request.args.get('index_below', None)
    limit  = request.args.get('limit', None)
    offset = request.args.get('offset', None)
    sort   = request.args.get('sort', None)
    parentid = request.args.get('parentid', None)
    predecessorid = request.args.get('predecessorid', None)

    try:
        older and float(older)
        newer and float(newer)
        limit and int(limit)
        offset and int(offset)
        index_above and int(index_above)
        index_below and int(index_below)
    except ValueError:
        raise BadRequest

    if limit is not None:
        limit = int(limit)

    if offset is not None:
        # we need both
        if limit is None:
            offset = None
        else:
            offset = int(offset)

    if not full:
        fields = ['id']
    else:
        fields = FIELDS

    # filters used in WHERE clause
    filters = {}
    if ids is not None:
        filters['id'] =  'IN', '(%s)' % ids
    if older is not None:
        filters['modified'] = '<', float(older)
    if newer is not None:
        filters['modified'] = '>', float(newer)
    if index_above is not None:
        filters['sortindex'] = '>', int(index_above)
    if index_below is not None:
        filters['sortindex'] = '<', int(index_below)
    if parentid is not None:
        filters['parentid'] = '=', "'%s'" % parentid
    if predecessorid is not None:
        filters['predecessorid'] = '=', "'%s'" % predecessorid

    filter_query, sort_query, limit_query = '', '', ''

    # ORDER BY x ASC|DESC
    if sort is not None:
        if sort == 'index':
            sort_query = ' ORDER BY sortindex DESC'
        elif sort == 'oldest':
            sort_query = ' ORDER BY modified ASC'
        elif sort == 'newest':
            sort_query = ' ORDER BY modified DESC'

    # WHERE x<y AND ...
    if filters:
        filter_query = ' WHERE '
        filter_query += ' AND '.join([k + ' ' + v[0] + ' ' + str(v[1])
            for k, v in iteritems(filters)])

    # LIMIT x [OFFSET y]
    if limit:
        limit_query += ' LIMIT %i' % limit
        if offset:
            limit_query += ' OFFSET %i' % offset

    if request.method == 'GET':
        # Returns a list of the WBO or ids contained in a collection.

        with sqlite3.connect(dbpath) as db:
            try:
                res = db.execute('SELECT %s FROM %s' % (','.join(fields), cid) \
                      + filter_query + sort_query + limit_query).fetchall()
            except sqlite3.OperationalError:
                res = []

        res = [v[0] if len(fields) == 1 else wbo2dict(v) for v in res]
        res, mime, records = convert(res, request.accept_mimetypes.best)

        return Response(res, 200, content_type=mime,
                        headers={'X-Weave-Records': str(records)})

    # before we write, check if the data has not been modified since the request
    since = request.headers.get('X-If-Unmodified-Since', None)
    if since and has_modified(float(since), dbpath, cid):
        raise PreconditionFailed

    if request.method == 'DELETE':
        try:
            with sqlite3.connect(dbpath) as db:
                select = 'SELECT id FROM %s' % cid + filter_query \
                       + sort_query + limit_query
                db.execute('DELETE FROM %s WHERE id IN (%s)' % (cid, select))
        except sqlite3.OperationalError:
            pass
        return Response(json.dumps(time.time()), 200)

    elif request.method in ('PUT', 'POST'):

        data = request.get_json()

        if isinstance(data, dict):
            data = [data]

        success, failed = [], []
        for item in data:
            if 'id' not in item:
                failed.append(item)
                continue

            try:
                o = set_item(dbpath, uid, cid, item)
                success.append(o['id'])
            except ValueError:
                failed.append(item['id'])

        js = json.dumps({'modified': round(time.time(), 2), 'success': success,
                         'failed': failed})
        return Response(js, 200, content_type='application/json',
                        headers={'X-Weave-Timestamp': round(time.time(), 2)})
예제 #4
0
def collection(app, environ, request, version, uid, cid):
    """/<float:version>/<username>/storage/<collection>"""

    if request.method == 'HEAD' or request.authorization.username != uid:
        return Response('Not Authorized', 401)

    dbpath = app.dbpath(uid, request.authorization.password)
    expire(dbpath, cid)

    ids = request.args.get('ids', None)
    offset = request.args.get('offset', None)
    older = request.args.get('older', None)
    newer = request.args.get('newer', None)
    full = request.args.get('full', False)
    index_above = request.args.get('index_above', None)
    index_below = request.args.get('index_below', None)
    limit = request.args.get('limit', None)
    offset = request.args.get('offset', None)
    sort = request.args.get('sort', None)
    parentid = request.args.get('parentid', None)
    predecessorid = request.args.get('predecessorid', None)

    try:
        older and float(older)
        newer and float(newer)
        limit and int(limit)
        offset and int(offset)
        index_above and int(index_above)
        index_below and int(index_below)
    except ValueError:
        raise BadRequest

    if limit is not None:
        limit = int(limit)

    if offset is not None:
        # we need both
        if limit is None:
            offset = None
        else:
            offset = int(offset)

    if not full:
        fields = ['id']
    else:
        fields = FIELDS

    # filters used in WHERE clause
    filters = {}
    if ids is not None:
        filters['id'] = 'IN', '(%s)' % ",".join("'" + x.strip() + "'"
                                                for x in ids.split(","))
    if older is not None:
        filters['modified'] = '<', float(older)
    if newer is not None:
        filters['modified'] = '>', float(newer)
    if index_above is not None:
        filters['sortindex'] = '>', int(index_above)
    if index_below is not None:
        filters['sortindex'] = '<', int(index_below)
    if parentid is not None:
        filters['parentid'] = '=', "'%s'" % parentid
    if predecessorid is not None:
        filters['predecessorid'] = '=', "'%s'" % predecessorid

    filter_query, sort_query, limit_query = '', '', ''

    # ORDER BY x ASC|DESC
    if sort is not None:
        if sort == 'index':
            sort_query = ' ORDER BY sortindex DESC'
        elif sort == 'oldest':
            sort_query = ' ORDER BY modified ASC'
        elif sort == 'newest':
            sort_query = ' ORDER BY modified DESC'

    # WHERE x<y AND ...
    if filters:
        filter_query = ' WHERE '
        filter_query += ' AND '.join(
            [k + ' ' + v[0] + ' ' + str(v[1]) for k, v in iteritems(filters)])

    # LIMIT x [OFFSET y]
    if limit:
        limit_query += ' LIMIT %i' % limit
        if offset:
            limit_query += ' OFFSET %i' % offset

    if request.method == 'GET':
        # Returns a list of the WBO or ids contained in a collection.

        with sqlite3.connect(dbpath) as db:
            try:
                res = db.execute('SELECT %s FROM %s' % (','.join(fields), cid) \
                      + filter_query + sort_query + limit_query).fetchall()
            except sqlite3.OperationalError:
                res = []

        res = [v[0] if len(fields) == 1 else wbo2dict(v) for v in res]
        res, mime, records = convert(res, request.accept_mimetypes.best)

        return Response(res,
                        200,
                        content_type=mime,
                        headers={'X-Weave-Records': str(records)})

    # before we write, check if the data has not been modified since the request
    since = request.headers.get('X-If-Unmodified-Since', None)
    if since and has_modified(float(since), dbpath, cid):
        raise PreconditionFailed

    if request.method == 'DELETE':
        try:
            with sqlite3.connect(dbpath) as db:
                select = 'SELECT id FROM %s' % cid + filter_query \
                       + sort_query + limit_query
                db.execute('DELETE FROM %s WHERE id IN (%s)' % (cid, select))
        except sqlite3.OperationalError:
            pass
        return Response(json.dumps(time.time()), 200)

    elif request.method in ('PUT', 'POST'):

        data = request.get_json()

        if isinstance(data, dict):
            data = [data]

        success, failed = [], []
        for item in data:
            if 'id' not in item:
                failed.append(item)
                continue

            try:
                o = set_item(dbpath, uid, cid, item)
                success.append(o['id'])
            except ValueError:
                failed.append(item['id'])

        js = json.dumps({
            'modified': round(time.time(), 2),
            'success': success,
            'failed': failed
        })
        return Response(js,
                        200,
                        content_type='application/json',
                        headers={'X-Weave-Timestamp': round(time.time(), 2)})