def test_project_create_read(self): """ Tests creation by POST to /save and reading with GET of /project/:id/ """ django_client = self.django_root_client group = self.ctx.groupId version = api_settings.API_VERSIONS[-1] # Need to get the Schema url to create @type base_url = reverse('api_base', kwargs={'api_version': version}) rsp = get_json(django_client, base_url) schema_url = rsp['url:schema'] # specify group via query params save_url = "%s?group=%s" % (rsp['url:save'], group) projects_url = rsp['url:projects'] project_name = 'test_api_projects' payload = {'Name': project_name, '@type': schema_url + '#Project'} rsp = post_json(django_client, save_url, payload, status_code=201) new_proj = rsp['data'] # We get the complete new Project returned assert new_proj['Name'] == project_name project_id = new_proj['@id'] # Read Project project_url = "%s%s/" % (projects_url, project_id) rsp = get_json(django_client, project_url) new_proj = rsp['data'] assert new_proj['@id'] == project_id conn = BlitzGateway(client_obj=self.root) assert_objects(conn, [new_proj], [project_id])
def test_link_unlink_tagset_tags(self): """ Tests linking of tagset to tag, then unlinking """ tag = self.make_tag() tagset = self.make_tag(ns=omero.constants.metadata.NSINSIGHTTAGSET) tagId = tag.id.val tagsetId = tagset.id.val links_url = reverse("api_links") # Link tagset to tag data = {'tagset': {tagsetId: {'tag': [tagId]}}} rsp = post_json(self.django_client, links_url, data) assert rsp == {"success": True} # Check that tag is listed under tagset... tags_url = reverse("api_tags_and_tagged") r = get_json(self.django_client, tags_url, {'id': tagsetId}) assert len(r['tags']) == 1 assert r['tags'][0]['id'] == tagId # Unlink first Tag from Tagset # data {} is same as for creating link above response = delete_json(self.django_client, links_url, data) assert response["success"] # Since the Delete is ansync - need to check repeatedly for deletion for i in range(10): rsp = get_json(self.django_client, tags_url, {'id': tagsetId}) if len(rsp['tags']) == 0: break sleep(0.5) # Check that link has been deleted assert len(rsp['tags']) == 0
def test_validation_exception(self, user_A): """Test handling when we try to save something invalid.""" conn = get_connection(user_A) group = conn.getEventContext().groupId userName = conn.getUser().getName() django_client = self.new_django_client(userName, userName) version = api_settings.API_VERSIONS[-1] save_url = reverse('api_save', kwargs={'api_version': version}) save_url += '?group=' + native_str(group) # Create Tag tag = TagAnnotationI() tag.textValue = rstring('test_tag') tag = conn.getUpdateService().saveAndReturnObject(tag) tag_json = {'Value': 'test_tag', '@id': tag.id.val, '@type': OME_SCHEMA_URL + '#TagAnnotation'} # Add Tag twice to Project to get Validation Exception payload = {'Name': 'test_validation', '@type': OME_SCHEMA_URL + '#Project', 'Annotations': [tag_json, tag_json]} rsp = post_json(django_client, save_url, payload, status_code=400) # NB: message contains whole stack trace assert "ValidationException" in rsp['message'] assert rsp['stacktrace'].startswith( 'Traceback (most recent call last):')
def test_security_violation(self, group_B, user_A): """Test saving to incorrect group.""" conn = get_connection(user_A) group_A_id = conn.getEventContext().groupId userName = conn.getUser().getName() django_client = self.new_django_client(userName, userName) version = api_settings.API_VERSIONS[-1] group_B_id = group_B.id.val save_url = reverse('api_save', kwargs={'api_version': version}) # Create project in group_A (default group) payload = {'Name': 'test_security_violation', '@type': OME_SCHEMA_URL + '#Project'} save_url_grp_A = save_url + '?group=' + native_str(group_A_id) rsp = post_json(django_client, save_url_grp_A, payload, status_code=201) pr_json = rsp['data'] projectId = pr_json['@id'] # Try to save again into group B save_url_grp_B = save_url + '?group=' + native_str(group_B_id) rsp = put_json(django_client, save_url_grp_B, pr_json, status_code=403) assert 'message' in rsp msg = "Cannot read ome.model.containers.Project:Id_%s" % projectId assert msg in rsp['message'] assert rsp['stacktrace'].startswith( 'Traceback (most recent call last):')
def test_marshal_type(self): """If no decoder found for @type, get suitable message.""" django_client = self.django_root_client version = api_settings.API_VERSIONS[-1] save_url = reverse('api_save', kwargs={'api_version': version}) objType = 'SomeInvalidSchema#Project' payload = {'Name': 'test_marshal_type', '@type': objType} rsp = post_json(django_client, save_url, payload, status_code=400) assert (rsp['message'] == 'No decoder found for type: %s' % objType)
def test_link_datasets_images(self, datasets, images): # Link Datasets to Images request_url = reverse("api_links") dids = [d.id.val for d in datasets] iids = [i.id.val for i in images] # Link first dataset to first image, # Second dataset linked to both images data = { 'dataset': { dids[0]: { 'image': [iids[0]] }, dids[1]: { 'image': iids } } } rsp = post_json(self.django_client, request_url, data) assert rsp == {"success": True} # Check links images_url = reverse("api_images") # First Dataset has single image rsp = get_json(self.django_client, images_url, {'id': dids[0]}) assert len(rsp['images']) == 1 assert rsp['images'][0]['id'] == iids[0] # Second Dataset has both images rsp = get_json(self.django_client, images_url, {'id': dids[1]}) assert len(rsp['images']) == 2 assert rsp['images'][0]['id'] == iids[0] assert rsp['images'][1]['id'] == iids[1] # Link BOTH images to first Dataset. Shouldn't get any # Validation Exception, even though first image is already linked data = {'dataset': {dids[0]: {'image': iids}}} rsp = post_json(self.django_client, request_url, data) assert rsp == {"success": True} # Check first Dataset now has both images rsp = get_json(self.django_client, images_url, {'id': dids[0]}) assert len(rsp['images']) == 2 assert rsp['images'][0]['id'] == iids[0] assert rsp['images'][1]['id'] == iids[1]
def test_save_post_no_id(self): """If POST to /save/ data shouldn't contain @id.""" django_client = self.django_root_client version = api_settings.API_VERSIONS[-1] save_url = reverse('api_save', kwargs={'api_version': version}) payload = {'Name': 'test_save_post_no_id', '@type': '%s#Project' % OME_SCHEMA_URL, '@id': 1} rsp = post_json(django_client, save_url, payload, status_code=400) assert (rsp['message'] == "Object has '@id' attribute. Use PUT to update objects")
def test_project_create_other_group(self, user1, projects_user1_group2): """ Test saving to non-default group """ conn = get_connection(user1) user_name = conn.getUser().getName() django_client = self.new_django_client(user_name, user_name) version = api_settings.API_VERSIONS[-1] # We're only using projects_user1_group2 to get group2 id group2_id = projects_user1_group2[0].getDetails().group.id.val # This seems to be the minimum details needed to pass group ID group2_details = { 'group': { '@id': group2_id, '@type': OME_SCHEMA_URL + '#ExperimenterGroup' }, '@type': 'TBD#Details' } save_url = reverse('api_save', kwargs={'api_version': version}) project_name = 'test_project_create_group' payload = {'Name': project_name, '@type': OME_SCHEMA_URL + '#Project'} # Saving fails with NO group specified rsp = post_json(django_client, save_url, payload, status_code=400) assert rsp['message'] == ("Specify Group in omero:details or " "query parameters ?group=:id") # Add group details and try again payload['omero:details'] = group2_details rsp = post_json(django_client, save_url, payload, status_code=201) new_proj = rsp['data'] new_project_id = new_proj['@id'] assert new_proj['omero:details']['group']['@id'] == group2_id # Read Project project_url = reverse('api_project', kwargs={ 'api_version': version, 'object_id': new_project_id }) rsp = get_json(django_client, project_url) assert rsp['data']['omero:details']['group']['@id'] == group2_id
def test_marshal_validation(self): """Test that we get expected error with invalid @type in json.""" django_client = self.django_root_client version = api_settings.API_VERSIONS[-1] save_url = reverse('api_save', kwargs={'api_version': version}) payload = {'Name': 'test_marshal_validation', '@type': OME_SCHEMA_URL + '#Project', 'omero:details': {'@type': 'foo'}} rsp = post_json(django_client, save_url, payload, status_code=400) assert (rsp['message'] == "Error in decode of json data by omero_marshal") assert rsp['stacktrace'].startswith( 'Traceback (most recent call last):')
def test_container_crud(self, dtype): """ Test create, read, update and delete of Containers. Create with POST to /save Read with GET of /m/dtype/:id/ Update with PUT to /m/dtype/:id/ Delete with DELETE to /m/dtype/:id/ """ django_client = self.django_root_client group = self.ctx.groupId version = api_settings.API_VERSIONS[-1] # Need to get the Schema url to create @type base_url = reverse('api_base', kwargs={'api_version': version}) rsp = get_json(django_client, base_url) schema_url = rsp['url:schema'] # specify group via query params save_url = "%s?group=%s" % (rsp['url:save'], group) project_name = 'test_container_create_read' payload = { 'Name': project_name, '@type': '%s#%s' % (schema_url, dtype) } rsp = post_json(django_client, save_url, payload, status_code=201) new_obj = rsp['data'] # We get the complete new Object returned assert new_obj['Name'] == project_name object_id = new_obj['@id'] # Read Object object_url = "%sm/%ss/%s/" % (base_url, dtype.lower(), object_id) rsp = get_json(django_client, object_url) object_json = rsp['data'] assert object_json['@id'] == object_id conn = BlitzGateway(client_obj=self.root) assert_objects(conn, [object_json], [object_id], dtype=dtype) # Update Object... object_json['Name'] = 'new name' rsp = put_json(django_client, save_url, object_json) # ...and read again to check rsp = get_json(django_client, object_url) updated_json = rsp['data'] assert updated_json['Name'] == 'new name' # Delete delete_json(django_client, object_url, {}) # Get should now return 404 rsp = get_json(django_client, object_url, status_code=404)
def test_paste_move_remove_deletamany_image(self): # Add dataset request_url = reverse("manage_action_containers", args=["addnewcontainer"]) data = {'folder_type': 'dataset', 'name': 'foobar'} response = post(self.django_client, request_url, data) did = json.loads(response.content).get("id") img = self.make_image() print img # Link image to Dataset request_url = reverse("api_links") data = {'dataset': {did: {'image': [img.id.val]}}} post_json(self.django_client, request_url, data) # Unlink image from Dataset request_url = reverse("api_links") data = {'dataset': {did: {'image': [img.id.val]}}} response = delete_json(self.django_client, request_url, data) # Response will contain remaining links from image (see test_links.py) assert response == {"success": True}
def test_link_project_datasets(self, project, datasets): # Link Project to Datasets request_url = reverse("api_links") pid = project.id.val dids = [d.id.val for d in datasets] data = {'project': {pid: {'dataset': dids}}} rsp = post_json(self.django_client, request_url, data) assert rsp == {"success": True} # Check links request_url = reverse("api_datasets") rsp = get_json(self.django_client, request_url, {'id': pid}) # Expect a single Dataset with correct id assert len(rsp['datasets']) == 2 assert rsp['datasets'][0]['id'] == dids[0] assert rsp['datasets'][1]['id'] == dids[1]
def test_unlink_screen_plate(self, screens, plates): # Link both plates to both screens request_url = reverse("api_links") sids = [s.id.val for s in screens] pids = [p.id.val for p in plates] data = { 'screen': {sids[0]: {'plate': pids}, sids[1]: {'plate': pids}} } rsp = post_json(self.django_client, request_url, data) assert rsp == {"success": True} # Confirm that first Screen linked to 2 Plates plates_url = reverse("api_plates") rsp = get_json(self.django_client, plates_url, {'id': sids[0]}) assert len(rsp['plates']) == 2 # Unlink first Plate from first Screen request_url = reverse("api_links") data = { 'screen': {sids[0]: {'plate': pids[:1]}} } response = delete_json(self.django_client, request_url, data) # Returns remaining link from 2nd Screen to first Plate assert response == {"success": True, "screen": {str(sids[1]): {"plate": pids[:1]}} } # Since the Delete is ansync - need to check repeatedly for deletion # by counting plates under screen... plates_url = reverse("api_plates") for i in range(10): rsp = get_json(self.django_client, plates_url, {'id': sids[0]}) if len(rsp['plates']) == 1: break sleep(0.5) # Check that link has been deleted, leaving 2nd plate under 1st screen assert len(rsp['plates']) == 1 assert rsp['plates'][0]['id'] == pids[1]
def test_save_rois(self, conn, django_client): """Save new ROIs to an Image""" image = self.make_image(client=conn.c) roi = RoiI() roi.name = rstring("roi_name") roi.setImage(ImageI(image.id.val, False)) point = PointI() point.x = rdouble(1) point.y = rdouble(2) encoder = get_encoder(point.__class__) point_json = encoder.encode(point) unsaved_id = "-1:-1" point_json['oldId'] = unsaved_id persist_url = reverse('omero_iviewer_persist_rois') data = { 'imageId': image.id.val, 'rois': { 'count': 1, 'new': [point_json] } } rsp = post_json(django_client, persist_url, data) print('rsp', rsp) # {"ids": {"-1:-1": "225504:416603"}} assert "ids" in rsp new_ids = rsp["ids"].values() assert len(new_ids) == 1 new_id = rsp["ids"][unsaved_id] roi_id = int(new_id.split(':')[0]) shape_id = int(new_id.split(':')[1]) # Add Tag to ROI and Shape tag = TagAnnotationWrapper(conn) tag.setValue("ROI/Shape Tag") tag.save() roi = conn.getObject("Roi", roi_id) roi.linkAnnotation(tag) shape = conn.getObject("Shape", shape_id) shape.linkAnnotation(tag) # check... assert len(list(conn.getAnnotationLinks( "Shape", parent_ids=[shape_id]))) == 1 # Load Shape rois_url = reverse('api_rois', kwargs={'api_version': 0}) rois_url += '?image=%s' % image.id.val rsp = get_json(django_client, rois_url) assert len(rsp['data']) == 1 # Edit Shape point_json = rsp['data'][0]['shapes'][0] point_json["X"] = 100 point_json["Y"] = 200 # iviewer wants to know ROI:Shape ID point_json["oldId"] = new_id # Unload details del point_json["omero:details"] data = { 'imageId': image.id.val, 'rois': { 'count': 1, 'modified': [point_json] } } rsp = post_json(django_client, persist_url, data) # IDs shouldn't have changed, e.g. # {"ids": {"225504:416603": "225504:416603"}} print('post rsp', rsp) assert rsp["ids"][new_id] == new_id # Check annotations not lost roi = conn.getObject("Roi", roi_id) assert len(list(roi.listAnnotations())) == 1 assert len(list(conn.getAnnotationLinks( "Shape", parent_ids=[shape_id]))) == 1