예제 #1
0
    def create(cls, **kwargs):
        if 'release_group' in kwargs:
            entity_id = kwargs.pop('release_group')
            entity_type = 'release_group'
        else:
            entity_id = kwargs.pop('entity_id')
            entity_type = kwargs.pop('entity_type')

        review = Review(entity_id=entity_id,
                        entity_type=entity_type,
                        user_id=kwargs.pop('user_id'),
                        language=kwargs.pop('language', None),
                        is_draft=kwargs.pop('is_draft', False),
                        license_id=kwargs.pop('license_id',
                                              DEFAULT_LICENSE_ID),
                        source=kwargs.pop('source', None),
                        source_url=kwargs.pop('source_url', None))
        db.session.add(review)
        db.session.flush()
        db.session.add(Revision(review_id=review.id, text=kwargs.pop('text')))

        if kwargs:
            db.session.rollback()
            raise TypeError('Unexpected **kwargs: %r' % kwargs)

        db.session.commit()
        cache.invalidate_namespace(Review.CACHE_NAMESPACE)

        return review
예제 #2
0
def update(review_id,
           *,
           drafted,
           text=None,
           rating=None,
           license_id=None,
           language=None,
           is_draft=None):
    # TODO: Get rid of `drafted` argument. This information about review should be retrieved inside this function.
    """Update a review.

    Args:
        review_id (uuid): ID of the review.
        drafted (bool): Whether the review is currently set as a draft.
        license_id (str): ID of a license that needs to be associated with this review.
        is_draft (bool): Whether to publish review (False) or keep it as a graft (True).
        text (str): Updated text part of a review.
        rating (int): Updated rating part of a review.
    """
    if text is None and rating is None:
        raise db_exceptions.BadDataException(
            "Text part and rating part of a review can not be None simultaneously"
        )

    updates = []
    updated_info = {}

    if license_id is not None:
        if not drafted:  # If trying to convert published review into draft
            raise db_exceptions.BadDataException(
                "Changing license of a published review is not allowed.")
        updates.append("license_id = :license_id")
        updated_info["license_id"] = license_id

    if language is not None:
        updates.append("language = :language")
        updated_info["language"] = language

    if is_draft is not None:
        if not drafted and is_draft:  # If trying to convert published review into draft
            raise db_exceptions.BadDataException(
                "Converting published reviews back to drafts is not allowed.")
        updates.append("is_draft = :is_draft")
        updated_info["is_draft"] = is_draft

    setstr = ", ".join(updates)
    query = sqlalchemy.text("""
        UPDATE review
           SET {setstr}
         WHERE id = :review_id
    """.format(setstr=setstr))

    if setstr:
        updated_info["review_id"] = review_id
        with db.engine.connect() as connection:
            connection.execute(query, updated_info)

    db_revision.create(review_id, text, rating)
    cache.invalidate_namespace(REVIEW_CACHE_NAMESPACE)
예제 #3
0
    def test_namespace_version(self):
        name = "test"
        self.assertIsNone(cache.get_namespace_version(name))
        self.assertEqual(cache.invalidate_namespace(name), 1)
        self.assertEqual(cache.get_namespace_version(name), 1)
        self.assertEqual(cache.invalidate_namespace(name), 2)
        self.assertEqual(cache.get_namespace_version(name), 2)

        with self.assertRaises(ValueError):
            cache.get_namespace_version(u"Тест")
        with self.assertRaises(ValueError):
            cache.get_namespace_version("Hello!")
예제 #4
0
    def test_namespace_version(self):
        name = "test"
        self.assertIsNone(cache.get_namespace_version(name))
        self.assertEqual(cache.invalidate_namespace(name), 1)
        self.assertEqual(cache.get_namespace_version(name), 1)
        self.assertEqual(cache.invalidate_namespace(name), 2)
        self.assertEqual(cache.get_namespace_version(name), 2)

        with self.assertRaises(ValueError):
            cache.get_namespace_version(u"Тест")
        with self.assertRaises(ValueError):
            cache.get_namespace_version("Hello!")
예제 #5
0
def update(review_id, *, drafted, text=None, rating=None, license_id=None, language=None, is_draft=None):
    # TODO: Get rid of `drafted` argument. This information about review should be retrieved inside this function.
    """Update a review.

    Args:
        review_id (uuid): ID of the review.
        drafted (bool): Whether the review is currently set as a draft.
        license_id (str): ID of a license that needs to be associated with this review.
        is_draft (bool): Whether to publish review (False) or keep it as a draft (True).
        text (str): Updated text part of a review.
        rating (int): Updated rating part of a review.
    """
    if text is None and rating is None:
        raise db_exceptions.BadDataException("Text part and rating part of a review can not be None simultaneously")

    updates = []
    updated_info = {}

    if license_id is not None:
        if not drafted:  # If trying to convert published review into draft
            raise db_exceptions.BadDataException("Changing license of a published review is not allowed.")
        updates.append("license_id = :license_id")
        updated_info["license_id"] = license_id

    if language is not None:
        updates.append("language = :language")
        updated_info["language"] = language

    if is_draft is not None:
        if not drafted and is_draft:  # If trying to convert published review into draft
            raise db_exceptions.BadDataException("Converting published reviews back to drafts is not allowed.")
        if drafted and not is_draft:
            published_on = datetime.now()
            updates.append("published_on = :published_on")
            updated_info["published_on"] = published_on
        updates.append("is_draft = :is_draft")
        updated_info["is_draft"] = is_draft

    setstr = ", ".join(updates)
    query = sqlalchemy.text("""
        UPDATE review
           SET {setstr}
         WHERE id = :review_id
    """.format(setstr=setstr))

    if setstr:
        updated_info["review_id"] = review_id
        with db.engine.connect() as connection:
            connection.execute(query, updated_info)

    db_revision.create(review_id, text, rating)
    cache.invalidate_namespace(REVIEW_CACHE_NAMESPACE)
예제 #6
0
    def update(self, **kwargs):
        """Update contents of this review.

        Returns:
            New revision of this review.
        """
        license_id = kwargs.pop('license_id', None)
        if license_id is not None:
            if not self.is_draft:  # If trying to convert published review into draft.
                raise BadRequest(
                    lazy_gettext(
                        "Changing license of a published review is not allowed."
                    ))
            self.license_id = license_id

        language = kwargs.pop('language', None)
        if language is not None:
            self.language = language

        is_draft = kwargs.pop('is_draft', None)
        if is_draft is not None:  # This should be done after all changes that depend on review being a draft.
            if not self.is_draft and is_draft:  # If trying to convert published review into draft.
                raise BadRequest(
                    lazy_gettext(
                        "Converting published reviews back to drafts is not allowed."
                    ))
            self.is_draft = is_draft

        new_revision = Revision.create(self.id, kwargs.pop('text'))
        cache.invalidate_namespace(Review.CACHE_NAMESPACE)

        if kwargs:
            # FIXME: Revision creation and other changes need to be rolled back
            # there, but there's a `commit` in Revision.create.
            raise TypeError('Unexpected **kwargs: %r' % kwargs)

        return new_revision
예제 #7
0
    def test_invalidate_namespace(self):
        namespace = "test"
        self.assertEqual(cache.invalidate_namespace(namespace), 1)
        self.assertEqual(cache.invalidate_namespace(namespace), 2)

        with self.assertRaises(ValueError):
            cache.invalidate_namespace(u"Тест")
        with self.assertRaises(ValueError):
            cache.invalidate_namespace("Hello!")
예제 #8
0
    def test_invalidate_namespace(self):
        namespace = "test"
        self.assertEqual(cache.invalidate_namespace(namespace), 1)
        self.assertEqual(cache.invalidate_namespace(namespace), 2)

        with self.assertRaises(ValueError):
            cache.invalidate_namespace(u"Тест")
        with self.assertRaises(ValueError):
            cache.invalidate_namespace("Hello!")
예제 #9
0
def create(*,
           entity_id,
           entity_type,
           user_id,
           is_draft,
           text=None,
           rating=None,
           language=DEFAULT_LANG,
           license_id=DEFAULT_LICENSE_ID,
           source=None,
           source_url=None):
    """Create a new review.

    Optionally, if a review is being imported from external source which needs
    a reference, you can specify `source` and `source_url` arguments. This
    reference will accompany the review.

    Args:
        entity_id (uuid): ID of an entity that review is for.
        entity_type (str): Entity type associated with the `entity_id`.
        user_id (uuid): ID of the reviewer.
        is_draft (bool): Whether this review is a draft (not shown to public).
        text (str): Text part of the review.
        rating (int): Rating part of the review.
        language (str): Language code that indicates which language the review
                        is written in.
        license_id (str): ID of the license.
        source (str): Name of the source of the review.
        source_url (str): URL pointing to the source of the review.

    Returns:
        Dictionary with the following structure
        {
            "id": uuid,
            "entity_id": uuid,
            "entity_type": str,
            "user_id": uuid,
            "user": dict,
            "edits": int,
            "is_draft": bool,
            "is_hidden": bool,
            "language": str,
            "license_id": str,
            "source": str,
            "source_url": str,
            "last_revision: dict,
            "votes": dict,
            "popularity": int,
            "text": str,
            "rating": int,
            "created": datetime,
            "license": dict,
        }
    """
    if text is None and rating is None:
        raise db_exceptions.BadDataException(
            "Text part and rating part of a review can not be None simultaneously"
        )
    if language not in supported_languages:
        raise ValueError("Language: {} is not supported".format(language))

    with db.engine.connect() as connection:
        result = connection.execute(sqlalchemy.text("""
            INSERT INTO review (id, entity_id, entity_type, user_id, edits, is_draft, is_hidden, license_id, language, source, source_url)
            VALUES (:id, :entity_id, :entity_type, :user_id, :edits, :is_draft, :is_hidden, :license_id, :language, :source, :source_url)
         RETURNING id;
        """), {  # noqa: E501
            "id": str(uuid.uuid4()),
            "entity_id": entity_id,
            "entity_type": entity_type,
            "user_id": user_id,
            "edits": 0,
            "is_draft": is_draft,
            "is_hidden": False,
            "language": language,
            "license_id": license_id,
            "source": source,
            "source_url": source_url,
        })
        review_id = result.fetchone()[0]
        # TODO(roman): It would be better to create review and revision in one transaction
        db_revision.create(review_id, text, rating)
        cache.invalidate_namespace(REVIEW_CACHE_NAMESPACE)
    return get_by_id(review_id)
예제 #10
0
def create(*, entity_id, entity_type, user_id, is_draft, text=None, rating=None,
           language=DEFAULT_LANG, license_id=DEFAULT_LICENSE_ID,
           source=None, source_url=None):
    """Create a new review.

    Optionally, if a review is being imported from external source which needs
    a reference, you can specify `source` and `source_url` arguments. This
    reference will accompany the review.

    Args:
        entity_id (uuid): ID of an entity that review is for.
        entity_type (str): Entity type associated with the `entity_id`.
        user_id (uuid): ID of the reviewer.
        is_draft (bool): Whether this review is a draft (not shown to public).
        text (str): Text part of the review.
        rating (int): Rating part of the review.
        language (str): Language code that indicates which language the review
                        is written in.
        license_id (str): ID of the license.
        source (str): Name of the source of the review.
        source_url (str): URL pointing to the source of the review.

    Returns:
        Dictionary with the following structure
        {
            "id": uuid,
            "entity_id": uuid,
            "entity_type": str,
            "user_id": uuid,
            "user": dict,
            "edits": int,
            "is_draft": bool,
            "is_hidden": bool,
            "language": str,
            "license_id": str,
            "source": str,
            "source_url": str,
            "last_revision: dict,
            "votes": dict,
            "popularity": int,
            "text": str,
            "rating": int,
            "license": dict,
            "published_on": datetime,
        }
    """
    if text is None and rating is None:
        raise db_exceptions.BadDataException("Text part and rating part of a review can not be None simultaneously")
    if language not in supported_languages:
        raise ValueError("Language: {} is not supported".format(language))
    if is_draft:
        published_on = None
    else:
        published_on = datetime.now()

    with db.engine.connect() as connection:
        result = connection.execute(sqlalchemy.text("""
            INSERT INTO review (id, entity_id, entity_type, user_id, edits, is_draft, is_hidden, license_id, language, source, source_url, published_on)
            VALUES (:id, :entity_id, :entity_type, :user_id, :edits, :is_draft, :is_hidden, :license_id, :language, :source, :source_url, :published_on)
         RETURNING id;
        """), {  # noqa: E501
            "id": str(uuid.uuid4()),
            "entity_id": entity_id,
            "entity_type": entity_type,
            "user_id": user_id,
            "edits": 0,
            "is_draft": is_draft,
            "is_hidden": False,
            "language": language,
            "license_id": license_id,
            "source": source,
            "source_url": source_url,
            "published_on": published_on,
        })
        review_id = result.fetchone()[0]
        # TODO(roman): It would be better to create review and revision in one transaction
        db_revision.create(review_id, text, rating)
        cache.invalidate_namespace(REVIEW_CACHE_NAMESPACE)
    return get_by_id(review_id)