def testGetOpaqueValues(self): """ L{getOpaqueValues} returns L{OpaqueValue}s for the given L{TagValue}s. """ user = createUser(u'name', u'password', u'User', u'*****@*****.**') user.namespaceID = createNamespace(user, user.username, None).id tag = createTag(user, user.namespace, u'tag') value1 = createTagValue(user.id, tag.id, uuid4(), None) value2 = createTagValue(user.id, tag.id, uuid4(), None) self.store.commit() opaque1 = createOpaqueValue(value1.id, 'content1') opaque2 = createOpaqueValue(value2.id, 'content2') self.assertEqual(sorted([opaque1, opaque2]), sorted(getOpaqueValues([value1.id, value2.id])))
def testCreateOpaqueValueWithSameContent(self): """ L{createOpaqueValue} doesn't create duplicate L{OpaqueValue}s if the content is the same. """ user = createUser(u'name', u'password', u'User', u'*****@*****.**') user.namespaceID = createNamespace(user, user.username, None).id tag = createTag(user, user.namespace, u'tag') value1 = createTagValue(user.id, tag.id, uuid4(), None) value2 = createTagValue(user.id, tag.id, uuid4(), None) self.store.commit() createOpaqueValue(value1.id, 'content') createOpaqueValue(value2.id, 'content') fileID = sha256('content').hexdigest() result = self.store.find(OpaqueValue, OpaqueValue.fileID == fileID) self.assertNotIdentical(None, result.one()) result = self.store.find(OpaqueValueLink, OpaqueValueLink.fileID == fileID) self.assertEqual(2, result.count())
def testCreateOpaqueValue(self): """ L{createOpaqueValue} creates an L{OpaqueValue} and the corresponding L{OpaqueValueLink} referencing the given L{TagValue}. """ user = createUser(u'name', u'password', u'User', u'*****@*****.**') user.namespaceID = createNamespace(user, user.username, None).id tag = createTag(user, user.namespace, u'tag') value = createTagValue(user.id, tag.id, uuid4(), None) self.store.commit() createOpaqueValue(value.id, 'content') fileID = sha256('content').hexdigest() result = self.store.find(OpaqueValue, OpaqueValue.fileID == fileID).one() self.assertNotIdentical(None, result) self.assertEqual(fileID, result.fileID) self.assertEqual('content', result.content) result = self.store.find(OpaqueValueLink, OpaqueValueLink.fileID == fileID, OpaqueValueLink.valueID == value.id) self.assertNotIdentical(None, result.one())
def set(self, values): """Set or update L{TagValue}s. L{Tag}s that don't exist are created automatically before L{TagValue}s are stored. Associated L{TagPermission}s are created automatically with the system-wide default permissions. @param values: A C{dict} mapping object IDs to tags and values, matching the following format:: {<object-id>: {<path>: <value>, <path>: {'mime-type': <mime-type>, 'contents': <contents>}}} A binary L{TagValue} is represented using a different layout than other values types, as shown for the second value. @raise FeatureError: Raised if the given list of values is empty. @raise MalformedPathError: Raised if one of the given paths for a nonexistent tag is empty or has unacceptable characters. """ if not values: raise FeatureError("Can't set an empty list of tag values.") objectIDs = set(values.keys()) # Implicitly create missing tags, if there are any. paths = set() for tagValues in values.itervalues(): paths.update(tagValues.iterkeys()) tagIDs = dict(getTags(paths=paths).values(Tag.path, Tag.id)) existingPaths = set(tagIDs.iterkeys()) unknownPaths = paths - existingPaths if unknownPaths: tags = [(path, u'Object for the attribute %s' % path) for path in unknownPaths] self._factory.tags(self._user).create(tags) tagIDs = dict(getTags(paths=paths).values(Tag.path, Tag.id)) # Delete all existing tag values for the specified object IDs and # paths. deleteValues = [] for objectID in values: for path in values[objectID].iterkeys(): deleteValues.append((objectID, tagIDs[path])) getTagValues(deleteValues).remove() # Set new tag values for the specified object IDs and paths. for objectID in values: tagValues = values[objectID] for path, value in tagValues.iteritems(): tagID = tagIDs[path] if isinstance(value, dict): content = value['contents'] value = createTagValue(self._user.id, tagID, objectID, {'mime-type': value['mime-type'], 'size': len(content)}) # This is necessary to tell PostgreSQL that generates a # `value.id` immediately. value.id = AutoReload createOpaqueValue(value.id, content) else: createTagValue(self._user.id, tagID, objectID, value) touchObjects(objectIDs)
if __name__ == '__main__': store = setupStore('postgres:///fluidinfo', 'main') print __doc__ result = store.execute("""SELECT id, value FROM tag_values WHERE value LIKE '{%'""") for id, value in list(result): value = json.loads(str(value)) if u'file-id' not in value: print >> sys.stderr, 'Opaque value already migrated:', id continue print 'migrating', id, value[u'file-id'] filename = getFilename(value[u'file-id']) try: with open(filename, 'rb') as opaqueFile: content = opaqueFile.read() except IOError: print >> sys.stderr, 'File not found:', value[u'file-id'] continue tagValue = store.find(TagValue, TagValue.id == id).one() if tagValue is None: print >> sys.stderr, 'Tag value', id, 'is none.' continue tagValue.value = { 'mime-type': value['mime-type'], 'size': len(content) } createOpaqueValue(id, content) store.commit()
def set(self, values): """Set or update L{TagValue}s. L{Tag}s that don't exist are created automatically before L{TagValue}s are stored. Associated L{TagPermission}s are created automatically with the system-wide default permissions. @param values: A C{dict} mapping object IDs to tags and values, matching the following format:: {<object-id>: {<path>: <value>, <path>: {'mime-type': <mime-type>, 'contents': <contents>}}} A binary L{TagValue} is represented using a different layout than other values types, as shown for the second value. @raise FeatureError: Raised if the given list of values is empty. @raise MalformedPathError: Raised if one of the given paths for a nonexistent tag is empty or has unacceptable characters. """ if not values: raise FeatureError("Can't set an empty list of tag values.") objectIDs = set(values.keys()) # Implicitly create missing tags, if there are any. paths = set() for tagValues in values.itervalues(): paths.update(tagValues.iterkeys()) tagIDs = dict(getTags(paths=paths).values(Tag.path, Tag.id)) existingPaths = set(tagIDs.iterkeys()) unknownPaths = paths - existingPaths if unknownPaths: tags = [(path, u'Object for the attribute %s' % path) for path in unknownPaths] self._factory.tags(self._user).create(tags) tagIDs = dict(getTags(paths=paths).values(Tag.path, Tag.id)) # Delete all existing tag values for the specified object IDs and # paths. deleteValues = [] for objectID in values: for path in values[objectID].iterkeys(): deleteValues.append((objectID, tagIDs[path])) getTagValues(deleteValues).remove() # Set new tag values for the specified object IDs and paths. for objectID in values: tagValues = values[objectID] for path, value in tagValues.iteritems(): tagID = tagIDs[path] if isinstance(value, dict): content = value['contents'] value = createTagValue(self._user.id, tagID, objectID, { 'mime-type': value['mime-type'], 'size': len(content) }) # This is necessary to tell PostgreSQL that generates a # `value.id` immediately. value.id = AutoReload createOpaqueValue(value.id, content) else: createTagValue(self._user.id, tagID, objectID, value) touchObjects(objectIDs)
if __name__ == '__main__': store = setupStore('postgres:///fluidinfo', 'main') print __doc__ result = store.execute("""SELECT id, value FROM tag_values WHERE value LIKE '{%'""") for id, value in list(result): value = json.loads(str(value)) if u'file-id' not in value: print >>sys.stderr, 'Opaque value already migrated:', id continue print 'migrating', id, value[u'file-id'] filename = getFilename(value[u'file-id']) try: with open(filename, 'rb') as opaqueFile: content = opaqueFile.read() except IOError: print >>sys.stderr, 'File not found:', value[u'file-id'] continue tagValue = store.find(TagValue, TagValue.id == id).one() if tagValue is None: print >>sys.stderr, 'Tag value', id, 'is none.' continue tagValue.value = {'mime-type': value['mime-type'], 'size': len(content)} createOpaqueValue(id, content) store.commit()