Exemple #1
0
    def test_it_calls_first(self, annotation, session, Document):
        """If it finds only one document it calls first()."""
        Document.find_or_create_by_uris.return_value = mock.Mock(
            count=mock.Mock(return_value=1)
        )

        document.update_document_metadata(session, annotation, [], [])

        Document.find_or_create_by_uris.return_value.first.assert_called_once_with()
Exemple #2
0
    def test_it_calls_first(self, annotation, session, Document):
        """If it finds only one document it calls first()."""
        Document.find_or_create_by_uris.return_value = mock.Mock(
            count=mock.Mock(return_value=1))

        document.update_document_metadata(session, annotation, [], [])

        Document.find_or_create_by_uris.return_value.first.assert_called_once_with(
        )
Exemple #3
0
    def test_it_updates_document_web_uri(self, annotation, Document, factories,
                                         session):
        document_ = mock.Mock(web_uri=None)
        Document.find_or_create_by_uris.return_value.count.return_value = 1
        Document.find_or_create_by_uris.return_value.first.return_value = document_

        document.update_document_metadata(session, annotation.target_uri, [],
                                          [], annotation.created,
                                          annotation.updated)

        document_.update_web_uri.assert_called_once_with()
Exemple #4
0
    def test_it_updates_document_updated(self, annotation, Document,
                                         merge_documents, session):
        yesterday_ = "yesterday"
        document_ = merge_documents.return_value = mock.Mock(
            updated=yesterday_)
        Document.find_or_create_by_uris.return_value.first.return_value = (
            document_)

        document.update_document_metadata(session, annotation.target_uri, [],
                                          [], annotation.created,
                                          annotation.updated)

        assert document_.updated == annotation.updated
Exemple #5
0
    def test_if_there_are_multiple_documents_it_merges_them_into_one(
            self, annotation, Document, merge_documents, session):
        """If it finds more than one document it calls merge_documents()."""
        Document.find_or_create_by_uris.return_value = mock.Mock(
            count=mock.Mock(return_value=3))

        document.update_document_metadata(session, annotation.target_uri, [],
                                          [], annotation.created,
                                          annotation.updated)

        merge_documents.assert_called_once_with(
            session,
            Document.find_or_create_by_uris.return_value,
            updated=annotation.updated)
Exemple #6
0
def create_annotation(request, data, group_service):
    """
    Create an annotation from passed data.

    :param request: the request object
    :type request: pyramid.request.Request

    :param data: a dictionary of annotation properties
    :type data: dict

    :param group_service: a service object that adheres to ``h.interfaces.IGroupService``
    :type group_service: h.interfaces.IGroupService

    :returns: the created and flushed annotation
    :rtype: dict
    """
    created = updated = datetime.utcnow()

    document_uri_dicts = data['document']['document_uri_dicts']
    document_meta_dicts = data['document']['document_meta_dicts']
    del data['document']

    # Replies must have the same group as their parent.
    if data['references']:
        top_level_annotation_id = data['references'][0]
        top_level_annotation = fetch_annotation(request.db,
                                                top_level_annotation_id)
        if top_level_annotation:
            data['groupid'] = top_level_annotation.groupid
        else:
            raise schemas.ValidationError(
                'references.0: ' + _('Annotation {id} does not exist').format(
                    id=top_level_annotation_id))

    # The user must have permission to create an annotation in the group
    # they've asked to create one in. If the application didn't configure
    # a groupfinder we will allow writing this annotation without any
    # further checks.
    group = group_service.find(data['groupid'])
    if group is None or not request.has_permission('write', context=group):
        raise schemas.ValidationError('group: ' +
                                      _('You may not create annotations '
                                        'in the specified group!'))

    annotation = models.Annotation(**data)
    annotation.created = created
    annotation.updated = updated

    document = update_document_metadata(request.db,
                                        annotation.target_uri,
                                        document_meta_dicts,
                                        document_uri_dicts,
                                        created=created,
                                        updated=updated)
    annotation.document = document

    request.db.add(annotation)
    request.db.flush()

    return annotation
Exemple #7
0
def update_annotation(request, id_, data, group_service):
    """
    Update an existing annotation and its associated document metadata.

    Update the annotation identified by ``id_`` with the given
    data. Create, delete and update document metadata as appropriate.

    :param request: the request object

    :param id_: the ID of the annotation to be updated, this is assumed to be a
        validated ID of an annotation that does already exist in the database
    :type id_: string

    :param data: the validated data with which to update the annotation
    :type data: dict

    :type group_service: :py:class:`h.interfaces.IGroupService`

    :returns: the updated annotation
    :rtype: h.models.Annotation

    """
    updated = datetime.utcnow()

    # Remove any 'document' field first so that we don't try to save it on the
    # annotation object.
    document = data.pop("document", None)

    annotation = request.db.query(models.Annotation).get(id_)
    annotation.updated = updated

    group = group_service.find(annotation.groupid)
    if group is None:
        raise schemas.ValidationError(
            "group: " + _("Invalid group specified for annotation"))
    if data.get("target_uri", None):
        _validate_group_scope(group, data["target_uri"])

    annotation.extra.update(data.pop("extra", {}))

    for key, value in data.items():
        setattr(annotation, key, value)

    if document:
        document_uri_dicts = document["document_uri_dicts"]
        document_meta_dicts = document["document_meta_dicts"]
        document = update_document_metadata(
            request.db,
            annotation.target_uri,
            document_meta_dicts,
            document_uri_dicts,
            updated=updated,
        )
        annotation.document = document

    request.find_service(name="search_index")._queue.add_by_id(
        id_, tag="storage.update_annotation", schedule_in=60)

    return annotation
Exemple #8
0
    def make_metadata(self, create, extracted, **kwargs):
        """Create associated document metadata for the annotation."""
        # The metadata objects are going to be added to the db, so if we're not
        # using the create strategy then simply don't make any.
        if not create:
            return

        def document_uri_dict():
            """
            Return a randomly generated DocumentURI dict for this annotation.

            This doesn't add anything to the database session yet.
            """
            document_uri = DocumentURI.build(document=self.document,
                                             claimant=self.target_uri,
                                             uri=self.target_uri)
            return dict(
                claimant=document_uri.claimant,
                uri=document_uri.uri,
                type=document_uri.type,
                content_type=document_uri.content_type,
            )

        document_uri_dicts = [
            document_uri_dict() for _ in range(random.randint(1, 3))
        ]

        def document_meta_dict(**kwargs):
            """
            Return a randomly generated DocumentMeta dict for this annotation.

            This doesn't add anything to the database session yet.
            """
            kwargs.setdefault('document', self.document)
            kwargs.setdefault('claimant', self.target_uri)
            document_meta = DocumentMeta.build(**kwargs)
            return dict(
                claimant=document_meta.claimant,
                type=document_meta.type,
                value=document_meta.value,
            )

        document_meta_dicts = [
            document_meta_dict() for _ in range(random.randint(1, 3))
        ]

        # Make sure that there's always at least one DocumentMeta with
        # type='title', so that we never get annotation.document.title is None:
        if 'title' not in [m['type'] for m in document_meta_dicts]:
            document_meta_dicts.append(document_meta_dict(type='title'))

        self.document = update_document_metadata(
            orm.object_session(self),
            self.target_uri,
            document_meta_dicts=document_meta_dicts,
            document_uri_dicts=document_uri_dicts,
            created=self.created,
            updated=self.updated,
        )
Exemple #9
0
    def test_it_updates_document_updated(
        self, annotation, Document, merge_documents, session
    ):
        yesterday_ = "yesterday"
        document_ = merge_documents.return_value = mock.Mock(updated=yesterday_)
        Document.find_or_create_by_uris.return_value.first.return_value = document_

        document.update_document_metadata(
            session,
            annotation.target_uri,
            [],
            [],
            annotation.created,
            annotation.updated,
        )

        assert document_.updated == annotation.updated
Exemple #10
0
    def test_it_updates_document_web_uri(
        self, annotation, Document, factories, session
    ):
        document_ = mock.Mock(web_uri=None)
        Document.find_or_create_by_uris.return_value.count.return_value = 1
        Document.find_or_create_by_uris.return_value.first.return_value = document_

        document.update_document_metadata(
            session,
            annotation.target_uri,
            [],
            [],
            annotation.created,
            annotation.updated,
        )

        document_.update_web_uri.assert_called_once_with()
Exemple #11
0
    def test_it_saves_all_the_document_uris(
        self, session, annotation, Document, create_or_update_document_uri
    ):
        """It creates or updates a DocumentURI for each document URI dict."""
        Document.find_or_create_by_uris.return_value.count.return_value = 1

        document_uri_dicts = [
            {
                "uri": "http://example.com/example_1",
                "claimant": "http://example.com/claimant",
                "type": "type",
                "content_type": None,
            },
            {
                "uri": "http://example.com/example_2",
                "claimant": "http://example.com/claimant",
                "type": "type",
                "content_type": None,
            },
            {
                "uri": "http://example.com/example_3",
                "claimant": "http://example.com/claimant",
                "type": "type",
                "content_type": None,
            },
        ]

        document.update_document_metadata(
            session,
            annotation.target_uri,
            [],
            document_uri_dicts,
            annotation.created,
            annotation.updated,
        )

        assert create_or_update_document_uri.call_count == 3
        for doc_uri_dict in document_uri_dicts:
            create_or_update_document_uri.assert_any_call(
                session=session,
                document=Document.find_or_create_by_uris.return_value.first.return_value,
                created=annotation.created,
                updated=annotation.updated,
                **doc_uri_dict
            )
Exemple #12
0
    def test_it_saves_all_the_document_uris(self, session, annotation,
                                            Document,
                                            create_or_update_document_uri):
        """It creates or updates a DocumentURI for each document URI dict."""
        Document.find_or_create_by_uris.return_value.count.return_value = 1

        document_uri_dicts = [
            {
                "uri": "http://example.com/example_1",
                "claimant": "http://example.com/claimant",
                "type": "type",
                "content_type": None,
            },
            {
                "uri": "http://example.com/example_2",
                "claimant": "http://example.com/claimant",
                "type": "type",
                "content_type": None,
            },
            {
                "uri": "http://example.com/example_3",
                "claimant": "http://example.com/claimant",
                "type": "type",
                "content_type": None,
            },
        ]

        document.update_document_metadata(
            session,
            annotation.target_uri,
            [],
            document_uri_dicts,
            annotation.created,
            annotation.updated,
        )

        assert create_or_update_document_uri.call_count == 3
        for doc_uri_dict in document_uri_dicts:
            create_or_update_document_uri.assert_any_call(
                session=session,
                document=Document.find_or_create_by_uris.return_value.first.
                return_value,
                created=annotation.created,
                updated=annotation.updated,
                **doc_uri_dict)
Exemple #13
0
    def make_metadata(self, create, extracted, **kwargs):
        """Create associated document metadata for the annotation."""
        # The metadata objects are going to be added to the db, so if we're not
        # using the create strategy then simply don't make any.
        if not create:
            return

        def document_uri_dict():
            """
            Return a randomly generated DocumentURI dict for this annotation.

            This doesn't add anything to the database session yet.
            """
            document_uri = DocumentURI.build(document=self.document,
                                             claimant=self.target_uri,
                                             uri=self.target_uri)
            return dict(
                claimant=document_uri.claimant,
                uri=document_uri.uri,
                type=document_uri.type,
                content_type=document_uri.content_type,
            )

        document_uri_dicts = [document_uri_dict()
                              for _ in range(random.randint(1, 3))]

        def document_meta_dict(**kwargs):
            """
            Return a randomly generated DocumentMeta dict for this annotation.

            This doesn't add anything to the database session yet.
            """
            kwargs.setdefault('document', self.document)
            kwargs.setdefault('claimant', self.target_uri)
            document_meta = DocumentMeta.build(**kwargs)
            return dict(
                claimant=document_meta.claimant,
                type=document_meta.type,
                value=document_meta.value,
            )

        document_meta_dicts = [document_meta_dict()
                               for _ in range(random.randint(1, 3))]

        # Make sure that there's always at least one DocumentMeta with
        # type='title', so that we never get annotation.document.title is None:
        if 'title' not in [m['type'] for m in document_meta_dicts]:
            document_meta_dicts.append(document_meta_dict(type='title'))

        self.document = update_document_metadata(
            orm.object_session(self),
            self.target_uri,
            document_meta_dicts=document_meta_dicts,
            document_uri_dicts=document_uri_dicts,
            created=self.created,
            updated=self.updated,
        )
Exemple #14
0
def update_annotation(request, id_, data, group_service):
    """
    Update an existing annotation and its associated document metadata.

    Update the annotation identified by ``id_`` with the given
    data. Create, delete and update document metadata as appropriate.

    :param request: the request object

    :param id_: the ID of the annotation to be updated, this is assumed to be a
        validated ID of an annotation that does already exist in the database
    :type id_: string

    :param data: the validated data with which to update the annotation
    :type data: dict

    :type group_service: :py:class:`h.interfaces.IGroupService`

    :returns: the updated annotation
    :rtype: h.models.Annotation

    """
    updated = datetime.utcnow()

    # Remove any 'document' field first so that we don't try to save it on the
    # annotation object.
    document = data.pop("document", None)

    annotation = request.db.query(models.Annotation).get(id_)
    annotation.updated = updated

    group = group_service.find(annotation.groupid)
    if group is None:
        raise schemas.ValidationError(
            "group: " + _("Invalid group specified for annotation")
        )
    if data.get("target_uri", None):
        _validate_group_scope(group, data["target_uri"])

    annotation.extra.update(data.pop("extra", {}))

    for key, value in data.items():
        setattr(annotation, key, value)

    if document:
        document_uri_dicts = document["document_uri_dicts"]
        document_meta_dicts = document["document_meta_dicts"]
        document = update_document_metadata(
            request.db,
            annotation.target_uri,
            document_meta_dicts,
            document_uri_dicts,
            updated=updated,
        )
        annotation.document = document

    return annotation
Exemple #15
0
    def test_it_uses_the_target_uri_to_get_the_document(
        self, annotation, Document, session
    ):
        document_uri_dicts = [
            {
                "uri": "http://example.com/example_1",
                "claimant": "http://example.com/claimant",
                "type": "type",
                "content_type": None,
            },
            {
                "uri": "http://example.com/example_2",
                "claimant": "http://example.com/claimant",
                "type": "type",
                "content_type": None,
            },
            {
                "uri": "http://example.com/example_3",
                "claimant": "http://example.com/claimant",
                "type": "type",
                "content_type": None,
            },
        ]

        document.update_document_metadata(
            session,
            annotation.target_uri,
            [],
            document_uri_dicts,
            annotation.created,
            annotation.updated,
        )

        Document.find_or_create_by_uris.assert_called_once_with(
            session,
            annotation.target_uri,
            [
                "http://example.com/example_1",
                "http://example.com/example_2",
                "http://example.com/example_3",
            ],
            created=annotation.created,
            updated=annotation.updated,
        )
Exemple #16
0
    def test_it_uses_the_target_uri_to_get_the_document(self,
                                                        annotation,
                                                        Document,
                                                        session):
        document_uri_dicts = [
            {
                'uri': 'http://example.com/example_1',
                'claimant': 'http://example.com/claimant',
                'type': 'type',
                'content_type': None,
            },
            {
                'uri': 'http://example.com/example_2',
                'claimant': 'http://example.com/claimant',
                'type': 'type',
                'content_type': None,
            },
            {
                'uri': 'http://example.com/example_3',
                'claimant': 'http://example.com/claimant',
                'type': 'type',
                'content_type': None,
            },
        ]

        document.update_document_metadata(session,
                                          annotation.target_uri,
                                          [],
                                          document_uri_dicts,
                                          annotation.created,
                                          annotation.updated)

        Document.find_or_create_by_uris.assert_called_once_with(
            session,
            annotation.target_uri,
            [
                'http://example.com/example_1',
                'http://example.com/example_2',
                'http://example.com/example_3',
            ],
            created=annotation.created,
            updated=annotation.updated,
        )
Exemple #17
0
    def test_it_uses_the_target_uri_to_get_the_document(
            self, annotation, Document, session):
        document_uri_dicts = [
            {
                "uri": "http://example.com/example_1",
                "claimant": "http://example.com/claimant",
                "type": "type",
                "content_type": None,
            },
            {
                "uri": "http://example.com/example_2",
                "claimant": "http://example.com/claimant",
                "type": "type",
                "content_type": None,
            },
            {
                "uri": "http://example.com/example_3",
                "claimant": "http://example.com/claimant",
                "type": "type",
                "content_type": None,
            },
        ]

        document.update_document_metadata(
            session,
            annotation.target_uri,
            [],
            document_uri_dicts,
            annotation.created,
            annotation.updated,
        )

        Document.find_or_create_by_uris.assert_called_once_with(
            session,
            annotation.target_uri,
            [
                "http://example.com/example_1",
                "http://example.com/example_2",
                "http://example.com/example_3",
            ],
            created=annotation.created,
            updated=annotation.updated,
        )
Exemple #18
0
    def test_it_saves_all_the_document_metas(self,
                                             annotation,
                                             create_or_update_document_meta,
                                             Document,
                                             session):
        """It creates or updates a DocumentMeta for each document meta dict."""
        Document.find_or_create_by_uris.return_value.count\
            .return_value = 1

        document_meta_dicts = [
            {
                'claimant': 'http://example.com/claimant',
                'type': 'title',
                'value': 'foo',
            },
            {
                'type': 'article title',
                'value': 'bar',
                'claimant': 'http://example.com/claimant',
            },
            {
                'type': 'site title',
                'value': 'gar',
                'claimant': 'http://example.com/claimant',
            },
        ]

        document.update_document_metadata(session,
                                          annotation.target_uri,
                                          document_meta_dicts,
                                          [],
                                          annotation.created,
                                          annotation.updated)

        assert create_or_update_document_meta.call_count == 3
        for document_meta_dict in document_meta_dicts:
            create_or_update_document_meta.assert_any_call(
                session=session,
                document=Document.find_or_create_by_uris.return_value.first.return_value,
                created=annotation.created,
                updated=annotation.updated,
                **document_meta_dict
            )
Exemple #19
0
    def test_it_saves_all_the_document_metas(self,
                                             annotation,
                                             create_or_update_document_meta,
                                             Document,
                                             session):
        """It creates or updates a DocumentMeta for each document meta dict."""
        Document.find_or_create_by_uris.return_value.count\
            .return_value = 1

        document_meta_dicts = [
            {
                'claimant': 'http://example.com/claimant',
                'type': 'title',
                'value': 'foo',
            },
            {
                'type': 'article title',
                'value': 'bar',
                'claimant': 'http://example.com/claimant',
            },
            {
                'type': 'site title',
                'value': 'gar',
                'claimant': 'http://example.com/claimant',
            },
        ]

        document.update_document_metadata(session,
                                          annotation.target_uri,
                                          document_meta_dicts,
                                          [],
                                          annotation.created,
                                          annotation.updated)

        assert create_or_update_document_meta.call_count == 3
        for document_meta_dict in document_meta_dicts:
            create_or_update_document_meta.assert_any_call(
                session=session,
                document=Document.find_or_create_by_uris.return_value.first.return_value,
                created=annotation.created,
                updated=annotation.updated,
                **document_meta_dict
            )
Exemple #20
0
    def test_it_uses_the_target_uri_to_get_the_document(self,
                                                        annotation,
                                                        Document,
                                                        session):
        document_uri_dicts = [
            {
                'uri': 'http://example.com/example_1',
                'claimant': 'http://example.com/claimant',
                'type': 'type',
                'content_type': None,
            },
            {
                'uri': 'http://example.com/example_2',
                'claimant': 'http://example.com/claimant',
                'type': 'type',
                'content_type': None,
            },
            {
                'uri': 'http://example.com/example_3',
                'claimant': 'http://example.com/claimant',
                'type': 'type',
                'content_type': None,
            },
        ]

        document.update_document_metadata(session,
                                          annotation.target_uri,
                                          [],
                                          document_uri_dicts,
                                          annotation.created,
                                          annotation.updated)

        Document.find_or_create_by_uris.assert_called_once_with(
            session,
            annotation.target_uri,
            [
                'http://example.com/example_1',
                'http://example.com/example_2',
                'http://example.com/example_3',
            ],
            created=annotation.created,
            updated=annotation.updated,
        )
Exemple #21
0
def update_annotation(request, id_, data, group_service):
    """
    Update an existing annotation and its associated document metadata.

    Update the annotation identified by id_ with the given
    data. Create, delete and update document metadata as appropriate.

    :param request: the request object

    :param id_: the ID of the annotation to be updated, this is assumed to be a
        validated ID of an annotation that does already exist in the database
    :type id_: string

    :param data: the validated data with which to update the annotation
    :type data: dict

    :type group_service: :py:class:`h.interfaces.IGroupService`

    :returns: the updated annotation
    :rtype: h.models.Annotation

    """
    updated = datetime.utcnow()

    # Remove any 'document' field first so that we don't try to save it on the
    # annotation object.
    document = data.pop('document', None)

    annotation = request.db.query(models.Annotation).get(id_)
    annotation.updated = updated

    group = group_service.find(annotation.groupid)
    if group is None:
        raise schemas.ValidationError(
            'group: ' + _('Invalid group specified for annotation'))
    if request.feature('filter_groups_by_scope') and data.get(
            'target_uri', None):
        _validate_group_scope(group, data['target_uri'])

    annotation.extra.update(data.pop('extra', {}))

    for key, value in data.items():
        setattr(annotation, key, value)

    if document:
        document_uri_dicts = document['document_uri_dicts']
        document_meta_dicts = document['document_meta_dicts']
        document = update_document_metadata(request.db,
                                            annotation.target_uri,
                                            document_meta_dicts,
                                            document_uri_dicts,
                                            updated=updated)
        annotation.document = document

    return annotation
Exemple #22
0
    def test_it_saves_all_the_document_metas(
        self, annotation, create_or_update_document_meta, Document, session
    ):
        """It creates or updates a DocumentMeta for each document meta dict."""
        Document.find_or_create_by_uris.return_value.count.return_value = 1

        document_meta_dicts = [
            {
                "claimant": "http://example.com/claimant",
                "type": "title",
                "value": "foo",
            },
            {
                "type": "article title",
                "value": "bar",
                "claimant": "http://example.com/claimant",
            },
            {
                "type": "site title",
                "value": "gar",
                "claimant": "http://example.com/claimant",
            },
        ]

        document.update_document_metadata(
            session,
            annotation.target_uri,
            document_meta_dicts,
            [],
            annotation.created,
            annotation.updated,
        )

        assert create_or_update_document_meta.call_count == 3
        for document_meta_dict in document_meta_dicts:
            create_or_update_document_meta.assert_any_call(
                session=session,
                document=Document.find_or_create_by_uris.return_value.first.return_value,
                created=annotation.created,
                updated=annotation.updated,
                **document_meta_dict
            )
Exemple #23
0
    def test_it_saves_all_the_document_metas(self, annotation,
                                             create_or_update_document_meta,
                                             Document, session):
        """It creates or updates a DocumentMeta for each document meta dict."""
        Document.find_or_create_by_uris.return_value.count.return_value = 1

        document_meta_dicts = [
            {
                "claimant": "http://example.com/claimant",
                "type": "title",
                "value": "foo",
            },
            {
                "type": "article title",
                "value": "bar",
                "claimant": "http://example.com/claimant",
            },
            {
                "type": "site title",
                "value": "gar",
                "claimant": "http://example.com/claimant",
            },
        ]

        document.update_document_metadata(
            session,
            annotation.target_uri,
            document_meta_dicts,
            [],
            annotation.created,
            annotation.updated,
        )

        assert create_or_update_document_meta.call_count == 3
        for document_meta_dict in document_meta_dicts:
            create_or_update_document_meta.assert_any_call(
                session=session,
                document=Document.find_or_create_by_uris.return_value.first.
                return_value,
                created=annotation.created,
                updated=annotation.updated,
                **document_meta_dict)
Exemple #24
0
    def test_it_returns_a_document(self, annotation,
                                   create_or_update_document_meta, Document,
                                   session):
        Document.find_or_create_by_uris.return_value.count.return_value = 1

        result = document.update_document_metadata(session,
                                                   annotation.target_uri, [],
                                                   [], annotation.created,
                                                   annotation.updated)

        assert result == Document.find_or_create_by_uris.return_value.first.return_value
Exemple #25
0
    def test_if_there_are_multiple_documents_it_merges_them_into_one(
            self,
            annotation,
            Document,
            merge_documents,
            session):
        """If it finds more than one document it calls merge_documents()."""
        Document.find_or_create_by_uris.return_value = mock.Mock(
            count=mock.Mock(return_value=3))

        document.update_document_metadata(session,
                                          annotation.target_uri,
                                          [],
                                          [],
                                          annotation.created,
                                          annotation.updated)

        merge_documents.assert_called_once_with(
            session,
            Document.find_or_create_by_uris.return_value,
            updated=annotation.updated)
Exemple #26
0
    def test_it_returns_a_document(
        self, annotation, create_or_update_document_meta, Document, session
    ):
        Document.find_or_create_by_uris.return_value.count.return_value = 1

        result = document.update_document_metadata(
            session,
            annotation.target_uri,
            [],
            [],
            annotation.created,
            annotation.updated,
        )

        assert result == Document.find_or_create_by_uris.return_value.first.return_value
Exemple #27
0
def update_annotation(session, id_, data):
    """
    Update an existing annotation and its associated document metadata.

    Update the annotation identified by id_ with the given
    data. Create, delete and update document metadata as appropriate.

    :param session: the database session
    :type session: sqlalchemy.orm.session.Session

    :param id_: the ID of the annotation to be updated, this is assumed to be a
        validated ID of an annotation that does already exist in the database
    :type id_: string

    :param data: the validated data with which to update the annotation
    :type data: dict

    :returns: the updated annotation
    :rtype: h.models.Annotation

    """
    updated = datetime.utcnow()

    # Remove any 'document' field first so that we don't try to save it on the
    # annotation object.
    document = data.pop('document', None)

    annotation = session.query(models.Annotation).get(id_)
    annotation.updated = updated

    annotation.extra.update(data.pop('extra', {}))

    for key, value in data.items():
        setattr(annotation, key, value)

    if document:
        document_uri_dicts = document['document_uri_dicts']
        document_meta_dicts = document['document_meta_dicts']
        document = update_document_metadata(session,
                                            annotation.target_uri,
                                            document_meta_dicts,
                                            document_uri_dicts,
                                            updated=updated)
        annotation.document = document

    return annotation
Exemple #28
0
def update_annotation(session, id_, data):
    """
    Update an existing annotation and its associated document metadata.

    Update the annotation identified by id_ with the given
    data. Create, delete and update document metadata as appropriate.

    :param session: the database session
    :type session: sqlalchemy.orm.session.Session

    :param id_: the ID of the annotation to be updated, this is assumed to be a
        validated ID of an annotation that does already exist in the database
    :type id_: string

    :param data: the validated data with which to update the annotation
    :type data: dict

    :returns: the updated annotation
    :rtype: h.models.Annotation

    """
    updated = datetime.utcnow()

    # Remove any 'document' field first so that we don't try to save it on the
    # annotation object.
    document = data.pop('document', None)

    annotation = session.query(models.Annotation).get(id_)
    annotation.updated = updated

    annotation.extra.update(data.pop('extra', {}))

    for key, value in data.items():
        setattr(annotation, key, value)

    if document:
        document_uri_dicts = document['document_uri_dicts']
        document_meta_dicts = document['document_meta_dicts']
        document = update_document_metadata(session,
                                            annotation.target_uri,
                                            document_meta_dicts,
                                            document_uri_dicts,
                                            updated=updated)
        annotation.document = document

    return annotation
Exemple #29
0
def create_annotation(request, data, group_service):
    """
    Create an annotation from already-validated data.

    :param request: the request object
    :type request: pyramid.request.Request

    :param data: an annotation data dict that has already been validated by
        :py:class:`h.schemas.annotation.CreateAnnotationSchema`
    :type data: dict

    :param group_service: a service object that implements
        :py:class:`h.interfaces.IGroupService`
    :type group_service: :py:class:`h.interfaces.IGroupService`

    :returns: the created and flushed annotation
    :rtype: :py:class:`h.models.Annotation`
    """
    created = updated = datetime.utcnow()

    document_uri_dicts = data["document"]["document_uri_dicts"]
    document_meta_dicts = data["document"]["document_meta_dicts"]
    del data["document"]

    # Replies must have the same group as their parent.
    if data["references"]:
        top_level_annotation_id = data["references"][0]
        top_level_annotation = fetch_annotation(request.db,
                                                top_level_annotation_id)
        if top_level_annotation:
            data["groupid"] = top_level_annotation.groupid
        else:
            raise schemas.ValidationError(
                "references.0: " + _("Annotation {id} does not exist").format(
                    id=top_level_annotation_id))

    # The user must have permission to create an annotation in the group
    # they've asked to create one in. If the application didn't configure
    # a groupfinder we will allow writing this annotation without any
    # further checks.
    group = group_service.find(data["groupid"])
    if group is None or not request.has_permission("write", context=group):
        raise schemas.ValidationError("group: " +
                                      _("You may not create annotations "
                                        "in the specified group!"))

    _validate_group_scope(group, data["target_uri"])

    annotation = models.Annotation(**data)
    annotation.created = created
    annotation.updated = updated

    document = update_document_metadata(
        request.db,
        annotation.target_uri,
        document_meta_dicts,
        document_uri_dicts,
        created=created,
        updated=updated,
    )
    annotation.document = document

    request.db.add(annotation)
    request.db.flush()

    request.find_service(name="search_index")._queue.add_by_id(
        annotation.id, tag="storage.create_annotation", schedule_in=60)

    return annotation
Exemple #30
0
def create_annotation(request, data, group_service):
    """
    Create an annotation from passed data.

    :param request: the request object
    :type request: pyramid.request.Request

    :param data: a dictionary of annotation properties
    :type data: dict

    :param group_service: a service object that adheres to ``h.interfaces.IGroupService``
    :type group_service: h.interfaces.IGroupService

    :returns: the created and flushed annotation
    :rtype: dict
    """
    created = updated = datetime.utcnow()

    document_uri_dicts = data['document']['document_uri_dicts']
    document_meta_dicts = data['document']['document_meta_dicts']
    del data['document']

    # Replies must have the same group as their parent.
    if data['references']:
        top_level_annotation_id = data['references'][0]
        top_level_annotation = fetch_annotation(request.db,
                                                top_level_annotation_id)
        if top_level_annotation:
            data['groupid'] = top_level_annotation.groupid
        else:
            raise schemas.ValidationError(
                'references.0: ' +
                _('Annotation {id} does not exist').format(
                    id=top_level_annotation_id)
            )

    # The user must have permission to create an annotation in the group
    # they've asked to create one in. If the application didn't configure
    # a groupfinder we will allow writing this annotation without any
    # further checks.
    group = group_service.find(data['groupid'])
    if group is None or not request.has_permission('write', context=group):
        raise schemas.ValidationError('group: ' +
                                      _('You may not create annotations '
                                        'in the specified group!'))

    annotation = models.Annotation(**data)
    annotation.created = created
    annotation.updated = updated

    document = update_document_metadata(
        request.db,
        annotation.target_uri,
        document_meta_dicts,
        document_uri_dicts,
        created=created,
        updated=updated)
    annotation.document = document

    request.db.add(annotation)
    request.db.flush()

    return annotation
Exemple #31
0
def create_annotation(request, data, group_service):
    """
    Create an annotation from already-validated data.

    :param request: the request object
    :type request: pyramid.request.Request

    :param data: an annotation data dict that has already been validated by
        :py:class:`h.schemas.annotation.CreateAnnotationSchema`
    :type data: dict

    :param group_service: a service object that implements
        :py:class:`h.interfaces.IGroupService`
    :type group_service: :py:class:`h.interfaces.IGroupService`

    :returns: the created and flushed annotation
    :rtype: :py:class:`h.models.Annotation`
    """
    created = updated = datetime.utcnow()

    document_uri_dicts = data['document']['document_uri_dicts']
    document_meta_dicts = data['document']['document_meta_dicts']
    del data['document']

    # Replies must have the same group as their parent.
    if data['references']:
        top_level_annotation_id = data['references'][0]
        top_level_annotation = fetch_annotation(request.db,
                                                top_level_annotation_id)
        if top_level_annotation:
            data['groupid'] = top_level_annotation.groupid
        else:
            raise schemas.ValidationError(
                'references.0: ' + _('Annotation {id} does not exist').format(
                    id=top_level_annotation_id))

    # The user must have permission to create an annotation in the group
    # they've asked to create one in. If the application didn't configure
    # a groupfinder we will allow writing this annotation without any
    # further checks.
    group = group_service.find(data['groupid'])
    if group is None or not request.has_permission('write', context=group):
        raise schemas.ValidationError('group: ' +
                                      _('You may not create annotations '
                                        'in the specified group!'))

    if request.feature('filter_groups_by_scope') and group.scopes:
        # The scope (origin) of the target URI must match at least one
        # of a group's defined scopes, if the group has any
        group_scopes = [scope.origin for scope in group.scopes]
        if not group_scope_match(data['target_uri'], group_scopes):
            raise schemas.ValidationError('group scope: ' +
                                          _('Annotations for this target URI '
                                            'are not allowed in this group'))

    annotation = models.Annotation(**data)
    annotation.created = created
    annotation.updated = updated

    document = update_document_metadata(request.db,
                                        annotation.target_uri,
                                        document_meta_dicts,
                                        document_uri_dicts,
                                        created=created,
                                        updated=updated)
    annotation.document = document

    request.db.add(annotation)
    request.db.flush()

    return annotation
Exemple #32
0
def create_annotation(request, data, group_service):
    """
    Create an annotation from already-validated data.

    :param request: the request object
    :type request: pyramid.request.Request

    :param data: an annotation data dict that has already been validated by
        :py:class:`h.schemas.annotation.CreateAnnotationSchema`
    :type data: dict

    :param group_service: a service object that implements
        :py:class:`h.interfaces.IGroupService`
    :type group_service: :py:class:`h.interfaces.IGroupService`

    :returns: the created and flushed annotation
    :rtype: :py:class:`h.models.Annotation`
    """
    created = updated = datetime.utcnow()

    document_uri_dicts = data["document"]["document_uri_dicts"]
    document_meta_dicts = data["document"]["document_meta_dicts"]
    del data["document"]

    # Replies must have the same group as their parent.
    if data["references"]:
        top_level_annotation_id = data["references"][0]
        top_level_annotation = fetch_annotation(request.db, top_level_annotation_id)
        if top_level_annotation:
            data["groupid"] = top_level_annotation.groupid
        else:
            raise schemas.ValidationError(
                "references.0: "
                + _("Annotation {id} does not exist").format(id=top_level_annotation_id)
            )

    # The user must have permission to create an annotation in the group
    # they've asked to create one in. If the application didn't configure
    # a groupfinder we will allow writing this annotation without any
    # further checks.
    group = group_service.find(data["groupid"])
    if group is None or not request.has_permission("write", context=group):
        raise schemas.ValidationError(
            "group: " + _("You may not create annotations " "in the specified group!")
        )

    _validate_group_scope(group, data["target_uri"])

    annotation = models.Annotation(**data)
    annotation.created = created
    annotation.updated = updated

    document = update_document_metadata(
        request.db,
        annotation.target_uri,
        document_meta_dicts,
        document_uri_dicts,
        created=created,
        updated=updated,
    )
    annotation.document = document

    request.db.add(annotation)
    request.db.flush()

    return annotation
Exemple #33
0
    # The user must have permission to create an annotation in the group
    # they've asked to create one in.
    if not request.has_permission(Permission.Group.WRITE,
                                  context=GroupContext(group)):
        raise schemas.ValidationError(
            "group: " +
            _("You may not create annotations in the specified group!"))

    _validate_group_scope(group, data["target_uri"])

    annotation.created = annotation.updated = datetime.utcnow()
    annotation.document = update_document_metadata(
        request.db,
        annotation.target_uri,
        document_data["document_meta_dicts"],
        document_data["document_uri_dicts"],
        created=annotation.created,
        updated=annotation.updated,
    )

    request.db.add(annotation)
    request.db.flush()

    request.find_service(  # pylint: disable=protected-access
        name="search_index")._queue.add_by_id(annotation.id,
                                              tag="storage.create_annotation",
                                              schedule_in=60)

    return annotation