From 9a976d5ec8372b555474e14d110323de6861d7c5 Mon Sep 17 00:00:00 2001 From: Swen Kooij Date: Thu, 2 Feb 2017 15:01:40 +0200 Subject: [PATCH] Added max retries option + tests --- localized_fields/models.py | 11 +++++++++-- settings.py | 4 ++++ tests/test_db_backend.py | 2 +- tests/test_localized_slug_fields.py | 30 ++++++++++++++++++++++++----- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/localized_fields/models.py b/localized_fields/models.py index 06be787..c55e7b8 100644 --- a/localized_fields/models.py +++ b/localized_fields/models.py @@ -1,5 +1,6 @@ from django.db import models, transaction from django.db.utils import IntegrityError +from django.conf import settings from .fields import LocalizedField from .localized_value import LocalizedValue @@ -37,6 +38,12 @@ class LocalizedModel(models.Model): def save(self, *args, **kwargs): """Saves this model instance to the database.""" + max_retries = getattr( + settings, + 'LOCALIZED_FIELDS_MAX_RETRIES', + 100 + ) + if not hasattr(self, 'retries'): self.retries = 0 @@ -49,8 +56,8 @@ class LocalizedModel(models.Model): # field class... we can also not only catch exceptions # that apply to slug fields... so yea.. this is as # retarded as it gets... i am sorry :( - if 'slug' not in str(ex): - if self.retries >= 100: + if 'slug' in str(ex): + if self.retries >= max_retries: raise ex self.retries += 1 diff --git a/settings.py b/settings.py index 1d29ae8..eb492c0 100644 --- a/settings.py +++ b/settings.py @@ -23,3 +23,7 @@ LANGUAGES = ( INSTALLED_APPS = ( 'tests', ) + +# set to a lower number than the default, since +# we want the tests to be fast, default is 100 +LOCALIZED_FIELDS_MAX_RETRIES = 3 diff --git a/tests/test_db_backend.py b/tests/test_db_backend.py index 8096e79..a37f852 100644 --- a/tests/test_db_backend.py +++ b/tests/test_db_backend.py @@ -1,6 +1,7 @@ from unittest import mock from django.db import connection +from django.apps import apps from django.conf import settings from django.test import TestCase from django.db.backends.base.schema import BaseDatabaseSchemaEditor @@ -8,7 +9,6 @@ from django.db.backends.base.schema import BaseDatabaseSchemaEditor from localized_fields import LocalizedField, get_language_codes from .fake_model import define_fake_model -from django.apps import apps class DBBackendTestCase(TestCase): diff --git a/tests/test_localized_slug_fields.py b/tests/test_localized_slug_fields.py index 90a0001..566fd98 100644 --- a/tests/test_localized_slug_fields.py +++ b/tests/test_localized_slug_fields.py @@ -1,9 +1,11 @@ from django import forms from django.conf import settings from django.test import TestCase +from django.db.utils import IntegrityError +from django.utils.text import slugify + from localized_fields import (LocalizedField, LocalizedAutoSlugField, LocalizedMagicSlugField) -from django.utils.text import slugify from .fake_model import get_fake_model @@ -60,6 +62,22 @@ class LocalizedSlugFieldTestCase(TestCase): def test_unique_slug_magic(cls): cls._test_unique_slug(cls.MagicSlugModel) + def test_unique_slug_magic_max_retries(self): + """Tests whether the magic slug implementation doesn't + try to find a slug forever and gives up after a while.""" + + title = 'mymagictitle' + + obj = self.MagicSlugModel() + obj.title.en = title + obj.save() + + with self.assertRaises(IntegrityError): + for _ in range(0, settings.LOCALIZED_FIELDS_MAX_RETRIES + 1): + another_obj = self.MagicSlugModel() + another_obj.title.en = title + another_obj.save() + @classmethod def test_unique_slug_utf_auto(cls): cls._test_unique_slug_utf(cls.AutoSlugModel) @@ -112,16 +130,18 @@ class LocalizedSlugFieldTestCase(TestCase): def _test_unique_slug(model): """Tests whether unique slugs are properly generated.""" + title = 'mymagictitle' + obj = model() - obj.title.en = 'title' + obj.title.en = title obj.save() - for i in range(1, 90): + for i in range(1, settings.LOCALIZED_FIELDS_MAX_RETRIES - 1): another_obj = model() - another_obj.title.en = 'title' + another_obj.title.en = title another_obj.save() - assert another_obj.slug.en == 'title-%d' % i + assert another_obj.slug.en == '%s-%d' % (title, i) @staticmethod def _test_unique_slug_utf(model):