Ejemplo n.º 1
0
    def delete(self, paths):
        """Delete L{Tag}s matching C{paths}.

        L{TagValue}s and permissions associated with the deleted L{Tag}s are
        removed by cascading deletes in the database schema.

        @param paths: A sequence of L{Tag.path}s.
        @return: A C{list} of C{(objectID, Tag.path)} 2-tuples representing the
            L{Tag}s that were removed.
        """
        if isgenerator(paths):
            paths = list(paths)
        result = getTags(paths=paths)
        deletedTagPaths = list(result.values(Tag.objectID, Tag.path))
        # Delete the fluiddb/tags/description tag values stored for removed
        # tags.  Associated TagValue's are removed by an ON DELETE CASCADE
        # trigger.
        self._factory.tagValues(self._user).delete(
            [(objectID, path) for objectID, _ in deletedTagPaths
             for path in [u'fluiddb/tags/description', u'fluiddb/tags/path']])

        # Touch all the objects for the given tag paths.
        objectIDs = list(getObjectIDs(paths))
        touchObjects(objectIDs)

        result.remove()
        return deletedTagPaths
Ejemplo n.º 2
0
    def get(self, paths, withDescriptions=None):
        """Get information about L{Tag}s matching C{paths}.

        @param paths: A sequence of L{Tag.path}s.
        @param withDescriptions: Optionally, a C{bool} indicating whether or
            not to include L{Tag} descriptions in the result.  Default is
            C{False}.
        @return: A C{dict} that maps L{Tag.path}s to C{dict}s with information
            about matching L{Tag}s, matching the following format::

              {<path>: {'id': <object-id>,
                        'description': <description>}}
        """
        if not paths:
            raise FeatureError("Can't retrieve an empty list of tags.")

        result = getTags(paths=paths)
        values = list(result.values(Tag.path, Tag.objectID))
        descriptions = (
            self._getDescriptions(objectID for path, objectID in values)
            if withDescriptions else None)

        tags = {}
        for path, objectID in values:
            value = {'id': objectID}
            if withDescriptions:
                value['description'] = descriptions.get(objectID, u'')
            tags[path] = value
        return tags
Ejemplo n.º 3
0
 def testGetTags(self):
     """L{getTags} returns all L{Tag}s in the database, by default."""
     user = createUser(u'username', u'password', u'User',
                       u'*****@*****.**')
     user.namespaceID = createNamespace(user, user.username, None).id
     tag = createTag(user, user.namespace, u'name')
     self.assertEqual(tag, getTags().one())
Ejemplo n.º 4
0
 def testCreateStoresTagPaths(self):
     """
     L{TagAPI.create} creates new C{fluiddb/tags/path} L{TagValue}s to store
     the specified L{Tag} paths.
     """
     values = [(u'username/tag', u'A tag description')]
     [(objectID, path)] = self.tags.create(values)
     tag = getTags(paths=[u'fluiddb/tags/path']).one()
     value = getTagValues([(objectID, tag.id)]).one()
     self.assertEqual(u'username/tag', value.value)
Ejemplo n.º 5
0
 def testCreateCreatesAboutTag(self):
     """
     L{UserAPI.create} creates new C{fluiddb/about} L{TagValue}s when
     creating new L{User}s.
     """
     values = [(u'username', u'secret', u'User', u'*****@*****.**')]
     [(objectID, username)] = self.users.create(values)
     tag = getTags(paths=[u'fluiddb/about']).one()
     value = getTagValues([(objectID, tag.id)]).one()
     self.assertEqual(u'@username', value.value)
Ejemplo n.º 6
0
 def testCreateCreatesAboutTag(self):
     """
     L{TagAPI.create} creates new C{fluiddb/about} L{TagValue}s when
     creating new L{Tag}s.
     """
     values = [(u'username/tag', u'A tag description')]
     [(objectID, path)] = self.tags.create(values)
     tag = getTags(paths=[u'fluiddb/about']).one()
     value = getTagValues([(objectID, tag.id)]).one()
     self.assertEqual(u'Object for the attribute username/tag', value.value)
Ejemplo n.º 7
0
 def testDeleteDoesNotDeleteOtherTags(self):
     """
     L{TagAPI.delete} removes just the L{Tag} is is asked to and not any
     other tags.
     """
     self.tags.create([(u'username/child1', u'A description')])
     self.tags.create([(u'username/child2', u'A description')])
     self.tags.delete([u'username/child1'])
     tag = getTags(paths=[u'username/child2']).one()
     self.assertEqual(u'username/child2', tag.path)
Ejemplo n.º 8
0
 def testDeleteDoesNotDeleteOtherTagsWhenPassedAGenerator(self):
     """
     L{TagAPI.delete} removes just the L{Tag} is is asked to and not any
     other tags when it is passed a generator (as opposed to a C{list}).
     """
     self.tags.create([(u'username/child1', u'A description')])
     self.tags.create([(u'username/child2', u'A description')])
     self.tags.delete(name for name in [u'username/child1'])
     tag = getTags(paths=[u'username/child2']).one()
     self.assertEqual(u'username/child2', tag.path)
Ejemplo n.º 9
0
 def testCreateCreatesAboutTag(self):
     """
     L{UserAPI.create} creates new C{fluiddb/about} L{TagValue}s when
     creating new L{User}s.
     """
     values = [(u'username', u'secret', u'User', u'*****@*****.**')]
     [(objectID, username)] = self.users.create(values)
     tag = getTags(paths=[u'fluiddb/about']).one()
     value = getTagValues([(objectID, tag.id)]).one()
     self.assertEqual(u'@username', value.value)
Ejemplo n.º 10
0
 def testCreateStoresNamespacePaths(self):
     """
     L{NamespaceAPI.create} creates new C{fluiddb/namespaces/path}
     L{TagValue}s to store the specified L{Namespace} paths.
     """
     values = [(u'username/namespace', u'A namespace description')]
     [(objectID, path)] = self.namespaces.create(values)
     tag = getTags(paths=[u'fluiddb/namespaces/path']).one()
     value = getTagValues([(objectID, tag.id)]).one()
     self.assertEqual(u'username/namespace', value.value)
Ejemplo n.º 11
0
 def testCreateStoresNamespaceDescriptions(self):
     """
     L{NamespaceAPI.create} creates new C{fluiddb/namespaces/description}
     L{TagValue}s to store the specified L{Namespace} descriptions.
     """
     values = [(u'username/namespace', u'A namespace description')]
     [(objectID, path)] = self.namespaces.create(values)
     tag = getTags(paths=[u'fluiddb/namespaces/description']).one()
     value = getTagValues([(objectID, tag.id)]).one()
     self.assertEqual(u'A namespace description', value.value)
Ejemplo n.º 12
0
 def testGetTagsWithPaths(self):
     """
     When L{Tag.path}s are provided L{getTags} returns matching L{Tag}s.
     """
     user = createUser(u'username', u'password', u'User',
                       u'*****@*****.**')
     user.namespaceID = createNamespace(user, user.username, None).id
     tag = createTag(user, user.namespace, u'name1')
     createTag(user, user.namespace, u'name2')
     result = getTags(paths=[u'username/name1'])
     self.assertIdentical(tag, result.one())
Ejemplo n.º 13
0
 def testCreateCreatesAboutTag(self):
     """
     L{NamespaceAPI.create} creates new C{fluiddb/about} L{TagValue}s when
     creating new L{Namespace}s.
     """
     values = [(u'username/namespace', u'A namespace description')]
     [(objectID, path)] = self.namespaces.create(values)
     tag = getTags(paths=[u'fluiddb/about']).one()
     value = getTagValues([(objectID, tag.id)]).one()
     self.assertEqual(u'Object for the namespace username/namespace',
                      value.value)
Ejemplo n.º 14
0
 def testDeleteKeepsTheAboutTag(self):
     """
     L{TagAPI.delete} keeps the C{fluiddb/about} tag value for the deleted
     tag.
     """
     values = [(u'username/tag', u'A tag description')]
     [(objectID, path)] = self.tags.create(values)
     self.tags.delete([u'username/tag'])
     tag = getTags(paths=[u'fluiddb/about']).one()
     value = getTagValues([(objectID, tag.id)]).one()
     self.assertEqual(u'Object for the attribute username/tag', value.value)
Ejemplo n.º 15
0
    def _getSystemTag(self, path):
        """Get a system L{Tag} showing an error if it doesn't exist.

        @param path: The path of the requested L{Tag}.
        @return The requested L{Tag}.
        """
        tag = getTags(paths=[path]).one()
        if not tag:
            logging.critical(
                'Fatal Error: system tag %r does not exist.' % path)
            sys.exit(1)
        return tag
Ejemplo n.º 16
0
 def testDeleteKeepsTheAboutTag(self):
     """
     L{NamespaceAPI.delete} keeps the C{fluiddb/about} tag value for the
     deleted namespace.
     """
     values = [(u'username/namespace', u'A namespace description')]
     [(objectID, path)] = self.namespaces.create(values)
     self.namespaces.delete([u'username/namespace'])
     tag = getTags(paths=[u'fluiddb/about']).one()
     value = getTagValues([(objectID, tag.id)]).one()
     self.assertEqual(u'Object for the namespace username/namespace',
                      value.value)
Ejemplo n.º 17
0
 def testDeleteKeepsTheAboutTag(self):
     """
     L{NamespaceAPI.delete} keeps the C{fluiddb/about} tag value for the
     deleted namespace.
     """
     values = [(u'username/namespace', u'A namespace description')]
     [(objectID, path)] = self.namespaces.create(values)
     self.namespaces.delete([u'username/namespace'])
     tag = getTags(paths=[u'fluiddb/about']).one()
     value = getTagValues([(objectID, tag.id)]).one()
     self.assertEqual(u'Object for the namespace username/namespace',
                      value.value)
Ejemplo n.º 18
0
    def _getSystemTag(self, path):
        """Get a system L{Tag} showing an error if it doesn't exist.

        @param path: The path of the requested L{Tag}.
        @return The requested L{Tag}.
        """
        tag = getTags(paths=[path]).one()
        if not tag:
            logging.critical('Fatal Error: system tag %r does not exist.' %
                             path)
            sys.exit(1)
        return tag
Ejemplo n.º 19
0
    def testDeleteInvalidatesCachedTagPermissions(self):
        """
        L{CachingTagAPI.delete} invalidates L{TagPermission}s to ensure the
        cache is always fresh.
        """
        self.tags.create([(u'username/tag', u'A tag')])
        tag = getTags(paths=[u'username/tag']).one()
        cache = PermissionCache()
        cache.saveTagPermissions({u'username/tag': tag.permission})

        self.tags.delete([u'username/tag'])
        cached = cache.getTagPermissions([u'username/tag'])
        self.assertEqual({}, cached.results)
        self.assertEqual([u'username/tag'], cached.uncachedValues)
Ejemplo n.º 20
0
    def testDeleteInvalidatesCachedTagPermissions(self):
        """
        L{CachingTagAPI.delete} invalidates L{TagPermission}s to ensure the
        cache is always fresh.
        """
        self.tags.create([(u'username/tag', u'A tag')])
        tag = getTags(paths=[u'username/tag']).one()
        cache = PermissionCache()
        cache.saveTagPermissions({u'username/tag': tag.permission})

        self.tags.delete([u'username/tag'])
        cached = cache.getTagPermissions([u'username/tag'])
        self.assertEqual({}, cached.results)
        self.assertEqual([u'username/tag'], cached.uncachedValues)
Ejemplo n.º 21
0
    def testCreateTag(self):
        """L{FacadeTagMixin.createTag} creates a new L{Tag}."""
        self.store.commit()
        with login(u'username', uuid4(), self.transact) as session:
            objectID = yield self.facade.createTag(
                session, u'username', u'tag', u'A tag.', 'ignored', 'ignored')
            self.assertNotIdentical(None, objectID)

        self.store.rollback()
        tag = getTags(paths=[u'username/tag']).one()
        self.assertIdentical(self.user, tag.creator)
        self.assertIdentical(self.user.namespace, tag.namespace)
        self.assertEqual(u'username/tag', tag.path)
        self.assertEqual(u'tag', tag.name)
        self.assertEqual(objectID, str(tag.objectID))
def migrate(store):
    # Find all the @name about values.
    result = store.execute('SELECT value, object_id'
                           '    FROM about_tag_values'
                           "    WHERE value LIKE '@%'")
    aboutValues = dict((value, UUID(objectID)) for value, objectID in result)
    logging.info('Loaded %d @name about values', len(aboutValues))

    # Remove all the links between comments and @name values.
    affectedComments = set()
    i = 0
    for aboutValue, objectID in aboutValues.iteritems():
        result = store.find(
            CommentObjectLink,
            CommentObjectLink.objectID == objectID)
        comments = set(result.values(CommentObjectLink.commentID))
        affectedComments.update(comments)
        result.remove()
        store.commit()
        if len(comments):
            logging.info('Removed %s comment links for %d comments.',
                         aboutValue, len(comments))
    logging.info('Removed @name comment links for %d comments.',
                 len(affectedComments))

    # Find fluidinfo.com/info/about values for affected comments and remove
    # @names from the about lists.
    tagID = getTags([u'fluidinfo.com/info/about']).one().id
    comments = list(affectedComments)
    while comments:
        batch = comments[0:min(len(comments), BATCH_SIZE)]
        if not batch:
            break
        result = store.find(TagValue,
                            TagValue.tagID == tagID,
                            TagValue.objectID.is_in(batch))
        for i, value in enumerate(result):
            pass
            value.value = [about for about in value.value
                           if about not in aboutValues]
        logging.info('Updated about values for %d comments.', i + 1)
        store.commit()
        comments = comments[len(batch):]

    logging.info('Finished updating about values for %d comments.',
                 len(affectedComments))
Ejemplo n.º 23
0
def migrate(store):
    # Find all the @name about values.
    result = store.execute('SELECT value, object_id'
                           '    FROM about_tag_values'
                           "    WHERE value LIKE '@%'")
    aboutValues = dict((value, UUID(objectID)) for value, objectID in result)
    logging.info('Loaded %d @name about values', len(aboutValues))

    # Remove all the links between comments and @name values.
    affectedComments = set()
    i = 0
    for aboutValue, objectID in aboutValues.iteritems():
        result = store.find(CommentObjectLink,
                            CommentObjectLink.objectID == objectID)
        comments = set(result.values(CommentObjectLink.commentID))
        affectedComments.update(comments)
        result.remove()
        store.commit()
        if len(comments):
            logging.info('Removed %s comment links for %d comments.',
                         aboutValue, len(comments))
    logging.info('Removed @name comment links for %d comments.',
                 len(affectedComments))

    # Find fluidinfo.com/info/about values for affected comments and remove
    # @names from the about lists.
    tagID = getTags([u'fluidinfo.com/info/about']).one().id
    comments = list(affectedComments)
    while comments:
        batch = comments[0:min(len(comments), BATCH_SIZE)]
        if not batch:
            break
        result = store.find(TagValue, TagValue.tagID == tagID,
                            TagValue.objectID.is_in(batch))
        for i, value in enumerate(result):
            pass
            value.value = [
                about for about in value.value if about not in aboutValues
            ]
        logging.info('Updated about values for %d comments.', i + 1)
        store.commit()
        comments = comments[len(batch):]

    logging.info('Finished updating about values for %d comments.',
                 len(affectedComments))
Ejemplo n.º 24
0
    def create(self, values):
        """Create new L{Tag}s.

        L{Namespace}s that don't exist are created automatically before
        L{Tag}s are created.  Associated L{NamespacePermission} and
        L{TagPermission}s are created automatically with the system-wide
        default permissions.

        @param values: A sequence of C{(Tag.path, description)} 2-tuples.
        @raise DuplicatePathError: Raised if the path for a new L{Tag}
            collides with an existing one.
        @raise FeatureError: Raised if the given list of values is empty.
        @raise UnknownParentPathError: Raised if the parent for a new L{Tag}
            can't be found.
        @raise MalformedPathError: Raised if one of the given paths is empty
            or has unacceptable characters.
        @return: A C{list} of C{(objectID, path)} 2-tuples for the new L{Tag}s.
        """
        if not values:
            raise FeatureError("Can't create an empty list of tags.")

        # Make sure tag paths don't exist before trying to create new tags.
        paths = [path for path, _ in values]
        existingPaths = list(getTags(paths=paths).values(Tag.path))
        if existingPaths:
            raise DuplicatePathError(
                'Paths already exist: %s' % ', '.join(existingPaths))

        # Get intermediate namespaces.  If they don't exist, create them
        # automatically.
        paths = [path for (path, _) in values]
        parentPaths = getParentPaths(paths)
        missingParentPaths = self._getMissingNamespaces(parentPaths)
        self._factory.namespaces(self._user).create(
            [(path, u'Object for the namespace %s' % path)
             for path in missingParentPaths])

        # Create the new tags.
        result = getNamespaces(paths=parentPaths)
        parentNamespaces = dict((namespace.path, namespace)
                                for namespace in result)
        return self._createTags(values, parentNamespaces)
Ejemplo n.º 25
0
    def set(self, values):
        """Set or update L{Tag}s.

        @param values: A C{dict} mapping L{Tag.path}s to descriptions.
        @return: A C{list} of C{(objectID, Tag.path)} 2-tuples representing the
            L{Tag}s that were updated.
        """
        result = []
        paths = set(values.iterkeys())
        tags = dict(getTags(paths=paths).values(Tag.path, Tag.objectID))
        descriptions = {}
        for path, description in values.iteritems():
            if path not in tags:
                raise UnknownPathError([path])
            objectID = tags[path]
            descriptions[objectID] = {u'fluiddb/tags/description': description}
            result.append((objectID, path))

        admin = getUser(u'fluiddb')
        self._factory.tagValues(admin).set(descriptions)
        return result
Ejemplo n.º 26
0
    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)
Ejemplo n.º 27
0
    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)
Ejemplo n.º 28
0
    def delete(self, values):
        """Delete L{TagValue}s.

        @param values: A sequence of C{(objectID, Tag.path)} 2-tuples to
            delete values for.
        @raise FeatureError: Raised if the given list of values is empty.
        @return: The number of values deleted.
        """
        if isgenerator(values):
            values = list(values)
        if not values:
            raise FeatureError("Can't delete an empty list of tag values.")

        paths = set([path for objectID, path in values])
        objectIDs = set([objectID for objectID, path in values])
        tagIDs = dict(getTags(paths).values(Tag.path, Tag.id))
        values = [(objectID, tagIDs[path]) for objectID, path in values]
        result = getTagValues(values).remove()
        if result:
            touchObjects(objectIDs)
        return result
Ejemplo n.º 29
0
    def delete(self, values):
        """Delete L{TagValue}s.

        @param values: A sequence of C{(objectID, Tag.path)} 2-tuples to
            delete values for.
        @raise FeatureError: Raised if the given list of values is empty.
        @return: The number of values deleted.
        """
        if isgenerator(values):
            values = list(values)
        if not values:
            raise FeatureError("Can't delete an empty list of tag values.")

        paths = set([path for objectID, path in values])
        objectIDs = set([objectID for objectID, path in values])
        tagIDs = dict(getTags(paths).values(Tag.path, Tag.id))
        values = [(objectID, tagIDs[path]) for objectID, path in values]
        result = getTagValues(values).remove()
        if result:
            touchObjects(objectIDs)
        return result
Ejemplo n.º 30
0
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)
Ejemplo n.º 31
0
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)
Ejemplo n.º 32
0
    def getUnknownPaths(self, values):
        """Check if the paths in a sequence of path-operation exist.

        @param values: A sequence of C{(path, Operation)} 2-tuples.
        @raise FeatureError: Raised if an invalid path or L{Operation} is
            given.
        @return: A C{set} with the unknown paths.
        """
        tagPaths = set()
        namespacePaths = set()
        for path, operation in values:
            if path is None:
                raise FeatureError('A path must be provided.')
            elif operation in Operation.TAG_OPERATIONS:
                tagPaths.add(path)
            elif operation in Operation.NAMESPACE_OPERATIONS:
                namespacePaths.add(path)
            else:
                raise FeatureError('Invalid operation %s for the path %r' %
                                   (operation, path))

        if tagPaths:
            existingTags = set(getTags(paths=tagPaths).values(Tag.path))
            unknownTags = tagPaths - existingTags
            unknownTags.discard(u'fluiddb/id')
        else:
            unknownTags = set()

        if namespacePaths:
            result = getNamespaces(paths=namespacePaths).values(Namespace.path)
            existingNamespaces = set(result)
            unknownNamespaces = namespacePaths - existingNamespaces
        else:
            unknownNamespaces = set()

        return unknownTags.union(unknownNamespaces)
Ejemplo n.º 33
0
    def getUnknownPaths(self, values):
        """Check if the paths in a sequence of path-operation exist.

        @param values: A sequence of C{(path, Operation)} 2-tuples.
        @raise FeatureError: Raised if an invalid path or L{Operation} is
            given.
        @return: A C{set} with the unknown paths.
        """
        tagPaths = set()
        namespacePaths = set()
        for path, operation in values:
            if path is None:
                raise FeatureError('A path must be provided.')
            elif operation in Operation.TAG_OPERATIONS:
                tagPaths.add(path)
            elif operation in Operation.NAMESPACE_OPERATIONS:
                namespacePaths.add(path)
            else:
                raise FeatureError('Invalid operation %s for the path %r'
                                   % (operation, path))

        if tagPaths:
            existingTags = set(getTags(paths=tagPaths).values(Tag.path))
            unknownTags = tagPaths - existingTags
            unknownTags.discard(u'fluiddb/id')
        else:
            unknownTags = set()

        if namespacePaths:
            result = getNamespaces(paths=namespacePaths).values(Namespace.path)
            existingNamespaces = set(result)
            unknownNamespaces = namespacePaths - existingNamespaces
        else:
            unknownNamespaces = set()

        return unknownTags.union(unknownNamespaces)
Ejemplo n.º 34
0
    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)
Ejemplo n.º 35
0
class Config(object):
    store = setupStore('postgres:///fluidinfo', 'main')
    fluidinfoUser = getUser(u'fluidinfo.com')
    aboutTag = getTags(paths=[u'fluiddb/about']).one()
    start = datetime.strptime('2012-05-27 00:01', '%Y-%m-%d %H:%M')
Ejemplo n.º 36
0
Change the creator id of all the fluiddb/about values to the fluiddb user.
"""

from fluiddb.data.tag import getTags
from fluiddb.data.user import getUsers
from fluiddb.scripts.commands import setupStore
from fluiddb.data.value import TagValue

if __name__ == '__main__':

    store = setupStore('postgres:///fluidinfo', 'main')

    print __doc__

    superUser = getUsers(usernames=[u'fluiddb']).one()
    aboutTag = getTags(paths=[u'fluiddb/about']).one()

    print 'Getting value IDs. This might take some minutes.'
    result = store.find(TagValue, TagValue.tagID == aboutTag.id,
                        TagValue.creatorID != superUser.id)
    allValueIDs = list(result.values(TagValue.id))
    i = 0
    valueIDs = allValueIDs[i:i + 100]
    while valueIDs:
        result = store.find(TagValue, TagValue.id.is_in(valueIDs))
        result.set(creatorID=superUser.id)

        print 'Fixed', i + len(valueIDs), 'of', len(allValueIDs), 'tag values',
        print '%00.3f%%.' % (100.0 * (i + len(valueIDs)) / len(allValueIDs))
        i += 100
        valueIDs = allValueIDs[i:i + 100]
Ejemplo n.º 37
0
    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)
Ejemplo n.º 38
0
from fluiddb.application import setConfig, setupConfig
from fluiddb.data.tag import getTags
from fluiddb.data.user import getUsers
from fluiddb.data.value import (
    TagValue, getTagValues, getAboutTagValues, AboutTagValue)
from fluiddb.model.object import ObjectAPI
from fluiddb.scripts.commands import setupStore


if __name__ == '__main__':
    print __doc__

    store = setupStore('postgres:///fluidinfo', 'main')
    setConfig(setupConfig(None))

    aboutTag = getTags(paths=[u'fluiddb/about']).one()
    superUser = getUsers(usernames=[u'fluiddb']).one()

    result = store.find(AboutTagValue, AboutTagValue.value.like(u'@%'))
    for aboutValue in result:
        if aboutValue.value == aboutValue.value.lower():
            continue
        print 'Migrating mixed cased', aboutValue.value.encode('utf-8')

        newAbout = u'@%s' % aboutValue.value.lower()
        oldObjectID = aboutValue.objectID
        newObjectID = ObjectAPI(superUser).create(newAbout)
        result = store.find(TagValue,
                            TagValue.objectID == oldObjectID,
                            TagValue.tagID != aboutTag.id)
        for tagValue in result:
Ejemplo n.º 39
0
 def testDelete(self):
     """L{TagAPI.delete} removes L{Tag}s."""
     self.tags.create([(u'username/child', u'A description')])
     self.tags.delete([u'username/child'])
     self.assertIdentical(None, getTags(paths=[u'username/child']).one())
Ejemplo n.º 40
0
if __name__ == '__main__':

    store = setupStore('postgres:///fluidinfo', 'main')
    setConfig(setupConfig(None))

    BATCH_SIZE = 50

    print __doc__

    superUser = getUser(u'fluiddb')
    tagValues = TagValueAPI(superUser)

    print 'Getting tags to fix.'
    tagsToFix = []
    for tagID, path in getTags().values(Tag.id, Tag.path):
        root = path.split('/', 1)[0]
        if not root.islower():
            tagsToFix.append(tagID)

    print 'Getting namespaces to fix.'
    namespacesToFix = []
    for namespaceID, path in getNamespaces().values(Namespace.id,
                                                    Namespace.path):
        root = path.split('/', 1)[0]
        if not root.islower():
            namespacesToFix.append(namespaceID)

    print 'Fixing tags.'
    i = 0
    currentIDs = tagsToFix[i:i + BATCH_SIZE]