Beispiel #1
0
    def test_update_from_request(self):
        # create test note to update
        note = Annotation(text="Here's the thing", quote="really",
            extra_data=json.dumps({'sample data': 'foobar'}))
        note.save()

        # permissions check requires a real user
        user = get_user_model().objects.get(username='******')
        self.mockrequest.user = user

        with patch.object(note, 'db_permissions') as mock_db_perms:
            note.update_from_request(self.mockrequest)
            self.assertEqual(self.annotation_data['text'], note.text)
            self.assertEqual(self.annotation_data['quote'], note.quote)
            self.assertEqual(self.annotation_data['uri'], note.uri)
            self.assert_('ranges' in note.extra_data)
            self.assertEqual(self.annotation_data['ranges'][0]['start'],
                note.extra_data['ranges'][0]['start'])
            self.assert_('permissions' not in note.extra_data)
            # existing extra data should no longer present
            self.assert_('sample data' not in note.extra_data)

            # testuser does not have admin on this annotation;
            # permissions should not be updated
            mock_db_perms.assert_not_called()

            # give user admin permission and update again
            note.assign_permission('admin_annotation', user)
            note.update_from_request(self.mockrequest)
            mock_db_perms.assert_called_with(self.annotation_data['permissions'])
Beispiel #2
0
    def test_update_from_request(self):
        # create test note to update
        note = Annotation(text="Here's the thing",
                          quote="really",
                          extra_data=json.dumps({'sample data': 'foobar'}))
        note.save()

        # permissions check requires a real user
        user = get_user_model().objects.get(username='******')
        self.mockrequest.user = user

        with patch.object(note, 'db_permissions') as mock_db_perms:
            note.update_from_request(self.mockrequest)
            self.assertEqual(self.annotation_data['text'], note.text)
            self.assertEqual(self.annotation_data['quote'], note.quote)
            self.assertEqual(self.annotation_data['uri'], note.uri)
            self.assert_('ranges' in note.extra_data)
            self.assertEqual(self.annotation_data['ranges'][0]['start'],
                             note.extra_data['ranges'][0]['start'])
            self.assert_('permissions' not in note.extra_data)
            # existing extra data should no longer present
            self.assert_('sample data' not in note.extra_data)

            # testuser does not have admin on this annotation;
            # permissions should not be updated
            mock_db_perms.assert_not_called()

            # give user admin permission and update again
            note.assign_permission('admin_annotation', user)
            note.update_from_request(self.mockrequest)
            mock_db_perms.assert_called_with(
                self.annotation_data['permissions'])
Beispiel #3
0
    def import_annotation(self, data):
        '''Create and save a new annotation, setting fields based on a
        dictionary of data passed in.  Raises an error if an annotation
        author is not found as a user in the database.'''
        note = Annotation()

        # NOTE: because we are using uuid for annotation id field,
        # importing an annotation twice does not error, but simply
        # replaces the old copy.  Might want to add checks for this...

        # required fields that should always be present
        # (not normally set by user)
        for field in ['updated', 'created', 'id']:
            setattr(note, field, data[field])
            del data[field]
        # user is special: annotation data only includes username,
        # but we need a user object
        # NOTE: this could result in making one person's annotations
        # available to someone else, if someone is using a different
        # username in another instance
        if 'user' in data:
            try:
                note.user = get_user_model().objects.get(username=data['user'])
                del data['user']
            except get_user_model().DoesNotExist:
                raise CommandError(
                    'Cannot import annotations for user %s (does not exist)' %
                    data['user'])

        for field in Annotation.common_fields:
            if field in data:
                setattr(note, field, data[field])
                del data[field]

        # put any other data that is left in extra data json field
        if data:
            note.extra_data.update(data)

        note.save()
Beispiel #4
0
    def import_annotation(self, data):
        '''Create and save a new annotation, setting fields based on a
        dictionary of data passed in.  Raises an error if an annotation
        author is not found as a user in the database.'''
        note = Annotation()

        # NOTE: because we are using uuid for annotation id field,
        # importing an annotation twice does not error, but simply
        # replaces the old copy.  Might want to add checks for this...

        # required fields that should always be present
        # (not normally set by user)
        for field in ['updated', 'created', 'id']:
            setattr(note, field, data[field])
            del data[field]
        # user is special: annotation data only includes username,
        # but we need a user object
        # NOTE: this could result in making one person's annotations
        # available to someone else, if someone is using a different
        # username in another instance
        if 'user' in data:
            try:
                note.user = get_user_model().objects.get(username=data['user'])
                del data['user']
            except get_user_model().DoesNotExist:
                raise CommandError('Cannot import annotations for user %s (does not exist)' % data['user'])

        for field in Annotation.common_fields:
            if field in data:
                setattr(note, field, data[field])
                del data[field]

        # put any other data that is left in extra data json field
        if data:
            note.extra_data.update(data)

        note.save()
Beispiel #5
0
    def test_annotated_tei(self):
        # create annotation with a user
        user = get_user_model()(username='******',
            first_name="Anne", last_name="O'Tater")
        user.save()
        page_uri = "http://readux.co/books/pages/some:1/"
        note = Annotation(text="Here's the thing", quote="really",
            uri=page_uri,
            extra_data=json.dumps({
                'sample data': 'foobar',
                'tags': ['test', 'one', 'two'],
                'ranges': [
                    {'start': '//div[@id="fnstr.idm320760248608"]/span[1]',
                     'end': '//div[@id="fnstr.idm320760242176"]/span[1]',
                     'startOffset': 0,
                     'endOffset': 6
                     }
                ],
                'ark': page_uri
                }),
            user=user)
        note.save()
        imagenote = Annotation(text='interesting image detail', uri=page_uri,
            user=user,
            extra_data=json.dumps({
                'image_selection': {
                    # NOTE: image src currently not checked when generating annotated tei
                    'h': '20.73%',
                    'w': '14.70%',
                    'y': '62.42%',
                    'x': '61.60%'
                    },
                'ark': page_uri
                })
            )
        imagenote.save()

        # use page tei fixture as starting point
        title = 'Lecoq'
        teidoc = load_xmlobject_from_file(os.path.join(FIXTURE_DIR, 'teifacsimile.xml'),
            tei.AnnotatedFacsimile)
        teidoc.title = title
        teidoc.page.href = page_uri
        del teidoc.responsible_names[0]  # remove empty resp name from fixture

        annotei = annotated_tei(teidoc, Annotation.objects.all())
        self.assert_(isinstance(annotei, tei.AnnotatedFacsimile),
            'annotated_tei should return an insance of tei.AnnotatedFacsimile')

        # title should be updated, split into main and subtitle parts
        self.assertEqual(title, annotei.main_title)
        self.assertEqual(', an annotated digital edition', annotei.subtitle)
        self.assertEqual('annotated by', annotei.responsibility)
        # annotation authors should be added in resp statement
        self.assertEqual(user.username, annotei.responsible_names[0].id)
        self.assertEqual(user.get_full_name(), annotei.responsible_names[0].value)

        # publication statement should include readux version, current date
        self.assert_('Annotated TEI generated by Readux' in annotei.pubstmt.desc)
        self.assert_(__version__ in annotei.pubstmt.desc)
        today = datetime.date.today()
        self.assertEqual(today, annotei.pubstmt.date)
        self.assertEqual(today, annotei.pubstmt.date_normal)

        # tei annotation should be added to body for text note
        self.assertEqual('annotation-%s' % note.id, annotei.annotations[0].id)
        # start/end highlight anchors should be added to facsimile
        self.assert_(annotei.node.xpath('//tei:anchor[@xml:id="highlight-start-%s"]' % note.id,
            namespaces=tei.Zone.ROOT_NAMESPACES))
        self.assert_(annotei.node.xpath('//tei:anchor[@xml:id="highlight-end-%s"]' % note.id,
            namespaces=tei.Zone.ROOT_NAMESPACES))

        # tei annotation should be added to body for image note
        self.assertEqual('annotation-%s' % imagenote.id, annotei.annotations[1].id)
        # zone added for image highlight
        self.assert_(annotei.node.xpath('//tei:zone[@xml:id="highlight-%s"][@type="image-annotation-highlight"]' % imagenote.id,
            namespaces=tei.Zone.ROOT_NAMESPACES))

        # tags added to back as interp group
        self.assertEqual('test', annotei.tags.interp[0].id)
        self.assertEqual('test', annotei.tags.interp[0].value)

        # encoding desc should be present
        self.assert_(annotei.encoding_desc)