示例#1
0
    def testCreateComment(self):
        """
        L{createComment} creates a L{Comment} object and the related
        L{CommentObjectLink} objects.
        """
        commentID = uuid4()
        target1 = uuid4()
        target2 = uuid4()
        createAboutTagValue(target1, u'target1')
        createAboutTagValue(target2, u'target2')
        timestamp = datetime.now()
        createComment(commentID, [target1, target2], u'username', timestamp)

        result = self.store.find(Comment, Comment.objectID == commentID)
        comment = result.one()
        self.assertNotIdentical(None, comment)
        self.assertEqual(u'username', comment.username)
        self.assertEqual(timestamp, comment.creationTime)

        result = self.store.find(CommentObjectLink,
                                 CommentObjectLink.commentID == commentID)
        targets = [relation.objectID for relation in result]
        self.assertEqual(sorted([target1, target2]), sorted(targets))

        comments = [relation.commentID for relation in result]
        self.assertEqual([commentID, commentID], comments)
示例#2
0
    def testCreateExistingComment(self):
        """
        L{createComment} with an existent comment ID will remove the old
        comment and relations before creating a new one.
        """
        commentID = uuid4()
        target1 = uuid4()
        target2 = uuid4()
        createAboutTagValue(target1, u'target1')
        createAboutTagValue(target2, u'target2')
        timestamp = datetime.now()
        createComment(commentID, [target1], u'username', timestamp)
        createComment(commentID, [target2], u'otheruser', timestamp)

        result = self.store.find(Comment, Comment.objectID == commentID)
        comment = result.one()
        self.assertNotIdentical(None, comment)
        self.assertEqual(u'otheruser', comment.username)
        self.assertEqual(timestamp, comment.creationTime)

        result = self.store.find(CommentObjectLink,
                                 CommentObjectLink.commentID == commentID)
        self.assertEqual([target2], [relation.objectID for relation in result])
        comments = [relation.commentID for relation in result]
        self.assertEqual([commentID], comments)
示例#3
0
    def testCreateExistingComment(self):
        """
        L{createComment} with an existent comment ID will remove the old
        comment and relations before creating a new one.
        """
        commentID = uuid4()
        target1 = uuid4()
        target2 = uuid4()
        createAboutTagValue(target1, u'target1')
        createAboutTagValue(target2, u'target2')
        timestamp = datetime.now()
        createComment(commentID, [target1], u'username', timestamp)
        createComment(commentID, [target2], u'otheruser', timestamp)

        result = self.store.find(Comment, Comment.objectID == commentID)
        comment = result.one()
        self.assertNotIdentical(None, comment)
        self.assertEqual(u'otheruser', comment.username)
        self.assertEqual(timestamp, comment.creationTime)

        result = self.store.find(CommentObjectLink,
                                 CommentObjectLink.commentID == commentID)
        self.assertEqual([target2], [relation.objectID for relation in result])
        comments = [relation.commentID for relation in result]
        self.assertEqual([commentID], comments)
示例#4
0
    def testCreateComment(self):
        """
        L{createComment} creates a L{Comment} object and the related
        L{CommentObjectLink} objects.
        """
        commentID = uuid4()
        target1 = uuid4()
        target2 = uuid4()
        createAboutTagValue(target1, u'target1')
        createAboutTagValue(target2, u'target2')
        timestamp = datetime.now()
        createComment(commentID, [target1, target2], u'username', timestamp)

        result = self.store.find(Comment, Comment.objectID == commentID)
        comment = result.one()
        self.assertNotIdentical(None, comment)
        self.assertEqual(u'username', comment.username)
        self.assertEqual(timestamp, comment.creationTime)

        result = self.store.find(CommentObjectLink,
                                 CommentObjectLink.commentID == commentID)
        targets = [relation.objectID for relation in result]
        self.assertEqual(sorted([target1, target2]), sorted(targets))

        comments = [relation.commentID for relation in result]
        self.assertEqual([commentID, commentID], comments)
示例#5
0
    def testCreateCommentWithoutTimestamp(self):
        """
        L{createComment} uses C{now} if no default creation time is provided.
        """
        commentID = uuid4()
        target1 = uuid4()
        target2 = uuid4()
        createAboutTagValue(target1, u'target1')
        createAboutTagValue(target2, u'target2')
        createComment(commentID, [target1, target2], u'username')

        result = self.store.find(Comment, Comment.objectID == commentID)
        comment = result.one()
        self.assertNotIdentical(None, comment)
        self.assertEqual(u'username', comment.username)
        self.assertNotIdentical(None, comment.creationTime)
示例#6
0
    def testCreateCommentWithoutTimestamp(self):
        """
        L{createComment} uses C{now} if no default creation time is provided.
        """
        commentID = uuid4()
        target1 = uuid4()
        target2 = uuid4()
        createAboutTagValue(target1, u'target1')
        createAboutTagValue(target2, u'target2')
        createComment(commentID, [target1, target2], u'username')

        result = self.store.find(Comment, Comment.objectID == commentID)
        comment = result.one()
        self.assertNotIdentical(None, comment)
        self.assertEqual(u'username', comment.username)
        self.assertNotIdentical(None, comment.creationTime)
示例#7
0
    def testDeleteComment(self):
        """
        L{deleteComment} removes a L{Comment} object and its related
        L{CommentObjectLink} objects.
        """
        commentID = uuid4()
        target1 = uuid4()
        target2 = uuid4()
        createAboutTagValue(target1, u'target1')
        createAboutTagValue(target2, u'target2')
        timestamp = datetime.now()
        createComment(commentID, [target1, target2], u'username', timestamp)

        self.assertEqual(1, deleteComment(commentID))

        # The entry in the comments table must be gone.
        result = self.store.find(Comment, Comment.objectID == commentID)
        self.assertTrue(result.is_empty())

        # The entries in the comment object link table must be gone.
        result = self.store.find(CommentObjectLink,
                                 CommentObjectLink.commentID == commentID)
        self.assertTrue(result.is_empty())
示例#8
0
    def testDeleteComment(self):
        """
        L{deleteComment} removes a L{Comment} object and its related
        L{CommentObjectLink} objects.
        """
        commentID = uuid4()
        target1 = uuid4()
        target2 = uuid4()
        createAboutTagValue(target1, u'target1')
        createAboutTagValue(target2, u'target2')
        timestamp = datetime.now()
        createComment(commentID, [target1, target2], u'username', timestamp)

        self.assertEqual(1, deleteComment(commentID))

        # The entry in the comments table must be gone.
        result = self.store.find(Comment, Comment.objectID == commentID)
        self.assertTrue(result.is_empty())

        # The entries in the comment object link table must be gone.
        result = self.store.find(CommentObjectLink,
                                 CommentObjectLink.commentID == commentID)
        self.assertTrue(result.is_empty())
示例#9
0
    def create(self,
               text,
               username,
               about=None,
               importer=None,
               when=None,
               url=None):
        """Create a new comment.

        @param text: The C{unicode} comment text.
        @param username: the C{unicode} username of the commenter.
        @param about: Optionally, a C{list} of C{unicode} values the comment is
            about.
        @param importer: A C{unicode} string giving the name of the importer.
        @param when: A C{datetime.datetime} instance or C{None} if the
            current time should be used.
        @param url: A C{str} URL or C{None} if there is no URL associated with
            this comment.
        @raise L{FeatureError}: if (1) the comment text is C{None} or is all
            whitespace, or (2) if the importer name contains the separator
            (space) that we use in the about value for comment objects.
        @return: A C{dict} as follows:
            {
                fluidinfo.com/info/about: A C{list} of all the about values
                    (i.e., URLs and hashtags) in the comment text, including
                    the thing the comment was about (if anything). The hashtags
                    are in lowercase.
                fluidinfo.com/info/timestamp: The C{int} UTC timestamp (seconds
                    since the epoch) the comment was created at.
                fluidinfo.com/info/url: The C{url}, as received.
                fluidinfo.com/info/username: The C{username}, as received.
            }
        """
        if not text or text.strip() == '':
            raise FeatureError('Comment text non-existent or just whitespace.')

        if importer:
            if ' ' in importer:
                raise FeatureError('Comment importer name contains a space.')
        else:
            importer = u'fluidinfo.com'

        when = when or datetime.utcnow()
        floatTime = timegm(when.utctimetuple()) + float(when.strftime('0.%f'))
        isoTime = when.isoformat()

        if not url:
            url = 'https://fluidinfo.com/comment/%s/%s/%s' % (
                importer, username, isoTime)

        # Put all the explicit about values into a list called abouts. Items
        # are stripped and those that are not URLs are lowercased.
        abouts = []
        if about:
            for item in map(unicode.strip, about):
                abouts.append(item if URL_REGEX.match(item) else item.lower())
        abouts.extend(self._extractAbouts(text))
        abouts = uniqueList(abouts)

        commentObjectAbout = u'%s %s %s' % (importer, username, isoTime)
        commentID = self._objects.create(commentObjectAbout)

        values = {
            u'fluidinfo.com/info/about': abouts,
            u'fluidinfo.com/info/username': username,
            u'fluidinfo.com/info/text': text,
            u'fluidinfo.com/info/url': url,
            u'fluidinfo.com/info/timestamp': floatTime
        }
        self._tagValues.set({commentID: values})

        if abouts:
            # Get all the object IDs of the target objects. If an object does
            # not exist, create it.
            result = getAboutTagValues(values=abouts)
            existingObjects = dict(
                result.values(AboutTagValue.value, AboutTagValue.objectID))
            missingAbouts = set(abouts) - set(existingObjects.iterkeys())
            for aboutValue in missingAbouts:
                existingObjects[aboutValue] = self._objects.create(aboutValue)
            createComment(commentID, existingObjects.values(), username, when)
        return values
示例#10
0
    def create(self, text, username, about=None, importer=None, when=None,
               url=None):
        """Create a new comment.

        @param text: The C{unicode} comment text.
        @param username: the C{unicode} username of the commenter.
        @param about: Optionally, a C{list} of C{unicode} values the comment is
            about.
        @param importer: A C{unicode} string giving the name of the importer.
        @param when: A C{datetime.datetime} instance or C{None} if the
            current time should be used.
        @param url: A C{str} URL or C{None} if there is no URL associated with
            this comment.
        @raise L{FeatureError}: if (1) the comment text is C{None} or is all
            whitespace, or (2) if the importer name contains the separator
            (space) that we use in the about value for comment objects.
        @return: A C{dict} as follows:
            {
                fluidinfo.com/info/about: A C{list} of all the about values
                    (i.e., URLs and hashtags) in the comment text, including
                    the thing the comment was about (if anything). The hashtags
                    are in lowercase.
                fluidinfo.com/info/timestamp: The C{int} UTC timestamp (seconds
                    since the epoch) the comment was created at.
                fluidinfo.com/info/url: The C{url}, as received.
                fluidinfo.com/info/username: The C{username}, as received.
            }
        """
        if not text or text.strip() == '':
            raise FeatureError('Comment text non-existent or just whitespace.')

        if importer:
            if ' ' in importer:
                raise FeatureError('Comment importer name contains a space.')
        else:
            importer = u'fluidinfo.com'

        when = when or datetime.utcnow()
        floatTime = timegm(when.utctimetuple()) + float(when.strftime('0.%f'))
        isoTime = when.isoformat()

        if not url:
            url = 'https://fluidinfo.com/comment/%s/%s/%s' % (
                importer, username, isoTime)

        # Put all the explicit about values into a list called abouts. Items
        # are stripped and those that are not URLs are lowercased.
        abouts = []
        if about:
            for item in map(unicode.strip, about):
                abouts.append(item if URL_REGEX.match(item) else item.lower())
        abouts.extend(self._extractAbouts(text))
        abouts = uniqueList(abouts)

        commentObjectAbout = u'%s %s %s' % (importer, username, isoTime)
        commentID = self._objects.create(commentObjectAbout)

        values = {u'fluidinfo.com/info/about': abouts,
                  u'fluidinfo.com/info/username': username,
                  u'fluidinfo.com/info/text': text,
                  u'fluidinfo.com/info/url': url,
                  u'fluidinfo.com/info/timestamp': floatTime}
        self._tagValues.set({commentID: values})

        if abouts:
            # Get all the object IDs of the target objects. If an object does
            # not exist, create it.
            result = getAboutTagValues(values=abouts)
            existingObjects = dict(result.values(AboutTagValue.value,
                                                 AboutTagValue.objectID))
            missingAbouts = set(abouts) - set(existingObjects.iterkeys())
            for aboutValue in missingAbouts:
                existingObjects[aboutValue] = self._objects.create(aboutValue)
            createComment(commentID, existingObjects.values(), username, when)
        return values