from django.db import models, transaction

from core.lib_models import TimeStampedModel


class CDMSModel(TimeStampedModel):
    cdms_pk = models.CharField(max_length=255, blank=True)

    cdms_migrator = None  # should be subclass of migrator.cdms_migrator.BaseCDMSMigrator

    def __init__(self, *args, **kwargs):
        super(CDMSModel, self).__init__(*args, **kwargs)
        self._cdms_skip = False

    def save(self, *args, **kwargs):
        # a bit hacky but it makes things work :-P
        original_cdms_skip = self._cdms_skip
        self._cdms_skip = kwargs.pop('skip_cdms', self._cdms_skip)
        try:
            ret = super(CDMSModel, self).save(*args, **kwargs)
        finally:
            self._cdms_skip = original_cdms_skip

        return ret

    def _do_insert(self, manager, using, fields, update_pk, raw):
        if self._cdms_skip:
            manager = manager.skip_cdms()
        return super(CDMSModel, self)._do_insert(manager, using, fields, update_pk, raw)

    def _do_update(self, base_qs, using, pk_val, values, update_fields, forced_update):
        if self._cdms_skip:
            base_qs = base_qs.skip_cdms()
        return super(CDMSModel, self)._do_update(base_qs, using, pk_val, values, update_fields, forced_update)

    def _do_delete_cdms_obj(self):
        """
        Private method which only deletes the cdms object. Not meant to be used publicly.
        """
        from .query import DeleteQuery

        assert self.cdms_pk, \
            "%s object can't be deleted because its cdms_pk attribute is not set." % self._meta.object_name

        query = DeleteQuery(self.__class__)
        query.set_cdms_pk(self.cdms_pk)
        query.get_compiler().execute()

    def delete(self, *args, **kwargs):
        original_cdms_skip = self._cdms_skip
        self._cdms_skip = kwargs.pop('skip_cdms', self._cdms_skip)

        try:
            with transaction.atomic():
                ret = super(CDMSModel, self).delete(*args, **kwargs)

                if not self._cdms_skip:
                    self._do_delete_cdms_obj()
        finally:
            self._cdms_skip = original_cdms_skip

        return ret

    class Meta:
        abstract = True

@@ -1,12 +1,53 @@
+from contextlib import ContextDecorator%0A%0A
 from django.
@@ -124,16 +124,630 @@
 Model%0A%0A%0A
+class override_skip_cdms(ContextDecorator):%0A    %22%22%22%0A    Context Manager used to temporarily override the _cdms_skip%0A    class attribute with the %60overriding_skip_cdms%60 given.%0A    %22%22%22%0A    def __init__(self, obj, overriding_skip_cdms):%0A        self.obj = obj%0A        self.overriding_skip_cdms = overriding_skip_cdms%0A%0A    def __enter__(self):%0A        self.original_skip_cdms = self.obj._cdms_skip%0A        self.obj._cdms_skip = self.overriding_skip_cdms%0A        return self%0A%0A    def __exit__(self, *exc):%0A        self.obj._cdms_skip = self.original_skip_cdms%0A        del self.original_skip_cdms%0A        return False%0A%0A%0A
 class CD
@@ -1104,119 +1104,28 @@
     
-# a bit hacky but it makes things work :-P%0A        original_cdms_skip = self._cdms_skip%0A        self._cdms_skip
+overriding_skip_cdms
  = k
@@ -1164,35 +1164,83 @@
 s_skip)%0A        
-try
+with override_skip_cdms(self, overriding_skip_cdms)
 :%0A            re
@@ -1232,34 +1232,35 @@
 %0A            ret
- =
+urn
  super(CDMSModel
@@ -1292,94 +1292,8 @@
 rgs)
-%0A        finally:%0A            self._cdms_skip = original_cdms_skip%0A%0A        return ret
 %0A%0A  
@@ -2290,68 +2290,47 @@
     
-original_cdms_skip = self._cdms_skip%0A        self._cdms_skip
+ret = None%0A        overriding_skip_cdms
  = k
@@ -2369,25 +2369,24 @@
 s_skip)%0A
-%0A
         
 try:%0A   
@@ -2381,11 +2381,59 @@
     
-try
+with override_skip_cdms(self, overriding_skip_cdms)
 :%0A  
@@ -2629,74 +2629,8 @@
 bj()
-%0A        finally:%0A            self._cdms_skip = original_cdms_skip
 %0A%0A  

Use context manager for overriding self._cdms_skip