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
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)
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!")
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)
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
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!")
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)
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)