def extract_with_range_submitted_in_reply_post_1(request, discussion_admin_user, reply_post_1, subidea_1_1, discussion, test_session): """ Create an extract of a given range of text in a message """ from assembl.models import Extract, TextFragmentIdentifier, ExtractStates extract_body = "variable-temperature spectra indicate the onset of oxide-ion motion involving the interstitials at 130 °C, which is linked to an orthorhombic−tetragonal phase transition. For the V-doped phases, an oxide-ion conduction mechanism is observed that involves oxygen exchange between the Bi-O sublattice and rapidly rotating VO4 tetrahedral units. The more poorly conducting P-doped phase exhibits only vacancy conduction with no evidence of sublattice exchange, a result ascribed to the differing propensities of the dopants to undergo variable oxygen coordination. So I think it would be a very bad idea to allow hot beverages in coworking spaces." xpathStart = u"//div[@id='message-body-local:Content/%s']/" % reply_post_1.id xpathEnd = xpathStart offsetStart = 314 offsetEnd = 958 lang = 'en' extract_hash = Extract.get_extract_hash(lang, xpathStart, xpathEnd, offsetStart, offsetEnd, reply_post_1.id) new_extract = Extract(creator_id=discussion_admin_user.id, owner_id=discussion_admin_user.id, discussion_id=discussion.id, body=extract_body, important=True, content=reply_post_1, extract_state=ExtractStates.SUBMITTED.value, extract_hash=extract_hash) new_extract.lang = lang test_session.add(new_extract) new_range = TextFragmentIdentifier(extract=new_extract, xpath_start=xpathStart, offset_start=offsetStart, xpath_end=xpathEnd, offset_end=offsetEnd) test_session.add(new_range) test_session.flush() def fin(): print "finalizer extract_with_range_submitted_in_reply_post_1" test_session.delete(new_range) test_session.delete(new_extract) test_session.flush() request.addfinalizer(fin) return new_extract
def post_extract(request): """ Create a new extract. """ extract_data = json.loads(request.body) discussion_id = int(request.matchdict['discussion_id']) user_id = request.authenticated_userid if not user_id: # Straight from annotator token = request.headers.get('X-Annotator-Auth-Token') if token: token = decode_token(token, request.registry.settings['session.secret']) if token: user_id = token['userId'] user_id = user_id or Everyone if not user_has_permission(discussion_id, user_id, P_ADD_EXTRACT): #TODO: maparent: restore this code once it works: #return HTTPForbidden(result=ACLDenied(permission=P_ADD_EXTRACT)) return HTTPForbidden() if not user_id or user_id == Everyone: # TODO: Create an anonymous user. raise HTTPServerError("Anonymous extracts are not implemeted yet.") content = None uri = extract_data.get('uri') important = extract_data.get('important', False) annotation_text = None if uri: # Straight from annotator annotation_text = extract_data.get('text') else: target = extract_data.get('target') if not (target or uri): raise HTTPBadRequest("No target") target_class = sqla.get_named_class(target.get('@type')) if issubclass(target_class, Post): post_id = target.get('@id') post = Post.get_instance(post_id) if not post: raise HTTPNotFound("Post with id '%s' not found." % post_id) content = post elif issubclass(target_class, Webpage): uri = target.get('url') if uri and not content: content = Webpage.get_instance(uri) if not content: # TODO: maparent: This is actually a singleton pattern, should be # handled by the AnnotatorSource now that it exists... source = AnnotatorSource.default_db.query( AnnotatorSource).filter_by(discussion_id=discussion_id).filter( cast(AnnotatorSource.name, Unicode) == 'Annotator').first() if not source: source = AnnotatorSource(name='Annotator', discussion_id=discussion_id) content = Webpage(url=uri, discussion_id=discussion_id) extract_body = extract_data.get('quote', '') idea_id = extract_data.get('idIdea', None) if idea_id: idea = Idea.get_instance(idea_id) if (idea.discussion.id != discussion_id): raise HTTPBadRequest( "Extract from discussion %s cannot be associated with an idea from a different discussion." % extract.get_discussion_id()) else: idea = None ranges = extract_data.get('ranges', []) extract_hash = Extract.get_extract_hash( None, u"".join([r['start'] for r in ranges]), u"".join([r['end'] for r in ranges]), u"".join([r['startOffset'] for r in ranges]), u"".join([r['endOffset'] for r in ranges]), content.id) new_extract = Extract(creator_id=user_id, owner_id=user_id, discussion_id=discussion_id, body=extract_body, idea=idea, important=important, annotation_text=annotation_text, content=content, extract_hash=extract_hash) Extract.default_db.add(new_extract) for range_data in ranges: range = TextFragmentIdentifier(extract=new_extract, xpath_start=range_data['start'], offset_start=range_data['startOffset'], xpath_end=range_data['end'], offset_end=range_data['endOffset']) TextFragmentIdentifier.default_db.add(range) Extract.default_db.flush() return {'ok': True, '@id': new_extract.uri()}
def post_extract(request): """ Create a new extract. """ extract_data = json.loads(request.body) discussion_id = int(request.matchdict['discussion_id']) user_id = request.authenticated_userid if not user_id: # Straight from annotator token = request.headers.get('X-Annotator-Auth-Token') if token: token = decode_token( token, request.registry.settings['session.secret']) if token: user_id = token['userId'] user_id = user_id or Everyone if not user_has_permission(discussion_id, user_id, P_ADD_EXTRACT): #TODO: maparent: restore this code once it works: #return HTTPForbidden(result=ACLDenied(permission=P_ADD_EXTRACT)) return HTTPForbidden() if not user_id or user_id == Everyone: # TODO: Create an anonymous user. raise HTTPServerError("Anonymous extracts are not implemeted yet.") content = None uri = extract_data.get('uri') important = extract_data.get('important', False) annotation_text = None if uri: # Straight from annotator annotation_text = extract_data.get('text') else: target = extract_data.get('target') if not (target or uri): raise HTTPBadRequest("No target") target_class = sqla.get_named_class(target.get('@type')) if issubclass(target_class, Post): post_id = target.get('@id') post = Post.get_instance(post_id) if not post: raise HTTPNotFound( "Post with id '%s' not found." % post_id) content = post elif issubclass(target_class, Webpage): uri = target.get('url') if uri and not content: content = Webpage.get_instance(uri) if not content: # TODO: maparent: This is actually a singleton pattern, should be # handled by the AnnotatorSource now that it exists... source = AnnotatorSource.default_db.query(AnnotatorSource).filter_by( discussion_id=discussion_id).filter( cast(AnnotatorSource.name, Unicode) == 'Annotator').first() if not source: source = AnnotatorSource( name='Annotator', discussion_id=discussion_id) content = Webpage(url=uri, discussion_id=discussion_id) extract_body = extract_data.get('quote', '') idea_id = extract_data.get('idIdea', None) if idea_id: idea = Idea.get_instance(idea_id) if(idea.discussion.id != discussion_id): raise HTTPBadRequest( "Extract from discussion %s cannot be associated with an idea from a different discussion." % extract.get_discussion_id()) else: idea = None ranges = extract_data.get('ranges', []) extract_hash = Extract.get_extract_hash( None, u"".join([r['start'] for r in ranges]), u"".join([r['end'] for r in ranges]), u"".join([r['startOffset'] for r in ranges]), u"".join([r['endOffset'] for r in ranges]), content.id ) new_extract = Extract( creator_id=user_id, owner_id=user_id, discussion_id=discussion_id, body=extract_body, idea=idea, important=important, annotation_text=annotation_text, content=content, extract_hash=extract_hash ) Extract.default_db.add(new_extract) for range_data in ranges: range = TextFragmentIdentifier( extract=new_extract, xpath_start=range_data['start'], offset_start=range_data['startOffset'], xpath_end=range_data['end'], offset_end=range_data['endOffset']) TextFragmentIdentifier.default_db.add(range) Extract.default_db.flush() return {'ok': True, '@id': new_extract.uri()}