def test_validation(self): data = {'parentid': 'bigid' * 30} wbo = WBO(data) result, failure = wbo.validate() self.assertFalse(result) data = {'parentid': 'id', 'sortindex': 9999999999} wbo = WBO(data) result, failure = wbo.validate() self.assertFalse(result) data = {'parentid': 'id', 'sortindex': '9999.1'} wbo = WBO(data) result, failure = wbo.validate() self.assertTrue(result) self.assertTrue(wbo['sortindex'], 9999) data = {'parentid': 'id', 'sortindex': 'ok'} wbo = WBO(data) result, failure = wbo.validate() self.assertFalse(result) data = {'parentid': 33, 'sortindex': '12'} wbo = WBO(data) result, failure = wbo.validate() self.assertTrue(result) self.assertEquals(wbo['parentid'], '33') self.assertEquals(wbo['sortindex'], 12) for bad_ttl in ('bouh', -1, 31537000): data = {'parentid': 33, 'ttl': bad_ttl} wbo = WBO(data) result, failure = wbo.validate() self.assertFalse(result) data = {'parentid': 33, 'ttl': 3600} wbo = WBO(data) result, failure = wbo.validate() self.assertTrue(result) data = {'payload': "X" * 30000} wbo = WBO(data) result, failure = wbo.validate() self.assertTrue(result) data = {'payload': "X" * 300000} wbo = WBO(data) result, failure = wbo.validate() self.assertFalse(result)
def test_validation(self): data = {'parentid': 'bigid' * 30} wbo = WBO(data) result, failure = wbo.validate() self.assertFalse(result) data = {'parentid': 'id', 'sortindex': 9999999999} wbo = WBO(data) result, failure = wbo.validate() self.assertFalse(result) data = {'parentid': 'id', 'sortindex': '9999.1'} wbo = WBO(data) result, failure = wbo.validate() self.assertTrue(result) self.assertTrue(wbo['sortindex'], 9999) data = {'parentid': 'id', 'sortindex': 'ok'} wbo = WBO(data) result, failure = wbo.validate() self.assertFalse(result) data = {'parentid': 33, 'sortindex': '12'} wbo = WBO(data) result, failure = wbo.validate() self.assertTrue(result) self.assertEquals(wbo['parentid'], '33') self.assertEquals(wbo['sortindex'], 12) for bad_ttl in ('bouh', -1, 31537000): data = {'parentid': 33, 'ttl': bad_ttl} wbo = WBO(data) result, failure = wbo.validate() self.assertFalse(result) data = {'parentid': 33, 'ttl': 3600} wbo = WBO(data) result, failure = wbo.validate() self.assertTrue(result) data = {'payload': "X" * 30000} wbo = WBO(data) result, failure = wbo.validate() self.assertTrue(result) data = {'payload': "X" * 300000} wbo = WBO(data) result, failure = wbo.validate() self.assertFalse(result)
def set_item(self, request): """Sets a single WBO object.""" storage = self._get_storage(request) if storage.use_quota: left = self._check_quota(request) else: left = 0. user_id = request.user['userid'] collection_name = request.sync_info['collection'] item_id = request.sync_info['item'] if self._was_modified(request, user_id, collection_name): raise HTTPPreconditionFailed(collection_name) try: data = json.loads(request.body) except ValueError: raise HTTPJsonBadRequest(WEAVE_MALFORMED_JSON) try: wbo = WBO(data) except ValueError: raise HTTPJsonBadRequest(WEAVE_INVALID_WBO) consistent, msg = wbo.validate() if not consistent: raise HTTPJsonBadRequest(WEAVE_INVALID_WBO) if self._has_modifiers(wbo): wbo['modified'] = request.server_time try: res = storage.set_item(user_id, collection_name, item_id, storage_time=request.server_time, **wbo) except StorageConflictError: raise HTTPJsonBadRequest(WEAVE_INVALID_WRITE) response = json_response(res) if storage.use_quota and left <= _ONE_MEG: response.headers['X-Weave-Quota-Remaining'] = str(left) return response
def set_collection(self, request): """Sets a batch of WBO objects into a collection.""" user_id = request.user['userid'] collection_name = request.sync_info['collection'] if self._was_modified(request, user_id, collection_name): raise HTTPPreconditionFailed(collection_name) try: wbos = json.loads(request.body) except ValueError: raise HTTPJsonBadRequest(WEAVE_MALFORMED_JSON) if not isinstance(wbos, (tuple, list)): # thats a batch of one try: id_ = str(wbos['id']) except (KeyError, TypeError): raise HTTPJsonBadRequest(WEAVE_INVALID_WBO) if '/' in id_: raise HTTPJsonBadRequest(WEAVE_INVALID_WBO) request.sync_info['item'] = id_ return self.set_item(request) res = {'success': [], 'failed': {}} # Sanity-check each of the WBOs. # Limit the batch based on both count and payload size. kept_wbos = [] total_bytes = 0 for count, wbo in enumerate(wbos): try: wbo = WBO(wbo) except ValueError: res['failed'][''] = ['invalid wbo'] continue if 'id' not in wbo: res['failed'][''] = ['invalid id'] continue consistent, msg = wbo.validate() item_id = wbo['id'] if not consistent: res['failed'][item_id] = [msg] continue if count >= self.batch_max_count: res['failed'][item_id] = ['retry wbo'] continue if 'payload' in wbo: total_bytes += len(wbo['payload']) if total_bytes >= self.batch_max_bytes: res['failed'][item_id] = ['retry bytes'] continue if self._has_modifiers(wbo): wbo['modified'] = request.server_time kept_wbos.append(wbo) storage = self._get_storage(request) if storage.use_quota: left = self._check_quota(request) else: left = 0. storage_time = request.server_time for wbos in batch(kept_wbos, size=self.batch_size): wbos = list(wbos) # to avoid exhaustion try: storage.set_items(user_id, collection_name, wbos, storage_time=storage_time) except Exception, e: # we want to swallow the 503 in that case # something went wrong self.logger.error('Could not set items') self.logger.error(str(e)) for wbo in wbos: res['failed'][wbo['id']] = "db error" else: res['success'].extend([wbo['id'] for wbo in wbos])