コード例 #1
0
ファイル: test_object.py プロジェクト: xanixon/fluiddb
    def testSearchAboutValueUsesTheCache(self):
        """
        L{ObjectAPI.search} uses the cache to get the results of
        C{fluiddb/about = "..."} queries if they're available.
        """
        objectID = self.objects.create(u'about')
        query = parseQuery('fluiddb/about = "about"')
        # Get the value once to store it in the cache.
        self.objects.search([query])

        # Remove the value from the store to check that we're using the cache.
        getAboutTagValues(values=[u'about']).remove()
        result = self.objects.search([query])
        result = yield result.get()
        self.assertEqual({query: set([objectID])}, result)
コード例 #2
0
    def create(self, value=None):
        """Create a new object.

        If the about C{value} already exists, the matching object ID will be
        returned.  Otherwise, a new one is created.  An L{AboutTagValue} is
        not created if C{value} is not provided.

        @param value: Optionally, an L{AboutTagValue.value} to associate with
            the new object.
        @return: A L{UUID} representing the object ID for the exsiting object,
            if one matching the value already exists, or a new object ID.
        """
        if not value:
            return uuid4()

        from fluiddb.model.user import getUser

        existingValue = getAboutTagValues(values=[value]).one()
        if existingValue:
            return existingValue.objectID
        else:
            objectID = uuid4()
            updates = {objectID: {u'fluiddb/about': value}}
            self._factory.tagValues(getUser(u'fluiddb')).set(updates)
            createAboutTagValue(objectID, value)
            return objectID
コード例 #3
0
ファイル: object.py プロジェクト: fluidinfo/fluiddb
    def create(self, value=None):
        """Create a new object.

        If the about C{value} already exists, the matching object ID will be
        returned.  Otherwise, a new one is created.  An L{AboutTagValue} is
        not created if C{value} is not provided.

        @param value: Optionally, an L{AboutTagValue.value} to associate with
            the new object.
        @return: A L{UUID} representing the object ID for the exsiting object,
            if one matching the value already exists, or a new object ID.
        """
        if not value:
            return uuid4()

        from fluiddb.model.user import getUser

        existingValue = getAboutTagValues(values=[value]).one()
        if existingValue:
            return existingValue.objectID
        else:
            objectID = uuid4()
            updates = {objectID: {u'fluiddb/about': value}}
            self._factory.tagValues(getUser(u'fluiddb')).set(updates)
            createAboutTagValue(objectID, value)
            return objectID
コード例 #4
0
    def get(self, values):
        """Get object IDs matching C{fluiddb/about} tag values.

        @param values: A C{list} of C{fluiddb/about} tag values.
        @return: A C{dict} mapping C{fluiddb/about} tag values to object IDs.
        """
        result = getAboutTagValues(values=values)
        return dict(result.values(AboutTagValue.value, AboutTagValue.objectID))
コード例 #5
0
ファイル: object.py プロジェクト: fluidinfo/fluiddb
    def get(self, values):
        """Get object IDs matching C{fluiddb/about} tag values.

        @param values: A C{list} of C{fluiddb/about} tag values.
        @return: A C{dict} mapping C{fluiddb/about} tag values to object IDs.
        """
        result = getAboutTagValues(values=values)
        return dict(result.values(AboutTagValue.value, AboutTagValue.objectID))
コード例 #6
0
ファイル: test_value.py プロジェクト: xanixon/fluiddb
 def testGetAboutTagValues(self):
     """
     L{getAboutTagValues} returns all L{AboutTagValue}s in the database, by
     default.
     """
     value1 = self.store.add(AboutTagValue(uuid4(), u'foo'))
     value2 = self.store.add(AboutTagValue(uuid4(), u'bar'))
     self.assertEqual(sorted([value1, value2]), sorted(getAboutTagValues()))
コード例 #7
0
ファイル: test_value.py プロジェクト: xanixon/fluiddb
 def testGetAboutTagValuesWithObjectIDs(self):
     """
     When C{objectID}s are provided L{getAboutTagValues} returns
     matching C{AboutTagValue}s.
     """
     objectID1 = uuid4()
     objectID2 = uuid4()
     value = self.store.add(AboutTagValue(objectID1, u'foo'))
     self.store.add(AboutTagValue(objectID2, u'bar'))
     self.assertEqual(value, getAboutTagValues(objectIDs=[objectID1]).one())
コード例 #8
0
ファイル: comment.py プロジェクト: xanixon/fluiddb
    def update(self, importer, username, when, newText):
        """Updates the text of a comment.

        All object associations previously extracted from the old comment's
        text are removed and new associations extracted from the new text are
        added. Object associations not extracted from the text are kept.

        @param importer: A C{unicode} string giving the name of the importer.
        @param username: The C{unicode} username of the commenter.
        @param when: A C{datetime.datetime} instance.
        @param text: The new text for the comment.
        @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.
            }
        """
        # 1. Get the object ID of the comment object.
        isoTime = when.isoformat()
        commentObjectAbout = u'%s %s %s' % (importer, username, isoTime)
        aboutValue = getAboutTagValues(values=[commentObjectAbout]).one()
        if aboutValue is None:
            raise RuntimeError('Comment does not exist.')
        commentID = aboutValue.objectID

        # 2. Get the old text and url of the comment.
        result = self._tagValues.get(
            [commentID],
            [u'fluidinfo.com/info/text', u'fluidinfo.com/info/url'])
        oldText = result[commentID][u'fluidinfo.com/info/text'].value
        url = result[commentID][u'fluidinfo.com/info/url'].value

        # 3. Get abouts in comment's text.
        aboutsInText = self._extractAbouts(oldText)

        # 4. Get all the about values associated with the comment.
        store = getMainStore()
        allAbouts = store.find(
            AboutTagValue.value, CommentObjectLink.commentID == commentID,
            AboutTagValue.objectID == CommentObjectLink.objectID)

        # 5. Get abouts not in comment's text:
        aboutsNotInText = set(allAbouts) - set(aboutsInText)

        self.delete(importer, username, when)
        return self.create(newText, username, aboutsNotInText, importer, when,
                           url)
コード例 #9
0
ファイル: test_value.py プロジェクト: xanixon/fluiddb
 def testGetAboutTagValuesWithValuesAndObjectIDs(self):
     """
     When C{AboutValue.value}s and C{objectID}s are provided
     L{getAboutTagValues} returns matching C{AboutTagValue}s.
     """
     objectID1 = uuid4()
     objectID2 = uuid4()
     value1 = self.store.add(AboutTagValue(objectID1, u'foo'))
     value2 = self.store.add(AboutTagValue(objectID2, u'bar'))
     results = list(
         getAboutTagValues(values=[u'bar'], objectIDs=[objectID1]))
     self.assertEqual([value1, value2], results)
コード例 #10
0
ファイル: comment.py プロジェクト: fluidinfo/fluiddb
    def update(self, importer, username, when, newText):
        """Updates the text of a comment.

        All object associations previously extracted from the old comment's
        text are removed and new associations extracted from the new text are
        added. Object associations not extracted from the text are kept.

        @param importer: A C{unicode} string giving the name of the importer.
        @param username: The C{unicode} username of the commenter.
        @param when: A C{datetime.datetime} instance.
        @param text: The new text for the comment.
        @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.
            }
        """
        # 1. Get the object ID of the comment object.
        isoTime = when.isoformat()
        commentObjectAbout = u'%s %s %s' % (importer, username, isoTime)
        aboutValue = getAboutTagValues(values=[commentObjectAbout]).one()
        if aboutValue is None:
            raise RuntimeError('Comment does not exist.')
        commentID = aboutValue.objectID

        # 2. Get the old text and url of the comment.
        result = self._tagValues.get([commentID], [u'fluidinfo.com/info/text',
                                                   u'fluidinfo.com/info/url'])
        oldText = result[commentID][u'fluidinfo.com/info/text'].value
        url = result[commentID][u'fluidinfo.com/info/url'].value

        # 3. Get abouts in comment's text.
        aboutsInText = self._extractAbouts(oldText)

        # 4. Get all the about values associated with the comment.
        store = getMainStore()
        allAbouts = store.find(
            AboutTagValue.value,
            CommentObjectLink.commentID == commentID,
            AboutTagValue.objectID == CommentObjectLink.objectID)

        # 5. Get abouts not in comment's text:
        aboutsNotInText = set(allAbouts) - set(aboutsInText)

        self.delete(importer, username, when)
        return self.create(newText, username, aboutsNotInText, importer, when,
                           url)
コード例 #11
0
ファイル: comment.py プロジェクト: fluidinfo/fluiddb
    def delete(self, importer, username, when):
        """Delete a comment.

        @param importer: A C{unicode} string giving the name of the importer.
        @param username: The C{unicode} username of the commenter.
        @param when: A C{datetime.datetime} instance.
        @return: An C{int} count of the number of comments removed.
        """
        isoTime = when.isoformat()
        commentObjectAbout = u'%s %s %s' % (importer, username, isoTime)
        aboutValue = getAboutTagValues(values=[commentObjectAbout]).one()
        if aboutValue is None:
            return 0
        objectID = aboutValue.objectID
        self._tagValues.delete((objectID, path) for path in self.COMMENT_TAGS)
        return deleteComment(objectID)
コード例 #12
0
ファイル: comment.py プロジェクト: xanixon/fluiddb
    def delete(self, importer, username, when):
        """Delete a comment.

        @param importer: A C{unicode} string giving the name of the importer.
        @param username: The C{unicode} username of the commenter.
        @param when: A C{datetime.datetime} instance.
        @return: An C{int} count of the number of comments removed.
        """
        isoTime = when.isoformat()
        commentObjectAbout = u'%s %s %s' % (importer, username, isoTime)
        aboutValue = getAboutTagValues(values=[commentObjectAbout]).one()
        if aboutValue is None:
            return 0
        objectID = aboutValue.objectID
        self._tagValues.delete((objectID, path) for path in self.COMMENT_TAGS)
        return deleteComment(objectID)
コード例 #13
0
ファイル: test_object.py プロジェクト: fluidinfo/fluiddb
    def testCreateObjectWithAboutValue(self):
        """
        L{FacadeObjectAPI.createObject} always returns a valid C{UUID} in a
        C{str} for a new object ID if an about value is given and it doesn't
        already exist.
        """
        self.store.commit()

        with login(self.user.username, uuid4(), self.transact) as session:
            objectID = yield self.facade.createObject(session, about='foo')
            objectID = UUID(objectID)

        self.store.rollback()
        value = getAboutTagValues([objectID], [u'foo']).one()
        self.assertEqual(u'foo', value.value)

        tag = self.system.tags[u'fluiddb/about']
        value = getTagValues(values=[(objectID, tag.id)]).one()
        self.assertIdentical(self.system.users[u'fluiddb'], value.creator)
コード例 #14
0
ファイル: test_object.py プロジェクト: xanixon/fluiddb
    def testCreateObjectWithAboutValue(self):
        """
        L{FacadeObjectAPI.createObject} always returns a valid C{UUID} in a
        C{str} for a new object ID if an about value is given and it doesn't
        already exist.
        """
        self.store.commit()

        with login(self.user.username, uuid4(), self.transact) as session:
            objectID = yield self.facade.createObject(session, about='foo')
            objectID = UUID(objectID)

        self.store.rollback()
        value = getAboutTagValues([objectID], [u'foo']).one()
        self.assertEqual(u'foo', value.value)

        tag = self.system.tags[u'fluiddb/about']
        value = getTagValues(values=[(objectID, tag.id)]).one()
        self.assertIdentical(self.system.users[u'fluiddb'], value.creator)
コード例 #15
0
ファイル: checker.py プロジェクト: xanixon/fluiddb
    def check(self, tagValues):
        """Check a given L{TagValue}s for integrity errors.

        @param tagValues: A sequence of L{TagValue}s to be checked.
        """
        objectIDs = [tagValue.objectID for tagValue in tagValues]
        aboutTagValues = getAboutTagValues(objectIDs=objectIDs)
        aboutTagValues = dict((aboutTagValue.objectID, aboutTagValue)
                              for aboutTagValue in aboutTagValues)
        namespaces = dict((namespace.objectID, namespace)
                          for namespace in getNamespaces(objectIDs=objectIDs))
        users = dict(
            (user.objectID, user) for user in getUsers(objectIDs=objectIDs))
        tags = dict(
            (tag.objectID, tag) for tag in getTags(objectIDs=objectIDs))

        for tagValue in tagValues:
            self.checkAboutTagValue(tagValue, aboutTagValues)
            self.checkNamespaceValues(tagValue, namespaces)
            self.checkTagValues(tagValue, tags)
            self.checkUserValues(tagValue, users)
コード例 #16
0
ファイル: checker.py プロジェクト: fluidinfo/fluiddb
    def check(self, tagValues):
        """Check a given L{TagValue}s for integrity errors.

        @param tagValues: A sequence of L{TagValue}s to be checked.
        """
        objectIDs = [tagValue.objectID for tagValue in tagValues]
        aboutTagValues = getAboutTagValues(objectIDs=objectIDs)
        aboutTagValues = dict((aboutTagValue.objectID, aboutTagValue)
                              for aboutTagValue in aboutTagValues)
        namespaces = dict((namespace.objectID, namespace)
                          for namespace in getNamespaces(objectIDs=objectIDs))
        users = dict((user.objectID, user)
                     for user in getUsers(objectIDs=objectIDs))
        tags = dict((tag.objectID, tag)
                    for tag in getTags(objectIDs=objectIDs))

        for tagValue in tagValues:
            self.checkAboutTagValue(tagValue, aboutTagValues)
            self.checkNamespaceValues(tagValue, namespaces)
            self.checkTagValues(tagValue, tags)
            self.checkUserValues(tagValue, users)
コード例 #17
0
ファイル: checker.py プロジェクト: fluidinfo/fluiddb
def checkIntegrity(maxRowsPerQuery=10000):
    """
    Check the integrity of the database for cases which the database
    engine can't detect.

    @param maxRowsPerQuery: Limit the number of rows fetched by SQL queries to
        avoid excessive use of memory.
    """
    results = _splitResult(getNamespaces(), Namespace.id, maxRowsPerQuery)
    for result in results:
        namespaces = list(result)
        NamespaceIntegrityChecker().check(namespaces)

    results = _splitResult(getTags(), Tag.id, maxRowsPerQuery)
    for result in results:
        tags = list(result)
        TagIntegrityChecker().check(tags)

    results = _splitResult(getUsers(), User.id, maxRowsPerQuery)
    for result in results:
        users = list(result)
        UserIntegrityChecker().check(users)

    results = _splitResult(getAboutTagValues(), AboutTagValue.objectID,
                           maxRowsPerQuery)
    for result in results:
        aboutTagValues = list(result)
        AboutTagValueIntegrityChecker().check(aboutTagValues)

    # In the case of TagValues we limit the query to only tag paths starting
    # with "fluiddb" because these are the only ones we're checking and we
    # don't want a huge result.
    store = getMainStore()
    result = store.find(TagValue,
                        TagValue.tagID == Tag.id,
                        Tag.path.startswith(u'fluiddb/'))
    results = _splitResult(getTagValues(), TagValue.id, maxRowsPerQuery)
    for result in results:
        tagValues = list(result)
        TagValueIntegrityChecker().check(tagValues)
コード例 #18
0
ファイル: checker.py プロジェクト: xanixon/fluiddb
def checkIntegrity(maxRowsPerQuery=10000):
    """
    Check the integrity of the database for cases which the database
    engine can't detect.

    @param maxRowsPerQuery: Limit the number of rows fetched by SQL queries to
        avoid excessive use of memory.
    """
    results = _splitResult(getNamespaces(), Namespace.id, maxRowsPerQuery)
    for result in results:
        namespaces = list(result)
        NamespaceIntegrityChecker().check(namespaces)

    results = _splitResult(getTags(), Tag.id, maxRowsPerQuery)
    for result in results:
        tags = list(result)
        TagIntegrityChecker().check(tags)

    results = _splitResult(getUsers(), User.id, maxRowsPerQuery)
    for result in results:
        users = list(result)
        UserIntegrityChecker().check(users)

    results = _splitResult(getAboutTagValues(), AboutTagValue.objectID,
                           maxRowsPerQuery)
    for result in results:
        aboutTagValues = list(result)
        AboutTagValueIntegrityChecker().check(aboutTagValues)

    # In the case of TagValues we limit the query to only tag paths starting
    # with "fluiddb" because these are the only ones we're checking and we
    # don't want a huge result.
    store = getMainStore()
    result = store.find(TagValue, TagValue.tagID == Tag.id,
                        Tag.path.startswith(u'fluiddb/'))
    results = _splitResult(getTagValues(), TagValue.id, maxRowsPerQuery)
    for result in results:
        tagValues = list(result)
        TagValueIntegrityChecker().check(tagValues)
コード例 #19
0
ファイル: test_object.py プロジェクト: xanixon/fluiddb
    def testGetUsesTheCache(self):
        """
        L{ObjectAPI.get} returns a C{dict} that maps L{AboutTagValue.value}s
        to object IDs.
        """
        objectID = uuid4()
        aboutValue = createAboutTagValue(objectID, u'Hello world!')

        # The first time the value is fetched from the DB.
        self.assertEqual({u'Hello world!': objectID},
                         self.objects.get([u'Hello world!']))

        # Change the value without updating the cache.
        aboutValue.value = u'Different'

        # Check the object is not in the Data Base anymore.
        result = getAboutTagValues(values=[u'Hello world!'])
        self.assertIdentical(None, result.one())

        # Check the value is fetched from the cache this time.
        self.assertEqual({u'Hello world!': objectID},
                         self.objects.get([u'Hello world!']))
コード例 #20
0
ファイル: comment.py プロジェクト: fluidinfo/fluiddb
    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
コード例 #21
0
ファイル: unfollow_urls.py プロジェクト: fluidinfo/fluiddb
        print 'Examining objects followed by', username

        followTag = username + u'/follows'
        result = store.find(TagValue.objectID,
                            TagValue.tagID == Tag.id,
                            Tag.path == followTag,
                            TagValue.creationTime > OLDER_THAN)

        allObjectIDs = list(result)
        print '\t Found', len(allObjectIDs), 'followed objects.'
        BATCH_SIZE = 100
        while allObjectIDs:
            objectIDs = allObjectIDs[:BATCH_SIZE]
            allObjectIDs = allObjectIDs[BATCH_SIZE:]
            result = getAboutTagValues(objectIDs=objectIDs)
            followedURLsObjectIDs = [about.objectID for about in result
                                     if URL_REGEX.match(about.value)]
            if not followedURLsObjectIDs:
                continue
            print '\t Unfollowing', len(followedURLsObjectIDs), 'URLs'
            count += len(followedURLsObjectIDs)
            TagValueAPI(user).delete([(objectID, followTag)
                                      for objectID in followedURLsObjectIDs])

            store.commit()
            if count > 50000:
                print '** Sleeping one minute. Giving a breath to the DIH. **'
                time.sleep(60)
                count = 0
    print 'Done.'
コード例 #22
0
ファイル: unfollow_urls.py プロジェクト: xanixon/fluiddb
            continue

        print 'Examining objects followed by', username

        followTag = username + u'/follows'
        result = store.find(TagValue.objectID, TagValue.tagID == Tag.id,
                            Tag.path == followTag,
                            TagValue.creationTime > OLDER_THAN)

        allObjectIDs = list(result)
        print '\t Found', len(allObjectIDs), 'followed objects.'
        BATCH_SIZE = 100
        while allObjectIDs:
            objectIDs = allObjectIDs[:BATCH_SIZE]
            allObjectIDs = allObjectIDs[BATCH_SIZE:]
            result = getAboutTagValues(objectIDs=objectIDs)
            followedURLsObjectIDs = [
                about.objectID for about in result
                if URL_REGEX.match(about.value)
            ]
            if not followedURLsObjectIDs:
                continue
            print '\t Unfollowing', len(followedURLsObjectIDs), 'URLs'
            count += len(followedURLsObjectIDs)
            TagValueAPI(user).delete([(objectID, followTag)
                                      for objectID in followedURLsObjectIDs])

            store.commit()
            if count > 50000:
                print '** Sleeping one minute. Giving a breath to the DIH. **'
                time.sleep(60)
コード例 #23
0
        systemValues = {}
        for tag in store.find(Tag, Tag.id.is_in(currentIDs)):
            root, rest = tag.path.split('/', 1)
            newPath = u'/'.join([root.lower(), rest])
            print 'Replacing tag', tag.path, 'with', newPath
            tag.path = newPath

            newAbout = 'Object for the attribute %s' % newPath
            systemValues[tag.objectID] = {
                u'fluiddb/about': newAbout,
                u'fluiddb/tags/path': newPath
            }

            print 'Fixing about tag value.'
            # Remove the new value if it exists to avoid integrity errors.
            result = getAboutTagValues(values=[newAbout])
            value = result.one()
            if value is not None:
                print 'ERROR about tag value already exists. Deleting it.'
                # Wipe all the tag values for that objectID
                result2 = store.find(TagValue,
                                     TagValue.objectID == value.objectID)
                result2.remove()
                result.remove()
            # Update the about value.
            value = getAboutTagValues(objectIDs=[tag.objectID]).one()
            if value is not None:
                value.value = newAbout
            else:
                createAboutTagValue(tag.objectID, newAbout)
コード例 #24
0
ファイル: comment.py プロジェクト: xanixon/fluiddb
    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
コード例 #25
0
            existingValue = getTagValues([(newObjectID, tagValue.tagID)]).one()
            if existingValue is not None:
                error = ('ERROR: Cannot migrate value {path} on {about} '
                         'because the value already exist.')
                print error.format(path=tagValue.tag.path,
                                   about=aboutValue.value.encode('utf-8'))
            else:
                tagValue.objectID = newObjectID

    store.commit()

    for i, user in enumerate(getUsers()):
        print 'Migrating', user.username.encode('utf-8'), 'object.'

        newAbout = u'@%s' % user.username
        aboutValue = getAboutTagValues(objectIDs=[user.objectID]).one()
        if aboutValue and aboutValue.value == newAbout:
            print 'User already migrated.'
            continue

        oldObjectID = user.objectID
        newObjectID = ObjectAPI(superUser).create(newAbout)
        result = store.find(TagValue,
                            TagValue.objectID == oldObjectID,
                            TagValue.tagID != aboutTag.id)
        for tagValue in result:
            existingValue = getTagValues([(newObjectID, tagValue.tagID)]).one()
            if existingValue is not None:
                error = ('ERROR: Cannot migrate value {path} on {username} '
                         'because the value already exist.')
                print error.format(path=tagValue.tag.path,