def _check_require_fields(self, spec): for k, v in self.require_fields.items(): if k not in spec: raise WriteError("{0} isn't exists ".format(k)) if not isinstance(spec.get(k), v): raise WriteError("{0} is required {1} not {2}".format( k, v, type(spec.get(k))))
def add_notification_message(username, message, user_ref=None, post_ref=None): timestamp = datetime.utcnow().isoformat() notification_payload = {'timestamp': timestamp, 'message': message} if user_ref: notification_payload['user_ref'] = user_ref notification_payload['user_pic'] = UserModel.get_picture(user_ref) if post_ref: from api.main.models.posts_model import PostModel notification_payload['post_ref'] = post_ref notification_payload['post_pic'] = PostModel.get_picture(post_ref) resp = DB.users.find_one_and_update({'_id': username}, { '$push': { 'notifications': { '$each': [notification_payload], '$sort': { 'timestamp': -1 } } } }) if resp: return UserModel.get_user(username, show_following_pics=True, show_follower_pics=True) raise WriteError(f'Error in updating {username}. User may not exist.')
def add_user_post(username, post_id, title, audio_link, timestamp, description=None, image_link=None): user = UserModel.get_user(username) if user: DB.posts.insert({ '_id': post_id, 'username': username, 'title': title, 'description': description, 'audio_link': audio_link, 'image_link': image_link, 'timestamp': timestamp, 'comments': [], 'liked_by': [], 'view_count': 0 }) DB.users.find_one_and_update({'_id': username}, {'$addToSet': { 'posts': post_id }}) return PostModel.get_post(post_id) raise WriteError('Error in creating post. User may not exist.')
def __setitem__(self, fields, value): """ Atomically does either: Sets 'self[key] = value' or sets 'self[key][field1][field2][...] = value' """ key, dots, _ = self._process_inputs(fields) try: if isinstance(fields, str) and isinstance(value, dict): result = self._db.update_one(filter={'_id': key}, update={'$set': value}, upsert=True) else: result = self._db.update_one(filter={'_id': key}, update={'$set': { dots: value }}, upsert=True) except WriteError: raise WriteError( "Likely due to trying to set a subfield of a field that does not exists." + "\n Try setting a dict rather than a value. Ex. store['id_key', 'key', 'field'] = {'subfield': 'value'}" ) if result.raw_result['nModified'] == 0: if not 'upserted' in result.raw_result: logger.debug( f'Field not modified, old value likely the same as new. Key: {key}, Fields: {dots}, Value: {value}' )
def get_user(username, show_follower_pics=False, show_following_pics=False): LOGGER.info(f'DB: Retrieving user with username {username}') resp = DB.users.find_one({'_id': username}) if resp: # TODO: Optimise this in the future when no. followers grow if show_follower_pics: for i, un in enumerate(resp['followers']): picture = UserModel.get_user(un)['picture'] resp['followers'][i] = {'username': un, 'picture': picture} # TODO: Optimise this in the future when no. followings grow if show_following_pics: for i, un in enumerate(resp['followings']): picture = UserModel.get_user(un)['picture'] resp['followings'][i] = { 'username': un, 'picture': picture } LOGGER.info(f'Successfully retrieving user: {resp}') if 'notifications' not in resp: resp['notifications'] = [] return resp raise WriteError( f'Error in querying for {username}. User may not exist.')
def __write_fail_if_exists(self, collection, old_docs, new_docs): for old in old_docs: if collection.find(old): raise WriteError( "Found existing doc %s and fail_if_exists set to True." " Aborting write for all docs." % old) collection.insert_many(new_docs)
def _check_write_command_response(results): """Backward compatibility helper for write command error handling. """ errors = [ res for res in results if "writeErrors" in res[1] or "writeConcernError" in res[1] ] if errors: # If multiple batches had errors # raise from the last batch. offset, result = errors[-1] # Prefer write errors over write concern errors write_errors = result.get("writeErrors") if write_errors: # If the last batch had multiple errors only report # the last error to emulate continue_on_error. error = write_errors[-1] error["index"] += offset if error.get("code") == 11000: raise DuplicateKeyError(error.get("errmsg"), 11000, error) raise WriteError(error.get("errmsg"), error.get("code"), error) else: error = result["writeConcernError"] if "errInfo" in error and error["errInfo"].get('wtimeout'): # Make sure we raise WTimeoutError raise WTimeoutError(error.get("errmsg"), error.get("code"), error) raise WriteConcernError(error.get("errmsg"), error.get("code"), error)
def get_user_posts(username, skip=0, limit=10): user = UserModel.get_user(username) if user: posts = [PostModel.get_post(post_id) for post_id in user['posts']] posts.sort(key=lambda post: post['timestamp'], reverse=True) return posts[skip:skip + limit] raise WriteError(f'Error in querying posts. User may not exist.')
def _raise_last_write_error(write_errors): # If the last batch had multiple errors only report # the last error to emulate continue_on_error. error = write_errors[-1] if error.get("code") == 11000: raise DuplicateKeyError(error.get("errmsg"), 11000, error) raise WriteError(error.get("errmsg"), error.get("code"), error)
def get_user_discover_posts(username, skip=0, limit=10, seed=0): user = UserModel.get_user(username) if user: all_posts = list(DB.posts.find({'username': {'$ne': username}})) permuted_posts = PostModel.permute_with_discovery_algorithm( all_posts, seed) return permuted_posts[skip:skip + limit] raise WriteError(f'Error in querying posts. User may not exist.')
def get_post(post_id): resp = list( DB.posts.aggregate([ { '$match': { '_id': post_id } }, { '$unwind': { 'path': '$comments', "preserveNullAndEmptyArrays": True } }, { '$sort': { 'comments.timestamp': -1 } }, { '$group': { '_id': '$_id', 'username': { '$first': '$username' }, 'title': { '$first': '$title' }, 'description': { '$first': '$description' }, 'audio_link': { '$first': '$audio_link' }, 'image_link': { '$first': '$image_link' }, 'view_count': { '$first': '$view_count' }, 'timestamp': { '$first': '$timestamp' }, 'liked_by': { '$first': '$liked_by' }, 'comments': { '$push': '$comments' } } }, ])) if resp and resp[0]: post_info = resp[0] return post_info raise WriteError('Error in getting post. Post may not exist.')
def like_post(post_id, username): user = UserModel.get_user(username) post = PostModel.get_post(post_id) if user and post: DB.posts.find_one_and_update({'_id': post_id}, {'$addToSet': { 'liked_by': username }}) return PostModel.get_post(post_id) raise WriteError(f'Error in liking post. User or post may not exist.')
def get_user_feed_posts(username, skip=0, limit=10): user = UserModel.get_user(username) if user: followings = [username for username in user['followings']] posts = [] for username in followings: posts.extend(PostModel.get_user_posts(username)) posts.sort(key=lambda post: post['timestamp'], reverse=True) return posts[skip:skip + limit] raise WriteError(f'Error in querying posts. User may not exist.')
def update_object(self, currency_id, updated_fields): if 'code' in updated_fields.keys(): raise WriteError("You cant update currency code") result = self.db.currencies.update_one({'code': currency_id}, {'$set': updated_fields}, upsert=False) if result.matched_count == 1: return result else: raise NoMatchedCurrency( f'Unable to find currency code {currency_id}')
def inc_view_count_by_n(post_id, n=1): post = PostModel.get_post(post_id) if post: resp = DB.posts.find_one_and_update({'_id': post_id}, {'$inc': { 'view_count': n }}) if resp: return PostModel.get_post(post_id) raise WriteError( 'Error in incrementing the view count. Post may not exist.')
def __write_fail_if_not_exists(self, collection, old_docs, new_docs): for old in old_docs: if not collection.find(old): raise WriteError( "Did not find existing doc %s and fail_if_not_exists " "set to True. Aborting write for all docs." % old) bulk_query = [ReplaceOne(old, new, upsert=False) for old, new in zip(old_docs, new_docs)] result = collection.bulk_write(bulk_query, ordered=False) assert len(new_docs) == result.matched_count,\ ("Supposed to replace %s docs, but only replaced %s" % (len(new_docs), result.matched_count))
def update_user(username, **kwargs): updated_document = {'_id': username} if ('description' in kwargs) and (kwargs['description'] is not None): updated_document['description'] = kwargs['description'] if ('picture' in kwargs) and (kwargs['picture'] is not None): updated_document['picture'] = kwargs['picture'] resp = DB.users.find_one_and_update({'_id': username}, {'$set': updated_document}) if resp: return UserModel.get_user(username, show_following_pics=True, show_follower_pics=True) raise WriteError(f'Error in updating {username}. User may not exist.')
def remove_user_post(username, post_id): user = UserModel.get_user(username) post = PostModel.get_post(post_id) if post['_id'] in user['posts']: post_resp = DB.posts.find_one_and_delete({'_id': post_id}) user_resp = DB.users.find_one_and_update( {'_id': username}, {'$pull': { 'posts': post_id }}) return user_resp, post_resp raise WriteError( f'Error in removing post. User may not be authorized to remove this post.' )
def add_comment(post_id, username, text, timestamp): post = PostModel.get_post(post_id) user = UserModel.get_user(username) if user and post: comment = { 'username': username, 'text': text, 'timestamp': timestamp } DB.posts.find_one_and_update({'_id': post_id}, {'$push': { 'comments': comment }}) return PostModel.get_post(post_id) raise WriteError( f'Error in adding comment. User or post may not exist.')
def update_user_post(username, post_id, **updates): user = UserModel.get_user(username) post = PostModel.get_post(post_id) if post['_id'] in user['posts']: updated_document = {'_id': post_id} if 'title' in updates: updated_document['title'] = updates['title'] if 'description' in updates: updated_document['description'] = updates['description'] if 'audio_link' in updates: updated_document['audio_link'] = updates['audio_link'] if 'image_link' in updates: updated_document['image_link'] = updates['image_link'] DB.posts.find_one_and_update({'_id': post_id}, {'$set': updated_document}) return PostModel.get_post(post_id) raise WriteError( f'Error in removing post. User may not be authorized to remove this post.' )
def unfollow(username, other_username): user = UserModel.get_user(username) other_user = UserModel.get_user(other_username) if user and other_user: DB.users.find_one_and_update( {'_id': username}, {'$pull': { 'followings': other_username }}) DB.users.find_one_and_update({'_id': other_username}, {'$pull': { 'followers': username }}) updated_user = UserModel.get_user(username, show_follower_pics=True, show_following_pics=True) updated_other_user = UserModel.get_user(other_username, show_follower_pics=True, show_following_pics=True) return updated_user, updated_other_user raise WriteError( f'Error in making {username} unfollow {other_username}. One or both users may not exist.' )
def test_check_retry_exception(): msg = "Error=16500, RetryAfterMs=125, Details=" details = {"errmsg": msg} e = WriteError(msg, code=16500, details=details) delay = ShylockMotorAsyncIOBackend._check_retry_exception(e) assert delay == 0.125
def remove_user(username): resp = DB.users.find_one_and_delete({'_id': username}) if resp: return resp raise WriteError(f'Error in removing {username}. User may not exist.')