correct critical sections handling
authorymh <ymh.work@gmail.com>
Thu, 10 Sep 2015 12:04:06 +0200
changeset 1428 26e3ee748327
parent 1427 19d1f3311e89
child 1429 bb5fc6324484
correct critical sections handling
src/ldt/ldt/api/ldt/resources/annotation.py
--- a/src/ldt/ldt/api/ldt/resources/annotation.py	Mon Sep 07 17:25:08 2015 +0200
+++ b/src/ldt/ldt/api/ldt/resources/annotation.py	Thu Sep 10 12:04:06 2015 +0200
@@ -2,6 +2,7 @@
 from ldt.ldt_utils.models import Project, Content, Segment
 from ldt.ldt_utils.utils import LdtAnnotation
 from ldt.security import protect_models, unprotect_models
+
 from tastypie import fields
 from tastypie.authorization import Authorization
 from tastypie.exceptions import NotFound, BadRequest
@@ -9,7 +10,7 @@
 
 
 class AnnotationObject(object):
-    def __init__(self, id="", project = "", type = "", type_title = "", ensemble="", media = "", begin = 0, end = 0, content = {"title":"", "description":""}, tags = [], meta = {"creator":"","created":""}):  # @ReservedAssignment
+    def __init__(self, id="", project="", type="", type_title="", ensemble="", media="", begin=0, end=0, content={"title":"", "description":""}, tags=[], meta={"creator":"", "created":""}):  # @ReservedAssignment
         self.id = id
         self.project = project
         self.type = type
@@ -21,20 +22,20 @@
         self.content = content
         self.tags = tags
         self.meta = meta
-    
+
 class AnnotationResource(Resource):
     # For the moment, these attributes are useless. We just prepare relations to AnnotationObject
-    id = fields.CharField(attribute = 'id')
-    project = fields.CharField(attribute = 'project')
-    type = fields.CharField(attribute = 'type')
-    type_title = fields.CharField(attribute = 'type_title')
-    media = fields.CharField(attribute = 'media')
-    begin = fields.IntegerField(attribute = 'begin')
-    end = fields.IntegerField(attribute = 'end')
-    content = fields.DictField(attribute = 'content')
-    tags = fields.ListField(attribute = 'tags')
-    meta = fields.DictField(attribute = 'meta')
-    
+    id = fields.CharField(attribute='id')
+    project = fields.CharField(attribute='project')
+    type = fields.CharField(attribute='type')
+    type_title = fields.CharField(attribute='type_title')
+    media = fields.CharField(attribute='media')
+    begin = fields.IntegerField(attribute='begin')
+    end = fields.IntegerField(attribute='end')
+    content = fields.DictField(attribute='content')
+    tags = fields.ListField(attribute='tags')
+    meta = fields.DictField(attribute='meta')
+
     class Meta:
         allowed_methods = ['post', 'put', 'delete']
         resource_name = 'annotations'
@@ -43,19 +44,19 @@
         # always_return_data = True because we want the api returns the data with the updated ids
         always_return_data = True
         include_resource_uri = False
-    
+
     def extract_annotation_data(self, data):
         # This method extracts and validates the data we receive from the user for adding or editing an annotation
-        
+
         project_id = ""
         if data.has_key('project') :
             project_id = data["project"]
-            
+
         if data.has_key('media') :
             iri_id = data["media"]
         else :
             raise BadRequest
-        
+
         if project_id and project_id != "" :
             try:
                 project = Project.objects.get(ldt_id=project_id)
@@ -69,40 +70,40 @@
                 raise NotFound("Content not found. iri_id = " + iri_id)
             project = content.get_or_create_front_project()
             project_id = project.ldt_id
-        
-        ann_duration = -1
-        ann_begin = -1
-        ann_end = -1
+
+        ann_duration = 0
+        ann_begin = 0
+        ann_end = 0
         if (data.has_key('begin') and data.has_key('end')):
             ann_duration = str(data['end'] - data['begin'])
             ann_begin = str(data['begin'])
             ann_end = str(data['end'])
-        
+
         ann_audio_src = data.get('content', {}).get('audio', {}).get('src', "")
         ann_audio_href = data.get('content', {}).get('audio', {}).get('href', "")
-        
+
         ann_author = data.get('meta', {}).get('creator', "")
         ann_date = data.get('meta', {}).get('created', "")
-        
+
         ann_type_id = data.get('type', '')
         ann_type_title = data.get('type_title', '')
         ann_id = data.get("id", "")
-        ann_title = data.get('content', {}).get('title', "") 
+        ann_title = data.get('content', {}).get('title', "")
         ann_description = data.get('content', {}).get('description')
         ann_tags = data.get('tags', [])
-        
+
         content = project.contents.get(iri_id=iri_id)
-        
+
         return {
             "project_obj" : project,
             "project_id" : project_id,
-            "content_obj" : content,  
+            "content_obj" : content,
             "iri_id" : iri_id,
-            "ann_type_id" : ann_type_id, 
+            "ann_type_id" : ann_type_id,
             "ann_type_title" : ann_type_title,
             "ann_id" : ann_id,
-            "ann_content" : { 
-                "title" : ann_title, 
+            "ann_content" : {
+                "title" : ann_title,
                 "description" : ann_description,
                 "audio" : {
                     "src" : ann_audio_src,
@@ -118,123 +119,49 @@
             "ann_end" : ann_end,
             "ann_duration" : ann_duration,
         }
-    
+
     def obj_delete_list(self, bundle, **kwargs):
         return True
-    
+
     def obj_create(self, bundle, **kwargs):
-        # Here the a has the datas for only one annotation. Tastypie's post allows only one resource addition 
+        # Here the a has the datas for only one annotation. Tastypie's post allows only one resource addition
         data_dict = self.extract_annotation_data(bundle.data)
         adder = LdtAnnotation(data_dict["project_obj"])
-        
-        unprotect_models() # Allows anonymous user to modify models in this request only
 
-        type_id, new_id, ensemble_id = adder.add(
-            data_dict['iri_id'], # media
-            data_dict['ann_type_id'], # cutting_id
-            data_dict['ann_type_title'], # cutting_title
-            data_dict['ann_content']['title'], # title
-            data_dict['ann_content']['description'], # text
-            data_dict['ann_tags'], # tags_list
-            data_dict['ann_begin'], # begin
-            data_dict['ann_duration'], # dur
-            data_dict['ann_meta']['creator'], # author
-            data_dict['ann_meta']['created'], # date
-            None, 
-            "2194379", 
-            data_dict['ann_content']['audio']['src'], 
-            data_dict['ann_content']['audio']['href']
-        )
-
-        if not new_id:
-            protect_models()
-            raise BadRequest
-                        
-        # We update the ids
-        data_dict['ann_type_id'] = type_id
-        data_dict['ensemble_id'] = ensemble_id
-        data_dict['ann_id'] = new_id
+        unprotect_models()  # Allows anonymous user to modify models in this request only
 
-        #add segment
-        add_segment({
-            "project" : data_dict["project_obj"],
-            "content" : data_dict["content_obj"],
-            "ensemble_id" : data_dict["ensemble_id"],
-            "cutting_id" :  data_dict['ann_type_id'],            
-            "element_id" : data_dict['ann_id'],
-            "title" : data_dict['ann_content']['title'],
-            "abstract" : data_dict['ann_content']['description'],
-            "tags" : ",".join(data_dict['ann_tags']),
-            "start_ts" : data_dict['ann_begin'],
-            "duration" :  data_dict['ann_duration'],
-            "author" : data_dict['ann_meta']['creator'],
-            "date" : data_dict['ann_meta']['created'], 
-            "audio_src" : data_dict['ann_content']['audio']['src'],            
-            "audio_href" : data_dict['ann_content']['audio']['href'],
-            "polemics": adder.get_polemic_syntax(data_dict['ann_content']['title'])
-        })
-            
-        # We save the added annotation and reprotect the contents and projects
-        adder.save(must_reindex=False)
-        protect_models()
-        # We update the AnnotationObject for the returned datas to be correct.
-        bundle.obj = AnnotationObject(
-            id = data_dict["ann_id"], 
-            project = data_dict["project_id"], 
-            type = data_dict["ann_type_id"], 
-            type_title = data_dict["ann_type_title"], 
-            ensemble = data_dict['ensemble_id'], 
-            media = data_dict["iri_id"], 
-            begin = data_dict["ann_begin"], 
-            end = data_dict["ann_end"], 
-            content = data_dict['ann_content'], 
-            tags = data_dict['ann_tags'], 
-            meta = data_dict['ann_meta']
-        )
-        return bundle
-    
-    def obj_update(self, bundle, **kwargs):
-        data_dict = self.extract_annotation_data(bundle.data)
-        if data_dict['ann_id'] == "":
-            data_dict['ann_id'] == kwargs["pk"]
-        
-        adder = LdtAnnotation(data_dict["project_obj"])
-        unprotect_models() # Allows anonymous user to modify models in this request only
-        
-        ensemble_id = adder.edit(
-            data_dict['ann_id'], # annotation_id
-            data_dict['iri_id'], # media
-            data_dict['ann_type_id'], # cutting_id
-            data_dict['ann_type_title'], # cutting_title
-            data_dict['ann_content']['title'], # title
-            data_dict['ann_content']['description'], # text
-            data_dict['ann_tags'], # tags_list
-            data_dict['ann_begin'], # begin
-            data_dict['ann_duration'], # dur
-            data_dict['ann_meta']['creator'], # author
-            data_dict['ann_meta']['created'], # date
-            None, 
-            "2194379", 
-            data_dict['ann_content']['audio']['src'], 
-            data_dict['ann_content']['audio']['href']
-        )
-        if not ensemble_id:
-            protect_models()
-            raise BadRequest
-        # We update the id
-        data_dict['ensemble_id'] = ensemble_id
-        #add segment
-        edit_segment(
-            data_dict["project_id"],
-            data_dict["iri_id"],
-            data_dict["ensemble_id"],
-            data_dict['ann_type_id'],
-            data_dict["ann_id"],
-            params = {
+        try:
+            type_id, new_id, ensemble_id = adder.add(
+                data_dict['iri_id'],  # media
+                data_dict['ann_type_id'],  # cutting_id
+                data_dict['ann_type_title'],  # cutting_title
+                data_dict['ann_content']['title'],  # title
+                data_dict['ann_content']['description'],  # text
+                data_dict['ann_tags'],  # tags_list
+                data_dict['ann_begin'],  # begin
+                data_dict['ann_duration'],  # dur
+                data_dict['ann_meta']['creator'],  # author
+                data_dict['ann_meta']['created'],  # date
+                None,
+                "2194379",
+                data_dict['ann_content']['audio']['src'],
+                data_dict['ann_content']['audio']['href']
+            )
+
+            if not new_id:
+                raise BadRequest
+
+            # We update the ids
+            data_dict['ann_type_id'] = type_id
+            data_dict['ensemble_id'] = ensemble_id
+            data_dict['ann_id'] = new_id
+
+            # add segment
+            add_segment({
                 "project" : data_dict["project_obj"],
                 "content" : data_dict["content_obj"],
                 "ensemble_id" : data_dict["ensemble_id"],
-                "cutting_id" :  data_dict['ann_type_id'],            
+                "cutting_id" :  data_dict['ann_type_id'],
                 "element_id" : data_dict['ann_id'],
                 "title" : data_dict['ann_content']['title'],
                 "abstract" : data_dict['ann_content']['description'],
@@ -242,58 +169,134 @@
                 "start_ts" : data_dict['ann_begin'],
                 "duration" :  data_dict['ann_duration'],
                 "author" : data_dict['ann_meta']['creator'],
-                "date" : data_dict['ann_meta']['created'], 
-                "audio_src" : data_dict['ann_content']['audio']['src'],            
+                "date" : data_dict['ann_meta']['created'],
+                "audio_src" : data_dict['ann_content']['audio']['src'],
                 "audio_href" : data_dict['ann_content']['audio']['href'],
                 "polemics": adder.get_polemic_syntax(data_dict['ann_content']['title'])
             })
-        
-        # We save the added annotation and reprotect the contents and projects
-        adder.save(must_reindex=False)
-        protect_models()
+
+            # We save the added annotation and reprotect the contents and projects
+            adder.save(must_reindex=False)
+        finally:
+            protect_models()
         # We update the AnnotationObject for the returned datas to be correct.
-        
         bundle.obj = AnnotationObject(
-            id = data_dict["ann_id"], 
-            project = data_dict["project_id"], 
-            type = data_dict["ann_type_id"], 
-            type_title = data_dict["ann_type_title"], 
-            ensemble = data_dict['ensemble_id'], 
-            media = data_dict["iri_id"], 
-            begin = data_dict["ann_begin"], 
-            end = data_dict["ann_end"], 
-            content = data_dict['ann_content'], 
-            tags = data_dict['ann_tags'], 
-            meta = data_dict['ann_meta']
+            id=data_dict["ann_id"],
+            project=data_dict["project_id"],
+            type=data_dict["ann_type_id"],
+            type_title=data_dict["ann_type_title"],
+            ensemble=data_dict['ensemble_id'],
+            media=data_dict["iri_id"],
+            begin=data_dict["ann_begin"],
+            end=data_dict["ann_end"],
+            content=data_dict['ann_content'],
+            tags=data_dict['ann_tags'],
+            meta=data_dict['ann_meta']
         )
         return bundle
-    
+
+    def obj_update(self, bundle, **kwargs):
+        data_dict = self.extract_annotation_data(bundle.data)
+        if not data_dict['ann_id']:
+            data_dict['ann_id'] = kwargs["pk"]
+
+        adder = LdtAnnotation(data_dict["project_obj"])
+        try:
+            unprotect_models()  # Allows anonymous user to modify models in this request only
+
+            ensemble_id = adder.edit(
+                data_dict['ann_id'],  # annotation_id
+                data_dict['iri_id'],  # media
+                data_dict['ann_type_id'],  # cutting_id
+                data_dict['ann_type_title'],  # cutting_title
+                data_dict['ann_content']['title'],  # title
+                data_dict['ann_content']['description'],  # text
+                data_dict['ann_tags'],  # tags_list
+                data_dict['ann_begin'],  # begin
+                data_dict['ann_duration'],  # dur
+                data_dict['ann_meta']['creator'],  # author
+                data_dict['ann_meta']['created'],  # date
+                None,
+                "2194379",
+                data_dict['ann_content']['audio']['src'],
+                data_dict['ann_content']['audio']['href']
+            )
+            if not ensemble_id:
+                raise BadRequest
+            # We update the id
+            data_dict['ensemble_id'] = ensemble_id
+            # add segment
+            edit_segment(
+                data_dict["project_id"],
+                data_dict["iri_id"],
+                data_dict["ensemble_id"],
+                data_dict['ann_type_id'],
+                data_dict["ann_id"],
+                params={
+                    "project" : data_dict["project_obj"],
+                    "content" : data_dict["content_obj"],
+                    "ensemble_id" : data_dict["ensemble_id"],
+                    "cutting_id" :  data_dict['ann_type_id'],
+                    "element_id" : data_dict['ann_id'],
+                    "title" : data_dict['ann_content']['title'],
+                    "abstract" : data_dict['ann_content']['description'],
+                    "tags" : ",".join(data_dict['ann_tags']),
+                    "start_ts" : data_dict['ann_begin'],
+                    "duration" :  data_dict['ann_duration'],
+                    "author" : data_dict['ann_meta']['creator'],
+                    "date" : data_dict['ann_meta']['created'],
+                    "audio_src" : data_dict['ann_content']['audio']['src'],
+                    "audio_href" : data_dict['ann_content']['audio']['href'],
+                    "polemics": adder.get_polemic_syntax(data_dict['ann_content']['title'])
+                })
+
+            # We save the added annotation and reprotect the contents and projects
+            adder.save(must_reindex=False)
+        finally:
+            protect_models()
+        # We update the AnnotationObject for the returned datas to be correct.
+
+        bundle.obj = AnnotationObject(
+            id=data_dict["ann_id"],
+            project=data_dict["project_id"],
+            type=data_dict["ann_type_id"],
+            type_title=data_dict["ann_type_title"],
+            ensemble=data_dict['ensemble_id'],
+            media=data_dict["iri_id"],
+            begin=data_dict["ann_begin"],
+            end=data_dict["ann_end"],
+            content=data_dict['ann_content'],
+            tags=data_dict['ann_tags'],
+            meta=data_dict['ann_meta']
+        )
+        return bundle
+
     def obj_delete(self, bundle, **kwargs):
         ann_id = kwargs.get("pk", "")
-        try: 
-            seg_to_delete = Segment.objects.get(element_id = ann_id)
+        try:
+            seg_to_delete = Segment.objects.get(element_id=ann_id)
         except Segment.DoesNotExist:
             raise NotFound("Segment not found. element_id = " + ann_id)
         project_id = seg_to_delete.project_id
         try:
-            project = Project.objects.get(ldt_id = project_id)
+            project = Project.objects.get(ldt_id=project_id)
         except Project.DoesNotExist:
             raise NotFound("Project not found. ldt_id = " + project_id)
         ann_type_id = seg_to_delete.cutting_id
         ensemble_id = seg_to_delete.ensemble_id
         iri_id = seg_to_delete.iri_id
         adder = LdtAnnotation(project)
-        unprotect_models()
-        deleted = adder.delete(ann_id, iri_id, ann_type_id)
-        if not deleted:
+        try:
+            unprotect_models()
+            deleted = adder.delete(ann_id, iri_id, ann_type_id)
+            if not deleted:
+                raise BadRequest
+            delete_segment(project, project_id, iri_id, ensemble_id, ann_type_id, ann_id)
+            adder.save()
+        finally:
             protect_models()
-            raise BadRequest
-        delete_segment(project, project_id, iri_id, ensemble_id, ann_type_id, ann_id)
-        adder.save()
-        protect_models()
         return bundle
-        
+
     def get_resource_uri(self, bundle_or_obj=None, url_name='api_dispatch_list'):
         return ''
 
-    
\ No newline at end of file