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'])
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'])
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()
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()
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)