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
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)
def testCheckIntegrityChecksErrorInAllRows(self): """ L{checkIntegrity} should check for integrity errors in L{Namespace}s, L{Tag}s, L{User}s, L{AboutTagValue}s and L{TagValue}s. """ createSystemData() [(userObjectID, _)] = UserAPI().create([(u'user', u'pass', u'Name', u'*****@*****.**')]) user = getUser(u'user') result = NamespaceAPI(user).create([(u'user/namespace', u'description') ]) [(namespaceObjectID, _)] = result [(tagObjectID, _)] = TagAPI(user).create([(u'user/tag', u'description') ]) objectID1 = uuid4() objectID2 = uuid4() createAboutTagValue(objectID1, u'Bad about tag') TagValueAPI(user).set({objectID2: {u'fluiddb/about': 'about value'}}) TagValueAPI(user).delete([(userObjectID, u'fluiddb/users/username')]) TagValueAPI(user).delete([(namespaceObjectID, u'fluiddb/namespaces/path')]) TagValueAPI(user).delete([(tagObjectID, u'fluiddb/tags/description')]) checkIntegrity() self.assertEqual( "Integrity Error in namespace u'user/namespace': " 'Path tag is missing.\n' "Integrity Error in tag u'user/tag': Description tag is missing.\n" "Integrity Error in user u'user': Username tag is missing.\n" "Integrity Error in object %s: AboutTagValue doesn't have an " 'associated TagValue.\n' "Integrity Error in object %s: fluiddb/about TagValue doesn't " 'have an associated AboutTagValue.\n' % (objectID1, objectID2), self.log.getvalue())
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)
def testCreateDuplicateAboutTagValue(self): """ L{ObjectAPI.create} returns the C{objectID} for an L{AboutTagValue} if it already exists in the database. """ objectID1 = uuid4() createAboutTagValue(objectID1, u'A fancy about tag value') objectID2 = self.objects.create(u'A fancy about tag value') self.assertEqual(objectID1, objectID2)
def createDirtyObject(self, about=None): """Helper function to create an object. @param about: Optionally, an about value for the object. """ objectID = uuid4() if about: createAboutTagValue(objectID, about) return objectID
def testGet(self): """ L{ObjectAPI.get} returns a C{dict} that maps L{AboutTagValue.value}s to object IDs. """ objectID = uuid4() createAboutTagValue(objectID, u'Hello world!') self.assertEqual({u'Hello world!': objectID}, self.objects.get([u'Hello world!']))
def testCreateObjectWithDuplicateAboutValue(self): """ L{FacadeObjectAPI.createObject} returns a valid C{UUID} in a C{str} for an existing object ID if an about value is given and already exists in the database. """ objectID = uuid4() createAboutTagValue(objectID, u'bar') values = {objectID: {u'fluiddb/about': u'bar'}} SecureTagValueAPI(self.system.superuser).set(values) self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: resultObjectID = yield self.facade.createObject(session, about='bar') self.assertEqual(str(objectID), resultObjectID)
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)
def _resolveAboutQueries(self, queries, implicitCreate): """ Find object IDs matching specified C{fluiddb/about == "..."} L{Query}s. @param queries: A sequence of L{Query}s to resolve. @param implicitCreate: A flag indicating if nonexistent objects should be created. """ from fluiddb.model.user import getUser results = {} aboutValues = set() queriesByAboutValue = {} for query in queries: aboutValue = query.rootNode.right.value if not isinstance(aboutValue, unicode): # Search errors should be raised by the asynchronous # SearchResult.get(). results[query] = SearchError('Invalid about value type.') continue aboutValues.add(aboutValue) queriesByAboutValue[aboutValue] = query if aboutValues: objectsByAbout = self._factory.objects(self._user).get(aboutValues) # Create non existent objects if the option is given. if implicitCreate: existingAboutValues = set(objectsByAbout) missingAboutValues = aboutValues - existingAboutValues updates = {} for aboutValue in missingAboutValues: objectID = uuid4() updates[objectID] = {u'fluiddb/about': aboutValue} createAboutTagValue(objectID, aboutValue) objectsByAbout[aboutValue] = objectID if missingAboutValues: # FIXME We should use cachingGetUser here when # possible. -jkakar admin = getUser(u'fluiddb') self._factory.tagValues(admin).set(updates) for aboutValue in aboutValues: objectID = objectsByAbout.get(aboutValue) query = queriesByAboutValue[aboutValue] results[query] = set([objectID]) if objectID else set() return results
def testAboutValueWithoutAboutTagValue(self): """ L{TagValueIntegrityChecker.check} logs an error if a given L{TagValue} for fluiddb/about doesn't have an associated L{AboutTagValue} row. """ tag = self.system.tags[u'fluiddb/about'] tagValue1 = createTagValue(self.superuser.id, tag.id, uuid4(), u'Test object 1') tagValue2 = createTagValue(self.superuser.id, tag.id, uuid4(), u'Test object 2') createAboutTagValue(tagValue2.objectID, u'Test object 2') self.checker.check([tagValue1, tagValue2]) self.assertEqual( 'Integrity Error in object %s: ' "fluiddb/about TagValue doesn't have an associated " 'AboutTagValue.\n' % tagValue1.objectID, self.log.getvalue())
def testAboutTagValueWithoutValue(self): """ L{AboutTagValueIntegrityChecker.check} logs an error if the given L{AboutTagValue} doesn't have an associated L{TagValue}. """ object1 = uuid4() object2 = uuid4() aboutTagValue1 = createAboutTagValue(object1, u'Test object 1') aboutTagValue2 = createAboutTagValue(object2, u'Test object 2') createTagValue(self.superuser.id, self.aboutTag.id, object2, u'Test object 2') self.checker.check([aboutTagValue1, aboutTagValue2]) self.assertEqual( 'Integrity Error in object %s: ' "AboutTagValue doesn't have an associated TagValue.\n" % object1, self.log.getvalue())
def testCreateTagValueAddsToDatabase(self): """ L{createAboutTagValue} automatically adds the new L{AboutTagValue} to the database. """ objectID = uuid4() value = createAboutTagValue(objectID, u'An about tag value') self.assertIdentical(value, self.store.find(AboutTagValue).one())
def testAboutTagValueWithoutValue(self): """ L{AboutTagValueIntegrityChecker.check} logs an error if the given L{AboutTagValue} doesn't have an associated L{TagValue}. """ object1 = uuid4() object2 = uuid4() aboutTagValue1 = createAboutTagValue(object1, u'Test object 1') aboutTagValue2 = createAboutTagValue(object2, u'Test object 2') createTagValue(self.superuser.id, self.aboutTag.id, object2, u'Test object 2') self.checker.check([aboutTagValue1, aboutTagValue2]) self.assertEqual('Integrity Error in object %s: ' "AboutTagValue doesn't have an associated TagValue.\n" % object1, self.log.getvalue())
def testAboutValueWithoutAboutTagValue(self): """ L{TagValueIntegrityChecker.check} logs an error if a given L{TagValue} for fluiddb/about doesn't have an associated L{AboutTagValue} row. """ tag = self.system.tags[u'fluiddb/about'] tagValue1 = createTagValue(self.superuser.id, tag.id, uuid4(), u'Test object 1') tagValue2 = createTagValue(self.superuser.id, tag.id, uuid4(), u'Test object 2') createAboutTagValue(tagValue2.objectID, u'Test object 2') self.checker.check([tagValue1, tagValue2]) self.assertEqual('Integrity Error in object %s: ' "fluiddb/about TagValue doesn't have an associated " 'AboutTagValue.\n' % tagValue1.objectID, self.log.getvalue())
def testAboutTagValueWithWrongValue(self): """ L{AboutTagValueIntegrityChecker.check} logs an error if the given L{AboutTagValue} and its L{TagValue} dont match. """ object1 = uuid4() object2 = uuid4() aboutTagValue1 = createAboutTagValue(object1, u'Test object 1') createTagValue(self.superuser.id, self.aboutTag.id, object1, u'Wrong tag value') aboutTagValue2 = createAboutTagValue(object2, u'Test object 2') createTagValue(self.superuser.id, self.aboutTag.id, object2, u'Test object 2') self.checker.check([aboutTagValue1, aboutTagValue2]) self.assertEqual( 'Integrity Error in object %s: ' "AboutTagValue doesn't match its TagValue.\n" % object1, self.log.getvalue())
def testAboutTagValueWithWrongValue(self): """ L{AboutTagValueIntegrityChecker.check} logs an error if the given L{AboutTagValue} and its L{TagValue} dont match. """ object1 = uuid4() object2 = uuid4() aboutTagValue1 = createAboutTagValue(object1, u'Test object 1') createTagValue(self.superuser.id, self.aboutTag.id, object1, u'Wrong tag value') aboutTagValue2 = createAboutTagValue(object2, u'Test object 2') createTagValue(self.superuser.id, self.aboutTag.id, object2, u'Test object 2') self.checker.check([aboutTagValue1, aboutTagValue2]) self.assertEqual('Integrity Error in object %s: ' "AboutTagValue doesn't match its TagValue.\n" % object1, self.log.getvalue())
def testGetObjectWithAboutValue(self): """ L{FacadeObjectAPI.getObject} returns a L{TObjectInfo} with the L{Tag.path}s for which the L{User} has L{Operation.READ_TAG_VALUE}, and the L{AboutTagValue.value} if it has one and C{showAbout} is C{True}. """ objectID = uuid4() SecureTagAPI(self.user).create([(u'username/foo', u'A description')]) values = {objectID: {u'username/foo': u'bar'}} SecureTagValueAPI(self.user).set(values) aboutTag = self.system.tags[u'fluiddb/about'] createAboutTagValue(objectID, u'bar') createTagValue(self.user.id, aboutTag.id, objectID, u'about value') self.store.commit() with login(self.user.username, uuid4(), self.transact) as session: objectInfo = yield self.facade.getObject(session, str(objectID), showAbout=True) self.assertEqual([u'fluiddb/about', u'username/foo'], sorted(objectInfo.tagPaths)) self.assertEqual('about value', objectInfo.about)
def testCheckIntegrityChecksErrorInAllRows(self): """ L{checkIntegrity} should check for integrity errors in L{Namespace}s, L{Tag}s, L{User}s, L{AboutTagValue}s and L{TagValue}s. """ createSystemData() [(userObjectID, _)] = UserAPI().create([(u'user', u'pass', u'Name', u'*****@*****.**')]) user = getUser(u'user') result = NamespaceAPI(user).create([(u'user/namespace', u'description')]) [(namespaceObjectID, _)] = result [(tagObjectID, _)] = TagAPI(user).create([(u'user/tag', u'description')]) objectID1 = uuid4() objectID2 = uuid4() createAboutTagValue(objectID1, u'Bad about tag') TagValueAPI(user).set({objectID2: {u'fluiddb/about': 'about value'}}) TagValueAPI(user).delete([(userObjectID, u'fluiddb/users/username')]) TagValueAPI(user).delete([(namespaceObjectID, u'fluiddb/namespaces/path')]) TagValueAPI(user).delete([(tagObjectID, u'fluiddb/tags/description')]) checkIntegrity() self.assertEqual( "Integrity Error in namespace u'user/namespace': " 'Path tag is missing.\n' "Integrity Error in tag u'user/tag': Description tag is missing.\n" "Integrity Error in user u'user': Username tag is missing.\n" "Integrity Error in object %s: AboutTagValue doesn't have an " 'associated TagValue.\n' "Integrity Error in object %s: fluiddb/about TagValue doesn't " 'have an associated AboutTagValue.\n' % (objectID1, objectID2), self.log.getvalue())
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())
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!']))
def _createMetaData(self): """Create system data.""" superuser = self.users[u'fluiddb'] tags = self.tags for user in self._data['users']: userObjectID = self.users[user['username']].objectID aboutValue = u'@%s' % user['username'] createAboutTagValue(userObjectID, aboutValue) createTagValue(superuser.id, tags[u'fluiddb/about'].id, userObjectID, aboutValue) createTagValue(superuser.id, tags[u'fluiddb/users/username'].id, userObjectID, user['username']) createTagValue(superuser.id, tags[u'fluiddb/users/name'].id, userObjectID, user['name']) createTagValue(superuser.id, tags[u'fluiddb/users/email'].id, userObjectID, user['email']) createTagValue(superuser.id, tags[u'fluiddb/users/role'].id, userObjectID, str(user['role'])) for namespace in self._data['namespaces']: namespaceObjectID = self.namespaces[namespace['path']].objectID aboutValue = u'Object for the namespace %s' % namespace['path'] createAboutTagValue(namespaceObjectID, aboutValue) createTagValue(superuser.id, tags[u'fluiddb/about'].id, namespaceObjectID, aboutValue) createTagValue(superuser.id, tags[u'fluiddb/namespaces/path'].id, namespaceObjectID, namespace['path']) createTagValue(superuser.id, tags[u'fluiddb/namespaces/description'].id, namespaceObjectID, namespace['description']) for tag in self._data['tags']: tagObjectID = self.tags[tag['path']].objectID aboutValue = u'Object for the attribute %s' % tag['path'] createAboutTagValue(tagObjectID, aboutValue) createTagValue(superuser.id, tags[u'fluiddb/about'].id, tagObjectID, aboutValue) createTagValue(superuser.id, tags[u'fluiddb/tags/path'].id, tagObjectID, tag['path']) createTagValue(superuser.id, tags[u'fluiddb/tags/description'].id, tagObjectID, tag['description'])
def testCreateAboutTagValue(self): """L{createAboutTagValue} creates a new L{AboutTagValue}.""" objectID = uuid4() aboutTagValue = createAboutTagValue(objectID, u'An about tag Value') self.assertEqual(objectID, aboutTagValue.objectID) self.assertEqual(u'An about tag Value', aboutTagValue.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) print 'Fixing system values' tagValues.set(systemValues) print 'Touching objects.' result = store.find(TagValue.objectID, TagValue.tagID.is_in(currentIDs)) touchObjects(list(result.config(distinct=True))) touchObjects(systemValues.keys()) i += BATCH_SIZE currentIDs = tagsToFix[i:i + BATCH_SIZE] print 'Fixing namespaces.' i = 0