Example #1
0
 def test_concurrency_conflict(self):
     import concurrency.api as api
     target = self._get_concurrency_target()
     target_copy = self._get_concurrency_target()
     v1 = api.get_revision_of_object(target)
     v2 = api.get_revision_of_object(target_copy)
     assert v1 == v2, "got same row with different version (%s/%s)" % (v1, v2)
     target.save()
     assert target.pk is not None  # sanity check
     self.assertRaises(RecordModifiedError, target_copy.save)
Example #2
0
    def test_concurrency_conflict(self):
        import concurrency.api as api

        target = self._get_concurrency_target()
        target_copy = self._get_concurrency_target()
        v1 = api.get_revision_of_object(target)
        v2 = api.get_revision_of_object(target_copy)
        assert v1 == v2, "got same row with different version (%s/%s)" % (v1, v2)
        target.save()
        assert target.pk is not None  # sanity check
        self.assertRaises(RecordModifiedError, target_copy.save)
Example #3
0
        def _do_update(model_instance, base_qs, using, pk_val, values, update_fields, forced_update):
            version_field = model_instance._concurrencymeta.field
            old_version = get_revision_of_object(model_instance)

            if not version_field.model._meta.abstract:
                if version_field.model is not base_qs.model:
                    return func(model_instance, base_qs, using, pk_val, values, update_fields, forced_update)

            for i, (field, _1, value) in enumerate(values):
                if field == version_field:
                    new_version = field._get_next_version(model_instance)
                    values[i] = (field, _1, new_version)
                    field._set_version_value(model_instance, new_version)
                    break
            if values:
                if (model_instance._concurrencymeta.enabled and
                        conf.ENABLED and
                        not getattr(model_instance, '_concurrency_disabled', False) and
                        old_version):
                    filter_kwargs = {'pk': pk_val, version_field.attname: old_version}
                    updated = base_qs.filter(**filter_kwargs)._update(values) >= 1
                    if not updated:
                        version_field._set_version_value(model_instance, old_version)
                        updated = conf._callback(model_instance)
                else:
                    filter_kwargs = {'pk': pk_val}
                    updated = base_qs.filter(**filter_kwargs)._update(values) >= 1
            else:
                updated = base_qs.filter(pk=pk_val).exists()

            return updated
Example #4
0
def identity(obj):
    """
    returns a string representing "<pk>,<version>" of the passed object
    """
    if hasattr(obj, 'RevisionMetaInfo'):
        return mark_safe("{0},{1}".format(unlocalize(obj.pk), get_revision_of_object(obj)))
    else:
        return mark_safe(unlocalize(obj.pk))
Example #5
0
 def action_checkbox(self, obj):
     """
     A list_display column containing a checkbox widget.
     """
     if self.check_concurrent_action:
         return helpers.checkbox.render(helpers.ACTION_CHECKBOX_NAME,
                                        force_text("%s,%s" % (obj.pk,
                                                              get_revision_of_object(obj))))
     else:
         return super(ConcurrencyActionMixin, self).action_checkbox(obj)
Example #6
0
 def action_checkbox(self, obj):
     """
     A list_display column containing a checkbox widget.
     """
     if self.check_concurrent_action:
         return helpers.checkbox.render(helpers.ACTION_CHECKBOX_NAME,
                                        force_text("%s,%s" % (obj.pk,
                                                              get_revision_of_object(obj))))
     else:
         return super(ConcurrencyActionMixin, self).action_checkbox(obj)
Example #7
0
 def inner(self, force_insert=False, force_update=False, using=None, **kwargs):
     reload = kwargs.pop('refetch', False)
     ret = func(self, force_insert, force_update, using, **kwargs)
     TriggerVersionField._increment_version_number(self)
     if reload:
         ret = refetch(self)
         setattr(self,
                 self._concurrencymeta.field.attname,
                 get_revision_of_object(ret))
     return ret
        def _do_update(model_instance, base_qs, using, pk_val, values,
                       update_fields, forced_update):
            version_field = model_instance._concurrencymeta.field
            old_version = get_revision_of_object(model_instance)

            if not version_field.model._meta.abstract:
                if version_field.model is not base_qs.model:
                    return func(model_instance, base_qs, using, pk_val, values,
                                update_fields, forced_update)

            for i, (field, _1, value) in enumerate(values):
                if field == version_field:
                    if (model_instance._concurrencymeta.increment
                            and not getattr(model_instance,
                                            '_concurrency_disable_increment',
                                            False)):
                        new_version = field._get_next_version(model_instance)
                        values[i] = (field, _1, new_version)
                        field._set_version_value(model_instance, new_version)
                    # else:
                    #     new_version = old_version
                    break

            # This provides a default if either (1) no values were provided or (2) we reached this code as part of a
            # create.  We don't need to worry about a race condition because a competing create should produce an
            # error anyway.
            updated = base_qs.filter(pk=pk_val).exists()

            # This second situation can occur because `Model.save_base` calls `Model._save_parent` without relaying
            # the `force_insert` flag that marks the process as a create.  Eventually, `Model._save_table` will call
            # this function as-if it were in the middle of an update.  The update is expected to fail because there
            # is no object to update and the caller will fall back on the create logic instead.  We need to ensure
            # the update fails (but does not raise an exception) under this circumstance by skipping the concurrency
            # logic.
            if values and updated:
                if (model_instance._concurrencymeta.enabled
                        and conf.ENABLED and not getattr(
                            model_instance, '_concurrency_disabled', False)
                        and (old_version or not conf.IGNORE_DEFAULT)):
                    filter_kwargs = {
                        'pk': pk_val,
                        version_field.attname: old_version
                    }
                    updated = base_qs.filter(
                        **filter_kwargs)._update(values) >= 1
                    if not updated:
                        version_field._set_version_value(
                            model_instance, old_version)
                        updated = conf._callback(model_instance)
                else:
                    filter_kwargs = {'pk': pk_val}
                    updated = base_qs.filter(
                        **filter_kwargs)._update(values) >= 1

            return updated
    def test_meta_inheritance(self):
        # TestModelWithCustomOptions extends ConcurrentModel
        # but we disabled concurrency only in TestModelWithCustomOptions
        import concurrency.api as api
        concurrency_enabled1 = SimpleConcurrentModel.objects.get_or_create(
            **{'username': '******'})[0]
        concurrency_enabled2 = SimpleConcurrentModel.objects.get_or_create(
            **{'username': '******'})[0]
        v1 = api.get_revision_of_object(concurrency_enabled1)
        v2 = api.get_revision_of_object(concurrency_enabled2)
        assert v1 == v2, "got same row with different version (%s/%s)" % (v1,
                                                                          v2)
        concurrency_enabled1.save()
        assert concurrency_enabled1.pk is not None  # sanity check
        self.assertRaises(RecordModifiedError, concurrency_enabled2.save)

        concurrency_disabled1 = ConcurrencyDisabledModel.objects.get_or_create(
            **{'username': '******'})[0]
        concurrency_disabled2 = ConcurrencyDisabledModel.objects.get_or_create(
            **{'username': '******'})[0]
        v1 = api.get_revision_of_object(concurrency_disabled1)
        v2 = api.get_revision_of_object(concurrency_disabled2)
        assert v1 == v2, "got same row with different version (%s/%s)" % (v1,
                                                                          v2)
        concurrency_disabled1.save()
        assert concurrency_disabled1.pk is not None  # sanity check
        v1 = api.get_revision_of_object(concurrency_disabled1)
        v2 = api.get_revision_of_object(concurrency_disabled2)
        assert v1 != v2
Example #10
0
 def _management_form(self):
     """Returns the ManagementForm instance for this FormSet."""
     if self.is_bound:
         form = ConcurrentManagementForm(self.data, auto_id=self.auto_id,
                                         prefix=self.prefix)
         if not form.is_valid():
             raise ValidationError('ManagementForm data is missing or has been tampered with')
     else:
         form = ConcurrentManagementForm(auto_id=self.auto_id,
                                         prefix=self.prefix,
                                         initial={TOTAL_FORM_COUNT: self.total_form_count(),
                                                  INITIAL_FORM_COUNT: self.initial_form_count(),
                                                  MAX_NUM_FORM_COUNT: self.max_num},
                                         versions=[(form.instance.pk, get_revision_of_object(form.instance)) for form
                                                   in self.initial_forms])
     return form
Example #11
0
 def _management_form(self):
     """Returns the ManagementForm instance for this FormSet."""
     if self.is_bound:
         form = ConcurrentManagementForm(self.data, auto_id=self.auto_id,
                                         prefix=self.prefix)
         if not form.is_valid():
             raise ValidationError('ManagementForm data is missing or has been tampered with')
     else:
         form = ConcurrentManagementForm(auto_id=self.auto_id,
                                         prefix=self.prefix,
                                         initial={TOTAL_FORM_COUNT: self.total_form_count(),
                                                  INITIAL_FORM_COUNT: self.initial_form_count(),
                                                  MAX_NUM_FORM_COUNT: self.max_num},
                                         versions=[(form.instance.pk, get_revision_of_object(form.instance)) for form
                                                   in self.initial_forms])
     return form
Example #12
0
        def _do_update(model_instance, base_qs, using, pk_val, values, update_fields, forced_update):
            version_field = model_instance._concurrencymeta.field
            old_version = get_revision_of_object(model_instance)

            if not version_field.model._meta.abstract:
                if version_field.model is not base_qs.model:
                    return func(model_instance, base_qs, using, pk_val, values, update_fields, forced_update)

            for i, (field, _1, value) in enumerate(values):
                if field == version_field:
                    if (model_instance._concurrencymeta.increment and not
                    getattr(model_instance, '_concurrency_disable_increment', False)):
                        new_version = field._get_next_version(model_instance)
                        values[i] = (field, _1, new_version)
                        field._set_version_value(model_instance, new_version)
                    # else:
                    #     new_version = old_version
                    break

            # This provides a default if either (1) no values were provided or (2) we reached this code as part of a
            # create.  We don't need to worry about a race condition because a competing create should produce an
            # error anyway.
            updated = base_qs.filter(pk=pk_val).exists()

            # This second situation can occur because `Model.save_base` calls `Model._save_parent` without relaying
            # the `force_insert` flag that marks the process as a create.  Eventually, `Model._save_table` will call
            # this function as-if it were in the middle of an update.  The update is expected to fail because there
            # is no object to update and the caller will fall back on the create logic instead.  We need to ensure
            # the update fails (but does not raise an exception) under this circumstance by skipping the concurrency
            # logic.
            if values and updated:
                if (model_instance._concurrencymeta.enabled and
                        conf.ENABLED and
                        not getattr(model_instance, '_concurrency_disabled', False) and
                        (old_version or not conf.IGNORE_DEFAULT)):
                    filter_kwargs = {'pk': pk_val, version_field.attname: old_version}
                    updated = base_qs.filter(**filter_kwargs)._update(values) >= 1
                    if not updated:
                        version_field._set_version_value(model_instance, old_version)
                        updated = conf._callback(model_instance)
                else:
                    filter_kwargs = {'pk': pk_val}
                    updated = base_qs.filter(**filter_kwargs)._update(values) >= 1

            return updated
    def test_meta_inheritance(self):
        # TestModelWithCustomOptions extends ConcurrentModel
        # but we disabled concurrency only in TestModelWithCustomOptions
        import concurrency.api as api
        concurrency_enabled1 = SimpleConcurrentModel.objects.get_or_create(**{'username': '******'})[0]
        concurrency_enabled2 = SimpleConcurrentModel.objects.get_or_create(**{'username': '******'})[0]
        v1 = api.get_revision_of_object(concurrency_enabled1)
        v2 = api.get_revision_of_object(concurrency_enabled2)
        assert v1 == v2, "got same row with different version (%s/%s)" % (v1, v2)
        concurrency_enabled1.save()
        assert concurrency_enabled1.pk is not None  # sanity check
        self.assertRaises(RecordModifiedError, concurrency_enabled2.save)

        concurrency_disabled1 = ConcurrencyDisabledModel.objects.get_or_create(**{'username': '******'})[0]
        concurrency_disabled2 = ConcurrencyDisabledModel.objects.get_or_create(**{'username': '******'})[0]
        v1 = api.get_revision_of_object(concurrency_disabled1)
        v2 = api.get_revision_of_object(concurrency_disabled2)
        assert v1 == v2, "got same row with different version (%s/%s)" % (v1, v2)
        concurrency_disabled1.save()
        assert concurrency_disabled1.pk is not None  # sanity check
        v1 = api.get_revision_of_object(concurrency_disabled1)
        v2 = api.get_revision_of_object(concurrency_disabled2)
        assert v1 != v2
Example #14
0
    def test_concurrency_safety(self):
        import concurrency.api as api

        target = self.concurrency_model()
        version = api.get_revision_of_object(target)
        self.assertFalse(bool(version), "version is not null %s" % version)
Example #15
0
 def _increment_version_number(obj):
     old_value = get_revision_of_object(obj)
     setattr(obj, obj._concurrencymeta.field.attname, int(old_value) + 1)
Example #16
0
def test_get_revision_of_object(model_class=SimpleConcurrentModel):
    instance = model_class(username=next(nextname))
    instance.save()
    assert get_revision_of_object(instance) == instance.version
Example #17
0
def test_get_revision_of_object(model_class=SimpleConcurrentModel):
    instance = model_class(username=next(nextname))
    instance.save()
    assert get_revision_of_object(instance) == instance.version
Example #18
0
def version(obj):
    """
    returns the value of the VersionField of the passed object
    """
    return get_revision_of_object(obj)
Example #19
0
 def test_get_revision_of_object(self):
     o1 = TestModel0.objects.create()
     self.assertEqual(get_revision_of_object(o1), o1.version)
Example #20
0
 def test_get_revision_of_object(self):
     o1 = TestModel0.objects.create()
     self.assertEqual(get_revision_of_object(o1), o1.version)
Example #21
0
 def test_concurrency_safety(self):
     import concurrency.api as api
     target = self.concurrency_model()
     version = api.get_revision_of_object(target)
     self.assertFalse(bool(version), "version is not null %s" % version)