Example #1
0
 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))))
Example #2
0
 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.')
Example #4
0
 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}'
             )
Example #5
0
    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.')
Example #6
0
 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)
Example #7
0
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.')
Example #9
0
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)
Example #10
0
 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.')
Example #11
0
 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.')
Example #12
0
 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.')
Example #13
0
 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.')
Example #14
0
 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}')
Example #15
0
 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.')
Example #16
0
 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))
Example #17
0
 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.')
Example #18
0
 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.'
     )
Example #19
0
 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.')
Example #20
0
 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.'
     )
Example #21
0
 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.'
     )
Example #22
0
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
Example #23
0
 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.')